Kaynağa Gözat

project: begin merge of Legacy and iOS builds

Mark SwiftUI classes with availability wrappers, move main() entry
osy 5 yıl önce
ebeveyn
işleme
3a3c96aef1
45 değiştirilmiş dosya ile 148 ekleme ve 15 silme
  1. 2 0
      Configuration/UTMConfigurationExtension.swift
  2. 4 0
      Platform/BusyOverlay.swift
  3. 44 0
      Platform/Main.swift
  4. 1 0
      Platform/Swift-Bridging-Header.h
  5. 1 13
      Platform/UTMApp.swift
  6. 2 0
      Platform/UTMData.swift
  7. 1 0
      Platform/UTMExtensions.swift
  8. 4 0
      Platform/VMCardView.swift
  9. 2 0
      Platform/VMConfigDisplayView.swift
  10. 2 0
      Platform/VMConfigDriveCreateView.swift
  11. 1 0
      Platform/VMConfigDriveDetailsView.swift
  12. 5 0
      Platform/VMConfigInfoView.swift
  13. 4 0
      Platform/VMConfigInputView.swift
  14. 3 0
      Platform/VMConfigNetworkView.swift
  15. 2 0
      Platform/VMConfigPortForwardForm.swift
  16. 3 0
      Platform/VMConfigQEMUView.swift
  17. 2 0
      Platform/VMConfigSharingView.swift
  18. 2 0
      Platform/VMConfigSoundView.swift
  19. 2 0
      Platform/VMConfigStringPicker.swift
  20. 2 0
      Platform/VMConfigSystemView.swift
  21. 5 0
      Platform/VMDetailsView.swift
  22. 1 0
      Platform/VMDriveImage.swift
  23. 2 0
      Platform/VMPlaceholderView.swift
  24. 2 0
      Platform/VMRemovableDrivesView.swift
  25. 1 0
      Platform/VMShareFileModifier.swift
  26. 1 0
      Platform/VMToolbarModifier.swift
  27. 2 0
      Platform/iOS/ActivityView.swift
  28. 2 0
      Platform/iOS/ContentView.swift
  29. 2 0
      Platform/iOS/ImagePicker.swift
  30. 2 0
      Platform/iOS/Info.plist
  31. 1 0
      Platform/iOS/UTMDataExtension.swift
  32. 3 0
      Platform/iOS/VMConfigDrivesView.swift
  33. 3 0
      Platform/iOS/VMConfigNetworkPortForwardView.swift
  34. 3 0
      Platform/iOS/VMSettingsView.swift
  35. 2 0
      Platform/macOS/ContentView.swift
  36. 2 0
      Platform/macOS/SettingsView.swift
  37. 1 0
      Platform/macOS/SharingServicePicker.swift
  38. 4 0
      Platform/macOS/ToolbarTabView.swift
  39. 1 0
      Platform/macOS/ToolbarTabViewController.swift
  40. 1 0
      Platform/macOS/UTMDataExtension.swift
  41. 1 0
      Platform/macOS/UTMTabViewController.swift
  42. 3 0
      Platform/macOS/VMConfigDrivesView.swift
  43. 3 0
      Platform/macOS/VMConfigNetworkPortForwardView.swift
  44. 3 0
      Platform/macOS/VMSettingsView.swift
  45. 8 2
      UTM.xcodeproj/project.pbxproj

+ 2 - 0
Configuration/UTMConfigurationExtension.swift

@@ -16,6 +16,7 @@
 
 
 import Combine
 import Combine
 
 
+@available(iOS 14, macOS 11, *)
 @objc extension UTMConfiguration: ObservableObject {
 @objc extension UTMConfiguration: ObservableObject {
     private static let gibInMib = 1024
     private static let gibInMib = 1024
     
     
@@ -90,6 +91,7 @@ import Combine
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 @objc extension UTMConfigurationPortForward: ObservableObject {
 @objc extension UTMConfigurationPortForward: ObservableObject {
     func propertyWillChange() -> Void {
     func propertyWillChange() -> Void {
         DispatchQueue.main.async { self.objectWillChange.send() }
         DispatchQueue.main.async { self.objectWillChange.send() }

+ 4 - 0
Platform/BusyOverlay.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct BusyOverlay: View {
 struct BusyOverlay: View {
     @EnvironmentObject private var data: UTMData
     @EnvironmentObject private var data: UTMData
     
     
@@ -38,6 +39,7 @@ struct BusyOverlay: View {
 }
 }
 
 
 #if os(macOS)
 #if os(macOS)
+@available(macOS 11, *)
 struct BigWhiteSpinner: NSViewRepresentable {
 struct BigWhiteSpinner: NSViewRepresentable {
     func makeNSView(context: Context) -> NSProgressIndicator {
     func makeNSView(context: Context) -> NSProgressIndicator {
         let view = NSProgressIndicator()
         let view = NSProgressIndicator()
@@ -50,6 +52,7 @@ struct BigWhiteSpinner: NSViewRepresentable {
     }
     }
 }
 }
 #else // iOS
 #else // iOS
+@available(iOS 14, *)
 struct BigWhiteSpinner: UIViewRepresentable {
 struct BigWhiteSpinner: UIViewRepresentable {
     func makeUIView(context: Context) -> UIActivityIndicatorView {
     func makeUIView(context: Context) -> UIActivityIndicatorView {
         let view = UIActivityIndicatorView(style: .large)
         let view = UIActivityIndicatorView(style: .large)
@@ -63,6 +66,7 @@ struct BigWhiteSpinner: UIViewRepresentable {
 }
 }
 #endif
 #endif
 
 
+@available(iOS 14, macOS 11, *)
 struct BusyOverlay_Previews: PreviewProvider {
 struct BusyOverlay_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         BusyOverlay()
         BusyOverlay()

+ 44 - 0
Platform/Main.swift

@@ -0,0 +1,44 @@
+//
+// Copyright © 2020 osy. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+import Logging
+
+let logger = Logger(label: "com.osy86.UTM")
+
+@main
+class Main {
+    static func main() {
+        setupLogging()
+        if #available(iOS 14, macOS 11, *) {
+            UTMApp.main()
+        } else {
+            #if os(macOS)
+            logger.critical("This version of macOS is not supported!")
+            #else
+            UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
+            #endif
+        }
+    }
+    
+    static private func setupLogging() {
+        LoggingSystem.bootstrap { label in
+            return MultiplexLogHandler([
+                UTMLoggingSwift(label: label),
+                StreamLogHandler.standardOutput(label: label)
+            ])
+        }
+    }
+}

+ 1 - 0
Platform/Swift-Bridging-Header.h

@@ -35,6 +35,7 @@
 #include "UTMSpiceIO.h"
 #include "UTMSpiceIO.h"
 #include "CocoaSpice.h"
 #include "CocoaSpice.h"
 #if TARGET_OS_IPHONE
 #if TARGET_OS_IPHONE
+#include "AppDelegate.h"
 #include "VMDisplayViewController.h"
 #include "VMDisplayViewController.h"
 #include "VMDisplayMetalViewController.h"
 #include "VMDisplayMetalViewController.h"
 #include "VMDisplayMetalViewController+Keyboard.h"
 #include "VMDisplayMetalViewController+Keyboard.h"

+ 1 - 13
Platform/UTMApp.swift

@@ -15,11 +15,8 @@
 //
 //
 
 
 import SwiftUI
 import SwiftUI
-import Logging
 
 
-let logger = Logger(label: "com.osy86.UTM")
-
-@main
+@available(iOS 14, macOS 11, *)
 struct UTMApp: App {
 struct UTMApp: App {
     @StateObject var data = UTMData()
     @StateObject var data = UTMData()
     
     
@@ -33,13 +30,4 @@ struct UTMApp: App {
         }
         }
         #endif
         #endif
     }
     }
-    
-    init() {
-        LoggingSystem.bootstrap { label in
-            return MultiplexLogHandler([
-                UTMLoggingSwift(label: label),
-                StreamLogHandler.standardOutput(label: label)
-            ])
-        }
-    }
 }
 }

+ 2 - 0
Platform/UTMData.swift

@@ -16,6 +16,7 @@
 
 
 import Foundation
 import Foundation
 
 
+@available(iOS 14, macOS 11, *)
 struct AlertMessage: Identifiable {
 struct AlertMessage: Identifiable {
     var message: String
     var message: String
     public var id: String {
     public var id: String {
@@ -27,6 +28,7 @@ struct AlertMessage: Identifiable {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 class UTMData: ObservableObject {
 class UTMData: ObservableObject {
     
     
     @Published var showSettingsModal: Bool
     @Published var showSettingsModal: Bool

+ 1 - 0
Platform/UTMExtensions.swift

@@ -36,6 +36,7 @@ extension Optional where Wrapped == String {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 extension LocalizedStringKey {
 extension LocalizedStringKey {
     var localizedString: String {
     var localizedString: String {
         let mirror = Mirror(reflecting: self)
         let mirror = Mirror(reflecting: self)

+ 4 - 0
Platform/VMCardView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMCardView: View {
 struct VMCardView: View {
     let vm: UTMVirtualMachine
     let vm: UTMVirtualMachine
     @EnvironmentObject private var data: UTMData
     @EnvironmentObject private var data: UTMData
@@ -94,6 +95,7 @@ struct VMCardView: View {
 }
 }
 
 
 #if os(macOS)
 #if os(macOS)
+@available(macOS 11, *)
 struct Logo: View {
 struct Logo: View {
     let logo: NSImage?
     let logo: NSImage?
     
     
@@ -114,6 +116,7 @@ struct Logo: View {
     }
     }
 }
 }
 #else // iOS
 #else // iOS
+@available(iOS 14, *)
 struct Logo: View {
 struct Logo: View {
     let logo: UIImage?
     let logo: UIImage?
     
     
@@ -134,6 +137,7 @@ struct Logo: View {
 }
 }
 #endif
 #endif
 
 
+@available(iOS 14, macOS 11, *)
 struct VMCardView_Previews: PreviewProvider {
 struct VMCardView_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         VMCardView(vm: UTMVirtualMachine(configuration: UTMConfiguration(name: "Test"), withDestinationURL: URL(fileURLWithPath: "/")))
         VMCardView(vm: UTMVirtualMachine(configuration: UTMConfiguration(name: "Test"), withDestinationURL: URL(fileURLWithPath: "/")))

+ 2 - 0
Platform/VMConfigDisplayView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigDisplayView: View {
 struct VMConfigDisplayView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -79,6 +80,7 @@ struct VMConfigDisplayView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigDisplayView_Previews: PreviewProvider {
 struct VMConfigDisplayView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 2 - 0
Platform/VMConfigDriveCreateView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigDriveCreateView: View {
 struct VMConfigDriveCreateView: View {
     let minSizeMib = 1
     let minSizeMib = 1
     
     
@@ -49,6 +50,7 @@ struct VMConfigDriveCreateView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigDriveCreateView_Previews: PreviewProvider {
 struct VMConfigDriveCreateView_Previews: PreviewProvider {
     @StateObject static private var driveImage = VMDriveImage()
     @StateObject static private var driveImage = VMDriveImage()
     
     

+ 1 - 0
Platform/VMConfigDriveDetailsView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigDriveDetailsView: View {
 struct VMConfigDriveDetailsView: View {
     @ObservedObject private var config: UTMConfiguration
     @ObservedObject private var config: UTMConfiguration
     @Binding private var removable: Bool
     @Binding private var removable: Bool

+ 5 - 0
Platform/VMConfigInfoView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 private enum IconStyle: String, Identifiable, CaseIterable {
 private enum IconStyle: String, Identifiable, CaseIterable {
     case generic = "Generic"
     case generic = "Generic"
     case operatingSystem = "Operating System"
     case operatingSystem = "Operating System"
@@ -25,6 +26,7 @@ private enum IconStyle: String, Identifiable, CaseIterable {
     var id: String { rawValue }
     var id: String { rawValue }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigInfoView: View {
 struct VMConfigInfoView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     @State private var imageSelectVisible: Bool = false
     @State private var imageSelectVisible: Bool = false
@@ -152,6 +154,7 @@ struct VMConfigInfoView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 private struct IconPreview: View {
 private struct IconPreview: View {
     let url: URL?
     let url: URL?
     
     
@@ -171,6 +174,7 @@ private struct IconPreview: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 private struct IconSelect: View {
 private struct IconSelect: View {
     let onIconSelected: (URL) -> Void
     let onIconSelected: (URL) -> Void
     private let gridLayout = [GridItem(.adaptive(minimum: 60))]
     private let gridLayout = [GridItem(.adaptive(minimum: 60))]
@@ -198,6 +202,7 @@ private struct IconSelect: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigInfoView_Previews: PreviewProvider {
 struct VMConfigInfoView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 4 - 0
Platform/VMConfigInputView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigInputView: View {
 struct VMConfigInputView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -41,12 +42,14 @@ struct VMConfigInputView: View {
 }
 }
 
 
 #if os(macOS)
 #if os(macOS)
+@available(macOS 11, *)
 struct GestureSettingsSection: View {
 struct GestureSettingsSection: View {
     var body: some View {
     var body: some View {
         EmptyView()
         EmptyView()
     }
     }
 }
 }
 #else
 #else
+@available(iOS 14, *)
 struct GestureSettingsSection: View {
 struct GestureSettingsSection: View {
     var body: some View {
     var body: some View {
         Section(header: Text("Additional Settings"), footer: EmptyView().padding(.bottom)) {
         Section(header: Text("Additional Settings"), footer: EmptyView().padding(.bottom)) {
@@ -60,6 +63,7 @@ struct GestureSettingsSection: View {
 }
 }
 #endif
 #endif
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigInputView_Previews: PreviewProvider {
 struct VMConfigInputView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 3 - 0
Platform/VMConfigNetworkView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigNetworkView: View {
 struct VMConfigNetworkView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     @State private var showAdvanced: Bool = false
     @State private var showAdvanced: Bool = false
@@ -52,6 +53,7 @@ struct VMConfigNetworkView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct IPConfigurationSection: View {
 struct IPConfigurationSection: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -126,6 +128,7 @@ struct IPConfigurationSection: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigNetworkingView_Previews: PreviewProvider {
 struct VMConfigNetworkingView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     
     

+ 2 - 0
Platform/VMConfigPortForwardForm.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigPortForwardForm: View {
 struct VMConfigPortForwardForm: View {
     @ObservedObject var configPort: UTMConfigurationPortForward
     @ObservedObject var configPort: UTMConfigurationPortForward
     
     
@@ -52,6 +53,7 @@ struct VMConfigPortForwardForm: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigPortForwardForm_Previews: PreviewProvider {
 struct VMConfigPortForwardForm_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var configPort = UTMConfigurationPortForward()
     @State static private var configPort = UTMConfigurationPortForward()

+ 3 - 0
Platform/VMConfigQEMUView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigQEMUView: View {
 struct VMConfigQEMUView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     @State private var customArgsOnly: Bool = false //FIXME: implement this
     @State private var customArgsOnly: Bool = false //FIXME: implement this
@@ -99,6 +100,7 @@ struct VMConfigQEMUView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct CustomArguments: View {
 struct CustomArguments: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -146,6 +148,7 @@ struct CustomArguments: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigQEMUView_Previews: PreviewProvider {
 struct VMConfigQEMUView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 2 - 0
Platform/VMConfigSharingView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigSharingView: View {
 struct VMConfigSharingView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -42,6 +43,7 @@ struct VMConfigSharingView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigSharingView_Previews: PreviewProvider {
 struct VMConfigSharingView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     
     

+ 2 - 0
Platform/VMConfigSoundView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigSoundView: View {
 struct VMConfigSoundView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -35,6 +36,7 @@ struct VMConfigSoundView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigSoundView_Previews: PreviewProvider {
 struct VMConfigSoundView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     
     

+ 2 - 0
Platform/VMConfigStringPicker.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigStringPicker<Label> : View where Label : View {
 struct VMConfigStringPicker<Label> : View where Label : View {
     @Binding var selection: String?
     @Binding var selection: String?
     var label: Label
     var label: Label
@@ -49,6 +50,7 @@ struct VMConfigStringPicker<Label> : View where Label : View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigStringPickerView_Previews: PreviewProvider {
 struct VMConfigStringPickerView_Previews: PreviewProvider {
     @State static private var selected: String? = nil
     @State static private var selected: String? = nil
     
     

+ 2 - 0
Platform/VMConfigSystemView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigSystemView: View {
 struct VMConfigSystemView: View {
     let validMemoryValues = [32, 64, 128, 256, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 32768]
     let validMemoryValues = [32, 64, 128, 256, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 32768]
     let bytesInMib: UInt64 = 1024 * 1024
     let bytesInMib: UInt64 = 1024 * 1024
@@ -153,6 +154,7 @@ struct VMConfigSystemView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMConfigSystemView_Previews: PreviewProvider {
 struct VMConfigSystemView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 5 - 0
Platform/VMDetailsView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMDetailsView: View {
 struct VMDetailsView: View {
     var vm: UTMVirtualMachine
     var vm: UTMVirtualMachine
     @EnvironmentObject private var data: UTMData
     @EnvironmentObject private var data: UTMData
@@ -67,6 +68,7 @@ struct VMDetailsView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct Screenshot: View {
 struct Screenshot: View {
     let vm: UTMVirtualMachine
     let vm: UTMVirtualMachine
     let large: Bool
     let large: Bool
@@ -100,6 +102,7 @@ struct Screenshot: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct Details: View {
 struct Details: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -134,6 +137,7 @@ struct Details: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct DetailsLabelStyle: LabelStyle {
 struct DetailsLabelStyle: LabelStyle {
     var color: Color = .accentColor
     var color: Color = .accentColor
     
     
@@ -151,6 +155,7 @@ struct DetailsLabelStyle: LabelStyle {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMDetailsView_Previews: PreviewProvider {
 struct VMDetailsView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     
     

+ 1 - 0
Platform/VMDriveImage.swift

@@ -14,6 +14,7 @@
 // limitations under the License.
 // limitations under the License.
 //
 //
 
 
+@available(iOS 14, macOS 11, *)
 class VMDriveImage: ObservableObject {
 class VMDriveImage: ObservableObject {
     @Published var size: Int = 10240
     @Published var size: Int = 10240
     @Published var removable: Bool = false
     @Published var removable: Bool = false

+ 2 - 0
Platform/VMPlaceholderView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMPlaceholderView: View {
 struct VMPlaceholderView: View {
     var body: some View {
     var body: some View {
         VStack {
         VStack {
@@ -35,6 +36,7 @@ struct VMPlaceholderView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMPlaceholderView_Previews: PreviewProvider {
 struct VMPlaceholderView_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         VMPlaceholderView()
         VMPlaceholderView()

+ 2 - 0
Platform/VMRemovableDrivesView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMRemovableDrivesView: View {
 struct VMRemovableDrivesView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -72,6 +73,7 @@ struct VMRemovableDrivesView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, macOS 11, *)
 struct VMRemovableDrivesView_Previews: PreviewProvider {
 struct VMRemovableDrivesView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 1 - 0
Platform/VMShareFileModifier.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, macOS 11, *)
 struct VMShareFileModifier: ViewModifier {
 struct VMShareFileModifier: ViewModifier {
     @Binding var isPresented: Bool
     @Binding var isPresented: Bool
     let files: () -> [URL]
     let files: () -> [URL]

+ 1 - 0
Platform/VMToolbarModifier.swift

@@ -17,6 +17,7 @@
 import SwiftUI
 import SwiftUI
 
 
 // Lots of dirty hacks to work around SwiftUI bugs introduced in Beta 2
 // Lots of dirty hacks to work around SwiftUI bugs introduced in Beta 2
+@available(iOS 14, macOS 11, *)
 struct VMToolbarModifier: ViewModifier {
 struct VMToolbarModifier: ViewModifier {
     let vm: UTMVirtualMachine
     let vm: UTMVirtualMachine
     let bottom: Bool
     let bottom: Bool

+ 2 - 0
Platform/iOS/ActivityView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, *)
 struct ActivityView: UIViewControllerRepresentable {
 struct ActivityView: UIViewControllerRepresentable {
     let activityItems: [Any]
     let activityItems: [Any]
     
     
@@ -28,6 +29,7 @@ struct ActivityView: UIViewControllerRepresentable {
     }
     }
 }
 }
 
 
+@available(iOS 14, *)
 struct ActivityView_Previews: PreviewProvider {
 struct ActivityView_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         ActivityView(activityItems: [])
         ActivityView(activityItems: [])

+ 2 - 0
Platform/iOS/ContentView.swift

@@ -17,6 +17,7 @@
 import SwiftUI
 import SwiftUI
 import IQKeyboardManagerSwift
 import IQKeyboardManagerSwift
 
 
+@available(iOS 14, *)
 struct ContentView: View {
 struct ContentView: View {
     @State private var editMode = false
     @State private var editMode = false
     @EnvironmentObject private var data: UTMData
     @EnvironmentObject private var data: UTMData
@@ -86,6 +87,7 @@ struct ContentView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, *)
 struct ContentView_Previews: PreviewProvider {
 struct ContentView_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         ContentView()
         ContentView()

+ 2 - 0
Platform/iOS/ImagePicker.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, *)
 struct ImagePicker: UIViewControllerRepresentable {
 struct ImagePicker: UIViewControllerRepresentable {
     class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
     class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
         let parent: ImagePicker
         let parent: ImagePicker
@@ -49,6 +50,7 @@ struct ImagePicker: UIViewControllerRepresentable {
     }
     }
 }
 }
 
 
+@available(iOS 14, *)
 struct ImagePicker_Previews: PreviewProvider {
 struct ImagePicker_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         ImagePicker() { _ in
         ImagePicker() { _ in

+ 2 - 0
Platform/iOS/Info.plist

@@ -69,6 +69,8 @@
 	<true/>
 	<true/>
 	<key>UIViewControllerBasedStatusBarAppearance</key>
 	<key>UIViewControllerBasedStatusBarAppearance</key>
 	<true/>
 	<true/>
+	<key>UIMainStoryboardFile</key>
+	<string>Main</string>
 	<key>UTExportedTypeDeclarations</key>
 	<key>UTExportedTypeDeclarations</key>
 	<array>
 	<array>
 		<dict>
 		<dict>

+ 1 - 0
Platform/iOS/UTMDataExtension.swift

@@ -16,6 +16,7 @@
 
 
 import Foundation
 import Foundation
 
 
+@available(iOS 14, *)
 extension UTMData {
 extension UTMData {
     private func createDisplay(vm: UTMVirtualMachine) -> VMDisplayViewController {
     private func createDisplay(vm: UTMVirtualMachine) -> VMDisplayViewController {
         if vm.configuration.displayConsoleOnly {
         if vm.configuration.displayConsoleOnly {

+ 3 - 0
Platform/iOS/VMConfigDrivesView.swift

@@ -18,6 +18,7 @@ import SwiftUI
 
 
 // MARK: - Drives list
 // MARK: - Drives list
 
 
+@available(iOS 14, *)
 struct VMConfigDrivesView: View {
 struct VMConfigDrivesView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     @State private var createDriveVisible: Bool = false
     @State private var createDriveVisible: Bool = false
@@ -118,6 +119,7 @@ struct VMConfigDrivesView: View {
 
 
 // MARK: - Create Drive
 // MARK: - Create Drive
 
 
+@available(iOS 14, *)
 private struct CreateDrive: View {
 private struct CreateDrive: View {
     let onDismiss: (VMDriveImage) -> Void
     let onDismiss: (VMDriveImage) -> Void
     @StateObject private var driveImage = VMDriveImage()
     @StateObject private var driveImage = VMDriveImage()
@@ -150,6 +152,7 @@ private struct CreateDrive: View {
 
 
 // MARK: - Preview
 // MARK: - Preview
 
 
+@available(iOS 14, *)
 struct VMConfigDrivesView_Previews: PreviewProvider {
 struct VMConfigDrivesView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 3 - 0
Platform/iOS/VMConfigNetworkPortForwardView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, *)
 struct VMConfigNetworkPortForwardView: View {
 struct VMConfigNetworkPortForwardView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     
     
@@ -49,6 +50,7 @@ struct VMConfigNetworkPortForwardView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, *)
 struct PortForwardEdit: View {
 struct PortForwardEdit: View {
     @StateObject private var configPort: UTMConfigurationPortForward
     @StateObject private var configPort: UTMConfigurationPortForward
     private let save: () -> Void
     private let save: () -> Void
@@ -85,6 +87,7 @@ struct PortForwardEdit: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, *)
 struct VMConfigNetworkPortForwardView_Previews: PreviewProvider {
 struct VMConfigNetworkPortForwardView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     static var previews: some View {
     static var previews: some View {

+ 3 - 0
Platform/iOS/VMSettingsView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(iOS 14, *)
 struct VMSettingsView: View {
 struct VMSettingsView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     var save: (UTMConfiguration) -> Void
     var save: (UTMConfiguration) -> Void
@@ -102,6 +103,7 @@ struct VMSettingsView: View {
     }
     }
 }
 }
 
 
+@available(iOS 14, *)
 struct RoundRectIconLabelStyle: LabelStyle {
 struct RoundRectIconLabelStyle: LabelStyle {
     var color: Color = .blue
     var color: Color = .blue
     
     
@@ -119,6 +121,7 @@ struct RoundRectIconLabelStyle: LabelStyle {
     }
     }
 }
 }
 
 
+@available(iOS 14, *)
 struct VMSettingsView_Previews: PreviewProvider {
 struct VMSettingsView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     
     

+ 2 - 0
Platform/macOS/ContentView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(macOS 11, *)
 struct ContentView: View {
 struct ContentView: View {
     @State private var editMode = false
     @State private var editMode = false
     @StateObject private var data = UTMData()
     @StateObject private var data = UTMData()
@@ -74,6 +75,7 @@ struct ContentView: View {
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
 struct ContentView_Previews: PreviewProvider {
 struct ContentView_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         ContentView()
         ContentView()

+ 2 - 0
Platform/macOS/SettingsView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(macOS 11, *)
 struct SettingsView: View {
 struct SettingsView: View {
     @AppStorage("AlwaysNativeResolution") var isAlwaysNativeResolution = false
     @AppStorage("AlwaysNativeResolution") var isAlwaysNativeResolution = false
     @AppStorage("DisplayFixed") var isVMDisplayFixed = false
     @AppStorage("DisplayFixed") var isVMDisplayFixed = false
@@ -40,6 +41,7 @@ extension UserDefaults {
     @objc dynamic var DisplayFixed: Bool { false }
     @objc dynamic var DisplayFixed: Bool { false }
 }
 }
 
 
+@available(macOS 11, *)
 struct SettingsView_Previews: PreviewProvider {
 struct SettingsView_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         SettingsView()
         SettingsView()

+ 1 - 0
Platform/macOS/SharingServicePicker.swift

@@ -17,6 +17,7 @@
 import SwiftUI
 import SwiftUI
 
 
 // https://stackoverflow.com/a/60955909/13914748
 // https://stackoverflow.com/a/60955909/13914748
+@available(macOS 11, *)
 struct SharingsPicker: NSViewRepresentable {
 struct SharingsPicker: NSViewRepresentable {
     @Binding var isPresented: Bool
     @Binding var isPresented: Bool
     var sharingItems: [Any] = []
     var sharingItems: [Any] = []

+ 4 - 0
Platform/macOS/ToolbarTabView.swift

@@ -18,6 +18,7 @@ import SwiftUI
 
 
 // MARK: - View
 // MARK: - View
 
 
+@available(macOS 11, *)
 public struct ToolbarTabView: View {
 public struct ToolbarTabView: View {
     let tabs: [AnyView]
     let tabs: [AnyView]
 
 
@@ -97,6 +98,7 @@ public struct ToolbarTabView: View {
 
 
 // MARK: - Tab Item Preference
 // MARK: - Tab Item Preference
 
 
+@available(macOS 11, *)
 private struct ToolbarTabItemPreference : Equatable {
 private struct ToolbarTabItemPreference : Equatable {
     let label: LocalizedStringKey
     let label: LocalizedStringKey
     let nsImage: NSImage?
     let nsImage: NSImage?
@@ -125,6 +127,7 @@ private struct ToolbarTabItemPreferenceKey: PreferenceKey {
 
 
 // MARK: - Toolbar item modifier
 // MARK: - Toolbar item modifier
 
 
+@available(macOS 11, *)
 extension View {
 extension View {
     func toolbarTabItem(_ label: LocalizedStringKey, nsImage: NSImage? = nil, tooltip: LocalizedStringKey? = nil) -> some View {
     func toolbarTabItem(_ label: LocalizedStringKey, nsImage: NSImage? = nil, tooltip: LocalizedStringKey? = nil) -> some View {
         self.preference(key: ToolbarTabItemPreferenceKey.self, value: ToolbarTabItemPreference(label: label, nsImage: nsImage, tooltip: tooltip))
         self.preference(key: ToolbarTabItemPreferenceKey.self, value: ToolbarTabItemPreference(label: label, nsImage: nsImage, tooltip: tooltip))
@@ -137,6 +140,7 @@ extension View {
 
 
 // MARK: - Preview
 // MARK: - Preview
 
 
+@available(macOS 11, *)
 struct ToolbarTabView_Previews: PreviewProvider {
 struct ToolbarTabView_Previews: PreviewProvider {
     static var previews: some View {
     static var previews: some View {
         ToolbarTabView {
         ToolbarTabView {

+ 1 - 0
Platform/macOS/ToolbarTabViewController.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(macOS 11, *)
 public struct ToolbarTabViewController: NSViewControllerRepresentable {
 public struct ToolbarTabViewController: NSViewControllerRepresentable {
     let tabViewItems: [NSTabViewItem]
     let tabViewItems: [NSTabViewItem]
     
     

+ 1 - 0
Platform/macOS/UTMDataExtension.swift

@@ -16,6 +16,7 @@
 
 
 import Foundation
 import Foundation
 
 
+@available(macOS 11, *)
 extension UTMData {
 extension UTMData {
     func run(vm: UTMVirtualMachine) {
     func run(vm: UTMVirtualMachine) {
         if vm.configuration.displayConsoleOnly {
         if vm.configuration.displayConsoleOnly {

+ 1 - 0
Platform/macOS/UTMTabViewController.swift

@@ -16,6 +16,7 @@
 
 
 import Foundation
 import Foundation
 
 
+@available(macOS 11, *)
 public class UTMTabViewController: NSTabViewController {
 public class UTMTabViewController: NSTabViewController {
     // FIXME: really dumb hack to get around lazy loading the labels
     // FIXME: really dumb hack to get around lazy loading the labels
     public override func viewDidAppear() {
     public override func viewDidAppear() {

+ 3 - 0
Platform/macOS/VMConfigDrivesView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(macOS 11, *)
 struct VMConfigDrivesView: View {
 struct VMConfigDrivesView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     @State private var newDrivePopover: Bool = false
     @State private var newDrivePopover: Bool = false
@@ -86,6 +87,7 @@ struct VMConfigDrivesView: View {
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
 struct DriveCard: View {
 struct DriveCard: View {
     let config: UTMConfiguration
     let config: UTMConfiguration
     let index: Int
     let index: Int
@@ -134,6 +136,7 @@ struct DriveCard: View {
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
 struct VMConfigDrivesView_Previews: PreviewProvider {
 struct VMConfigDrivesView_Previews: PreviewProvider {
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     @ObservedObject static private var config = UTMConfiguration(name: "Test")
     
     

+ 3 - 0
Platform/macOS/VMConfigNetworkPortForwardView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(macOS 11, *)
 struct VMConfigNetworkPortForwardView: View {
 struct VMConfigNetworkPortForwardView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     @StateObject private var newConfigPort = UTMConfigurationPortForward()
     @StateObject private var newConfigPort = UTMConfigurationPortForward()
@@ -59,6 +60,7 @@ struct VMConfigNetworkPortForwardView: View {
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
 struct PortForwardEdit: View {
 struct PortForwardEdit: View {
     @StateObject private var configPort: UTMConfigurationPortForward
     @StateObject private var configPort: UTMConfigurationPortForward
     private let save: () -> Void
     private let save: () -> Void
@@ -95,6 +97,7 @@ struct PortForwardEdit: View {
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
 struct VMConfigNetworkPortForwardView_Previews: PreviewProvider {
 struct VMConfigNetworkPortForwardView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var configPort = UTMConfigurationPortForward()
     @State static private var configPort = UTMConfigurationPortForward()

+ 3 - 0
Platform/macOS/VMSettingsView.swift

@@ -16,6 +16,7 @@
 
 
 import SwiftUI
 import SwiftUI
 
 
+@available(macOS 11, *)
 struct VMSettingsView: View {
 struct VMSettingsView: View {
     @ObservedObject var config: UTMConfiguration
     @ObservedObject var config: UTMConfiguration
     var save: (UTMConfiguration) -> Void
     var save: (UTMConfiguration) -> Void
@@ -59,6 +60,7 @@ struct VMSettingsView: View {
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
 struct PreferencePane<Content: View>: View {
 struct PreferencePane<Content: View>: View {
     let label: LocalizedStringKey
     let label: LocalizedStringKey
     let systemImage: String
     let systemImage: String
@@ -96,6 +98,7 @@ struct PreferencePane<Content: View>: View {
     }
     }
 }
 }
 
 
+@available(macOS 11, *)
 struct VMSettingsView_Previews: PreviewProvider {
 struct VMSettingsView_Previews: PreviewProvider {
     @State static private var config = UTMConfiguration(name: "Test")
     @State static private var config = UTMConfiguration(name: "Test")
     
     

+ 8 - 2
UTM.xcodeproj/project.pbxproj

@@ -975,6 +975,8 @@
 		CE9D197C226542FE00355E14 /* UTMQemu.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9D197B226542FE00355E14 /* UTMQemu.m */; };
 		CE9D197C226542FE00355E14 /* UTMQemu.m in Sources */ = {isa = PBXBuildFile; fileRef = CE9D197B226542FE00355E14 /* UTMQemu.m */; };
 		CEA02A962436C6480087E45F /* VMConfigPortForwardingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEA02A952436C6480087E45F /* VMConfigPortForwardingViewController.m */; };
 		CEA02A962436C6480087E45F /* VMConfigPortForwardingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEA02A952436C6480087E45F /* VMConfigPortForwardingViewController.m */; };
 		CEA02A992436C7A30087E45F /* UTMConfiguration+Networking.m in Sources */ = {isa = PBXBuildFile; fileRef = CEA02A982436C7A30087E45F /* UTMConfiguration+Networking.m */; };
 		CEA02A992436C7A30087E45F /* UTMConfiguration+Networking.m in Sources */ = {isa = PBXBuildFile; fileRef = CEA02A982436C7A30087E45F /* UTMConfiguration+Networking.m */; };
+		CEB63A7624F4654400CAF323 /* Main.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB63A7524F4654400CAF323 /* Main.swift */; };
+		CEB63A7724F4654400CAF323 /* Main.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEB63A7524F4654400CAF323 /* Main.swift */; };
 		CEBBF1A524B56A2900C15049 /* UTMDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBBF1A424B56A2900C15049 /* UTMDataExtension.swift */; };
 		CEBBF1A524B56A2900C15049 /* UTMDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBBF1A424B56A2900C15049 /* UTMDataExtension.swift */; };
 		CEBBF1A724B5730F00C15049 /* UTMDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBBF1A624B5730F00C15049 /* UTMDataExtension.swift */; };
 		CEBBF1A724B5730F00C15049 /* UTMDataExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEBBF1A624B5730F00C15049 /* UTMDataExtension.swift */; };
 		CEBBF1A824B921F000C15049 /* VMDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2D954B24AD4F980059923A /* VMDetailsView.swift */; };
 		CEBBF1A824B921F000C15049 /* VMDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE2D954B24AD4F980059923A /* VMDetailsView.swift */; };
@@ -1800,6 +1802,7 @@
 		CEA02A952436C6480087E45F /* VMConfigPortForwardingViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = VMConfigPortForwardingViewController.m; path = ConfigurationViews/VMConfigPortForwardingViewController.m; sourceTree = SOURCE_ROOT; };
 		CEA02A952436C6480087E45F /* VMConfigPortForwardingViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = VMConfigPortForwardingViewController.m; path = ConfigurationViews/VMConfigPortForwardingViewController.m; sourceTree = SOURCE_ROOT; };
 		CEA02A972436C7A30087E45F /* UTMConfiguration+Networking.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UTMConfiguration+Networking.h"; sourceTree = "<group>"; };
 		CEA02A972436C7A30087E45F /* UTMConfiguration+Networking.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UTMConfiguration+Networking.h"; sourceTree = "<group>"; };
 		CEA02A982436C7A30087E45F /* UTMConfiguration+Networking.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UTMConfiguration+Networking.m"; sourceTree = "<group>"; };
 		CEA02A982436C7A30087E45F /* UTMConfiguration+Networking.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UTMConfiguration+Networking.m"; sourceTree = "<group>"; };
+		CEB63A7524F4654400CAF323 /* Main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Main.swift; sourceTree = "<group>"; };
 		CEBBF1A424B56A2900C15049 /* UTMDataExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMDataExtension.swift; sourceTree = "<group>"; };
 		CEBBF1A424B56A2900C15049 /* UTMDataExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMDataExtension.swift; sourceTree = "<group>"; };
 		CEBBF1A624B5730F00C15049 /* UTMDataExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMDataExtension.swift; sourceTree = "<group>"; };
 		CEBBF1A624B5730F00C15049 /* UTMDataExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UTMDataExtension.swift; sourceTree = "<group>"; };
 		CEBCAF4C243525DB00C2B423 /* VMConfigTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VMConfigTextField.h; sourceTree = "<group>"; };
 		CEBCAF4C243525DB00C2B423 /* VMConfigTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VMConfigTextField.h; sourceTree = "<group>"; };
@@ -2201,6 +2204,7 @@
 				CE2D954A24AD4F980059923A /* iOS */,
 				CE2D954A24AD4F980059923A /* iOS */,
 				CE2D953B24AD4F980059923A /* macOS */,
 				CE2D953B24AD4F980059923A /* macOS */,
 				CE7D972B24B2B17D0080CB69 /* BusyOverlay.swift */,
 				CE7D972B24B2B17D0080CB69 /* BusyOverlay.swift */,
+				CEB63A7524F4654400CAF323 /* Main.swift */,
 				CE2D954324AD4F980059923A /* VMCardView.swift */,
 				CE2D954324AD4F980059923A /* VMCardView.swift */,
 				CE2D953724AD4F980059923A /* VMConfigDisplayView.swift */,
 				CE2D953724AD4F980059923A /* VMConfigDisplayView.swift */,
 				CED814E824C79F070042F0F1 /* VMConfigDriveCreateView.swift */,
 				CED814E824C79F070042F0F1 /* VMConfigDriveCreateView.swift */,
@@ -3247,6 +3251,7 @@
 				CE2D957924AD4F990059923A /* VMDetailsView.swift in Sources */,
 				CE2D957924AD4F990059923A /* VMDetailsView.swift in Sources */,
 				CE2D930524AD46670059923A /* VMDisplayMetalViewController.m in Sources */,
 				CE2D930524AD46670059923A /* VMDisplayMetalViewController.m in Sources */,
 				CE2D930624AD46670059923A /* qapi-commands-misc.c in Sources */,
 				CE2D930624AD46670059923A /* qapi-commands-misc.c in Sources */,
+				CEB63A7624F4654400CAF323 /* Main.swift in Sources */,
 				CE2D930824AD46670059923A /* qapi-events-run-state.c in Sources */,
 				CE2D930824AD46670059923A /* qapi-events-run-state.c in Sources */,
 				CE2D930924AD46670059923A /* VMDisplayViewController.m in Sources */,
 				CE2D930924AD46670059923A /* VMDisplayViewController.m in Sources */,
 				CE2D930A24AD46670059923A /* qapi-visit-transaction.c in Sources */,
 				CE2D930A24AD46670059923A /* qapi-visit-transaction.c in Sources */,
@@ -3288,6 +3293,7 @@
 			isa = PBXSourcesBuildPhase;
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				CEB63A7724F4654400CAF323 /* Main.swift in Sources */,
 				CE0B6D0024AD56AE00FE012D /* UTMVirtualMachine.m in Sources */,
 				CE0B6D0024AD56AE00FE012D /* UTMVirtualMachine.m in Sources */,
 				CE0B6D0E24AD56E500FE012D /* UTMShaders.metal in Sources */,
 				CE0B6D0E24AD56E500FE012D /* UTMShaders.metal in Sources */,
 				CE0B6D3924AD57FD00FE012D /* qapi-commands-job.c in Sources */,
 				CE0B6D3924AD57FD00FE012D /* qapi-commands-job.c in Sources */,
@@ -3772,7 +3778,7 @@
 					"$(PROJECT_DIR)/sysroot-$(PLATFORM_FAMILY_NAME)-$(PLATFORM_PREFERRED_ARCH)/include/spice-1",
 					"$(PROJECT_DIR)/sysroot-$(PLATFORM_FAMILY_NAME)-$(PLATFORM_PREFERRED_ARCH)/include/spice-1",
 				);
 				);
 				INFOPLIST_FILE = Platform/iOS/Info.plist;
 				INFOPLIST_FILE = Platform/iOS/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"@executable_path/Frameworks",
 					"@executable_path/Frameworks",
@@ -3808,7 +3814,7 @@
 					"$(PROJECT_DIR)/sysroot-$(PLATFORM_FAMILY_NAME)-$(PLATFORM_PREFERRED_ARCH)/include/spice-1",
 					"$(PROJECT_DIR)/sysroot-$(PLATFORM_FAMILY_NAME)-$(PLATFORM_PREFERRED_ARCH)/include/spice-1",
 				);
 				);
 				INFOPLIST_FILE = Platform/iOS/Info.plist;
 				INFOPLIST_FILE = Platform/iOS/Info.plist;
-				IPHONEOS_DEPLOYMENT_TARGET = 14.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 11.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"$(inherited)",
 					"@executable_path/Frameworks",
 					"@executable_path/Frameworks",