99
1010import SwiftUI
1111import UniformTypeIdentifiers
12+ import AppKit
1213
1314struct SettingsView : View {
14- @ObservedObject var viewModel : MainViewModel
15-
16- enum HardDiskLocation : String , CaseIterable , Identifiable {
15+ fileprivate enum HardDiskLocation : String , CaseIterable , Identifiable {
1716 case sandbox = " Sandbox "
18- case custom = " Select location where VM hard disk images will be stored. "
17+ case custom = " Select location where VM hard disk image will be stored. "
1918 var id : Self { self }
2019 }
21- enum RestoreImageType : String , CaseIterable , Identifiable {
20+ fileprivate enum RestoreImageType : String , CaseIterable , Identifiable {
2221 case latest = " Downloads latest restore image from Apple. "
23- case custom = " Select custom restore image (.ipsw) \n For example, download from [ https://ipsw.me](https://ipsw.me/ product/Mac) "
22+ case custom = " Select custom restore image (.ipsw) \n For example, download from https://ipsw.me/ product/mac "
2423 var id : Self { self }
2524 }
25+ fileprivate struct SizeConstants {
26+ static let totalWidth = CGFloat ( 470 )
27+ static let infoWidth = CGFloat ( 300 )
28+ static let diskWidth = CGFloat ( 140 )
29+ static let locationWidth = CGFloat ( 450 )
30+ static let minTextHeight = CGFloat ( 28 )
31+ }
2632
27- @State var diskSize = String ( UserDefaults . standard . diskSize )
28- @State var hardDisk = HardDiskLocation . sandbox
29- @State var restoreImageType = RestoreImageType . latest
30-
31- var hardDiskLocationInfo : String {
32- if let customHardDiskURL = viewModel . customHardDiskURL {
33- return " Using \( customHardDiskURL . path ) "
34- } else if hardDisk == . sandbox {
33+ @ObservedObject var viewModel : ViewModel
34+ @State fileprivate var diskSize = String ( UserDefaults . standard . diskSize )
35+ @State fileprivate var hardDiskLocation = HardDiskLocation . sandbox
36+ @ State fileprivate var restoreImageType = RestoreImageType . latest
37+ @ State fileprivate var showAlert = false
38+
39+ fileprivate var hardDiskLocationString : String {
40+ if hardDiskLocation == . sandbox {
3541 return URL . basePath
3642 } else {
37- return HardDiskLocation . custom. rawValue
43+ if let customHardDiskURL = viewModel. customHardDiskURL {
44+ return customHardDiskURL. path
45+ } else {
46+ return HardDiskLocation . custom. rawValue
47+ }
3848 }
3949 }
40- var restoreImageInfo : String {
50+ fileprivate var restoreImageInfoString : String {
4151 if let restoreImageURL = viewModel. customRestoreImageURL {
42- return " Using \( restoreImageURL. path) "
52+ return restoreImageURL. path
4353 } else {
4454 return restoreImageType. rawValue
4555 }
4656 }
4757
4858 var body : some View {
49- VStack {
50- Text ( " Settings " )
59+ VStack ( ) {
60+ Text ( " Settings " ) . font ( . headline )
5161 Form {
5262 HStack {
5363 TextField ( " Hard Disk Size: " , text: $diskSize)
54- . frame ( maxWidth: 130 )
64+ . frame ( maxWidth: SizeConstants . diskWidth )
5565 . onChange ( of: diskSize) { newValue in
5666 if let newDiskSize = Int ( diskSize) {
5767 viewModel. diskSize = newDiskSize
@@ -62,72 +72,70 @@ struct SettingsView: View {
6272 Text ( " (in GB) " )
6373 }
6474
65- Picker ( " Hard Disk Location: " , selection: $hardDisk ) {
75+ Picker ( " Hard Disk Location: " , selection: $hardDiskLocation ) {
6676 Text ( " Default " ) . tag ( HardDiskLocation . sandbox)
6777 Text ( " Custom " ) . tag ( HardDiskLocation . custom)
6878 }
6979 . pickerStyle ( . inline)
70- . onChange ( of: hardDisk ) { newValue in
80+ . onChange ( of: hardDiskLocation ) { newValue in
7181 if newValue == . sandbox {
7282 UserDefaults . standard. hardDiskDirectoryBookmarkData = nil
7383 }
7484 }
75-
85+
7686 HStack {
87+ Button ( " Show in Finder " ) {
88+ NSWorkspace . shared. selectFile ( nil , inFileViewerRootedAtPath: hardDiskLocationString)
89+ } . disabled ( hardDiskLocation != . sandbox && viewModel. customHardDiskURL == nil )
90+
7791 Button ( " Select Hard Disk Location " ) {
7892 selectCustomHardDiskLocation ( )
79- } . disabled ( hardDisk == . sandbox)
93+ } . disabled ( hardDiskLocation == . sandbox)
8094 }
8195
82- Text ( . init( " hardDiskLocationInfo " ) )
96+ Text ( . init( hardDiskLocationString ) )
8397 . font ( . caption)
84- . frame ( maxWidth: 270 , alignment: . leading)
85- . fixedSize ( horizontal: false , vertical: true )
98+ . frame ( maxWidth: SizeConstants . infoWidth, minHeight: SizeConstants . minTextHeight, alignment: . topLeading)
8699 . lineLimit ( nil )
87- . disabled ( hardDisk == . sandbox)
100+ . disabled ( hardDiskLocation == . sandbox)
88101
102+
89103 Picker ( " Restore Image: " , selection: $restoreImageType) {
90104 Text ( " Latest " ) . tag ( RestoreImageType . latest)
91105 Text ( " Custom " ) . tag ( RestoreImageType . custom)
92106 } . pickerStyle ( . inline)
107+
93108 Button ( " Select Restore Image " ) {
94109 selectRestoreImage ( )
95110 } . disabled ( restoreImageType == . latest)
96- Text ( restoreImageInfo)
111+
112+ Text ( restoreImageInfoString)
97113 . font ( . caption)
98- . frame ( maxWidth: 270 , alignment: . leading )
114+ . frame ( maxWidth: SizeConstants . infoWidth , minHeight : SizeConstants . minTextHeight , alignment: . topLeading )
99115 . fixedSize ( horizontal: false , vertical: true )
100116 . lineLimit ( nil )
101117 . disabled ( restoreImageType == . latest)
102118 } . padding ( . bottom)
103-
104- Text ( " To open the hard disk location directory: \n In Finder, in the 'Go' menu, select 'Go to Folder' and enter the path shown above. " )
105- . frame ( maxWidth: 370 , alignment: . leading)
106- . fixedSize ( horizontal: false , vertical: true )
107- . lineLimit ( nil )
108- . padding ( . bottom)
109- . textSelection ( . enabled)
110- . font ( . caption)
111-
119+
112120 Button ( " OK " ) {
113121 viewModel. showSettings = !viewModel. showSettings
114122 } . keyboardShortcut ( . defaultAction)
115123 }
116124 . padding ( )
117- . frame ( minWidth: 420 )
125+ . frame ( minWidth: SizeConstants . totalWidth , maxWidth : SizeConstants . totalWidth )
118126 . onAppear ( ) {
119127 diskSize = String ( viewModel. diskSize)
120128 if let hardDiskDirectoryBookmarkData = UserDefaults . standard. hardDiskDirectoryBookmarkData,
121129 let hardDiskURL = Bookmark . startAccess ( data: hardDiskDirectoryBookmarkData, forType: . hardDisk)
122130 {
123- hardDisk = . custom
131+ hardDiskLocation = . custom
124132 viewModel. customHardDiskURL = hardDiskURL
125133 }
126134 }
127135 }
128-
136+
129137 // MARK: - Private
130-
138+
131139 fileprivate func selectCustomHardDiskLocation( ) {
132140 let openPanel = NSOpenPanel ( )
133141 openPanel. directoryURL = URL ( fileURLWithPath: URL . basePath, isDirectory: true )
@@ -144,7 +152,7 @@ struct SettingsView: View {
144152 UserDefaults . standard. hardDiskDirectoryBookmarkData = hardDiskDirectoryBookmarkData
145153 }
146154 }
147-
155+
148156 fileprivate func selectRestoreImage( ) {
149157 guard let ipswContentType = UTType ( filenameExtension: " ipsw " ) else {
150158 return
@@ -159,13 +167,12 @@ struct SettingsView: View {
159167 viewModel. customRestoreImageURL = selectedURL
160168 }
161169 }
162-
163170}
164171
165172struct SettingsViewProvider_Previews : PreviewProvider {
166173 static var previews : some View {
167174 VStack {
168- SettingsView ( viewModel: MainViewModel ( ) )
175+ SettingsView ( viewModel: ViewModel ( ) )
169176 }
170177 }
171178}
0 commit comments