diff --git a/PyLeap.xcodeproj/project.pbxproj b/PyLeap.xcodeproj/project.pbxproj index b07f9e3..ab56435 100644 --- a/PyLeap.xcodeproj/project.pbxproj +++ b/PyLeap.xcodeproj/project.pbxproj @@ -36,6 +36,9 @@ D5597C3B26B98E1E00DF17C0 /* NumbersOnly.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5597C3A26B98E1E00DF17C0 /* NumbersOnly.swift */; }; D5640216271B54BF00AE1519 /* MainSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5640215271B54BF00AE1519 /* MainSelectionView.swift */; }; D567E2B628B81B730009F768 /* Queue.swift in Sources */ = {isa = PBXBuildFile; fileRef = D567E2B528B81B730009F768 /* Queue.swift */; }; + D567E2B828C137880009F768 /* WifiCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D567E2B728C137880009F768 /* WifiCell.swift */; }; + D567E2BA28C1382E0009F768 /* WifiSubViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D567E2B928C1382E0009F768 /* WifiSubViewCell.swift */; }; + D567E2BC28C1527F0009F768 /* WifiSubViewCellModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D567E2BB28C1527F0009F768 /* WifiSubViewCellModel.swift */; }; D56F640C270242CA000E5975 /* UIColor+LightAndDark.swift in Sources */ = {isa = PBXBuildFile; fileRef = D56F6407270242CA000E5975 /* UIColor+LightAndDark.swift */; }; D56F640D270242CA000E5975 /* FileTransferPathUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D56F640A270242CA000E5975 /* FileTransferPathUtils.swift */; }; D56F640E270242CA000E5975 /* String+DeletingPrefix.swift in Sources */ = {isa = PBXBuildFile; fileRef = D56F6408270242CA000E5975 /* String+DeletingPrefix.swift */; }; @@ -119,6 +122,9 @@ D5640215271B54BF00AE1519 /* MainSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainSelectionView.swift; sourceTree = ""; }; D567E2B428B80DC10009F768 /* Outline.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Outline.md; sourceTree = ""; }; D567E2B528B81B730009F768 /* Queue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Queue.swift; sourceTree = ""; }; + D567E2B728C137880009F768 /* WifiCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiCell.swift; sourceTree = ""; }; + D567E2B928C1382E0009F768 /* WifiSubViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiSubViewCell.swift; sourceTree = ""; }; + D567E2BB28C1527F0009F768 /* WifiSubViewCellModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiSubViewCellModel.swift; sourceTree = ""; }; D56F6407270242CA000E5975 /* UIColor+LightAndDark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+LightAndDark.swift"; sourceTree = ""; }; D56F6408270242CA000E5975 /* String+DeletingPrefix.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+DeletingPrefix.swift"; sourceTree = ""; }; D56F640A270242CA000E5975 /* FileTransferPathUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileTransferPathUtils.swift; sourceTree = ""; }; @@ -308,6 +314,9 @@ children = ( D58E1C8728A2B10B00AB683E /* WifiView.swift */, D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */, + D567E2B728C137880009F768 /* WifiCell.swift */, + D567E2B928C1382E0009F768 /* WifiSubViewCell.swift */, + D567E2BB28C1527F0009F768 /* WifiSubViewCellModel.swift */, D567E2B528B81B730009F768 /* Queue.swift */, D5BA1F7928B52A490012FC62 /* WifiListDetailView.swift */, D5BA1F7E28B66F280012FC62 /* Bonjour.swift */, @@ -608,6 +617,7 @@ D5BA1F8328B68ED40012FC62 /* NetworkPeripheral.swift in Sources */, D59DFDBC268CE0EB001737F6 /* RootView.swift in Sources */, D595FC2E2812C23D00569D8C /* Image Extension.swift in Sources */, + D567E2BA28C1382E0009F768 /* WifiSubViewCell.swift in Sources */, D59DFD8F268A4A4D001737F6 /* BTConnectionView.swift in Sources */, D58D887B26CC02B60085604A /* OnboardingViewPure.swift in Sources */, D52BE85426A0E39100630900 /* BTConnectionViewModel.swift in Sources */, @@ -617,9 +627,11 @@ D5507AD126C668BC00512BAA /* SearchBarView.swift in Sources */, D59DFDBA268CDEEC001737F6 /* RootViewModel.swift in Sources */, D5C74DF527EB93E300730505 /* DemoViewCell.swift in Sources */, + D567E2BC28C1527F0009F768 /* WifiSubViewCellModel.swift in Sources */, D52BE85526A0E5A400630900 /* PeripheralList.swift in Sources */, D5D7DF2D28B489C0008552D1 /* WebDirectoryModel.swift in Sources */, D5597C0226ADDCE300DF17C0 /* StartupView.swift in Sources */, + D567E2B828C137880009F768 /* WifiCell.swift in Sources */, D5D1F4B027ECFDE00040E2BF /* NavBarModifier.swift in Sources */, D5597C0C26AF018800DF17C0 /* View+If.swift in Sources */, D58E1C8D28A2B32C00AB683E /* Wifi_ifaddrs.m in Sources */, diff --git a/PyLeap.xcodeproj/project.xcworkspace/xcuserdata/trevorbeaton.xcuserdatad/UserInterfaceState.xcuserstate b/PyLeap.xcodeproj/project.xcworkspace/xcuserdata/trevorbeaton.xcuserdatad/UserInterfaceState.xcuserstate index b300f7b..3a38dd1 100644 Binary files a/PyLeap.xcodeproj/project.xcworkspace/xcuserdata/trevorbeaton.xcuserdatad/UserInterfaceState.xcuserstate and b/PyLeap.xcodeproj/project.xcworkspace/xcuserdata/trevorbeaton.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PyLeap/Download View/DownloadViewModel.swift b/PyLeap/Download View/DownloadViewModel.swift index 489f3d5..efe5077 100644 --- a/PyLeap/Download View/DownloadViewModel.swift +++ b/PyLeap/Download View/DownloadViewModel.swift @@ -191,7 +191,7 @@ class DownloadViewModel: NSObject, ObservableObject, URLSessionDownloadDelegate // Since URL Session will be running in the background thread // UI will be done on the main thread DispatchQueue.main.async { - + self.downloadProgress = numeralProgress print("Recorded downloadProgress Progress: \(self.downloadProgress)") print("Recorded numeralProgress Progress: \(numeralProgress)") diff --git a/PyLeap/Views/Paired View/SelectionView.swift b/PyLeap/Views/Paired View/SelectionView.swift index a3e23bd..19fa2cc 100644 --- a/PyLeap/Views/Paired View/SelectionView.swift +++ b/PyLeap/Views/Paired View/SelectionView.swift @@ -202,8 +202,13 @@ struct SelectionView: View { SubHeaderView() // .spotlight(enabled: spotlight.counter == 1, title: "1") + let check = model.pdemos.filter { + $0.compatibility[0] == boardBootInfo + } ForEach(model.pdemos) { demo in + + DemoViewCell(result: demo, isConnected: $inConnectedInSelectionView, bootOne: $boardBootInfo, onViewGeometryChanged: { withAnimation { scroll.scrollTo(demo.id) diff --git a/PyLeap/Views/UI Components/SubHeaderView.swift b/PyLeap/Views/UI Components/SubHeaderView.swift index d4e3656..e55746b 100644 --- a/PyLeap/Views/UI Components/SubHeaderView.swift +++ b/PyLeap/Views/UI Components/SubHeaderView.swift @@ -11,7 +11,7 @@ struct SubHeaderView: View { var body: some View { HStack { - Text("Browse all of the available PyLeap Projects") + Text("Browse available Wi-Fi PyLeap Projects") .multilineTextAlignment(/*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) .font(Font.custom("ReadexPro-Regular", size: 25)) diff --git a/PyLeap/Views/Wifi_test/WifiCell.swift b/PyLeap/Views/Wifi_test/WifiCell.swift new file mode 100644 index 0000000..c7d1def --- /dev/null +++ b/PyLeap/Views/Wifi_test/WifiCell.swift @@ -0,0 +1,77 @@ +// +// WifiCell.swift +// PyLeap +// +// Created by Trevor Beaton on 9/1/22. +// + +import SwiftUI +import Foundation + +struct WifiCell: View { + + let result : ResultItem + + @State private var isExpanded: Bool = false { + didSet { + onViewGeometryChanged() + } + } + + @Binding var isConnected: Bool + @Binding var bootOne: String + + let onViewGeometryChanged: ()->Void + + @Binding var stateBinder: DownloadState + + var body: some View { + content + .frame(maxWidth: .infinity) + } + + private var content: some View { + VStack(alignment: .leading, spacing: 8) { + header + + if isExpanded { + + Group { + WifiSubViewCell(bindingString: $bootOne, downloadStateBinder: $stateBinder, title: result.projectName, + image: result.projectImage, + description: result.description, + learnGuideLink: URLRequest(url: URL(string: result.learnGuideLink)!), + downloadLink: result.bundleLink, + compatibility: result.compatibility, + isConnected: $isConnected) + } + + } + } + } + + private var header: some View { + + HStack { + Text(result.projectName) + .font(Font.custom("ReadexPro-Regular", size: 24)) + .padding(8) + .foregroundColor(.white) + + Spacer() + + Image(systemName: "chevron.down") + .resizable() + .frame(width: 30, height: 15, alignment: .center) + .foregroundColor(.white) + .padding(.trailing, 30) + } + + .padding(.vertical, 5) + .padding(.leading) + .frame(maxWidth: .infinity) + .background(Color("pyleap_purple")) + .onTapGesture { isExpanded.toggle() } + } + +} diff --git a/PyLeap/Views/Wifi_test/WifiSubViewCell.swift b/PyLeap/Views/Wifi_test/WifiSubViewCell.swift new file mode 100644 index 0000000..218ed0e --- /dev/null +++ b/PyLeap/Views/Wifi_test/WifiSubViewCell.swift @@ -0,0 +1,314 @@ +// +// WifiSubViewCell.swift +// PyLeap +// +// Created by Trevor Beaton on 9/1/22. +// + +import SwiftUI +import FileTransferClient + +struct WifiSubViewCell: View { + @State var transferInProgress = false + @State var isDownloaded = false + + @EnvironmentObject var globalString : GlobalString + + @StateObject var viewModel = WifiViewModel() + + @Binding var bindingString: String + + @Binding var downloadStateBinder: DownloadState + + @State private var toggleView: Bool = false + + let title: String + let image: String + let description: String + let learnGuideLink: URLRequest + let downloadLink: String + let compatibility: [String] + + @EnvironmentObject var rootViewModel: RootViewModel + @StateObject var downloadModel = DownloadViewModel() + + @Binding var isConnected : Bool + + @State private var showWebViewPopover: Bool = false + @State var errorOccured = false + @State private var presentAlert = false + + @State var offlineWithoutProject = false + + + + var body: some View { + + VStack { + + + + VStack(alignment: .leading, spacing: 0, content: { + + ImageWithURL(image) + .scaledToFit() + .frame(maxWidth: .infinity) + .cornerRadius(14) + .padding(.top, 30) + + + Text(description) + .font(Font.custom("ReadexPro-Regular", size: 18)) + .multilineTextAlignment(.leading) + .minimumScaleFactor(0.1) + .padding(.top, 20) + Text("Compatible with:") + .font(Font.custom("ReadexPro-Bold", size: 18)) + .padding(.top, 5) + + + ForEach(compatibility, id: \.self) { string in + if string == "circuitplayground_bluefruit" { + + HStack { + Image(systemName: "checkmark") + .resizable() + .frame(width: 25, height: 22, alignment: .center) + .foregroundColor(.green) + Text("Circuit Playground Bluefruit") + .font(Font.custom("ReadexPro-Regular", size: 18)) + .foregroundColor(.black) + } + .padding(.top, 10) + } + + + + if string == "clue_nrf52840_express" { + + HStack { + Image(systemName: "checkmark") + .resizable() + .frame(width: 25, height: 22, alignment: .center) + .foregroundColor(.green) + Text("Adafruit CLUE") + .font(Font.custom("ReadexPro-Regular", size: 18)) + .foregroundColor(.black) + } + .padding(.top, 10) + } + } + }) + .ignoresSafeArea(.all) + .padding(.horizontal, 30) + + Button(action: { + showWebViewPopover = true + + }) { + LearnGuideButton() + .padding(.top, 20) + } + .sheet(isPresented: $showWebViewPopover, content: { + WebView(URLRequest(url: learnGuideLink.url!)) + }) + + + + + if isConnected { + + if compatibility.contains(bindingString) { + + Button { + print("Wifi Project Attempt \(title)") + + if viewModel.projectDownloaded { + viewModel.projectValidation(nameOf: title) + } else { + downloadModel.startDownload(urlString: downloadLink, projectTitle: title) { + print("DONE") + } + } + + + //viewModel.projectValidation(nameOf: title) + } label: { + RunItButton() + .padding(.top, 20) + } + + +// if downloadStateBinder == .idle { +// +// +// +// Button(action: { +// +// downloadStateBinder = .transferring +// globalString.isSendingG = true +// globalString.counterG = 0 +// globalString.numberOfFilesG = 1 +// +// +// globalString.downloadLinkString = downloadLink +// globalString.projectString = title +// globalString.attemptToDownload.toggle() +// +// +// +// +// +// if selectionModel.isConnectedToInternet == false { +// print("Going offline...") +// downloadStateBinder = .transferring +// +// globalString.projectString = title +// globalString.attemptToSend.toggle() +// } +// +// if viewModel.projectDownloaded == false && selectionModel.isConnectedToInternet == false { +// offlineWithoutProject = true +// downloadStateBinder = .idle +// +// } +// +// if viewModel.projectDownloaded == false { +// +// } +// +// }) { +// +// RunItButton() +// .padding(.top, 20) +// +// } +// } +// +// if downloadStateBinder == .failed { +// +// FailedButton() +// .padding(.top, 20) +// } +// +// +// if downloadStateBinder == .transferring { +// +// Button(action: { +// +// print("Project Selected: \(title) - DemoSubView") +// +// globalString.projectString = title +// globalString.numberOfTimesDownloaded += 1 +// +// }) { +// +// DownloadingButton() +// .padding(.top, 20) +// } +// .disabled(true) +// +// +// +// if globalString.isSendingG { +// +// VStack(alignment: .center, spacing: 0) { +// ProgressView("", value: CGFloat(globalString.counterG), total: CGFloat(globalString.numberOfFilesG) ) +// .padding(.horizontal, 90) +// .padding(.top, -8) +// .padding(.bottom, 10) +// .accentColor(Color.gray) +// .scaleEffect(x: 1, y: 2, anchor: .center) +// .cornerRadius(10) +// .frame(height: 10) +// +// ProgressView() +// } +// +// } +// +// +// } +// +// +// +// if downloadStateBinder == .complete { +// +// CompleteButton() +// .padding(.top, 20) +// } +// + } + + + } else { + + Button { + rootViewModel.goTobluetoothPairing() + } label: { + ConnectButton() + .padding(.top, 20) + } + + } + } + Spacer() + .frame(height: 30) + .ignoresSafeArea(.all) + + + + .alert("Project Not Found", isPresented: $offlineWithoutProject) { + Button("OK") { + // Handle acknowledgement. + print("OK") + offlineWithoutProject = false + downloadStateBinder = .idle + // selectionModel.state = .idle + print("\(offlineWithoutProject)") + } + } message: { + Text(""" + To use this project, connect to the internet. + """) + .multilineTextAlignment(.leading) + } + + .onChange(of: downloadModel.isDownloading, perform: { newValue in + viewModel.getProjectForSubClass(nameOf: title) + }) + + .onChange(of: downloadModel.didDownloadBundle, perform: { newValue in + print("For project: \(title), project download is \(newValue)") + + // globalString.projectString = title + + if newValue { + DispatchQueue.main.async { + print("Getting project from Subclass \(title)") + // viewModel.getProjectForSubClass(nameOf: title) + viewModel.projectValidation(nameOf: title) + + isDownloaded = true + } + }else { + print("Is not downloaded") + isDownloaded = false + } + + }) + .onAppear(perform: { + viewModel.getProjectForSubClass(nameOf: title) + if viewModel.projectDownloaded { + isDownloaded = true + } else { + isDownloaded = false + } + print("is downloaded? \(isDownloaded)") + }) + .padding(.top, 8) + + } +} + + diff --git a/PyLeap/Views/Wifi_test/WifiSubViewCellModel.swift b/PyLeap/Views/Wifi_test/WifiSubViewCellModel.swift new file mode 100644 index 0000000..ca8c480 --- /dev/null +++ b/PyLeap/Views/Wifi_test/WifiSubViewCellModel.swift @@ -0,0 +1,47 @@ +// +// WifiSubViewCellModel.swift +// PyLeap +// +// Created by Trevor Beaton on 9/1/22. +// + +import Foundation + +class WifiSubViewCellModel: ObservableObject { + + @Published var projectDownloaded = false + @Published var failedProjectLaunch = false + + let directoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + + func getProjectForSubClass(nameOf project: String) { + + if let enumerator = FileManager.default.enumerator(at: directoryPath, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles, .skipsPackageDescendants]) { + // for case condition: Only process URLs + for case let fileURL as URL in enumerator { + + if fileURL.lastPathComponent == project { + failedProjectLaunch = false + projectDownloaded = true + print(#function) + print("Searching for... \(project)") + print("URL Path: \(fileURL.path)") + print("URL : \(fileURL)") + + return + + } else { + failedProjectLaunch = true + projectDownloaded = false + print("Project was not found...") + + } + + + } + + } + + } + +} diff --git a/PyLeap/Views/Wifi_test/WifiView.swift b/PyLeap/Views/Wifi_test/WifiView.swift index 644eeed..ee4cde8 100644 --- a/PyLeap/Views/Wifi_test/WifiView.swift +++ b/PyLeap/Views/Wifi_test/WifiView.swift @@ -9,6 +9,11 @@ import SwiftUI struct WifiView: View { @StateObject var viewModel = WifiViewModel() + @ObservedObject var networkModel = NetworkService() + @State private var downloadState = DownloadState.idle + @State private var scrollViewID = UUID() + @State private var inConnectedInWifiView = true + @State private var boardBootInfo = "esp32-s2" @State private var ipAddressInput: String = "" @State private var foundIPAddress: String = "" @@ -19,78 +24,132 @@ struct WifiView: View { var body: some View { NavigationView { - VStack(alignment: .center, spacing: 12, content: { - - TextField("Enter your IP Address:", text: $ipAddressInput) - .frame(width: 200, height: 50, alignment: .center) + VStack(alignment: .center, spacing: 0, content: { + HeaderView() + +// HStack(alignment: .center, spacing: 8, content: { +// +// Button { +// // rootViewModel.goToWifiView() +// } label: { +// Text("Connect to Wifi") +// .font(Font.custom("ReadexPro-Regular", size: 16)) +// .underline() +// } +// +// }) + .padding(.all, 0.0) + .frame(maxWidth: .infinity) + .frame(maxHeight: 40) + .background(Color("pyleap_blue")) + .foregroundColor(.white) + + + ScrollView(.vertical, showsIndicators: true) { - .foregroundColor(.black) - - Button("Make Directory") { - // viewModel.putDirectory() - } - - Button("GET Request") { - viewModel.getRequest() - } - - Button("PUT Request") { - viewModel.putRequest() - } - - Button("DELETE Request") { viewModel.deleteRequest() } - - Button("Single IP Addr.") { print(viewModel.wifiService.getIPAddress()) } - - Button("IP Addr. List") { print(viewModel.wifiService.getIFAddresses()) } - - Button("Get Project") { - viewModel.projectValidation(nameOf: "ESP32-S2 NeoPixel LED") - } - - - ZStack { - Circle() - .foregroundColor(Color("pyleap_green")) - .frame(width: 60, height: 60, alignment: .center) - .opacity(0.8) +// TextField("Enter your IP Address:", text: $ipAddressInput) +// .frame(width: 200, height: 50, alignment: .center) +// +// .foregroundColor(.black) +// +// Button("Make Directory") { +// // viewModel.putDirectory() +// } +// +// Button("GET Request") { +// viewModel.getRequest() +// } +// +// Button("PUT Request") { +// viewModel.putRequest() +// } +// +// Button("DELETE Request") { viewModel.deleteRequest() } +// +// Button("Single IP Addr.") { print(viewModel.wifiService.getIPAddress()) } +// +// Button("IP Addr. List") { print(viewModel.wifiService.getIFAddresses()) } +// +// Button("Get Project") { +// +// +// +// // viewModel.projectValidation(nameOf: "Sensor Data Display") +// } + + +// ZStack { +// Circle() +// .foregroundColor(Color("pyleap_green")) +// .frame(width: 60, height: 60, alignment: .center) +// .opacity(0.8) +// +// Image(systemName: "checkmark") +// .resizable() +// .foregroundColor(.white) +// .frame(width: 30, height: 30, alignment: .center) +// } +// .isHidden(showConfirmation) + + ScrollViewReader { scroll in - Image(systemName: "checkmark") - .resizable() - .foregroundColor(.white) - .frame(width: 30, height: 30, alignment: .center) - } - .isHidden(showConfirmation) - - List(viewModel.webDirectoryInfo) { post in - - NavigationLink(destination: WifiListDetailView(text: post.name)) { - HStack(){ + SubHeaderView() + // .spotlight(enabled: spotlight.counter == 1, title: "1") + + let check = networkModel.pdemos.filter { + $0.compatibility[0] == boardBootInfo + } + + ForEach(check) { demo in - if post.directory == true { - Image(systemName: "folder") - } else { - Image(systemName: "doc") - } - Text(post.name) - - Spacer() - - if post.file_size > 1000 { - - Text("\(post.file_size/1000) KB") - - } else { - Text("\(post.file_size) Bytes") - } + WifiCell(result: demo, isConnected: $inConnectedInWifiView, bootOne: $boardBootInfo, onViewGeometryChanged: { + withAnimation { + scroll.scrollTo(demo.id) + } + }, stateBinder: $downloadState) + } + } - + .id(self.scrollViewID) } - .frame(height: UIScreen.main.bounds.height/2) + .foregroundColor(.black) + + + + +// List(viewModel.webDirectoryInfo) { post in +// +// NavigationLink(destination: WifiListDetailView(text: post.name)) { +// HStack(){ +// +// if post.directory == true { +// Image(systemName: "folder") +// } else { +// Image(systemName: "doc") +// } +// +// Text(post.name) +// +// Spacer() +// +// if post.file_size > 1000 { +// +// Text("\(post.file_size/1000) KB") +// +// } else { +// Text("\(post.file_size) Bytes") +// } +// +// } +// } +// +// +// } + .frame(height: UIScreen.main.bounds.height) }) // .navigationBarTitle(Text("PyLeap - Wi-Fi")) diff --git a/PyLeap/Views/Wifi_test/WifiViewModel.swift b/PyLeap/Views/Wifi_test/WifiViewModel.swift index 8ae33c9..a0a305e 100644 --- a/PyLeap/Views/Wifi_test/WifiViewModel.swift +++ b/PyLeap/Views/Wifi_test/WifiViewModel.swift @@ -313,35 +313,95 @@ class WifiViewModel: ObservableObject { print("Current projectDirectories: \(projectDirectories[0])") - // sortDirectory(directoryArray: projectDirectories, fileArray: fileURLs) - pathManipulation(arrayOfAny: projectDirectories) + // sortDirectory(directoryArray: projectDirectories, fileArray: fileURLs) + pathManipulation(arrayOfAny: filterOutCPDirectories(fileArray: projectDirectories), fileArray: fileURLs) } - - func pathManipulation(arrayOfAny: [URL]){ + func intakeArray(path: URL) { var indexOfCP = 0 - - var tempPath = arrayOfAny.first - // tempPath?.pathComponents.firstIndex(of: "CircuitPython%208.x") - print("CircuitPython%207.x \(String(describing: tempPath?.pathComponents.firstIndex(of: "CircuitPython 7.x")))") - - // indexOfCP = tempPath?.pathComponents.firstIndex(of: "CircuitPython 7.x") + //path.pathComponents.removeSubrange(0...indexOfCP) } - func sortDirectory(directoryArray: [URL], fileArray: [URL]) { + func filterOutCPDirectories(fileArray: [URL]) -> [URL] { + + let test = fileArray.filter { + $0.lastPathComponent != ("CircuitPython 8.x") + } + + let test2 = test.filter { + $0.lastPathComponent != ("CircuitPython 7.x") + } + + return test2 + + } + + func exit() { + + } + + var returnedArray = [[String]]() + + func pathManipulation(arrayOfAny: [URL], fileArray: [URL]) { print(#function) + var indexOfCP = 0 + + + print("RETURNED PATHS: \(returnedArray)") + + var tempArray = arrayOfAny + + if arrayOfAny.isEmpty { + // Continue + print("Done!") + validateDirectory(directoryArray: returnedArray, fileArray: fileArray) + + } else { + + var tempPath = arrayOfAny[0].pathComponents + + if arrayOfAny[0].pathComponents.contains("CircuitPython 7.x") { + print("Found CircuitPython 8.x") + + indexOfCP = arrayOfAny[0].pathComponents.firstIndex(of: "CircuitPython 7.x")! + + tempPath.removeSubrange(0...indexOfCP) + + tempArray.removeFirst() + returnedArray.append(tempPath) + pathManipulation(arrayOfAny: tempArray, fileArray: fileArray) + } + + if arrayOfAny[0].pathComponents.contains("CircuitPython 8.x") { + print("Found CircuitPython 7.x") + indexOfCP = arrayOfAny[0].pathComponents.firstIndex(of: "CircuitPython 8.x")! + + tempPath.removeSubrange(0...indexOfCP) + + tempArray.removeFirst() + returnedArray.append(tempPath) + pathManipulation(arrayOfAny: tempArray, fileArray: fileArray) + + } + + } - var sortedDirectoryArray = directoryArray.sorted(by: { $1.pathComponents.count > $0.pathComponents.count} ) - var sortedFileArray = fileArray.sorted(by: { $1.pathComponents.count > $0.pathComponents.count} ) - validateDirectory(directoryArray: sortedDirectoryArray, fileArray: sortedFileArray) } - func validateDirectory(directoryArray: [URL], fileArray: [URL]) { + // func sortDirectory(directoryArray: [URL], fileArray: [URL]) { + // print(#function) + // + // var sortedDirectoryArray = directoryArray.sorted(by: { $1.pathComponents.count > $0.pathComponents.count} ) + // var sortedFileArray = fileArray.sorted(by: { $1.pathComponents.count > $0.pathComponents.count} ) + // validateDirectory(directoryArray: sortedDirectoryArray, fileArray: sortedFileArray) + // } + + func validateDirectory(directoryArray: [[String]], fileArray: [URL]) { print(#function) // Use Recursion to go through each directory - if directoryArray.isEmpty { + if self.returnedArray.isEmpty { print("No directories left in queue") print("Start file transfer...") // self.transferFiles(files: fileArray) @@ -353,24 +413,21 @@ class WifiViewModel: ObservableObject { return } - print("Array count \(directoryArray.count)") + print("Array count \(returnedArray.count)") - makeDirectory(directoryArray: directoryArray, fileArray: fileArray, firstDirectory: firstDirectory) + makeDirectory(fileArray: fileArray) } } - func makeDirectory(directoryArray: [URL], fileArray: [URL], firstDirectory: URL) { + func makeDirectory(fileArray: [URL]) { print(#function) - var temp = directoryArray - var tempPath = firstDirectory.pathComponents - tempPath.removeFirst(12) - print("Original Path: \(firstDirectory.absoluteURL)") + var tempPath = returnedArray[0] let joined = tempPath.joined(separator: "/") print("Outgoing path:\(joined)") @@ -380,8 +437,8 @@ class WifiViewModel: ObservableObject { case .success(let consent): print("Successful") - temp.removeFirst() - self.validateDirectory(directoryArray: temp, fileArray: fileArray) + self.returnedArray.removeFirst() + self.validateDirectory(directoryArray: self.returnedArray, fileArray: fileArray) case .failure(let error): print("Error: \(error)") @@ -391,101 +448,196 @@ class WifiViewModel: ObservableObject { } func makeFile(files: [URL]) { - + print(#function) var copiedArray = files - + if files.isEmpty { print("Transfer Complete") } else { - - - // let file = files[0].pathComponents.removeFirst(12) //this is the file. we will write to and read from it - - + + + // let file = files[0].pathComponents.removeFirst(12) //this is the file. we will write to and read from it + + if copiedArray.first?.lastPathComponent == "README.txt" { - print("Removing README") + print("Removing README") copiedArray.removeFirst() makeFile(files: copiedArray) - + } else { - var tempURL = copiedArray[0].pathComponents - tempURL.removeFirst(12) - let joined = tempURL.joined(separator: "/") - print() - - var text = "some text" //just a text - + + // print("copiedArray[0] \(copiedArray[0].pathComponents)") + // var tempURL = copiedArray[0].pathComponents + // tempURL.removeFirst(12) + // let joined = tempURL.joined(separator: "/") + // print("Joined \(joined)") + + + + + + + // var text = "some text" //just a text + guard let data = try? Data(contentsOf: URL(fileURLWithPath: copiedArray[0].path, relativeTo: copiedArray[0])) else { print("File not found") return } + var tempPath = copiedArray[0].pathComponents + print("PRINT INCOMING: \(tempPath)") - sendPutRequest(the: joined, to: copiedArray[0].absoluteURL, body: data) { result in - switch result { + if copiedArray[0].pathComponents.contains("CircuitPython 7.x") { + print("Found CircuitPython 7.x") + + var indexOfCP = 0 + + indexOfCP = copiedArray[0].pathComponents.firstIndex(of: "CircuitPython 7.x")! + + tempPath.removeSubrange(0...indexOfCP) + + let joined = tempPath.joined(separator: "/") + + + + if (copiedArray[0].pathExtension == "py") || (copiedArray[0].pathExtension == "txt") { - case .success(_): - print("Success") + putRequest(fileName: joined, fileContent: data) { result in + switch result { + + case .success(let content): + copiedArray.removeFirst() + self.makeFile(files: copiedArray) + case .failure(let error): + print("Failed write") + } + } + + } else { + + sendPutRequest(fileName: joined, body: data) { result in + switch result { + + case .success(_): + print("Success") + + copiedArray.removeFirst() + self.makeFile(files: copiedArray) + case .failure(_): + print("Failed to write") + } + } - copiedArray.removeFirst() - self.makeFile(files: copiedArray) - case .failure(_): - print("Failed to write") } + + + } -// do { -// let text2 = try String(contentsOf: copiedArray[10], encoding: .utf8) -// text = text2 -// -// -// -// -//// putRequest(fileName: joined, fileContent: data) { result in -//// switch result { -//// -//// case .success(let content): -//// copiedArray.removeFirst() -//// self.makeFile(files: copiedArray) -//// case .failure(let error): -//// print("Failed write") -//// } -//// } -// -// } catch { -// print("catch error") -// } - + if copiedArray[0].pathComponents.contains("CircuitPython 8.x") { + print("Found CircuitPython 8.x") + var tempPath = copiedArray[0].pathComponents + + var indexOfCP = Int() + + indexOfCP = copiedArray[0].pathComponents.firstIndex(of: "CircuitPython 8.x")! + + tempPath.removeSubrange(0...indexOfCP) + let joined = tempPath.joined(separator: "/") + print("joined : \(joined)") + + if (copiedArray[0].pathExtension == "py") || (copiedArray[0].pathExtension == "txt") { + + putRequest(fileName: joined, fileContent: data) { result in + switch result { + + case .success(let content): + copiedArray.removeFirst() + self.makeFile(files: copiedArray) + case .failure(let error): + print("Failed write") + } + } + + } else { + + sendPutRequest(fileName: joined, body: data) { result in + switch result { + + case .success(_): + print("Success") + + copiedArray.removeFirst() + self.makeFile(files: copiedArray) + case .failure(_): + print("Failed to write") + } + } + + } + + + } + + } + + + + + + + + // do { + // let text2 = try String(contentsOf: copiedArray[10], encoding: .utf8) + // text = text2 + // + // + // + // + //// putRequest(fileName: joined, fileContent: data) { result in + //// switch result { + //// + //// case .success(let content): + //// copiedArray.removeFirst() + //// self.makeFile(files: copiedArray) + //// case .failure(let error): + //// print("Failed write") + //// } + //// } + // + // } catch { + // print("catch error") + // } + + + // + // do { + // let text2 = try String(contentsOf: fileURLs[0], encoding: .utf8) + // text = text2 + // putRequest(fileName: file, fileContent: text) + // } + // catch {/* error handling here */} + // + // print("Reading File:") + // print(""" + //\(text) + //""") - // - // do { - // let text2 = try String(contentsOf: fileURLs[0], encoding: .utf8) - // text = text2 - // putRequest(fileName: file, fileContent: text) - // } - // catch {/* error handling here */} - // - // print("Reading File:") - // print(""" - //\(text) - //""") - - } - -// var tempURL = files[0].pathComponents -// tempURL.removeFirst(12) -// print(tempURL.joined(separator: "/")) - - } - + + // var tempURL = files[0].pathComponents + // tempURL.removeFirst(12) + // print(tempURL.joined(separator: "/")) + + } - func sendPutRequest(the fileName: String, to url: URL, + + func sendPutRequest(fileName: String, body: Data, then handler: @escaping(Result) -> Void) { @@ -519,26 +671,26 @@ class WifiViewModel: ObservableObject { print(request.cURL(pretty: true)) let task = urlSession.dataTask( - with: request, - completionHandler: { data, response, error in - // Validate response and call handler - - if let error = error { - print("File write error") - - handler(.failure(error)) - - } - - if let data = data { - print("File write success!") - handler(.success(data)) - } - - } - ) - - task.resume() + with: request, + completionHandler: { data, response, error in + // Validate response and call handler + + if let error = error { + print("File write error") + + handler(.failure(error)) + + } + + if let data = data { + print("File write success!") + handler(.success(data)) + } + + } + ) + + task.resume() } @@ -670,8 +822,8 @@ class WifiViewModel: ObservableObject { semaphore.wait() return outgoingString } -// func putDirectory(directoryPath: String, completion: @escaping (Result) -> Void) { - + // func putDirectory(directoryPath: String, completion: @escaping (Result) -> Void) { + func putRequest(fileName: String, fileContent: Data, completion: @escaping (Result) -> Void) { print("Test Transfer") let parameters = fileContent @@ -701,7 +853,7 @@ class WifiViewModel: ObservableObject { let task = URLSession.shared.dataTask(with: request) { data, response, error in if let error = error { print("File write error") - + completion(.failure(error)) } @@ -711,7 +863,7 @@ class WifiViewModel: ObservableObject { completion(.success(data)) } - // print(String(data: data, encoding: .utf8)!) + // print(String(data: data, encoding: .utf8)!) } task.resume() @@ -739,7 +891,7 @@ class WifiViewModel: ObservableObject { print(request.cURL(pretty: true)) let task = URLSession.shared.dataTask(with: request) { data, response, error in - + if let error = error { completion(.failure(error)) @@ -802,9 +954,6 @@ class WifiViewModel: ObservableObject { func deleteRequest() { - - - let username = "" let password = "passw0rd" let loginString = "\(username):\(password)" @@ -843,6 +992,40 @@ class WifiViewModel: ObservableObject { task.resume() } + @Published var projectDownloaded = false + @Published var failedProjectLaunch = false + + + + func getProjectForSubClass(nameOf project: String) { + + if let enumerator = FileManager.default.enumerator(at: directoryPath, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles, .skipsPackageDescendants]) { + // for case condition: Only process URLs + for case let fileURL as URL in enumerator { + + if fileURL.lastPathComponent == project { + failedProjectLaunch = false + projectDownloaded = true + print(#function) + print("Searching for... \(project)") + print("URL Path: \(fileURL.path)") + print("URL : \(fileURL)") + + return + + } else { + failedProjectLaunch = true + projectDownloaded = false + print("Project was not found...") + + } + + + } + + } + + } // Enter IP Adress