@@ -10,40 +10,6 @@ import UniformTypeIdentifiers
1010import Foundation
1111import TabularData
1212
13-
14- //wip for multi-select of configs.
15- //struct configSelectionView:View
16- //{
17- // var results: String
18- // var body: some View{
19- // VStack(alignment:.center)
20- // {
21- // HStack(alignment:.center){
22- // //return home button
23- // //share button
24- // //view other result button
25- // }
26- // let configNameList: [ConfigIdentifier] = [ConfigIdentifier(name: "test1"), ConfigIdentifier(name: "test2")]
27- // List {
28- // ForEach(configNameList) {name in
29- // ConfigCardView(configName: "test")
30- // }
31- // }
32- // }
33- // }
34- //}
35-
36- //wip for multi-select of Configs
37- //struct ConfigCardView: View{
38- // let configName: String
39- // var body: some View {
40- // let buttontext = "test"
41- // Button(buttontext){
42- // //go to results view
43- // }
44- // }
45- //}
46-
4713struct BlueButton : ButtonStyle {
4814 func makeBody( configuration: Configuration ) -> some View {
4915 configuration. label
@@ -81,32 +47,57 @@ struct ResultsCardView: View {
8147}
8248
8349struct SelectAnotherDayView : View {
50+ @Binding var canaryResults : [ CanaryResult ]
51+
8452 var body : some View {
8553 VStack {
86- let resultsNames = getContentsOfResults ( )
87- ForEach ( resultsNames, id: \. self) { result in
88- Button ( result) {
89- viewingResult = result
90- let removeCSV = result. replacingOccurrences ( of: " .csv " , with: " " )
91- resultDate = removeCSV. replacingOccurrences ( of: " CanaryResults " , with: " " )
92- }
93- . buttonStyle ( BlueButton ( ) )
94- . padding ( )
54+ Text ( " Results " )
55+ canaryResults = getContentsOfResultsDirectory ( )
56+ List ( canaryResults)
57+ {
58+
59+ result in
60+
61+ //viewingResult = result.name
62+ Text ( result. name)
63+
9564 }
65+
66+ // ForEach(canaryResults, id: \.self){result in
67+ // Button(result){
68+ // viewingResult = result
69+ // let removeCSV = result.replacingOccurrences(of: resultExtension, with: "")
70+ // resultDate = removeCSV.replacingOccurrences(of: resultFileName, with: "")
71+ // }
72+ // .buttonStyle(BlueButton())
73+ // .padding()
74+ // }
9675 }
9776 }
9877
99- func getContentsOfResults ( ) -> [ String ] {
78+ func getContentsOfResultsDirectory ( ) -> [ CanaryResult ] {
10079 let appHomeDirectory = FileManager . default. urls ( for: . documentDirectory, in: . userDomainMask) [ 0 ]
101- let resultsDirectory = appHomeDirectory. appendingPathComponent ( " results " )
80+ let resultsDirectory = appHomeDirectory. appendingPathComponent ( resultDirectoryName )
10281
103- do {
82+ do
83+ {
10484 let results = try FileManager . default. contentsOfDirectory ( atPath: resultsDirectory. path)
105- return results
106- } catch {
107- print ( " yikes " )
85+ var canaryResults = [ CanaryResult] ( )
86+
87+ for result in results {
88+ let name = result. replacingOccurrences ( of: resultExtension, with: " " )
89+ let canaryResult = CanaryResult ( name: name, filename: result)
90+ canaryResults. append ( canaryResult)
91+ }
92+
93+ return canaryResults
94+ }
95+ catch
96+ {
97+ print ( " Failed to get the contents of \( resultsDirectory. path) " )
98+ print ( " Error: \( error) " )
99+ return [ ]
108100 }
109- return [ ]
110101 }
111102
112103 func getDate( ) -> String {
@@ -220,23 +211,26 @@ struct ResultsView:View {
220211
221212 //function which pulls the result of whatever day the global resultDate is pointed at.
222213 func getResultsURL( ) -> URL {
223- let fileName = " CanaryResults " + resultDate + " .csv "
214+ let fileName = resultFileName + resultDate + resultExtension
224215 let appHomeDirectory = FileManager . default. urls ( for: . documentDirectory, in: . userDomainMask) [ 0 ]
225- let resultsDirectory = appHomeDirectory. appendingPathComponent ( " results " )
216+ let resultsDirectory = appHomeDirectory. appendingPathComponent ( resultDirectoryName )
226217 let resultsFile = resultsDirectory. appendingPathComponent ( fileName)
227218 return resultsFile
228219 }
229220}
230221
231222struct ContentView : View
232223{
224+ @State private var isValidConfigPath = false
225+ @State private var configPath = UserDefaults . standard. string ( forKey: configPathKey) ?? " Config Directory Needed "
226+
233227 //Display Strings
234228 let configTitle : String = " Transport config directory: "
235229 let configSearchPrompt = " Please select the directory where your config files are located. "
236230 let browseButtonTitle = " Select Config Directory "
237231 let numberOfRunsPrompt = " How many times do you want to run the test? "
238232 let runButtonTitle = " Run Test "
239- let logTitle = " Run Log test "
233+ let logTitle = " Run Log "
240234 let runTimes = " Time(s) "
241235 let createSampleButtonTitle = " Create Sample Config "
242236 let step = 1
@@ -247,7 +241,7 @@ struct ContentView: View
247241 @State private var runLogs = " "
248242 @State private var insideResultsView = false
249243 @State var appHomeDirectory : URL = FileManager . default. urls ( for: . documentDirectory, in: . userDomainMask) [ 0 ]
250- @State var configDirectory : URL = FileManager . default. urls ( for: . documentDirectory, in: . userDomainMask) [ 0 ] . appendingPathComponent ( " CanaryConfigs " )
244+ @State var configDirectory : URL = FileManager . default. urls ( for: . documentDirectory, in: . userDomainMask) [ 0 ] . appendingPathComponent ( configDirectoryName )
251245 @State var showDirectoryPicker = false
252246 var justShared : some Scene {
253247 WindowGroup {
@@ -281,35 +275,6 @@ struct ContentView: View
281275 DirectoryPickerView ( directoryURL: $configDirectory)
282276 }
283277 }
284-
285- //create sample config button
286- // Button(createSampleButtonTitle)
287- // {
288- // do {
289- // //make URLs
290- // let AppDirectory = getDocumentsDirectory()
291- // let hotConfigDirectory = AppDirectory.appendingPathComponent("configsToUseInTest")
292- //
293- // //check to see if anything at configDirectory exists, if not, make the directory
294- // if !FileManager.default.fileExists(atPath: hotConfigDirectory.absoluteString){
295- // try! FileManager.default.createDirectory(at: hotConfigDirectory, withIntermediateDirectories: true, attributes: nil)
296- // }
297- // //save sample config
298- // let sampleConfigReference = hotConfigDirectory.appendingPathComponent("sampleShadowSocksConfig.json")
299- // let sampleConfigContents = ##" {"serverIP":"PII","port":PII,"password":"PII","cipherName":"DarkStar","cipherMode":"DarkStar"}"##
300- //
301- //
302- //
303- // try sampleConfigContents.write(to: sampleConfigReference, atomically: true, encoding: .utf8)
304- // //let checkWork = try String(contentsOf: sampleConfigReference)
305- // //print(checkWork)
306- // }
307- // catch{
308- // print("sampleConfig failed to write")
309- // print(error)
310- // }
311- //
312- // }
313278 . padding ( 10 )
314279 Divider ( )
315280 Spacer ( )
@@ -329,23 +294,28 @@ struct ContentView: View
329294 let canaryController = CanaryController ( )
330295 //make paths
331296 let AppDirectory = getDocumentsDirectory ( )
332- let resultsDirectory = AppDirectory . appendingPathComponent ( " results " )
333- //check to see if resultsDirectory exists, if not, make one.
334- if !FileManager. default. fileExists ( atPath: resultsDirectory. absoluteString) {
335- try ! FileManager . default. createDirectory ( at: resultsDirectory, withIntermediateDirectories: true , attributes: nil )
297+ let resultsDirectory = AppDirectory . appendingPathComponent ( resultDirectoryName)
298+
299+ //check to see if resultsDirectory exists, if not, make one.
300+ if !FileManager. default. fileExists ( atPath: resultsDirectory. absoluteString)
301+ {
302+ try FileManager . default. createDirectory ( at: resultsDirectory, withIntermediateDirectories: true , attributes: nil )
336303 }
304+
337305 //get today's date for the name of the results document
338- if !FileManager. default. fileExists ( atPath: resultsDirectory. path) {
339- try ! FileManager . default. createFile ( atPath: resultsDirectory. path, contents: nil , attributes: nil )
306+ if !FileManager. default. fileExists ( atPath: resultsDirectory. path)
307+ {
308+ FileManager . default. createFile ( atPath: resultsDirectory. path, contents: nil , attributes: nil )
340309 }
341- print ( " run button pressed " )
342- viewingResult = " CanaryResults " + getDate( ) + " .csv "
310+
311+ viewingResult = resultFileName + getDate( ) + resultExtension
343312 canaryController. runCanary ( configDirectory: configDirectory, resultsDirectory: resultsDirectory, numberOfTimesToRun: numberOfRuns)
344313 }
345-
346- NavigationLink ( destination: Text ( " secondView " ) , isActive: $insideResultsView) { EmptyView ( ) }
347- self . insideResultsView = true
348- } //Button(runButtonTitle)
314+ catch
315+ {
316+ print ( " Error preparing directories: \( error) " )
317+ }
318+ }
349319 . buttonStyle ( BlueButton ( ) )
350320
351321 NavigationLink ( destination: ResultsView ( ) )
@@ -354,42 +324,48 @@ struct ContentView: View
354324 }
355325 . buttonStyle ( BlueButton ( ) )
356326 . padding ( 10 )
357- } //HStack
358- } //VStack
327+ }
328+ }
359329
360330 Divider ( )
361331 Spacer ( )
362332
363333 VStack ( alignment: . center) // Logs UI
364- {
365- Text ( logTitle)
366-
367- ScrollViewReader // Test Log with automatic scrolling
368334 {
369- sp in
335+ Text ( logTitle )
370336
371- ScrollView
337+ ScrollViewReader // Test Log with automatic scrolling
372338 {
373- // TODO: add .textSelection(.enabled) when appropriate to discontinue support of macOS 11 (only available on macOS 12+)
374- Text ( runningLog. logString)
375- . id ( 0 )
376- . onChange ( of: runningLog. logString)
339+ sp in
340+
341+ ScrollView
377342 {
378- Value in
379- sp. scrollTo ( 0 , anchor: . bottom)
343+ // TODO: add .textSelection(.enabled) when appropriate to discontinue support of macOS 11 (only available on macOS 12+)
344+ Text ( runningLog. logString)
345+ . id ( 0 )
346+ . onChange ( of: runningLog. logString)
347+ {
348+ Value in
349+ sp. scrollTo ( 0 , anchor: . bottom)
350+ }
380351 }
352+ . frame ( maxHeight: 150 )
381353 }
382- . frame ( maxHeight: 150 )
383- }
384- ScrollView
385- {
386- VStack
354+ . onAppear ( )
387355 {
388- Text ( runLogs)
389- . lineLimit ( nil )
356+ isValidConfigPath = validate ( configURL: URL ( string: configPath) )
390357 }
391- . frame ( maxWidth: . infinity)
392- }
358+ . padding ( . vertical)
359+
360+ // ScrollView
361+ // {
362+ // VStack
363+ // {
364+ // Text(runLogs)
365+ // .lineLimit(nil)
366+ // }
367+ // .frame(maxWidth: .infinity)
368+ // }
393369 }
394370 . padding ( )
395371
@@ -398,6 +374,17 @@ struct ContentView: View
398374 } //NavigationView
399375 } //body
400376
377+ func validate( configURL: URL ? ) -> Bool
378+ {
379+ guard let isaURL = configURL
380+ else { return false }
381+
382+ var isDirectory = ObjCBool ( true )
383+ let exists = FileManager . default. fileExists ( atPath: isaURL. path, isDirectory: & isDirectory)
384+
385+ return exists && isDirectory. boolValue
386+ }
387+
401388 func getDate( ) -> String {
402389 let date = Date ( )
403390 let dateFormatter = DateFormatter ( )
@@ -500,4 +487,11 @@ struct ContentView_Previews: PreviewProvider {
500487 ContentView ( configDirectory: FileManager . default. temporaryDirectory)
501488 }
502489}
490+
491+ struct CanaryResult : Identifiable {
492+ let id = UUID ( )
493+ let name : String
494+ let filename : String
495+
496+ }
503497
0 commit comments