Compare commits
7 commits
master
...
iOS-17-Upd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e2ee8733b | ||
|
|
51e7ef0573 | ||
|
|
2ecc9a2ec9 | ||
|
|
0646453175 | ||
|
|
a34e2bf6d3 | ||
|
|
e5bb6df771 | ||
|
|
976bf512fa |
80 changed files with 976 additions and 1297 deletions
|
|
@ -98,7 +98,7 @@ public class FileTransferClient {
|
||||||
// Set current peripheral
|
// Set current peripheral
|
||||||
self.blePeripheral = blePeripheral
|
self.blePeripheral = blePeripheral
|
||||||
|
|
||||||
// Setup services
|
// Setup servic*es
|
||||||
let servicesGroup = DispatchGroup()
|
let servicesGroup = DispatchGroup()
|
||||||
|
|
||||||
var error: Error? = nil
|
var error: Error? = nil
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,19 @@
|
||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 52;
|
objectVersion = 54;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
D505B99C2755323C00386E9F /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D505B99B2755323C00386E9F /* NetworkMonitor.swift */; };
|
D505B99C2755323C00386E9F /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D505B99B2755323C00386E9F /* NetworkMonitor.swift */; };
|
||||||
D505B99E2756894300386E9F /* ViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D505B99D2756894300386E9F /* ViewModifier.swift */; };
|
D505B99E2756894300386E9F /* ViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D505B99D2756894300386E9F /* ViewModifier.swift */; };
|
||||||
|
D50887632A2E35510002B798 /* Wifi_ifaddrs.m in Sources */ = {isa = PBXBuildFile; fileRef = D50887622A2E35510002B798 /* Wifi_ifaddrs.m */; };
|
||||||
D517F68126C5771D002996E8 /* FillerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D517F68026C5771D002996E8 /* FillerView.swift */; };
|
D517F68126C5771D002996E8 /* FillerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D517F68026C5771D002996E8 /* FillerView.swift */; };
|
||||||
D5199A2F28DD16F100ACC34C /* BleContentTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5199A2E28DD16F100ACC34C /* BleContentTransfer.swift */; };
|
D5199A2F28DD16F100ACC34C /* BleContentTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5199A2E28DD16F100ACC34C /* BleContentTransfer.swift */; };
|
||||||
D51D1413293A53BD0028AEDD /* WifiCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */; };
|
D51D1413293A53BD0028AEDD /* WifiCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */; };
|
||||||
|
D520D69029D4C9380022048D /* WifiServiceCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D520D68F29D4C9380022048D /* WifiServiceCellView.swift */; };
|
||||||
|
D520D69229D4C9900022048D /* WifiServiceCellSubView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D520D69129D4C9900022048D /* WifiServiceCellSubView.swift */; };
|
||||||
D5267411292E902700D4C79E /* Networking.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5267410292E902700D4C79E /* Networking.swift */; };
|
D5267411292E902700D4C79E /* Networking.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5267410292E902700D4C79E /* Networking.swift */; };
|
||||||
D5269C00291960A300C0CE4B /* WifiSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5269BFF291960A300C0CE4B /* WifiSelection.swift */; };
|
|
||||||
D5269C02291997DE00C0CE4B /* WifiServiceCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5269C01291997DE00C0CE4B /* WifiServiceCellView.swift */; };
|
|
||||||
D5269C042919985400C0CE4B /* WifiServiceCellSubView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5269C032919985400C0CE4B /* WifiServiceCellSubView.swift */; };
|
|
||||||
D5269C08291AB75800C0CE4B /* WifiPairingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5269C07291AB75800C0CE4B /* WifiPairingView.swift */; };
|
D5269C08291AB75800C0CE4B /* WifiPairingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5269C07291AB75800C0CE4B /* WifiPairingView.swift */; };
|
||||||
D52A926D29071DF400973B6B /* SelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A926C29071DF400973B6B /* SelectionView.swift */; };
|
D52A926D29071DF400973B6B /* SelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A926C29071DF400973B6B /* SelectionView.swift */; };
|
||||||
D52A926F29078E0A00973B6B /* WifiServiceSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A926E29078E0A00973B6B /* WifiServiceSelectionView.swift */; };
|
D52A926F29078E0A00973B6B /* WifiServiceSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A926E29078E0A00973B6B /* WifiServiceSelectionView.swift */; };
|
||||||
|
|
@ -68,7 +68,6 @@
|
||||||
D58D887B26CC02B60085604A /* OnboardingViewPure.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58D887A26CC02B60085604A /* OnboardingViewPure.swift */; };
|
D58D887B26CC02B60085604A /* OnboardingViewPure.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58D887A26CC02B60085604A /* OnboardingViewPure.swift */; };
|
||||||
D58E1C8828A2B10B00AB683E /* WifiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8728A2B10B00AB683E /* WifiView.swift */; };
|
D58E1C8828A2B10B00AB683E /* WifiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8728A2B10B00AB683E /* WifiView.swift */; };
|
||||||
D58E1C8A28A2B15E00AB683E /* WifiViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */; };
|
D58E1C8A28A2B15E00AB683E /* WifiViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */; };
|
||||||
D58E1C8D28A2B32C00AB683E /* Wifi_ifaddrs.m in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8C28A2B32C00AB683E /* Wifi_ifaddrs.m */; };
|
|
||||||
D58E1C8F28A30A5300AB683E /* WifiNetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8E28A30A5300AB683E /* WifiNetworkService.swift */; };
|
D58E1C8F28A30A5300AB683E /* WifiNetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8E28A30A5300AB683E /* WifiNetworkService.swift */; };
|
||||||
D595FC2E2812C23D00569D8C /* Image Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D595FC2D2812C23D00569D8C /* Image Extension.swift */; };
|
D595FC2E2812C23D00569D8C /* Image Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D595FC2D2812C23D00569D8C /* Image Extension.swift */; };
|
||||||
D59DFD8F268A4A4D001737F6 /* BTConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59DFD8E268A4A4D001737F6 /* BTConnectionView.swift */; };
|
D59DFD8F268A4A4D001737F6 /* BTConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D59DFD8E268A4A4D001737F6 /* BTConnectionView.swift */; };
|
||||||
|
|
@ -84,6 +83,8 @@
|
||||||
D5BA1F7F28B66F280012FC62 /* WifiServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BA1F7E28B66F280012FC62 /* WifiServiceManager.swift */; };
|
D5BA1F7F28B66F280012FC62 /* WifiServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BA1F7E28B66F280012FC62 /* WifiServiceManager.swift */; };
|
||||||
D5BA1F8128B66F920012FC62 /* CircuitPythonService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BA1F8028B66F920012FC62 /* CircuitPythonService.swift */; };
|
D5BA1F8128B66F920012FC62 /* CircuitPythonService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BA1F8028B66F920012FC62 /* CircuitPythonService.swift */; };
|
||||||
D5BA1F8328B68ED40012FC62 /* NetworkPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BA1F8228B68ED40012FC62 /* NetworkPeripheral.swift */; };
|
D5BA1F8328B68ED40012FC62 /* NetworkPeripheral.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BA1F8228B68ED40012FC62 /* NetworkPeripheral.swift */; };
|
||||||
|
D5BBD12C2A1538C100961B68 /* BoardDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BBD12B2A1538C100961B68 /* BoardDataProvider.swift */; };
|
||||||
|
D5BBD12E2A1C6AB300961B68 /* BleBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BBD12D2A1C6AB300961B68 /* BleBannerView.swift */; };
|
||||||
D5C474AC27E174A5002DD160 /* WebView Content.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C474AB27E174A5002DD160 /* WebView Content.swift */; };
|
D5C474AC27E174A5002DD160 /* WebView Content.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C474AB27E174A5002DD160 /* WebView Content.swift */; };
|
||||||
D5C474C827E39FD7002DD160 /* ReadexPro-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D5C474C627E39FC8002DD160 /* ReadexPro-Medium.ttf */; };
|
D5C474C827E39FD7002DD160 /* ReadexPro-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D5C474C627E39FC8002DD160 /* ReadexPro-Medium.ttf */; };
|
||||||
D5C474C927E39FDA002DD160 /* ReadexPro-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D5C474C727E39FC8002DD160 /* ReadexPro-Regular.ttf */; };
|
D5C474C927E39FDA002DD160 /* ReadexPro-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D5C474C727E39FC8002DD160 /* ReadexPro-Regular.ttf */; };
|
||||||
|
|
@ -116,13 +117,14 @@
|
||||||
D50237E3280994F900F1EE8A /* PyLeap.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = PyLeap.entitlements; path = "../../../../Desktop/Copy Of PyLeap Entitlement/PyLeap.entitlements"; sourceTree = "<group>"; };
|
D50237E3280994F900F1EE8A /* PyLeap.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = PyLeap.entitlements; path = "../../../../Desktop/Copy Of PyLeap Entitlement/PyLeap.entitlements"; sourceTree = "<group>"; };
|
||||||
D505B99B2755323C00386E9F /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
|
D505B99B2755323C00386E9F /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = "<group>"; };
|
||||||
D505B99D2756894300386E9F /* ViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModifier.swift; sourceTree = "<group>"; };
|
D505B99D2756894300386E9F /* ViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModifier.swift; sourceTree = "<group>"; };
|
||||||
|
D50887612A2E35490002B798 /* PyLeap-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PyLeap-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
D50887622A2E35510002B798 /* Wifi_ifaddrs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Wifi_ifaddrs.m; sourceTree = "<group>"; };
|
||||||
D517F68026C5771D002996E8 /* FillerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FillerView.swift; sourceTree = "<group>"; };
|
D517F68026C5771D002996E8 /* FillerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FillerView.swift; sourceTree = "<group>"; };
|
||||||
D5199A2E28DD16F100ACC34C /* BleContentTransfer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BleContentTransfer.swift; sourceTree = "<group>"; };
|
D5199A2E28DD16F100ACC34C /* BleContentTransfer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BleContentTransfer.swift; sourceTree = "<group>"; };
|
||||||
D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiCellViewModel.swift; sourceTree = "<group>"; };
|
D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiCellViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
D520D68F29D4C9380022048D /* WifiServiceCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiServiceCellView.swift; sourceTree = "<group>"; };
|
||||||
|
D520D69129D4C9900022048D /* WifiServiceCellSubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiServiceCellSubView.swift; sourceTree = "<group>"; };
|
||||||
D5267410292E902700D4C79E /* Networking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Networking.swift; sourceTree = "<group>"; };
|
D5267410292E902700D4C79E /* Networking.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Networking.swift; sourceTree = "<group>"; };
|
||||||
D5269BFF291960A300C0CE4B /* WifiSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WifiSelection.swift; path = "PyLeap/Views/Unpaired View/WifiSelection.swift"; sourceTree = SOURCE_ROOT; };
|
|
||||||
D5269C01291997DE00C0CE4B /* WifiServiceCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WifiServiceCellView.swift; path = ../../../../../../Desktop/WifiServiceCellView.swift; sourceTree = "<group>"; };
|
|
||||||
D5269C032919985400C0CE4B /* WifiServiceCellSubView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WifiServiceCellSubView.swift; path = ../../../../../../Desktop/WifiServiceCellSubView.swift; sourceTree = "<group>"; };
|
|
||||||
D5269C07291AB75800C0CE4B /* WifiPairingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiPairingView.swift; sourceTree = "<group>"; };
|
D5269C07291AB75800C0CE4B /* WifiPairingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiPairingView.swift; sourceTree = "<group>"; };
|
||||||
D52A926C29071DF400973B6B /* SelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionView.swift; sourceTree = "<group>"; };
|
D52A926C29071DF400973B6B /* SelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectionView.swift; sourceTree = "<group>"; };
|
||||||
D52A926E29078E0A00973B6B /* WifiServiceSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiServiceSelectionView.swift; sourceTree = "<group>"; };
|
D52A926E29078E0A00973B6B /* WifiServiceSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiServiceSelectionView.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -177,7 +179,6 @@
|
||||||
D58D887A26CC02B60085604A /* OnboardingViewPure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewPure.swift; sourceTree = "<group>"; };
|
D58D887A26CC02B60085604A /* OnboardingViewPure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewPure.swift; sourceTree = "<group>"; };
|
||||||
D58E1C8728A2B10B00AB683E /* WifiView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiView.swift; sourceTree = "<group>"; };
|
D58E1C8728A2B10B00AB683E /* WifiView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiView.swift; sourceTree = "<group>"; };
|
||||||
D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiViewModel.swift; sourceTree = "<group>"; };
|
D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiViewModel.swift; sourceTree = "<group>"; };
|
||||||
D58E1C8C28A2B32C00AB683E /* Wifi_ifaddrs.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Wifi_ifaddrs.m; sourceTree = "<group>"; };
|
|
||||||
D58E1C8E28A30A5300AB683E /* WifiNetworkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiNetworkService.swift; sourceTree = "<group>"; };
|
D58E1C8E28A30A5300AB683E /* WifiNetworkService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiNetworkService.swift; sourceTree = "<group>"; };
|
||||||
D595FC2D2812C23D00569D8C /* Image Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Image Extension.swift"; sourceTree = "<group>"; };
|
D595FC2D2812C23D00569D8C /* Image Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Image Extension.swift"; sourceTree = "<group>"; };
|
||||||
D59DFD8E268A4A4D001737F6 /* BTConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTConnectionView.swift; sourceTree = "<group>"; };
|
D59DFD8E268A4A4D001737F6 /* BTConnectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTConnectionView.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -194,6 +195,8 @@
|
||||||
D5BA1F7E28B66F280012FC62 /* WifiServiceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiServiceManager.swift; sourceTree = "<group>"; };
|
D5BA1F7E28B66F280012FC62 /* WifiServiceManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiServiceManager.swift; sourceTree = "<group>"; };
|
||||||
D5BA1F8028B66F920012FC62 /* CircuitPythonService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircuitPythonService.swift; sourceTree = "<group>"; };
|
D5BA1F8028B66F920012FC62 /* CircuitPythonService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircuitPythonService.swift; sourceTree = "<group>"; };
|
||||||
D5BA1F8228B68ED40012FC62 /* NetworkPeripheral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkPeripheral.swift; sourceTree = "<group>"; };
|
D5BA1F8228B68ED40012FC62 /* NetworkPeripheral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkPeripheral.swift; sourceTree = "<group>"; };
|
||||||
|
D5BBD12B2A1538C100961B68 /* BoardDataProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BoardDataProvider.swift; sourceTree = "<group>"; };
|
||||||
|
D5BBD12D2A1C6AB300961B68 /* BleBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BleBannerView.swift; sourceTree = "<group>"; };
|
||||||
D5C474AB27E174A5002DD160 /* WebView Content.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebView Content.swift"; sourceTree = "<group>"; };
|
D5C474AB27E174A5002DD160 /* WebView Content.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebView Content.swift"; sourceTree = "<group>"; };
|
||||||
D5C474C227E39FAD002DD160 /* ReadexPro-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ReadexPro-Bold.ttf"; sourceTree = "<group>"; };
|
D5C474C227E39FAD002DD160 /* ReadexPro-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ReadexPro-Bold.ttf"; sourceTree = "<group>"; };
|
||||||
D5C474C527E39FC8002DD160 /* ReadexPro-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ReadexPro-Light.ttf"; sourceTree = "<group>"; };
|
D5C474C527E39FC8002DD160 /* ReadexPro-Light.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "ReadexPro-Light.ttf"; sourceTree = "<group>"; };
|
||||||
|
|
@ -218,7 +221,6 @@
|
||||||
D5DD39A628D11817000FAEB8 /* WifiFileTransfer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiFileTransfer.swift; sourceTree = "<group>"; };
|
D5DD39A628D11817000FAEB8 /* WifiFileTransfer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiFileTransfer.swift; sourceTree = "<group>"; };
|
||||||
D5DD39A828D11962000FAEB8 /* WifiTransferService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiTransferService.swift; sourceTree = "<group>"; };
|
D5DD39A828D11962000FAEB8 /* WifiTransferService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WifiTransferService.swift; sourceTree = "<group>"; };
|
||||||
D5DD39AA28D234C3000FAEB8 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
|
D5DD39AA28D234C3000FAEB8 /* SettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
|
||||||
D5ECF4B828C8E3C600FBF93D /* PyLeap-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PyLeap-Bridging-Header.h"; sourceTree = "<group>"; };
|
|
||||||
D5F53CEA2694B524007634C2 /* Blinka Animation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Blinka Animation.swift"; sourceTree = "<group>"; };
|
D5F53CEA2694B524007634C2 /* Blinka Animation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Blinka Animation.swift"; sourceTree = "<group>"; };
|
||||||
D5F53CEC2694B7A9007634C2 /* OnboardingBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundView.swift; sourceTree = "<group>"; };
|
D5F53CEC2694B7A9007634C2 /* OnboardingBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundView.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
@ -278,9 +280,11 @@
|
||||||
D59DFDB5268CD052001737F6 /* AppEnvironment.swift */,
|
D59DFDB5268CD052001737F6 /* AppEnvironment.swift */,
|
||||||
D534F3FB280B59090053699C /* ExampleView.swift */,
|
D534F3FB280B59090053699C /* ExampleView.swift */,
|
||||||
D544A2502822D4730038D483 /* Spotlight Extension.swift */,
|
D544A2502822D4730038D483 /* Spotlight Extension.swift */,
|
||||||
|
D5BBD12A2A15389400961B68 /* Helpers */,
|
||||||
D567E2B428B80DC10009F768 /* Outline.md */,
|
D567E2B428B80DC10009F768 /* Outline.md */,
|
||||||
|
D567E2DD28C8D3E20009F768 /* SettingsView */,
|
||||||
D5C74DF027EB92E900730505 /* Model */,
|
D5C74DF027EB92E900730505 /* Model */,
|
||||||
D59DFDB2268CCEAC001737F6 /* Views */,
|
D59DFDB2268CCEAC001737F6 /* Features */,
|
||||||
D5C74DEE27EB91D600730505 /* Networking */,
|
D5C74DEE27EB91D600730505 /* Networking */,
|
||||||
D5C74DED27EB919200730505 /* Resource */,
|
D5C74DED27EB919200730505 /* Resource */,
|
||||||
D5C41D6726C5F509004C38E3 /* Download View */,
|
D5C41D6726C5F509004C38E3 /* Download View */,
|
||||||
|
|
@ -376,23 +380,29 @@
|
||||||
path = BLESetttings;
|
path = BLESetttings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D58E1C8628A2B0DE00AB683E /* Wifi View */ = {
|
D56FFE1C2A2A4ED500EF1E3B /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D567E2DD28C8D3E20009F768 /* SettingsView */,
|
|
||||||
D58E1C8728A2B10B00AB683E /* WifiView.swift */,
|
D58E1C8728A2B10B00AB683E /* WifiView.swift */,
|
||||||
D567E2B728C137880009F768 /* WifiCell.swift */,
|
D567E2B728C137880009F768 /* WifiCell.swift */,
|
||||||
D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */,
|
|
||||||
D567E2B928C1382E0009F768 /* WifiSubViewCell.swift */,
|
D567E2B928C1382E0009F768 /* WifiSubViewCell.swift */,
|
||||||
|
);
|
||||||
|
path = Views;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
D58E1C8628A2B0DE00AB683E /* Wifi Module */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D56FFE1C2A2A4ED500EF1E3B /* Views */,
|
||||||
|
D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */,
|
||||||
D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */,
|
D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */,
|
||||||
D5269C07291AB75800C0CE4B /* WifiPairingView.swift */,
|
D5269C07291AB75800C0CE4B /* WifiPairingView.swift */,
|
||||||
D52A926E29078E0A00973B6B /* WifiServiceSelectionView.swift */,
|
D52A926E29078E0A00973B6B /* WifiServiceSelectionView.swift */,
|
||||||
D5269BFF291960A300C0CE4B /* WifiSelection.swift */,
|
D520D68F29D4C9380022048D /* WifiServiceCellView.swift */,
|
||||||
D5269C01291997DE00C0CE4B /* WifiServiceCellView.swift */,
|
|
||||||
D5269C032919985400C0CE4B /* WifiServiceCellSubView.swift */,
|
|
||||||
D5BA1F7E28B66F280012FC62 /* WifiServiceManager.swift */,
|
D5BA1F7E28B66F280012FC62 /* WifiServiceManager.swift */,
|
||||||
D5DD39A628D11817000FAEB8 /* WifiFileTransfer.swift */,
|
D5DD39A628D11817000FAEB8 /* WifiFileTransfer.swift */,
|
||||||
D5DD39A828D11962000FAEB8 /* WifiTransferService.swift */,
|
D5DD39A828D11962000FAEB8 /* WifiTransferService.swift */,
|
||||||
|
D520D69129D4C9900022048D /* WifiServiceCellSubView.swift */,
|
||||||
D5AA27F728CA785B001CCE25 /* CircuitPythonType.swift */,
|
D5AA27F728CA785B001CCE25 /* CircuitPythonType.swift */,
|
||||||
D5482F4A28E75053000B0C8E /* LocalNetworkAuth.swift */,
|
D5482F4A28E75053000B0C8E /* LocalNetworkAuth.swift */,
|
||||||
D5AA27F928CA8D46001CCE25 /* WifiStatusHeaderBarView.swift */,
|
D5AA27F928CA8D46001CCE25 /* WifiStatusHeaderBarView.swift */,
|
||||||
|
|
@ -402,17 +412,17 @@
|
||||||
D5BA1F8028B66F920012FC62 /* CircuitPythonService.swift */,
|
D5BA1F8028B66F920012FC62 /* CircuitPythonService.swift */,
|
||||||
D58E1C8E28A30A5300AB683E /* WifiNetworkService.swift */,
|
D58E1C8E28A30A5300AB683E /* WifiNetworkService.swift */,
|
||||||
D5BA1F8228B68ED40012FC62 /* NetworkPeripheral.swift */,
|
D5BA1F8228B68ED40012FC62 /* NetworkPeripheral.swift */,
|
||||||
|
D50887622A2E35510002B798 /* Wifi_ifaddrs.m */,
|
||||||
|
D50887612A2E35490002B798 /* PyLeap-Bridging-Header.h */,
|
||||||
D5D7DF2A28B3E321008552D1 /* BasicCredentials.swift */,
|
D5D7DF2A28B3E321008552D1 /* BasicCredentials.swift */,
|
||||||
D58E1C8C28A2B32C00AB683E /* Wifi_ifaddrs.m */,
|
|
||||||
D5ECF4B828C8E3C600FBF93D /* PyLeap-Bridging-Header.h */,
|
|
||||||
);
|
);
|
||||||
path = "Wifi View";
|
path = "Wifi Module";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D59DFDB2268CCEAC001737F6 /* Views */ = {
|
D59DFDB2268CCEAC001737F6 /* Features */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
D58E1C8628A2B0DE00AB683E /* Wifi View */,
|
D58E1C8628A2B0DE00AB683E /* Wifi Module */,
|
||||||
D5507ACE26C668BC00512BAA /* UI Components */,
|
D5507ACE26C668BC00512BAA /* UI Components */,
|
||||||
D59DFDB3268CCEB9001737F6 /* Onboarding Views */,
|
D59DFDB3268CCEB9001737F6 /* Onboarding Views */,
|
||||||
D5C474AA27E1746F002DD160 /* WebView */,
|
D5C474AA27E1746F002DD160 /* WebView */,
|
||||||
|
|
@ -424,7 +434,7 @@
|
||||||
D517F68026C5771D002996E8 /* FillerView.swift */,
|
D517F68026C5771D002996E8 /* FillerView.swift */,
|
||||||
D5D1F4AC27ECFD200040E2BF /* Startup View */,
|
D5D1F4AC27ECFD200040E2BF /* Startup View */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Features;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D59DFDB3268CCEB9001737F6 /* Onboarding Views */ = {
|
D59DFDB3268CCEB9001737F6 /* Onboarding Views */ = {
|
||||||
|
|
@ -438,6 +448,14 @@
|
||||||
path = "Onboarding Views";
|
path = "Onboarding Views";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
D5BBD12A2A15389400961B68 /* Helpers */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D5BBD12B2A1538C100961B68 /* BoardDataProvider.swift */,
|
||||||
|
);
|
||||||
|
path = Helpers;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D5C41D6726C5F509004C38E3 /* Download View */ = {
|
D5C41D6726C5F509004C38E3 /* Download View */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -535,6 +553,7 @@
|
||||||
children = (
|
children = (
|
||||||
D59E31A9281B8DD300D24211 /* DownloadState.swift */,
|
D59E31A9281B8DD300D24211 /* DownloadState.swift */,
|
||||||
D5507ACB26C668BC00512BAA /* BleModuleView.swift */,
|
D5507ACB26C668BC00512BAA /* BleModuleView.swift */,
|
||||||
|
D5BBD12D2A1C6AB300961B68 /* BleBannerView.swift */,
|
||||||
D5507ACC26C668BC00512BAA /* BleModuleViewModel.swift */,
|
D5507ACC26C668BC00512BAA /* BleModuleViewModel.swift */,
|
||||||
D5199A2E28DD16F100ACC34C /* BleContentTransfer.swift */,
|
D5199A2E28DD16F100ACC34C /* BleContentTransfer.swift */,
|
||||||
D5D5BB3828DD19F000E5D93F /* BleContentCommands.swift */,
|
D5D5BB3828DD19F000E5D93F /* BleContentCommands.swift */,
|
||||||
|
|
@ -605,8 +624,9 @@
|
||||||
D52F7E682672F4C400911D43 /* Project object */ = {
|
D52F7E682672F4C400911D43 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
|
BuildIndependentTargetsInParallel = YES;
|
||||||
LastSwiftUpdateCheck = 1250;
|
LastSwiftUpdateCheck = 1250;
|
||||||
LastUpgradeCheck = 1250;
|
LastUpgradeCheck = 1500;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
D52F7E6F2672F4C400911D43 = {
|
D52F7E6F2672F4C400911D43 = {
|
||||||
CreatedOnToolsVersion = 12.5;
|
CreatedOnToolsVersion = 12.5;
|
||||||
|
|
@ -659,6 +679,7 @@
|
||||||
D5D1F4B827ED2F4F0040E2BF /* FileManagerCheck.swift in Sources */,
|
D5D1F4B827ED2F4F0040E2BF /* FileManagerCheck.swift in Sources */,
|
||||||
D52BE82A26A0660200630900 /* KeyboardUtils.swift in Sources */,
|
D52BE82A26A0660200630900 /* KeyboardUtils.swift in Sources */,
|
||||||
D58182FB27F732E40091C43B /* SubCellViewModel.swift in Sources */,
|
D58182FB27F732E40091C43B /* SubCellViewModel.swift in Sources */,
|
||||||
|
D520D69229D4C9900022048D /* WifiServiceCellSubView.swift in Sources */,
|
||||||
D5D5BB3928DD19F000E5D93F /* BleContentCommands.swift in Sources */,
|
D5D5BB3928DD19F000E5D93F /* BleContentCommands.swift in Sources */,
|
||||||
D544A1D2281B9BB70038D483 /* Buttons.swift in Sources */,
|
D544A1D2281B9BB70038D483 /* Buttons.swift in Sources */,
|
||||||
D5D1F4AE27ECFDA10040E2BF /* GifImage.swift in Sources */,
|
D5D1F4AE27ECFDA10040E2BF /* GifImage.swift in Sources */,
|
||||||
|
|
@ -678,9 +699,9 @@
|
||||||
D56F640C270242CA000E5975 /* UIColor+LightAndDark.swift in Sources */,
|
D56F640C270242CA000E5975 /* UIColor+LightAndDark.swift in Sources */,
|
||||||
D5F53CED2694B7A9007634C2 /* OnboardingBackgroundView.swift in Sources */,
|
D5F53CED2694B7A9007634C2 /* OnboardingBackgroundView.swift in Sources */,
|
||||||
D5D1F4B227ECFF760040E2BF /* ProjectsModel.swift in Sources */,
|
D5D1F4B227ECFF760040E2BF /* ProjectsModel.swift in Sources */,
|
||||||
D5269C02291997DE00C0CE4B /* WifiServiceCellView.swift in Sources */,
|
|
||||||
D5BA1F7A28B52A490012FC62 /* WifiListDetailView.swift in Sources */,
|
D5BA1F7A28B52A490012FC62 /* WifiListDetailView.swift in Sources */,
|
||||||
D52F7E742672F4C400911D43 /* PyLeapApp.swift in Sources */,
|
D52F7E742672F4C400911D43 /* PyLeapApp.swift in Sources */,
|
||||||
|
D5BBD12E2A1C6AB300961B68 /* BleBannerView.swift in Sources */,
|
||||||
D567E2B628B81B730009F768 /* Queue.swift in Sources */,
|
D567E2B628B81B730009F768 /* Queue.swift in Sources */,
|
||||||
D534F3FC280B59090053699C /* ExampleView.swift in Sources */,
|
D534F3FC280B59090053699C /* ExampleView.swift in Sources */,
|
||||||
D57858ED28327E18008E8BE4 /* PairingTutorialView.swift in Sources */,
|
D57858ED28327E18008E8BE4 /* PairingTutorialView.swift in Sources */,
|
||||||
|
|
@ -702,7 +723,6 @@
|
||||||
D5DD39A728D11817000FAEB8 /* WifiFileTransfer.swift in Sources */,
|
D5DD39A728D11817000FAEB8 /* WifiFileTransfer.swift in Sources */,
|
||||||
D5AA27FA28CA8D46001CCE25 /* WifiStatusHeaderBarView.swift in Sources */,
|
D5AA27FA28CA8D46001CCE25 /* WifiStatusHeaderBarView.swift in Sources */,
|
||||||
D5F53CEB2694B524007634C2 /* Blinka Animation.swift in Sources */,
|
D5F53CEB2694B524007634C2 /* Blinka Animation.swift in Sources */,
|
||||||
D5269C00291960A300C0CE4B /* WifiSelection.swift in Sources */,
|
|
||||||
D5597BF826A9E14B00DF17C0 /* AppDelegate.swift in Sources */,
|
D5597BF826A9E14B00DF17C0 /* AppDelegate.swift in Sources */,
|
||||||
D56F640E270242CA000E5975 /* String+DeletingPrefix.swift in Sources */,
|
D56F640E270242CA000E5975 /* String+DeletingPrefix.swift in Sources */,
|
||||||
D57858F328333CBC008E8BE4 /* TroubleshootView.swift in Sources */,
|
D57858F328333CBC008E8BE4 /* TroubleshootView.swift in Sources */,
|
||||||
|
|
@ -739,18 +759,19 @@
|
||||||
D567E2B828C137880009F768 /* WifiCell.swift in Sources */,
|
D567E2B828C137880009F768 /* WifiCell.swift in Sources */,
|
||||||
D5D1F4B027ECFDE00040E2BF /* NavBarModifier.swift in Sources */,
|
D5D1F4B027ECFDE00040E2BF /* NavBarModifier.swift in Sources */,
|
||||||
D5597C0C26AF018800DF17C0 /* View+If.swift in Sources */,
|
D5597C0C26AF018800DF17C0 /* View+If.swift in Sources */,
|
||||||
D58E1C8D28A2B32C00AB683E /* Wifi_ifaddrs.m in Sources */,
|
|
||||||
D56B75D4294BAAB400D008E7 /* BLESettingsView.swift in Sources */,
|
D56B75D4294BAAB400D008E7 /* BLESettingsView.swift in Sources */,
|
||||||
|
D50887632A2E35510002B798 /* Wifi_ifaddrs.m in Sources */,
|
||||||
D52BE7EE269DF36E00630900 /* DownloadViewModel.swift in Sources */,
|
D52BE7EE269DF36E00630900 /* DownloadViewModel.swift in Sources */,
|
||||||
D59E31AA281B8DD300D24211 /* DownloadState.swift in Sources */,
|
D59E31AA281B8DD300D24211 /* DownloadState.swift in Sources */,
|
||||||
|
D520D69029D4C9380022048D /* WifiServiceCellView.swift in Sources */,
|
||||||
D5BA1F7F28B66F280012FC62 /* WifiServiceManager.swift in Sources */,
|
D5BA1F7F28B66F280012FC62 /* WifiServiceManager.swift in Sources */,
|
||||||
D5C74DF327EB92FA00730505 /* View+Extensions.swift in Sources */,
|
D5C74DF327EB92FA00730505 /* View+Extensions.swift in Sources */,
|
||||||
D5AA27F828CA785B001CCE25 /* CircuitPythonType.swift in Sources */,
|
D5AA27F828CA785B001CCE25 /* CircuitPythonType.swift in Sources */,
|
||||||
D5199A2F28DD16F100ACC34C /* BleContentTransfer.swift in Sources */,
|
D5199A2F28DD16F100ACC34C /* BleContentTransfer.swift in Sources */,
|
||||||
D535E21628E1FA910096E548 /* ScrollRefreshableView.swift in Sources */,
|
D535E21628E1FA910096E548 /* ScrollRefreshableView.swift in Sources */,
|
||||||
D5640216271B54BF00AE1519 /* MainSelectionView.swift in Sources */,
|
D5640216271B54BF00AE1519 /* MainSelectionView.swift in Sources */,
|
||||||
D5269C042919985400C0CE4B /* WifiServiceCellSubView.swift in Sources */,
|
|
||||||
D505B99C2755323C00386E9F /* NetworkMonitor.swift in Sources */,
|
D505B99C2755323C00386E9F /* NetworkMonitor.swift in Sources */,
|
||||||
|
D5BBD12C2A1538C100961B68 /* BoardDataProvider.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -794,6 +815,7 @@
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
|
@ -808,7 +830,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
|
@ -855,6 +877,7 @@
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
|
@ -863,7 +886,7 @@
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
|
@ -881,22 +904,22 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = PyLeap/PyLeap.entitlements;
|
CODE_SIGN_ENTITLEMENTS = PyLeap/PyLeap.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 0;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"PyLeap/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"PyLeap/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
INFOPLIST_FILE = PyLeap/Info.plist;
|
INFOPLIST_FILE = PyLeap/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 2.1.1;
|
MARKETING_VERSION = 2.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.PyLeap;
|
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.PyLeap;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "PyLeap/Views/Wifi View/PyLeap-Bridging-Header.h";
|
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
@ -911,22 +934,22 @@
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_ENTITLEMENTS = PyLeap/PyLeap.entitlements;
|
CODE_SIGN_ENTITLEMENTS = PyLeap/PyLeap.entitlements;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 0;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"PyLeap/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"PyLeap/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
INFOPLIST_FILE = PyLeap/Info.plist;
|
INFOPLIST_FILE = PyLeap/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 2.1.1;
|
MARKETING_VERSION = 2.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.PyLeap;
|
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.PyLeap;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "PyLeap/Views/Wifi View/PyLeap-Bridging-Header.h";
|
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1320"
|
LastUpgradeVersion = "1500"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|
|
||||||
21
PyLeap/Assets.xcassets/Placeholder Board Image.imageset/Contents.json
vendored
Normal file
21
PyLeap/Assets.xcassets/Placeholder Board Image.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Default device image.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
PyLeap/Assets.xcassets/Placeholder Board Image.imageset/Default device image.png
vendored
Normal file
BIN
PyLeap/Assets.xcassets/Placeholder Board Image.imageset/Default device image.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
47
PyLeap/Features/Paired View/BleBannerView.swift
Normal file
47
PyLeap/Features/Paired View/BleBannerView.swift
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// BleBannerView.swift
|
||||||
|
// PyLeap
|
||||||
|
//
|
||||||
|
// Created by Trevor Beaton on 5/22/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct BleBannerView: View {
|
||||||
|
var deviceName: String
|
||||||
|
var disconnectAction: () -> Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
HStack {
|
||||||
|
Image("bluetoothLogo")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 16, height: 16)
|
||||||
|
|
||||||
|
Text(deviceName)
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 14))
|
||||||
|
|
||||||
|
Button(action: disconnectAction) {
|
||||||
|
Text("Disconnect")
|
||||||
|
.font(Font.custom("ReadexPro-Bold", size: 14))
|
||||||
|
.underline()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// .background(GeometryReader {
|
||||||
|
// Color.clear.preference(key: ViewHeightKey.self,
|
||||||
|
// value: $0.frame(in: .local).size.height)
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BleBannerView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
BleBannerView(deviceName: "Test", disconnectAction: {
|
||||||
|
print("Dismiss Action")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,8 +13,8 @@ class BleContentCommands: ObservableObject {
|
||||||
|
|
||||||
private weak var fileTransferClient: FileTransferClient?
|
private weak var fileTransferClient: FileTransferClient?
|
||||||
@Published var transmissionProgress: TransmissionProgress?
|
@Published var transmissionProgress: TransmissionProgress?
|
||||||
|
|
||||||
@Published var isTransmiting = false
|
@Published var isTransmiting = false
|
||||||
@Published var bootUpInfo = String()
|
|
||||||
@Published var counter = 0
|
@Published var counter = 0
|
||||||
|
|
||||||
enum ProjectViewError: LocalizedError {
|
enum ProjectViewError: LocalizedError {
|
||||||
|
|
@ -63,7 +63,6 @@ class BleContentCommands: ObservableObject {
|
||||||
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
||||||
|
|
||||||
|
|
||||||
@Published var activeAlert: ActiveAlert?
|
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
private let bleManager = BleManager.shared
|
private let bleManager = BleManager.shared
|
||||||
|
|
@ -103,9 +102,6 @@ class BleContentCommands: ObservableObject {
|
||||||
self.lastTransmit = TransmissionLog(type: .read(data: data))
|
self.lastTransmit = TransmissionLog(type: .read(data: data))
|
||||||
let str = String(decoding: data, as: UTF8.self)
|
let str = String(decoding: data, as: UTF8.self)
|
||||||
print("Read: \(str)")
|
print("Read: \(str)")
|
||||||
self.bootUpInfo = str
|
|
||||||
sharedBootinfo = str
|
|
||||||
|
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
self.lastTransmit = TransmissionLog(type: .error(message: error.localizedDescription))
|
self.lastTransmit = TransmissionLog(type: .error(message: error.localizedDescription))
|
||||||
|
|
@ -8,7 +8,24 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import FileTransferClient
|
import FileTransferClient
|
||||||
|
|
||||||
class BleContentTransfer: ObservableObject {
|
protocol BoardInfoDelegate: AnyObject {
|
||||||
|
func boardInfoDidUpdate(to newBoard: Board?)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ListCommandError: Error {
|
||||||
|
case belowMinimum
|
||||||
|
case isPrime
|
||||||
|
}
|
||||||
|
|
||||||
|
class BleContentTransfer: ObservableObject, BoardInfoDelegate {
|
||||||
|
|
||||||
|
@Published var currentBoard: Board? {
|
||||||
|
didSet {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static let shared = BleContentTransfer()
|
||||||
|
|
||||||
private weak var fileTransferClient: FileTransferClient?
|
private weak var fileTransferClient: FileTransferClient?
|
||||||
|
|
||||||
|
|
@ -22,7 +39,6 @@ class BleContentTransfer: ObservableObject {
|
||||||
|
|
||||||
@Published var downloadState: DownloadState = .idle
|
@Published var downloadState: DownloadState = .idle
|
||||||
|
|
||||||
@State var circuitPythonVersion = String()
|
|
||||||
|
|
||||||
@Published var isTransmiting = false
|
@Published var isTransmiting = false
|
||||||
|
|
||||||
|
|
@ -32,18 +48,13 @@ class BleContentTransfer: ObservableObject {
|
||||||
|
|
||||||
@Published var downloaderror = false
|
@Published var downloaderror = false
|
||||||
|
|
||||||
@Published var bootUpInfo = ""
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Published var contentCommands = BleContentCommands()
|
@Published var contentCommands = BleContentCommands()
|
||||||
// CLEAN UP
|
// CLEAN UP
|
||||||
var projectDirectories: [URL] = []
|
var projectDirectories: [URL] = []
|
||||||
var projectFiles: [URL] = []
|
var projectFiles: [URL] = []
|
||||||
var returnedArray = [[String]]()
|
|
||||||
var fileTransferArray : [URL] = []
|
|
||||||
|
|
||||||
var filesReadyForTransfer : [URL] = []
|
|
||||||
|
|
||||||
@Published var sendingBundle = false
|
@Published var sendingBundle = false
|
||||||
@Published var didCompleteTranfer = false
|
@Published var didCompleteTranfer = false
|
||||||
|
|
@ -58,10 +69,12 @@ class BleContentTransfer: ObservableObject {
|
||||||
@Published var isConnectedToInternet = false
|
@Published var isConnectedToInternet = false
|
||||||
@Published var showAlert = false
|
@Published var showAlert = false
|
||||||
|
|
||||||
var downloadPhases: String = ""
|
|
||||||
|
|
||||||
let directoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
let directoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||||
|
|
||||||
|
func boardInfoDidUpdate(to newBoard: Board?) {
|
||||||
|
self.currentBoard = newBoard
|
||||||
|
// Add any other logic you need to handle the new board here.
|
||||||
|
}
|
||||||
|
|
||||||
enum ProjectViewError: LocalizedError {
|
enum ProjectViewError: LocalizedError {
|
||||||
case fileTransferUndefined
|
case fileTransferUndefined
|
||||||
|
|
@ -77,25 +90,9 @@ class BleContentTransfer: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
getCPVersion()
|
|
||||||
registerNotification(enabled: true)
|
registerNotification(enabled: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCPVersion() {
|
|
||||||
if sharedBootinfo.contains("CircuitPython 7") {
|
|
||||||
print("circuitPythonVersion = 7")
|
|
||||||
circuitPythonVersion = "7"
|
|
||||||
print(circuitPythonVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sharedBootinfo.contains("CircuitPython 8") {
|
|
||||||
print("circuitPythonVersion = 8")
|
|
||||||
circuitPythonVersion = "8"
|
|
||||||
print(circuitPythonVersion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private weak var didCompleteZip: NSObjectProtocol?
|
private weak var didCompleteZip: NSObjectProtocol?
|
||||||
private weak var didEncounterTransferError: NSObjectProtocol?
|
private weak var didEncounterTransferError: NSObjectProtocol?
|
||||||
private weak var downloadErrorDidOccur: NSObjectProtocol?
|
private weak var downloadErrorDidOccur: NSObjectProtocol?
|
||||||
|
|
@ -311,13 +308,6 @@ class BleContentTransfer: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// filterCPVersion(incomingArray: regularFileUrls)
|
|
||||||
// filterCPFiles(filesArray: regularFileUrls)
|
|
||||||
|
|
||||||
|
|
||||||
// pathManipulation(arrayOfAny: filterCPVersion(incomingArray: projectDirectories), regularArray: filterCPVersion(incomingArray: projectFiles))
|
|
||||||
|
|
||||||
projectDirectories.removeFirst()
|
projectDirectories.removeFirst()
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
@ -336,57 +326,19 @@ class BleContentTransfer: ObservableObject {
|
||||||
|
|
||||||
|
|
||||||
func filterCPVersion(incomingArray: [URL]) -> [URL] {
|
func filterCPVersion(incomingArray: [URL]) -> [URL] {
|
||||||
print("project name \(projectName)")
|
|
||||||
|
|
||||||
|
let filteredList = incomingArray.filter {
|
||||||
for i in incomingArray {
|
let lastPathComponent = $0.lastPathComponent
|
||||||
print("incoming Array \(i.absoluteString)")
|
return lastPathComponent != "CircuitPython 8.x"
|
||||||
|
&& lastPathComponent != "CircuitPython 7.x"
|
||||||
|
&& lastPathComponent != "CircuitPython_Templates"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let listForCurrentCPVersion = filteredList.filter {
|
||||||
|
$0.absoluteString.contains("CircuitPython%20\(Board.shared.versionNumber).x")
|
||||||
let listWithoutCP8Folder = incomingArray.filter {
|
|
||||||
$0.lastPathComponent != ("CircuitPython 8.x")
|
|
||||||
}
|
|
||||||
|
|
||||||
let listWithoutCP7Folder = listWithoutCP8Folder.filter {
|
|
||||||
$0.lastPathComponent != ("CircuitPython 7.x")
|
|
||||||
}
|
|
||||||
|
|
||||||
//CircuitPython_Templates
|
|
||||||
|
|
||||||
let removedCPTemplates = listWithoutCP7Folder.filter {
|
|
||||||
$0.lastPathComponent != ("CircuitPython_Templates")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if sharedBootinfo.contains("CircuitPython 8") {
|
|
||||||
let listForCurrentCPVersion = removedCPTemplates.filter {
|
|
||||||
!$0.absoluteString.contains("CircuitPython%207.x")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in listForCurrentCPVersion {
|
|
||||||
print("listForCurrentCPVersion :- \(i.absoluteString)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return listForCurrentCPVersion
|
return listForCurrentCPVersion
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if sharedBootinfo.contains("CircuitPython 7") {
|
|
||||||
|
|
||||||
let listForCurrentCPVersion = listWithoutCP7Folder.filter {
|
|
||||||
!$0.absoluteString.contains("CircuitPython%208.x")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in listForCurrentCPVersion {
|
|
||||||
print("listForCurrentCPVersion :- \(i.absoluteString)")
|
|
||||||
}
|
|
||||||
return listForCurrentCPVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
return listWithoutCP7Folder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -394,12 +346,8 @@ class BleContentTransfer: ObservableObject {
|
||||||
print("\(#function) @Line: \(#line)")
|
print("\(#function) @Line: \(#line)")
|
||||||
var recursiveArray = directoryArray
|
var recursiveArray = directoryArray
|
||||||
|
|
||||||
for i in recursiveArray {
|
|
||||||
print("recursiveArray \(i.absoluteString)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if directoryArray.isEmpty {
|
if directoryArray.isEmpty {
|
||||||
print("Array is empty. makeDirectory is done - Ready for file transfer!")
|
|
||||||
newTransfer(listOf: regularFilesArray)
|
newTransfer(listOf: regularFilesArray)
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -490,10 +438,7 @@ class BleContentTransfer: ObservableObject {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ListCommandError: Error {
|
|
||||||
case belowMinimum
|
|
||||||
case isPrime
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkIfFilesExistOnBoard(url: URL) {
|
func checkIfFilesExistOnBoard(url: URL) {
|
||||||
|
|
||||||
|
|
@ -527,29 +472,16 @@ class BleContentTransfer: ObservableObject {
|
||||||
var tempPathComponents = url.pathComponents
|
var tempPathComponents = url.pathComponents
|
||||||
print("Incoming URL for makeFileString: \(url.absoluteString)")
|
print("Incoming URL for makeFileString: \(url.absoluteString)")
|
||||||
|
|
||||||
|
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython \(Board.shared.versionNumber).x")!
|
||||||
if sharedBootinfo.contains("CircuitPython 7") {
|
|
||||||
|
|
||||||
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython 7.x")!
|
|
||||||
tempPathComponents.removeSubrange(0...indexOfCP)
|
|
||||||
tempPathComponents.removeLast()
|
|
||||||
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
print("Outgoing makeFileString: \(joinedArrayPath) for CP 7")
|
|
||||||
return joinedArrayPath
|
|
||||||
}
|
|
||||||
|
|
||||||
if sharedBootinfo.contains("CircuitPython 8") {
|
|
||||||
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython 8.x")!
|
|
||||||
tempPathComponents.removeSubrange(0...indexOfCP)
|
tempPathComponents.removeSubrange(0...indexOfCP)
|
||||||
tempPathComponents.removeLast()
|
tempPathComponents.removeLast()
|
||||||
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
||||||
print("\(#function) @Line: \(#line)")
|
print("\(#function) @Line: \(#line)")
|
||||||
print("Outgoing makeFileString: \(joinedArrayPath) for CP 8")
|
print("Outgoing makeFileString: \(joinedArrayPath) for CP 8")
|
||||||
return joinedArrayPath
|
return joinedArrayPath
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -561,256 +493,81 @@ class BleContentTransfer: ObservableObject {
|
||||||
|
|
||||||
print("Incoming URL: \(url.absoluteString) ")
|
print("Incoming URL: \(url.absoluteString) ")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if sharedBootinfo.contains("CircuitPython 7") {
|
|
||||||
print(tempPathComponents)
|
print(tempPathComponents)
|
||||||
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython 7.x")!
|
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython \(Board.shared.versionNumber).x")!
|
||||||
|
|
||||||
|
|
||||||
tempPathComponents.removeSubrange(0...indexOfCP)
|
tempPathComponents.removeSubrange(0...indexOfCP)
|
||||||
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
||||||
print("\(#function) @Line: \(#line)")
|
print("\(#function) @Line: \(#line)")
|
||||||
print("Outgoing String: \(joinedArrayPath) for CP 7")
|
print("Outgoing Directory String: \(joinedArrayPath) for CP \(Board.shared.versionNumber)")
|
||||||
return joinedArrayPath
|
return joinedArrayPath
|
||||||
}
|
|
||||||
|
|
||||||
if sharedBootinfo.contains("CircuitPython 8") {
|
|
||||||
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython 8.x")!
|
|
||||||
tempPathComponents.removeSubrange(0...indexOfCP)
|
|
||||||
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
print("Outgoing String: \(joinedArrayPath) for CP 8")
|
|
||||||
return joinedArrayPath
|
|
||||||
} else {
|
|
||||||
|
|
||||||
guard let projectName = projectName else {
|
|
||||||
return "Unknown"
|
|
||||||
}
|
|
||||||
|
|
||||||
indexOfCP = tempPathComponents.firstIndex(of: projectName)!
|
|
||||||
tempPathComponents.removeSubrange(0...indexOfCP)
|
|
||||||
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
print("Outgoing String: \(joinedArrayPath) for CP 7")
|
|
||||||
return joinedArrayPath
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func newTransfer(listOf urls: [URL]) {
|
func newTransfer(listOf urls: [URL]) {
|
||||||
print("\(#function) @Line: \(#line)")
|
guard !urls.isEmpty else {
|
||||||
var copiedFiles = urls
|
|
||||||
print("Files left for transfer: \(urls.count)")
|
|
||||||
|
|
||||||
print("Attempting to transfer... \(urls.first?.lastPathComponent ?? "No file found")")
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.counter += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if copiedFiles.isEmpty {
|
|
||||||
print("All Files Transferred! 👍")
|
print("All Files Transferred! 👍")
|
||||||
self.completedTransfer()
|
completedTransfer()
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2){
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2){
|
||||||
self.sendingBundle = false
|
self.resetTransferParameters()
|
||||||
self.completedTransfer()
|
}
|
||||||
self.numOfFiles = 0
|
return
|
||||||
self.counter = 0
|
|
||||||
self.contentList.removeAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
print("\(#function) @Line: \(#line)")
|
||||||
|
print("Files left for transfer: \(urls.count)")
|
||||||
|
print("Attempting to transfer... \(urls.first?.lastPathComponent ?? "No file found")")
|
||||||
|
DispatchQueue.main.async { self.counter += 1 }
|
||||||
|
|
||||||
guard let data = try? Data(contentsOf: URL(string: copiedFiles.first!.absoluteString)!) else {
|
guard let url = urls.first,
|
||||||
|
let data = try? Data(contentsOf: url) else {
|
||||||
print("File not found")
|
print("File not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let path = isDirectFile(name: url.lastPathComponent) ? url.lastPathComponent : makeDirectoryString(url: url)
|
||||||
|
|
||||||
if copiedFiles.first?.lastPathComponent == "code.py" || copiedFiles.first?.lastPathComponent == "README.txt" {
|
contentCommands.writeFileCommand(path: path, data: data) { result in
|
||||||
|
|
||||||
print("Input for writeFileCommand: \(copiedFiles.first?.absoluteString)")
|
|
||||||
|
|
||||||
|
|
||||||
self.contentCommands.writeFileCommand(path: copiedFiles.first!.lastPathComponent, data: data) { result in
|
|
||||||
switch result {
|
switch result {
|
||||||
|
case .success:
|
||||||
case .success(_):
|
|
||||||
print("Success ✅")
|
print("Success ✅")
|
||||||
copiedFiles.removeFirst()
|
self.newTransfer(listOf: Array(urls.dropFirst()))
|
||||||
self.newTransfer(listOf: copiedFiles)
|
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
print("Transfer Failure \(error)")
|
||||||
|
self.handleTransferError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleTransferError(_ error: Error) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
print("\(#function) @Line: \(#line)")
|
print("\(#function) @Line: \(#line)")
|
||||||
print(error)
|
print(error)
|
||||||
DispatchQueue.main.async {
|
|
||||||
print("Transfer Failure \(error)")
|
|
||||||
self.downloadState = .failed
|
self.downloadState = .failed
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
self.downloadState = .idle
|
self.downloadState = .idle
|
||||||
}
|
}
|
||||||
NotificationCenter.default.post(name: .didEncounterTransferError, object: nil, userInfo: nil)
|
NotificationCenter.default.post(name: .didEncounterTransferError, object: nil, userInfo: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
print("Checking... 🫥")
|
private func resetTransferParameters() {
|
||||||
// print("makeDirectoryString transfer \(makeDirectoryString(url: copiedFiles.first!))")
|
sendingBundle = false
|
||||||
|
completedTransfer()
|
||||||
let directoryPath = makeDirectoryString(url: copiedFiles.first!)
|
numOfFiles = 0
|
||||||
|
counter = 0
|
||||||
print("Input writeFileCommand: \(directoryPath)")
|
contentList.removeAll()
|
||||||
self.contentCommands.writeFileCommand(path: directoryPath, data: data) { result in
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(_):
|
|
||||||
print("Success ✅")
|
|
||||||
copiedFiles.removeFirst()
|
|
||||||
self.newTransfer(listOf: copiedFiles)
|
|
||||||
|
|
||||||
case .failure(let error):
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
print(error)
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
print("Transfer Failure \(error)")
|
|
||||||
self.downloadState = .failed
|
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
||||||
self.downloadState = .idle
|
|
||||||
}
|
|
||||||
NotificationCenter.default.post(name: .didEncounterTransferError, object: nil, userInfo: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func isDirectFile(name: String) -> Bool {
|
||||||
|
return name == "code.py" || name == "README.txt"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func filePathMod(listOf files: [URL]) {
|
|
||||||
var indexOfCP = 0
|
|
||||||
|
|
||||||
for i in files {
|
|
||||||
print("-\(i.absoluteString)-\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
var tempArray = files
|
|
||||||
|
|
||||||
if files.isEmpty {
|
|
||||||
// Continue
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
print("Done!")
|
|
||||||
// print("RETURNED PATHS: \(returnedArray)\n")
|
|
||||||
|
|
||||||
for i in filesReadyForTransfer {
|
|
||||||
print("\(i)")
|
|
||||||
}
|
|
||||||
|
|
||||||
// self.transferFiles(files: fileArray)
|
|
||||||
|
|
||||||
// validateDirectory(directoryArray: returnedArray, fileArray: fileArray)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
var tempPath = files[0].pathComponents
|
|
||||||
|
|
||||||
print("temp path \(tempPath)")
|
|
||||||
|
|
||||||
if tempPath.contains("CircuitPython 7.x") {
|
|
||||||
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
|
|
||||||
indexOfCP = tempPath.firstIndex(of: "CircuitPython 7.x")!
|
|
||||||
|
|
||||||
tempPath.removeSubrange(0...indexOfCP)
|
|
||||||
|
|
||||||
print("removeSubrange temp path - \(tempPath)")
|
|
||||||
|
|
||||||
|
|
||||||
tempArray.removeFirst()
|
|
||||||
|
|
||||||
var joinedArrayPath = tempPath.joined(separator: "/")
|
|
||||||
|
|
||||||
|
|
||||||
filesReadyForTransfer.append(URL(string: joinedArrayPath)!)
|
|
||||||
|
|
||||||
filePathMod(listOf: tempArray)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if tempPath.contains("CircuitPython 8.x") {
|
|
||||||
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
|
|
||||||
indexOfCP = tempPath.firstIndex(of: "CircuitPython 8.x")!
|
|
||||||
|
|
||||||
tempPath.removeSubrange(0...indexOfCP)
|
|
||||||
|
|
||||||
print("removeSubrange temp path - \(tempPath)")
|
|
||||||
|
|
||||||
|
|
||||||
tempArray.removeFirst()
|
|
||||||
|
|
||||||
var joinedArrayPath = tempPath.joined(separator: "/")
|
|
||||||
|
|
||||||
filesReadyForTransfer.append(URL(string: joinedArrayPath)!)
|
|
||||||
|
|
||||||
filePathMod(listOf: tempArray)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if tempPath.contains(projectName ?? "unknown") {
|
|
||||||
|
|
||||||
print("\(#function) @Line: \(#line)")
|
|
||||||
|
|
||||||
indexOfCP = tempPath.firstIndex(of: projectName!)!
|
|
||||||
|
|
||||||
tempPath.removeSubrange(0...indexOfCP+1)
|
|
||||||
|
|
||||||
print("removeSubrange temp path - \(tempPath)")
|
|
||||||
|
|
||||||
tempArray.removeFirst()
|
|
||||||
|
|
||||||
var joinedArrayPath = tempPath.joined(separator: "/")
|
|
||||||
|
|
||||||
filesReadyForTransfer.append(URL(string: joinedArrayPath)!)
|
|
||||||
|
|
||||||
filePathMod(listOf: tempArray)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func completedTransfer() {
|
func completedTransfer() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.downloadState = .complete
|
self.downloadState = .complete
|
||||||
self.didCompleteTranfer = true
|
self.didCompleteTranfer = true
|
||||||
|
|
@ -825,185 +582,6 @@ class BleContentTransfer: ObservableObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func transferFiles(files: [URL]) {
|
|
||||||
print(#function)
|
|
||||||
var copiedFiles = files
|
|
||||||
print("Number of files in filesArray \(files.count)")
|
|
||||||
print(files)
|
|
||||||
|
|
||||||
if files.isEmpty {
|
|
||||||
print("Array of contents empty - Check other directories")
|
|
||||||
self.completedTransfer()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2){
|
|
||||||
self.sendingBundle = false
|
|
||||||
self.completedTransfer()
|
|
||||||
self.numOfFiles = 0
|
|
||||||
self.contentList.removeAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
guard let selectedUrl = files.first else {
|
|
||||||
print("No such file exist here")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let data = try? Data(contentsOf: URL(fileURLWithPath: selectedUrl.deletingPathExtension().lastPathComponent, relativeTo: selectedUrl).appendingPathExtension(selectedUrl.pathExtension)) else {
|
|
||||||
print("File not found")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if selectedUrl.deletingLastPathComponent().lastPathComponent == "CircuitPython 7.x"{
|
|
||||||
|
|
||||||
print("Selected Path: \(selectedUrl.path)")
|
|
||||||
|
|
||||||
var tempURL = selectedUrl.pathComponents
|
|
||||||
|
|
||||||
tempURL.removeFirst(12)
|
|
||||||
let joined = tempURL.joined(separator: "/")
|
|
||||||
|
|
||||||
|
|
||||||
var newModPath = tempURL
|
|
||||||
newModPath.removeLast()
|
|
||||||
print("Test file path: \(tempURL)")
|
|
||||||
|
|
||||||
print("File transfer modified path xx: \(joined)")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.contentCommands.writeFileCommand(path: joined, data: data) { result in
|
|
||||||
switch result {
|
|
||||||
|
|
||||||
case .success(_):
|
|
||||||
copiedFiles.removeFirst()
|
|
||||||
self.transferFiles(files: copiedFiles)
|
|
||||||
|
|
||||||
case .failure(_):
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
|
|
||||||
print("Transfer Failure")
|
|
||||||
print("\(joined)")
|
|
||||||
self.downloadState = .failed
|
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
||||||
self.downloadState = .idle
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationCenter.default.post(name: .didEncounterTransferError, object: nil, userInfo: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else if selectedUrl.deletingLastPathComponent().lastPathComponent == "lib" {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var tempURL = selectedUrl.pathComponents
|
|
||||||
tempURL.removeFirst(12)
|
|
||||||
let joined = tempURL.joined(separator: "/")
|
|
||||||
print("File transfer modified path 11:\(joined)")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("Updated Path:\(joined)")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
contentCommands.writeFileCommand(path: joined, data: data) { result in
|
|
||||||
switch result {
|
|
||||||
case .success(_):
|
|
||||||
copiedFiles.removeFirst()
|
|
||||||
self.transferFiles(files: copiedFiles)
|
|
||||||
|
|
||||||
case .failure(_):
|
|
||||||
print("Transfer Failure - 2")
|
|
||||||
self.downloadState = .failed
|
|
||||||
NotificationCenter.default.post(name: .didEncounterTransferError, object: nil, userInfo: nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if selectedUrl.lastPathComponent == "README.txt" {
|
|
||||||
print("Got one")
|
|
||||||
copiedFiles.removeFirst()
|
|
||||||
self.transferFiles(files: copiedFiles)
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
var tempURL = selectedUrl.pathComponents
|
|
||||||
|
|
||||||
tempURL.removeFirst(12)
|
|
||||||
let joined = tempURL.joined(separator: "/")
|
|
||||||
print("File transfer modified path: \(joined)")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("Updated Path:\(joined)")
|
|
||||||
|
|
||||||
|
|
||||||
contentCommands.writeFileCommand(path: joined, data: data) { result in
|
|
||||||
switch result {
|
|
||||||
case .success(_):
|
|
||||||
copiedFiles.removeFirst()
|
|
||||||
self.transferFiles(files: copiedFiles)
|
|
||||||
case .failure(let error):
|
|
||||||
print("Failed: \(error): \(result)")
|
|
||||||
NotificationCenter.default.post(name: .didEncounterTransferError, object: nil, userInfo: nil)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.sendingBundle = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func readMyStatus() {
|
|
||||||
///model.readFile(filename: "boot_out.txt")
|
|
||||||
print(#function)
|
|
||||||
|
|
||||||
print("BOOT INFO: \(bootUpInfo)")
|
|
||||||
|
|
||||||
switch bootUpInfo.description {
|
|
||||||
|
|
||||||
case let str where str.contains("CircuitPython 7"):
|
|
||||||
print("CircuitPython 7")
|
|
||||||
circuitPythonVersion = "CircuitPython 7"
|
|
||||||
|
|
||||||
case let str where str.contains("CircuitPython 8"):
|
|
||||||
print("CircuitPython 8")
|
|
||||||
circuitPythonVersion = "CircuitPython 8"
|
|
||||||
default:
|
|
||||||
print("Unknown Device")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: System
|
// MARK: System
|
||||||
|
|
||||||
struct TransmissionProgress {
|
struct TransmissionProgress {
|
||||||
|
|
@ -1047,7 +625,6 @@ class BleContentTransfer: ObservableObject {
|
||||||
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
||||||
|
|
||||||
|
|
||||||
@Published var activeAlert: ActiveAlert?
|
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
private let bleManager = BleManager.shared
|
private let bleManager = BleManager.shared
|
||||||
|
|
@ -1088,8 +665,7 @@ class BleContentTransfer: ObservableObject {
|
||||||
let str = String(decoding: data, as: UTF8.self)
|
let str = String(decoding: data, as: UTF8.self)
|
||||||
print("\(#function) @Line: \(#line)")
|
print("\(#function) @Line: \(#line)")
|
||||||
print("Read: \(str)")
|
print("Read: \(str)")
|
||||||
//self.readMyStatus()
|
|
||||||
self.bootUpInfo = str
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,28 +12,36 @@ class ExpandedBLECellState: ObservableObject {
|
||||||
@Published var currentCell = ""
|
@Published var currentCell = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Board: Equatable {
|
||||||
|
|
||||||
|
static func == (lhs: Board, rhs: Board) -> Bool {
|
||||||
|
return lhs.name == rhs.name && lhs.versionNumber == rhs.versionNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
static let shared = Board(name: "Unrecognized Board", versionNumber: "8")
|
||||||
|
|
||||||
|
var name: String
|
||||||
|
var versionNumber: String
|
||||||
|
|
||||||
|
private init(name: String, versionNumber: String) {
|
||||||
|
self.name = name
|
||||||
|
self.versionNumber = versionNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct BleModuleView: View {
|
struct BleModuleView: View {
|
||||||
|
|
||||||
// Data
|
@State var boardInfoForView: Board?
|
||||||
enum ActiveAlert: Identifiable {
|
|
||||||
case confirmUnpair(blePeripheral: BlePeripheral)
|
|
||||||
|
|
||||||
var id: Int {
|
|
||||||
switch self {
|
|
||||||
case .confirmUnpair: return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Environment(\.presentationMode) var presentationMode
|
@Environment(\.presentationMode) var presentationMode
|
||||||
@EnvironmentObject var expandedState : ExpandedBLECellState
|
@EnvironmentObject var expandedState : ExpandedBLECellState
|
||||||
@ObservedObject var connectionManager = FileTransferConnectionManager.shared
|
@ObservedObject var connectionManager = FileTransferConnectionManager.shared
|
||||||
|
|
||||||
|
@State var unknownBoardName: String?
|
||||||
|
|
||||||
let selectedPeripheral = FileTransferConnectionManager.shared.selectedPeripheral
|
let selectedPeripheral = FileTransferConnectionManager.shared.selectedPeripheral
|
||||||
|
|
||||||
@StateObject var viewModel = BleModuleViewModel()
|
@StateObject var vm = BleModuleViewModel()
|
||||||
@EnvironmentObject var rootViewModel: RootViewModel
|
@EnvironmentObject var rootViewModel: RootViewModel
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -44,7 +52,6 @@ struct BleModuleView: View {
|
||||||
@State var isExpanded = true
|
@State var isExpanded = true
|
||||||
|
|
||||||
@State private var scrollViewID = UUID()
|
@State private var scrollViewID = UUID()
|
||||||
@State private var activeAlert: ActiveAlert?
|
|
||||||
@State private var boardBootInfo = ""
|
@State private var boardBootInfo = ""
|
||||||
@State private var inConnectedInSelectionView = true
|
@State private var inConnectedInSelectionView = true
|
||||||
|
|
||||||
|
|
@ -118,12 +125,7 @@ struct BleModuleView: View {
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else if boardBootInfo == "clue_nrf52840_express" {
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if boardBootInfo == "clue_nrf52840_express" {
|
|
||||||
Image("clue")
|
Image("clue")
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
|
|
@ -138,6 +140,20 @@ struct BleModuleView: View {
|
||||||
.lineLimit(2)
|
.lineLimit(2)
|
||||||
.padding(.horizontal, 20)
|
.padding(.horizontal, 20)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Image("Placeholder Board Image")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(width: 200, height: 200)
|
||||||
|
.padding(.horizontal, 60)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
|
||||||
|
Text(unknownBoardName ?? "")
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 30))
|
||||||
|
.minimumScaleFactor(0.01)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.lineLimit(2)
|
||||||
|
.padding(.horizontal, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -173,86 +189,11 @@ struct BleModuleView: View {
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
|
|
||||||
|
BleBannerView(deviceName: boardInfoForView?.name ?? "Unknown Device", disconnectAction: {
|
||||||
|
|
||||||
if boardBootInfo == "circuitplayground_bluefruit" {
|
|
||||||
HStack {
|
|
||||||
|
|
||||||
Image("bluetoothLogo")
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
.frame(width: 16, height: 16)
|
|
||||||
|
|
||||||
|
|
||||||
Text("Circuit Playground Bluefruit.")
|
|
||||||
.font(Font.custom("ReadexPro-Regular", size: 14))
|
|
||||||
.minimumScaleFactor(0.1)
|
|
||||||
|
|
||||||
|
|
||||||
Button {
|
|
||||||
showConfirmationPrompt()
|
showConfirmationPrompt()
|
||||||
} label: {
|
|
||||||
Text("Disconnect")
|
|
||||||
.font(Font.custom("ReadexPro-Bold", size: 14))
|
|
||||||
.underline()
|
|
||||||
.minimumScaleFactor(0.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if boardBootInfo == "clue_nrf52840_express" {
|
|
||||||
VStack {
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Image("bluetoothLogo")
|
|
||||||
.resizable()
|
|
||||||
.scaledToFit()
|
|
||||||
.frame(width: 16, height: 16)
|
|
||||||
|
|
||||||
Text("Adafruit CLUE.")
|
|
||||||
.font(Font.custom("ReadexPro-Regular", size: 14))
|
|
||||||
|
|
||||||
Button {
|
|
||||||
showConfirmationPrompt()
|
|
||||||
|
|
||||||
|
|
||||||
} label: {
|
|
||||||
Text("Disconnect")
|
|
||||||
.font(Font.custom("ReadexPro-Bold", size: 14))
|
|
||||||
.underline()
|
|
||||||
//.minimumScaleFactor(0.1)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// Expandable
|
|
||||||
VStack {
|
|
||||||
Text("More Info")
|
|
||||||
}
|
|
||||||
.background(GeometryReader {
|
|
||||||
Color.clear.preference(key: ViewHeightKey.self,
|
|
||||||
value: $0.frame(in: .local).size.height)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.onPreferenceChange(ViewHeightKey.self) { subviewHeight = $0 }
|
|
||||||
.frame(height: isExpanded ? subviewHeight : 50, alignment: .top)
|
|
||||||
|
|
||||||
.clipped()
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.transition(.move(edge: .bottom))
|
|
||||||
|
|
||||||
|
|
||||||
.onTapGesture {
|
|
||||||
withAnimation(.easeIn(duration: 0.5)) {
|
|
||||||
isExpanded.toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.padding(.all, 0.0)
|
.padding(.all, 0.0)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
|
|
@ -270,14 +211,32 @@ struct BleModuleView: View {
|
||||||
MainSubHeaderView(device: "Adafruit CLUE")
|
MainSubHeaderView(device: "Adafruit CLUE")
|
||||||
}
|
}
|
||||||
|
|
||||||
if boardBootInfo == "circuitplayground_bluefruit" {
|
else if boardInfoForView?.name == "Circuitplayground Bluefruit" {
|
||||||
MainSubHeaderView(device: "Circuit Playground")
|
MainSubHeaderView(device: "Circuit Playground")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
MainSubHeaderView(device: unknownBoardName ?? "device")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let check = vm.pdemos.filter {
|
||||||
|
|
||||||
|
if boardInfoForView?.name == "Circuitplayground Bluefruit" {
|
||||||
|
let cpbProjects = $0.compatibility.contains("circuitplayground_bluefruit")
|
||||||
|
print("Returned \(cpbProjects) for circuitplayground_bluefruit")
|
||||||
|
return cpbProjects
|
||||||
|
}
|
||||||
|
|
||||||
|
else if boardInfoForView?.name == "Clue Nrf52840 Express" {
|
||||||
|
let clueProjects = $0.compatibility.contains("clue_nrf52840_express")
|
||||||
|
return clueProjects
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
let check = viewModel.pdemos.filter {
|
|
||||||
$0.compatibility.contains(boardBootInfo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -311,6 +270,9 @@ struct BleModuleView: View {
|
||||||
.id(self.scrollViewID)
|
.id(self.scrollViewID)
|
||||||
}
|
}
|
||||||
.environmentObject(expandedState)
|
.environmentObject(expandedState)
|
||||||
|
.refreshable {
|
||||||
|
vm.fetchAndLoadProjectsFromStorage()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -318,49 +280,36 @@ struct BleModuleView: View {
|
||||||
.background(Color.white)
|
.background(Color.white)
|
||||||
|
|
||||||
|
|
||||||
.onChange(of: viewModel.bootUpInfo, perform: { newValue in
|
.onChange(of: vm.bootUpInfo, perform: { newValue in
|
||||||
viewModel.readMyStatus()
|
vm.readMyStatus()
|
||||||
|
|
||||||
print("newValue \(newValue)")
|
print("newValue \(newValue)")
|
||||||
boardBootInfo = newValue
|
boardBootInfo = newValue
|
||||||
})
|
})
|
||||||
|
|
||||||
.onChange(of: connectionManager.selectedClient) { selectedClient in
|
.onChange(of: connectionManager.selectedClient) { selectedClient in
|
||||||
viewModel.setup(fileTransferClient: selectedClient)
|
vm.setup(fileTransferClient: selectedClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
.onAppear(){
|
.onChange(of: vm.connectedBoard, perform: { newValue in
|
||||||
print("Opened BleModuleView")
|
dump(newValue)
|
||||||
// networkServiceModel.fetch()
|
boardInfoForView = newValue
|
||||||
|
unknownBoardName = newValue?.name
|
||||||
|
})
|
||||||
|
|
||||||
viewModel.setup(fileTransferClient:connectionManager.selectedClient)
|
.onAppear(){
|
||||||
|
|
||||||
|
|
||||||
|
vm.setup(fileTransferClient:connectionManager.selectedClient)
|
||||||
|
|
||||||
connectionManager.isSelectedPeripheralReconnecting = true
|
connectionManager.isSelectedPeripheralReconnecting = true
|
||||||
|
|
||||||
viewModel.readFile(filename: "boot_out.txt")
|
vm.readFile(filename: "boot_out.txt")
|
||||||
}
|
|
||||||
|
print("x\(boardBootInfo)")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Alerts: ViewModifier {
|
|
||||||
@Binding var activeAlert: ActiveAlert?
|
|
||||||
|
|
||||||
func body(content: Content) -> some View {
|
|
||||||
content
|
|
||||||
.alert(item: $activeAlert, content: { alert in
|
|
||||||
switch alert {
|
|
||||||
case .confirmUnpair(let blePeripheral):
|
|
||||||
return Alert(
|
|
||||||
title: Text("Confirm disconnect \(blePeripheral.name ?? "")"),
|
|
||||||
message: nil,
|
|
||||||
primaryButton: .destructive(Text("Disconnect")) {
|
|
||||||
//BleAutoReconnect.clearAutoconnectPeripheral()
|
|
||||||
BleManager.shared.disconnect(from: blePeripheral)
|
|
||||||
},
|
|
||||||
secondaryButton: .cancel(Text("Cancel")) {})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -11,19 +11,46 @@ import FileTransferClient
|
||||||
|
|
||||||
class BleModuleViewModel: ObservableObject {
|
class BleModuleViewModel: ObservableObject {
|
||||||
|
|
||||||
|
weak var delegate: BoardInfoDelegate?
|
||||||
|
|
||||||
|
@Published var boardInfoForView: Board? {
|
||||||
|
didSet {
|
||||||
|
print("Changed")
|
||||||
|
delegate?.boardInfoDidUpdate(to: boardInfoForView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private weak var fileTransferClient: FileTransferClient?
|
private weak var fileTransferClient: FileTransferClient?
|
||||||
@StateObject var contentTransfer = BleContentTransfer()
|
@State var contentTransfer = BleContentTransfer()
|
||||||
|
|
||||||
@Published var entries = [BlePeripheral.DirectoryEntry]()
|
@Published var entries = [BlePeripheral.DirectoryEntry]()
|
||||||
@Published var isTransmiting = false
|
@Published var isTransmiting = false
|
||||||
@Published var bootUpInfo = ""
|
@Published var bootUpInfo = ""
|
||||||
|
|
||||||
let dataStore = DataStore()
|
|
||||||
|
|
||||||
@Published var pdemos : [ResultItem] = []
|
var boardDataProvider = BoardDataProvider()
|
||||||
|
var connectedBoard: Board?
|
||||||
|
|
||||||
|
let dataStore = DataStore()
|
||||||
|
@ObservedObject var networkModel = NetworkService()
|
||||||
|
|
||||||
|
|
||||||
|
@Published var pdemos : [PyProject] = []
|
||||||
|
|
||||||
|
func loadProjectsFromStorage() {
|
||||||
|
self.pdemos = self.dataStore.loadDefaultList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchAndLoadProjectsFromStorage() {
|
||||||
|
self.networkModel.fetch {
|
||||||
|
self.pdemos = self.dataStore.loadDefaultList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
pdemos = dataStore.loadDefaultList()
|
loadProjectsFromStorage()
|
||||||
|
self.delegate = contentTransfer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -71,7 +98,6 @@ class BleModuleViewModel: ObservableObject {
|
||||||
|
|
||||||
@Published var transmissionProgress: TransmissionProgress?
|
@Published var transmissionProgress: TransmissionProgress?
|
||||||
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
||||||
@Published var activeAlert: ActiveAlert?
|
|
||||||
// Data
|
// Data
|
||||||
private let bleManager = BleManager.shared
|
private let bleManager = BleManager.shared
|
||||||
|
|
||||||
|
|
@ -121,6 +147,28 @@ class BleModuleViewModel: ObservableObject {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func setupBoardInfoForDisplay(_ boardInfo: String?) -> Board {
|
||||||
|
// First, safely unwrap the optional 'boardInfo' string
|
||||||
|
guard let info = boardInfo else {
|
||||||
|
print("boardInfo is nil")
|
||||||
|
return Board.shared
|
||||||
|
}
|
||||||
|
|
||||||
|
let boardID = boardDataProvider.getBoardID(from: info) ?? "Unrecognized Board"
|
||||||
|
// Board default version is set to 8
|
||||||
|
let boardVersion = boardDataProvider.getCircuitPythonMajorVersion(from: info) ?? "8"
|
||||||
|
|
||||||
|
Board.shared.name = boardID
|
||||||
|
Board.shared.versionNumber = boardVersion
|
||||||
|
|
||||||
|
// Create a new Board object with the acquired name and version
|
||||||
|
let board = Board.shared
|
||||||
|
|
||||||
|
return board
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Actions
|
// MARK: - Actions
|
||||||
|
|
||||||
func readFile(filename: String) {
|
func readFile(filename: String) {
|
||||||
|
|
@ -135,8 +183,10 @@ class BleModuleViewModel: ObservableObject {
|
||||||
let str = String(decoding: data, as: UTF8.self)
|
let str = String(decoding: data, as: UTF8.self)
|
||||||
|
|
||||||
print("Read: \(str)")
|
print("Read: \(str)")
|
||||||
self.bootUpInfo = str
|
|
||||||
sharedBootinfo = str
|
self.connectedBoard = self.setupBoardInfoForDisplay(str)
|
||||||
|
self.boardInfoForView = self.connectedBoard
|
||||||
|
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
self.lastTransmit = TransmissionLog(type: .error(message: error.localizedDescription))
|
self.lastTransmit = TransmissionLog(type: .error(message: error.localizedDescription))
|
||||||
|
|
@ -344,18 +394,4 @@ class BleModuleViewModel: ObservableObject {
|
||||||
completion?(result)
|
completion?(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public var sharedBootinfo = ""
|
|
||||||
|
|
||||||
enum ActiveAlert: Identifiable {
|
|
||||||
case error(error: Error)
|
|
||||||
|
|
||||||
var id: Int {
|
|
||||||
switch self {
|
|
||||||
case .error: return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -10,13 +10,13 @@ import FileTransferClient
|
||||||
|
|
||||||
struct DemoSubview: View {
|
struct DemoSubview: View {
|
||||||
|
|
||||||
@Binding var bindingString: String
|
let result: PyProject
|
||||||
|
|
||||||
let result: ResultItem
|
|
||||||
|
|
||||||
@EnvironmentObject var rootViewModel: RootViewModel
|
@EnvironmentObject var rootViewModel: RootViewModel
|
||||||
@StateObject var viewModel = SubCellViewModel()
|
@StateObject var viewModel = SubCellViewModel()
|
||||||
@StateObject var contentTransfer = BleContentTransfer()
|
//@StateObject var contentTransfer = BleContentTransfer()
|
||||||
|
@StateObject var contentTransfer = BleContentTransfer.shared
|
||||||
|
|
||||||
|
|
||||||
@ObservedObject var connectionManager = FileTransferConnectionManager.shared
|
@ObservedObject var connectionManager = FileTransferConnectionManager.shared
|
||||||
|
|
||||||
|
|
@ -150,15 +150,6 @@ Try again later
|
||||||
|
|
||||||
if isConnected {
|
if isConnected {
|
||||||
|
|
||||||
if result.compatibility.contains(bindingString) {
|
|
||||||
|
|
||||||
// Button {
|
|
||||||
// viewModel.deleteStoredFilesInFM()
|
|
||||||
// } label: {
|
|
||||||
// Text("Delete File Manager Contents")
|
|
||||||
// .bold()
|
|
||||||
// .padding(12)
|
|
||||||
// }
|
|
||||||
|
|
||||||
if contentTransfer.downloadState == .idle {
|
if contentTransfer.downloadState == .idle {
|
||||||
|
|
||||||
|
|
@ -210,7 +201,7 @@ Try again later
|
||||||
CompleteButton()
|
CompleteButton()
|
||||||
.padding(.top, 20)
|
.padding(.top, 20)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -231,8 +222,6 @@ Try again later
|
||||||
|
|
||||||
print("On Appear")
|
print("On Appear")
|
||||||
contentTransfer.contentCommands.setup(fileTransferClient: connectionManager.selectedClient)
|
contentTransfer.contentCommands.setup(fileTransferClient: connectionManager.selectedClient)
|
||||||
|
|
||||||
// viewModel.readFile(filename: "boot_out.txt")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.onChange(of: contentTransfer.transferError, perform: { newValue in
|
.onChange(of: contentTransfer.transferError, perform: { newValue in
|
||||||
|
|
@ -247,14 +236,8 @@ Try again later
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// .onChange(of: connectionManager.selectedClient) { selectedClient in
|
|
||||||
// viewModel.setup(fileTransferClient: selectedClient)
|
|
||||||
// }
|
|
||||||
|
|
||||||
.onAppear(perform: {
|
.onAppear(perform: {
|
||||||
|
|
||||||
contentTransfer.readMyStatus()
|
|
||||||
viewModel.searchPathForProject(nameOf: result.projectName)
|
viewModel.searchPathForProject(nameOf: result.projectName)
|
||||||
|
|
||||||
if viewModel.projectDownloaded {
|
if viewModel.projectDownloaded {
|
||||||
|
|
@ -11,7 +11,7 @@ struct DemoViewCell: View {
|
||||||
|
|
||||||
@EnvironmentObject var expandedState : ExpandedBLECellState
|
@EnvironmentObject var expandedState : ExpandedBLECellState
|
||||||
|
|
||||||
let result : ResultItem
|
let result : PyProject
|
||||||
|
|
||||||
@State var isExpanded: Bool = false {
|
@State var isExpanded: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
|
|
@ -36,7 +36,7 @@ struct DemoViewCell: View {
|
||||||
if isExpanded {
|
if isExpanded {
|
||||||
|
|
||||||
Group {
|
Group {
|
||||||
DemoSubview(bindingString: $deviceInfo, result: result, isConnected: $isConnected)
|
DemoSubview(result: result, isConnected: $isConnected)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -54,8 +54,7 @@ struct RootView: View {
|
||||||
case .selection:
|
case .selection:
|
||||||
SelectionView()
|
SelectionView()
|
||||||
|
|
||||||
case .wifiSelection:
|
|
||||||
WifiSelection()
|
|
||||||
|
|
||||||
case .wifiPairingTutorial:
|
case .wifiPairingTutorial:
|
||||||
WifiPairingView()
|
WifiPairingView()
|
||||||
|
|
@ -47,7 +47,7 @@ public class RootViewModel: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func goToWiFiSelection() {
|
func goToWiFiSelection() {
|
||||||
destination = .wifiSelection
|
destination = .wifiServiceSelection
|
||||||
}
|
}
|
||||||
|
|
||||||
func goToWifiView() {
|
func goToWifiView() {
|
||||||
|
|
@ -16,8 +16,6 @@ struct WifiHeaderView: View {
|
||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HStack (alignment: .center, spacing: 0) {
|
HStack (alignment: .center, spacing: 0) {
|
||||||
|
|
||||||
Image(systemName: "gearshape")
|
Image(systemName: "gearshape")
|
||||||
143
PyLeap/Features/Unpaired View/MainSelectionView.swift
Normal file
143
PyLeap/Features/Unpaired View/MainSelectionView.swift
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
//
|
||||||
|
// MainSelectionView.swift
|
||||||
|
// PyLeap
|
||||||
|
//
|
||||||
|
// Created by Trevor Beaton on 10/16/21.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import FileTransferClient
|
||||||
|
|
||||||
|
enum AdafruitDevices {
|
||||||
|
case clue_nrf52840_express
|
||||||
|
case circuitplayground_bluefruit
|
||||||
|
case esp32s2
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MainSelectionView: View {
|
||||||
|
|
||||||
|
@State private var showWebViewPopover: Bool = false
|
||||||
|
|
||||||
|
@State private var inConnectedInSelectionView = false
|
||||||
|
@State private var boardBootInfo = ""
|
||||||
|
@EnvironmentObject var expandedState : ExpandedBLECellState
|
||||||
|
|
||||||
|
@ObservedObject var vm = MainSelectionViewModel()
|
||||||
|
|
||||||
|
|
||||||
|
@State private var isConnected = false
|
||||||
|
|
||||||
|
@State private var test = ""
|
||||||
|
|
||||||
|
@State private var nilBinder = DownloadState.idle
|
||||||
|
@EnvironmentObject var rootViewModel: RootViewModel
|
||||||
|
|
||||||
|
@AppStorage("shouldShowOnboarding") var shouldShowOnboarding: Bool = true
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
|
||||||
|
VStack(alignment: .center, spacing: 0) {
|
||||||
|
MainHeaderView()
|
||||||
|
|
||||||
|
HStack(alignment: .center, spacing: 8, content: {
|
||||||
|
Text("Not Connected to a Device.")
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 16))
|
||||||
|
Button {
|
||||||
|
rootViewModel.goToSelection()
|
||||||
|
} label: {
|
||||||
|
Text("Connect Now")
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 16))
|
||||||
|
.underline()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.padding(.all, 0.0)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.frame(maxHeight: 40)
|
||||||
|
.background(Color("pyleap_burg"))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
|
||||||
|
MainSubHeaderView(device: "Adafruit device")
|
||||||
|
|
||||||
|
if vm.pdemos.isEmpty {
|
||||||
|
HStack{
|
||||||
|
Spacer()
|
||||||
|
ProgressView()
|
||||||
|
.scaleEffect(2)
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollViewReader { scroll in
|
||||||
|
|
||||||
|
ForEach(vm.pdemos) { demo in
|
||||||
|
|
||||||
|
if demo.bundleLink == expandedState.currentCell {
|
||||||
|
|
||||||
|
DemoViewCell(result: demo, isExpanded: true, isConnected: $inConnectedInSelectionView, deviceInfo: $boardBootInfo, onViewGeometryChanged: {
|
||||||
|
})
|
||||||
|
.onAppear(){
|
||||||
|
print("Cell Appeared")
|
||||||
|
withAnimation {
|
||||||
|
scroll.scrollTo(demo.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
DemoViewCell(result: demo, isExpanded: false, isConnected: $inConnectedInSelectionView, deviceInfo: $boardBootInfo, onViewGeometryChanged: {
|
||||||
|
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.refreshable {
|
||||||
|
vm.pdemos = []
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
|
vm.networkModel.fetch {
|
||||||
|
|
||||||
|
vm.loadProjectsFromStorage()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.onAppear() {
|
||||||
|
|
||||||
|
|
||||||
|
print("Opened MainSelectionView")
|
||||||
|
}
|
||||||
|
|
||||||
|
.fullScreenCover(isPresented: $shouldShowOnboarding, content: {
|
||||||
|
ExampleView(shouldShowOnboarding: $shouldShowOnboarding)
|
||||||
|
})
|
||||||
|
.preferredColorScheme(.light)
|
||||||
|
.background(Color.white)
|
||||||
|
.navigationBarColor(UIColor(named: "pyleap_gray"))
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -57,32 +57,43 @@ class MainSelectionViewModel: ObservableObject {
|
||||||
|
|
||||||
let dataStore = DataStore()
|
let dataStore = DataStore()
|
||||||
|
|
||||||
@Published var pdemos : [ResultItem] = []
|
@Published var pdemos: [PyProject] = []
|
||||||
|
|
||||||
var networkMonitorCancellable: AnyCancellable?
|
var networkMonitorCancellable: AnyCancellable?
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
let fileURL = documentsDirectory.appendingPathComponent("StandardPyLeapProjects.json")
|
startUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
networkMonitorCancellable = networkMonitor.$isConnected.sink { isConnected in
|
func loadProjectsFromStorage() {
|
||||||
if isConnected {
|
self.pdemos = self.dataStore.loadDefaultList()
|
||||||
print("The device is currently connected to the internet.")
|
}
|
||||||
// Perform some action when the device is connected to the internet.
|
|
||||||
|
func fetchAndLoadProjectsFromStorage() {
|
||||||
self.networkModel.fetch {
|
self.networkModel.fetch {
|
||||||
self.pdemos = self.dataStore.loadDefaultList()
|
self.pdemos = self.dataStore.loadDefaultList()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func startUp(){
|
||||||
|
networkMonitorCancellable = networkMonitor.$isConnected.sink { isConnected in
|
||||||
|
|
||||||
|
if isConnected {
|
||||||
|
// Perform some action when the device is connected to the internet.
|
||||||
|
self.fetchAndLoadProjectsFromStorage()
|
||||||
|
print("The device is currently connected to the internet.")
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
print("The device is not currently connected to the internet.")
|
print("The device is not currently connected to the internet.")
|
||||||
// Perform some action when the device is not connected to the internet.
|
// Perform some action when the device is not connected to the internet.
|
||||||
print("Loading cached remote data.")
|
print("Loading cached remote data.")
|
||||||
self.pdemos = self.dataStore.loadDefaultList()
|
self.loadProjectsFromStorage()
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +54,7 @@ struct SelectionView: View {
|
||||||
Button {
|
Button {
|
||||||
rootViewModel.goToWiFiSelection()
|
rootViewModel.goToWiFiSelection()
|
||||||
} label: {
|
} label: {
|
||||||
Text("Wifi")
|
Text("WiFi")
|
||||||
.font(Font.custom("ReadexPro-Regular", size: 25))
|
.font(Font.custom("ReadexPro-Regular", size: 25))
|
||||||
.foregroundColor(Color.white)
|
.foregroundColor(Color.white)
|
||||||
.frame(width: 270, height: 50, alignment: .center)
|
.frame(width: 270, height: 50, alignment: .center)
|
||||||
|
|
@ -110,6 +110,9 @@ struct SelectionView: View {
|
||||||
|
|
||||||
}
|
}
|
||||||
.padding(.bottom, 60)
|
.padding(.bottom, 60)
|
||||||
|
.onAppear() {
|
||||||
|
print("In Selection view")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ struct WifiCell: View {
|
||||||
|
|
||||||
@EnvironmentObject var expandedState : ExpandedState
|
@EnvironmentObject var expandedState : ExpandedState
|
||||||
|
|
||||||
let result : ResultItem
|
let result : PyProject
|
||||||
|
|
||||||
@State var isExpanded: Bool = false {
|
@State var isExpanded: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
|
|
@ -15,7 +15,7 @@ struct WifiSubViewCell: View {
|
||||||
|
|
||||||
@StateObject var wifiFileTransfer = WifiFileTransfer()
|
@StateObject var wifiFileTransfer = WifiFileTransfer()
|
||||||
@StateObject var wifiTransferService = WifiTransferService()
|
@StateObject var wifiTransferService = WifiTransferService()
|
||||||
let result : ResultItem
|
let result : PyProject
|
||||||
|
|
||||||
@Binding var bindingString: String
|
@Binding var bindingString: String
|
||||||
|
|
||||||
|
|
@ -85,7 +85,7 @@ Remove device from USB. Press "Reset" on the device.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func testOperation() {
|
func startOperationQueue() {
|
||||||
let operationQueue = OperationQueue()
|
let operationQueue = OperationQueue()
|
||||||
|
|
||||||
let operation1 = BlockOperation {
|
let operation1 = BlockOperation {
|
||||||
|
|
@ -158,48 +158,17 @@ Remove device from USB. Press "Reset" on the device.
|
||||||
.font(Font.custom("ReadexPro-Bold", size: 18))
|
.font(Font.custom("ReadexPro-Bold", size: 18))
|
||||||
.padding(.top, 5)
|
.padding(.top, 5)
|
||||||
|
|
||||||
|
ForEach(result.compatibility, id: \.self) { device in
|
||||||
HStack {
|
HStack {
|
||||||
Image(systemName: "checkmark")
|
Image(systemName: "checkmark")
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 25, height: 22, alignment: .center)
|
.frame(width: 25, height: 22, alignment: .center)
|
||||||
.foregroundColor(.green)
|
.foregroundColor(.green)
|
||||||
Text("ESP32-S2")
|
Text(formatDeviceName(device))
|
||||||
.font(Font.custom("ReadexPro-Regular", size: 18))
|
.font(Font.custom("ReadexPro-Regular", size: 18))
|
||||||
.foregroundColor(.black)
|
.foregroundColor(.black)
|
||||||
}
|
}
|
||||||
.padding(.top, 10)
|
.padding(.top, 10)
|
||||||
|
|
||||||
|
|
||||||
ForEach(result.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)
|
.ignoresSafeArea(.all)
|
||||||
|
|
@ -219,18 +188,15 @@ Remove device from USB. Press "Reset" on the device.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if isConnected {
|
|
||||||
|
|
||||||
if result.compatibility.contains(bindingString) {
|
|
||||||
|
|
||||||
|
|
||||||
if wifiFileTransfer.testIndex.downloadState == .idle {
|
if wifiFileTransfer.testIndex.downloadState == .idle {
|
||||||
|
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
// NotificationCenter.default.post(name: .didCompleteZip, object: nil, userInfo: projectResponse)
|
|
||||||
|
|
||||||
testOperation()
|
startOperationQueue()
|
||||||
|
|
||||||
} label: {
|
} label: {
|
||||||
RunItButton()
|
RunItButton()
|
||||||
|
|
@ -274,18 +240,6 @@ Remove device from USB. Press "Reset" on the device.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
Button {
|
|
||||||
rootViewModel.goTobluetoothPairing()
|
|
||||||
} label: {
|
|
||||||
ConnectButton()
|
|
||||||
.padding(.top, 20)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
.frame(height: 30)
|
.frame(height: 30)
|
||||||
.ignoresSafeArea(.all)
|
.ignoresSafeArea(.all)
|
||||||
|
|
@ -11,7 +11,7 @@ import Combine
|
||||||
|
|
||||||
struct WifiView: View {
|
struct WifiView: View {
|
||||||
|
|
||||||
@StateObject var viewModel = WifiViewModel()
|
@StateObject var vm = WifiViewModel()
|
||||||
private let kPrefix = Bundle.main.bundleIdentifier!
|
private let kPrefix = Bundle.main.bundleIdentifier!
|
||||||
|
|
||||||
// User Defaults
|
// User Defaults
|
||||||
|
|
@ -38,12 +38,12 @@ struct WifiView: View {
|
||||||
@State private var showPopover: Bool = false
|
@State private var showPopover: Bool = false
|
||||||
|
|
||||||
func toggleViewModelIP() {
|
func toggleViewModelIP() {
|
||||||
viewModel.isInvalidIP.toggle()
|
vm.isInvalidIP.toggle()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func scanNetworkWifi() {
|
func scanNetworkWifi() {
|
||||||
viewModel.wifiServiceManager.findService()
|
vm.wifiServiceManager.findService()
|
||||||
}
|
}
|
||||||
|
|
||||||
func printArray(array: [Any]) {
|
func printArray(array: [Any]) {
|
||||||
|
|
@ -59,9 +59,9 @@ struct WifiView: View {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
hostName = userDefaults.object(forKey: kPrefix+".storeResolvedAddress.hostName") as! String
|
hostName = userDefaults.object(forKey: kPrefix+".storeResolvedAddress.hostName") as! String
|
||||||
viewModel.ipAddressStored = true
|
vm.ipAddressStored = true
|
||||||
print("storeResolvedAddress - is stored")
|
print("storeResolvedAddress - is stored")
|
||||||
viewModel.connectionStatus = .connected
|
vm.connectionStatus = .connected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,28 +71,40 @@ struct WifiView: View {
|
||||||
hintText: "IP Address...",
|
hintText: "IP Address...",
|
||||||
primaryTitle: "Done",
|
primaryTitle: "Done",
|
||||||
secondaryTitle: "Cancel") { text in
|
secondaryTitle: "Cancel") { text in
|
||||||
viewModel.checkServices(ip: text)
|
vm.checkServices(ip: text)
|
||||||
|
|
||||||
} secondaryAction: {
|
} secondaryAction: {
|
||||||
print("Cancel")
|
print("Cancel")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showConfirmationPrompt() {
|
||||||
|
comfirmationAlertMessage(title: "Are you sure you want to disconnect?", exitTitle: "Cancel", primaryTitle: "Disconnect") {
|
||||||
|
rootViewModel.goToSelection()
|
||||||
|
} cancel: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func showAlertMessage() {
|
func showAlertMessage() {
|
||||||
alertMessage(title: "IP address Not Found", exitTitle: "Ok") {
|
alertMessage(title: "IP address Not Found", exitTitle: "Ok") {
|
||||||
showValidationPrompt()
|
showValidationPrompt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@State var boardInfoForView = Board.shared
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
WifiHeaderView()
|
WifiHeaderView()
|
||||||
|
|
||||||
Group{
|
Group{
|
||||||
switch viewModel.connectionStatus {
|
switch vm.connectionStatus {
|
||||||
case .connected:
|
case .connected:
|
||||||
WifiStatusConnectedView(hostName: $hostName)
|
WifiStatusConnectedView(hostName: $hostName, disconnectAction: {
|
||||||
|
showConfirmationPrompt()
|
||||||
|
})
|
||||||
case .noConnection:
|
case .noConnection:
|
||||||
WifiStatusNoConnectionView()
|
WifiStatusNoConnectionView()
|
||||||
case .connecting:
|
case .connecting:
|
||||||
|
|
@ -100,16 +112,14 @@ struct WifiView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ScrollView(.vertical, showsIndicators: false) {
|
ScrollView(.vertical, showsIndicators: false) {
|
||||||
|
|
||||||
ScrollViewReader { scroll in
|
ScrollViewReader { scroll in
|
||||||
|
|
||||||
SubHeaderView()
|
SubHeaderView()
|
||||||
|
|
||||||
|
let check = vm.pdemos.filter {
|
||||||
let check = viewModel.pdemos.filter {
|
$0.wifiCompatible
|
||||||
$0.compatibility.contains(boardBootInfo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ForEach(check) { demo in
|
ForEach(check) { demo in
|
||||||
|
|
@ -117,48 +127,43 @@ struct WifiView: View {
|
||||||
if demo.bundleLink == test.currentCell {
|
if demo.bundleLink == test.currentCell {
|
||||||
WifiCell(result: demo,isExpanded: trueTog, isConnected: $inConnectedInWifiView, bootOne: $boardBootInfo, stateBinder: $downloadState, onViewGeometryChanged: {
|
WifiCell(result: demo,isExpanded: trueTog, isConnected: $inConnectedInWifiView, bootOne: $boardBootInfo, stateBinder: $downloadState, onViewGeometryChanged: {
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.onAppear(){
|
.onAppear(){
|
||||||
|
|
||||||
withAnimation {
|
withAnimation {
|
||||||
scroll.scrollTo(demo.id)
|
scroll.scrollTo(demo.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
WifiCell(result: demo, isExpanded: falseTog, isConnected: $inConnectedInWifiView, bootOne: $boardBootInfo, stateBinder: $downloadState, onViewGeometryChanged: {
|
WifiCell(result: demo, isExpanded: falseTog, isConnected: $inConnectedInWifiView, bootOne: $boardBootInfo, stateBinder: $downloadState, onViewGeometryChanged: {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
// scroll.scrollTo(demo.id)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.id(self.scrollViewID)
|
.id(self.scrollViewID)
|
||||||
}
|
}
|
||||||
.foregroundColor(.black)
|
.foregroundColor(.black)
|
||||||
.environmentObject(test)
|
.environmentObject(test)
|
||||||
|
.refreshable {
|
||||||
|
vm.fetchAndLoadProjectsFromStorage()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.onChange(of: viewModel.connectionStatus, perform: { newValue in
|
.onChange(of: vm.connectionStatus, perform: { newValue in
|
||||||
if newValue == .connected {
|
if newValue == .connected {
|
||||||
hostName = userDefaults.object(forKey: kPrefix+".storeResolvedAddress.hostName") as! String
|
hostName = userDefaults.object(forKey: kPrefix+".storeResolvedAddress.hostName") as! String
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
.onChange(of: viewModel.wifiServiceManager.resolvedServices, perform: { newValue in
|
.onChange(of: vm.wifiServiceManager.resolvedServices, perform: { newValue in
|
||||||
print("Credential Check!")
|
print("Credential Check!")
|
||||||
print(newValue)
|
print(newValue)
|
||||||
|
|
||||||
|
|
@ -173,7 +178,7 @@ struct WifiView: View {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.onChange(of: viewModel.isInvalidIP, perform: { newValue in
|
.onChange(of: vm.isInvalidIP, perform: { newValue in
|
||||||
print("viewModel.isInvalidIP .onChange")
|
print("viewModel.isInvalidIP .onChange")
|
||||||
if newValue {
|
if newValue {
|
||||||
showAlertMessage()
|
showAlertMessage()
|
||||||
|
|
@ -185,8 +190,8 @@ struct WifiView: View {
|
||||||
|
|
||||||
.onAppear(){
|
.onAppear(){
|
||||||
checkForStoredIPAddress()
|
checkForStoredIPAddress()
|
||||||
viewModel.printStoredInfo()
|
vm.printStoredInfo()
|
||||||
viewModel.read()
|
vm.read()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -18,51 +18,6 @@ struct TestIndex {
|
||||||
|
|
||||||
class WifiFileTransfer: ObservableObject {
|
class WifiFileTransfer: ObservableObject {
|
||||||
|
|
||||||
|
|
||||||
// func fetchDocuments<T: Sequence>(in sequence: T) where T.Element == Int {
|
|
||||||
// var documentNumbers = sequence.map { String($0) }
|
|
||||||
//
|
|
||||||
// let timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] timer in
|
|
||||||
// guard
|
|
||||||
// let self = self,
|
|
||||||
// let documentNumber = documentNumbers.first
|
|
||||||
// else {
|
|
||||||
// timer.invalidate()
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// self.fetchDocument(byNumber: documentNumber)
|
|
||||||
// documentNumbers.removeLast()
|
|
||||||
// }
|
|
||||||
// timer.fire() // if you don't want to wait 2 seconds for the first one to fire, go ahead and fire it manually
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
func fetchDocumentsq<T: Sequence>(in sequence: T) where T.Element == URL {
|
|
||||||
|
|
||||||
print(sequence)
|
|
||||||
|
|
||||||
guard let value = sequence.first(where: { _ in true }) else {
|
|
||||||
print("Complete - fetchDocumentsq")
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// let docNumber = String(value)
|
|
||||||
// fetchDocument(byNumber: docNumber)
|
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
|
|
||||||
// self?.fetchDocuments(in: sequence.dropFirst())
|
|
||||||
|
|
||||||
print(value)
|
|
||||||
self?.fetchDocumentsq(in: sequence.dropFirst())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct TestIndex {
|
struct TestIndex {
|
||||||
var count = 0
|
var count = 0
|
||||||
var numberOfFiles = 0
|
var numberOfFiles = 0
|
||||||
|
|
@ -74,13 +29,10 @@ class WifiFileTransfer: ObservableObject {
|
||||||
downloadState = .idle
|
downloadState = .idle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var testIndex = TestIndex()
|
var testIndex = TestIndex()
|
||||||
|
|
||||||
|
|
||||||
func copy(with zone: NSZone? = nil) -> Any {
|
func copy(with zone: NSZone? = nil) -> Any {
|
||||||
let copy = WifiFileTransfer()
|
let copy = WifiFileTransfer()
|
||||||
copy.counter = counter
|
copy.counter = counter
|
||||||
|
|
@ -125,6 +77,7 @@ class WifiFileTransfer: ObservableObject {
|
||||||
|
|
||||||
func printArray(array: [Any]) {
|
func printArray(array: [Any]) {
|
||||||
|
|
||||||
|
print("From print array:")
|
||||||
for i in array {
|
for i in array {
|
||||||
print("\(i)")
|
print("\(i)")
|
||||||
}
|
}
|
||||||
|
|
@ -339,34 +292,20 @@ class WifiFileTransfer: ObservableObject {
|
||||||
|
|
||||||
func filterOutCPDirectories(urls: [URL]) -> [URL] {
|
func filterOutCPDirectories(urls: [URL]) -> [URL] {
|
||||||
// Removes - CircuitPython 8.x directory at the lastPathComponent
|
// Removes - CircuitPython 8.x directory at the lastPathComponent
|
||||||
let removingCP8FromArray = urls.filter {
|
let filteredList = urls.filter {
|
||||||
$0.lastPathComponent != ("CircuitPython 8.x")
|
let lastPathComponent = $0.lastPathComponent
|
||||||
|
return lastPathComponent != "CircuitPython 8.x"
|
||||||
|
&& lastPathComponent != "CircuitPython 7.x"
|
||||||
|
&& lastPathComponent != "CircuitPython_Templates"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes - CircuitPython 7.x directory at the lastPathComponent
|
let listForCurrentCPVersion = filteredList.filter {
|
||||||
let removingCP7FromArray = removingCP8FromArray.filter {
|
$0.absoluteString.contains("CircuitPython%20\(Board.shared.versionNumber).x")
|
||||||
$0.lastPathComponent != ("CircuitPython 7.x")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if WifiCPVersion.versionNumber == 8 {
|
printArray(array: listForCurrentCPVersion)
|
||||||
let listForCurrentCPVersion = removingCP7FromArray.filter {
|
|
||||||
!$0.absoluteString.contains("CircuitPython%207.x")
|
|
||||||
|
|
||||||
}
|
|
||||||
return listForCurrentCPVersion
|
return listForCurrentCPVersion
|
||||||
}
|
|
||||||
|
|
||||||
if WifiCPVersion.versionNumber == 7 {
|
|
||||||
let listForCurrentCPVersion = removingCP7FromArray.filter {
|
|
||||||
!$0.absoluteString.contains("CircuitPython%208.x")
|
|
||||||
|
|
||||||
}
|
|
||||||
return listForCurrentCPVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return removingCP7FromArray
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -419,8 +358,6 @@ class WifiFileTransfer: ObservableObject {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.numOfFiles = tempArray.count
|
self.numOfFiles = tempArray.count
|
||||||
self.makeFile(files: tempArray)
|
self.makeFile(files: tempArray)
|
||||||
// self.testIndex.numberOfFiles = self.numOfFiles
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -618,7 +555,6 @@ class WifiFileTransfer: ObservableObject {
|
||||||
printArray(array: files)
|
printArray(array: files)
|
||||||
var copiedArray = files
|
var copiedArray = files
|
||||||
|
|
||||||
// self.fetchDocumentsq(in: files)
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.counter += 1
|
self.counter += 1
|
||||||
99
PyLeap/Features/Wifi Module/WifiServiceCellSubView.swift
Normal file
99
PyLeap/Features/Wifi Module/WifiServiceCellSubView.swift
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
//
|
||||||
|
// WifiServiceCellSubView.swift
|
||||||
|
// PyLeap
|
||||||
|
//
|
||||||
|
// Created by Trevor Beaton on 3/29/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct WifiServiceCellSubView: View {
|
||||||
|
let resolvedService: ResolvedService
|
||||||
|
|
||||||
|
@EnvironmentObject var rootViewModel: RootViewModel
|
||||||
|
|
||||||
|
let userDefaults = UserDefaults.standard
|
||||||
|
private let kPrefix = Bundle.main.bundleIdentifier!
|
||||||
|
|
||||||
|
|
||||||
|
func storeResolvedAddress(service: ResolvedService) {
|
||||||
|
print("Storing resolved address")
|
||||||
|
userDefaults.set(service.ipAddress, forKey: kPrefix+".storeResolvedAddress.ipAddress" )
|
||||||
|
userDefaults.set(service.hostName, forKey: kPrefix+".storeResolvedAddress.hostName" )
|
||||||
|
userDefaults.set(service.device, forKey: kPrefix+".storeResolvedAddress.device" )
|
||||||
|
|
||||||
|
print("Stored UserDefaults")
|
||||||
|
|
||||||
|
print(userDefaults.object(forKey: kPrefix+".storeResolvedAddress.ipAddress"))
|
||||||
|
print(userDefaults.object(forKey: kPrefix+".storeResolvedAddress.hostName"))
|
||||||
|
print(userDefaults.object(forKey: kPrefix+".storeResolvedAddress.device"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func showConfirmationPrompt(service: ResolvedService, hostName: String) {
|
||||||
|
comfirmationAlertMessage(title: "Would you like to connect to \(hostName)?", exitTitle: "Cancel", primaryTitle: "Connect") {
|
||||||
|
storeResolvedAddress(service: service)
|
||||||
|
rootViewModel.goToWifiView()
|
||||||
|
} cancel: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
|
||||||
|
VStack {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
VStack {
|
||||||
|
|
||||||
|
Text("Device ID: \(resolvedService.hostName)")
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 18))
|
||||||
|
.multilineTextAlignment(.leading)
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
|
|
||||||
|
Text("Device IP: \(resolvedService.ipAddress)")
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 18))
|
||||||
|
.multilineTextAlignment(.leading)
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 30)
|
||||||
|
.padding(.vertical, 30)
|
||||||
|
|
||||||
|
HStack (
|
||||||
|
alignment: .center,
|
||||||
|
spacing: 0
|
||||||
|
) {
|
||||||
|
Spacer()
|
||||||
|
Button {
|
||||||
|
showConfirmationPrompt(service: resolvedService, hostName: resolvedService.hostName)
|
||||||
|
|
||||||
|
} label: {
|
||||||
|
Text("Connect")
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 25))
|
||||||
|
.foregroundColor(Color.white)
|
||||||
|
.frame(width: 270, height: 50, alignment: .center)
|
||||||
|
.background(Color("pyleap_pink"))
|
||||||
|
.clipShape(Capsule())
|
||||||
|
.padding(.bottom, 30)
|
||||||
|
}
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//struct WifiServiceCellSubView_Previews: PreviewProvider {
|
||||||
|
// static var previews: some View {
|
||||||
|
// WifiServiceCellSubView(resolvedService: .con)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
81
PyLeap/Features/Wifi Module/WifiServiceCellView.swift
Normal file
81
PyLeap/Features/Wifi Module/WifiServiceCellView.swift
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
//
|
||||||
|
// WifiServiceCellView.swift
|
||||||
|
// PyLeap
|
||||||
|
//
|
||||||
|
// Created by Trevor Beaton on 11/7/22.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct WifiServiceCellView: View {
|
||||||
|
|
||||||
|
let resolvedService: ResolvedService
|
||||||
|
|
||||||
|
@State private var isExpanded: Bool = false {
|
||||||
|
didSet {
|
||||||
|
onViewGeometryChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let onViewGeometryChanged: ()->Void
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
content
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var content: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
header
|
||||||
|
|
||||||
|
if isExpanded {
|
||||||
|
|
||||||
|
Group {
|
||||||
|
WifiServiceCellSubView(resolvedService: resolvedService)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeAdafruitString(text: String) -> String {
|
||||||
|
if text.contains("Adafruit") {
|
||||||
|
let parsed = text.replacingOccurrences(of: "Adafruit", with: "")
|
||||||
|
return parsed
|
||||||
|
} else {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var header: some View {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text(removeAdafruitString(text:resolvedService.device))
|
||||||
|
.font(Font.custom("ReadexPro-Regular", size: 24))
|
||||||
|
.minimumScaleFactor(0.1)
|
||||||
|
.lineLimit(1)
|
||||||
|
// .padding(.horizontal, 30)
|
||||||
|
.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)
|
||||||
|
.frame(height: 50)
|
||||||
|
.background(Color("alt-gray"))
|
||||||
|
.onTapGesture { isExpanded.toggle() }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// PyLeap
|
// PyLeap
|
||||||
//
|
//
|
||||||
// Created by Trevor Beaton on 10/24/22.
|
// Created by Trevor Beaton on 10/24/22.
|
||||||
//
|
// Testing
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
|
|
@ -10,18 +10,15 @@ import Foundation
|
||||||
|
|
||||||
struct WifiStatusConnectedView: View {
|
struct WifiStatusConnectedView: View {
|
||||||
|
|
||||||
let userDefaults = UserDefaults.standard
|
|
||||||
private let kPrefix = Bundle.main.bundleIdentifier!
|
|
||||||
@EnvironmentObject var rootViewModel: RootViewModel
|
|
||||||
|
|
||||||
@Binding var hostName: String
|
@Binding var hostName: String
|
||||||
|
|
||||||
func showConfirmationPrompt() {
|
var disconnectAction: () -> Void
|
||||||
comfirmationAlertMessage(title: "Are you sure you want to disconnect?", exitTitle: "Cancel", primaryTitle: "Disconnect") {
|
|
||||||
rootViewModel.goToSelection()
|
|
||||||
} cancel: {
|
|
||||||
|
|
||||||
}
|
func removeAdafruitString(from boardName: String) -> String {
|
||||||
|
let removeString = "Adafruit"
|
||||||
|
let updatedText = boardName.replacingOccurrences(of: removeString, with: "")
|
||||||
|
|
||||||
|
return updatedText
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
@ -33,16 +30,13 @@ struct WifiStatusConnectedView: View {
|
||||||
.frame(width: 20, height: 20)
|
.frame(width: 20, height: 20)
|
||||||
.padding(5)
|
.padding(5)
|
||||||
|
|
||||||
Text("Connected to \(hostName). ")
|
Text("Connected to \(hostName) ")
|
||||||
.font(Font.custom("ReadexPro-Regular", size: 14))
|
.font(Font.custom("ReadexPro-Regular", size: 14))
|
||||||
|
|
||||||
Button {
|
Button(action: disconnectAction) {
|
||||||
showConfirmationPrompt()
|
|
||||||
} label: {
|
|
||||||
Text("Disconnect")
|
Text("Disconnect")
|
||||||
.font(Font.custom("ReadexPro-Bold", size: 14))
|
.font(Font.custom("ReadexPro-Bold", size: 14))
|
||||||
.underline()
|
.underline()
|
||||||
.minimumScaleFactor(0.1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
@ -71,31 +71,6 @@ class WifiSubViewCellModel: ObservableObject {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if success.contains("GET, OPTIONS, PUT, DELETE, MOVE") {
|
|
||||||
//
|
|
||||||
// print("USB not in use.")
|
|
||||||
// DispatchQueue.main.async {
|
|
||||||
// self.usbInUse = false
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
|
||||||
// // if wifiFileTransfer.projectDownloaded {
|
|
||||||
// //
|
|
||||||
// // wifiFileTransfer.testFileExistance(for: result.projectName, bundleLink: result.bundleLink)
|
|
||||||
// //
|
|
||||||
// // } else {
|
|
||||||
// // downloadModel.trueDownload(useProject: result.bundleLink, projectName: result.projectName)
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// DispatchQueue.main.async {
|
|
||||||
// self.usbInUse = true
|
|
||||||
// }
|
|
||||||
// print("USB in use - files cannot be tranferred or moved while USB is in use. Show Error")
|
|
||||||
// }
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +173,7 @@ class WifiTransferService: ObservableObject {
|
||||||
}
|
}
|
||||||
let base64LoginString = loginData.base64EncodedString()
|
let base64LoginString = loginData.base64EncodedString()
|
||||||
|
|
||||||
// var request = URLRequest(url: URL(string: "http://cpy-9cbe10.local/fs/")!,timeoutInterval: Double.infinity)
|
|
||||||
var request = URLRequest(url: URL(string: "http://\(hostName).local/fs/")!,timeoutInterval: Double.infinity)
|
var request = URLRequest(url: URL(string: "http://\(hostName).local/fs/")!,timeoutInterval: Double.infinity)
|
||||||
|
|
||||||
request.addValue("application/json", forHTTPHeaderField: "Accept")
|
request.addValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
|
@ -226,7 +226,6 @@ class WifiTransferService: ObservableObject {
|
||||||
|
|
||||||
let loginData = loginString.data(using: String.Encoding.utf8)
|
let loginData = loginString.data(using: String.Encoding.utf8)
|
||||||
|
|
||||||
|
|
||||||
let base64LoginString = loginData!.base64EncodedString()
|
let base64LoginString = loginData!.base64EncodedString()
|
||||||
|
|
||||||
print("Host Name: \(hostName)")
|
print("Host Name: \(hostName)")
|
||||||
|
|
@ -27,6 +27,7 @@ class WifiViewModel: ObservableObject {
|
||||||
@Published var ipInputValidation = false
|
@Published var ipInputValidation = false
|
||||||
//Dependencies
|
//Dependencies
|
||||||
var networkMonitor = NetworkMonitor()
|
var networkMonitor = NetworkMonitor()
|
||||||
|
|
||||||
var networkAuth = LocalNetworkAuthorization()
|
var networkAuth = LocalNetworkAuthorization()
|
||||||
|
|
||||||
public var wifiNetworkService = WifiNetworkService()
|
public var wifiNetworkService = WifiNetworkService()
|
||||||
|
|
@ -34,7 +35,7 @@ class WifiViewModel: ObservableObject {
|
||||||
@Published var wifiTransferService = WifiTransferService()
|
@Published var wifiTransferService = WifiTransferService()
|
||||||
|
|
||||||
@Published var wifiServiceManager = WifiServiceManager()
|
@Published var wifiServiceManager = WifiServiceManager()
|
||||||
|
@ObservedObject var networkModel = NetworkService()
|
||||||
var circuitPythonVersion = Int()
|
var circuitPythonVersion = Int()
|
||||||
|
|
||||||
@Published var webDirectoryInfo = [WebDirectoryModel]()
|
@Published var webDirectoryInfo = [WebDirectoryModel]()
|
||||||
|
|
@ -45,9 +46,19 @@ class WifiViewModel: ObservableObject {
|
||||||
|
|
||||||
let dataStore = DataStore()
|
let dataStore = DataStore()
|
||||||
|
|
||||||
@Published var pdemos : [ResultItem] = []
|
@Published var pdemos : [PyProject] = []
|
||||||
|
|
||||||
|
|
||||||
|
func loadProjectsFromStorage() {
|
||||||
|
self.pdemos = self.dataStore.loadDefaultList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchAndLoadProjectsFromStorage() {
|
||||||
|
self.networkModel.fetch {
|
||||||
|
self.pdemos = self.dataStore.loadDefaultList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// File Manager Data
|
// File Manager Data
|
||||||
let directoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
let directoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||||
|
|
@ -59,11 +70,10 @@ class WifiViewModel: ObservableObject {
|
||||||
var ipAddressStored = false
|
var ipAddressStored = false
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
pdemos = dataStore.loadDefaultList()
|
loadProjectsFromStorage()
|
||||||
checkIP()
|
checkIP()
|
||||||
registerNotifications(enabled: true)
|
registerNotifications(enabled: true)
|
||||||
wifiServiceManager.findService()
|
wifiServiceManager.findService()
|
||||||
//read()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a network call to populate our project list
|
/// Makes a network call to populate our project list
|
||||||
|
|
@ -71,29 +81,39 @@ class WifiViewModel: ObservableObject {
|
||||||
// networkModel.fetch()
|
// networkModel.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published var pyleapProjects = [ResultItem]()
|
@Published var pyleapProjects = [PyProject]()
|
||||||
|
|
||||||
|
var boardDataProvider = BoardDataProvider()
|
||||||
|
|
||||||
|
|
||||||
|
// This function reads the boards the boot_out.txt file to then set the current board's name and version number for file transfer.
|
||||||
|
|
||||||
|
func setBoardToDefault() {
|
||||||
|
Board.shared.name = "Unrecognized Board"
|
||||||
|
Board.shared.versionNumber = "8"
|
||||||
|
}
|
||||||
|
|
||||||
func read() {
|
func read() {
|
||||||
|
setBoardToDefault()
|
||||||
// This method can't be used until the device has permission to communicate.
|
// This method can't be used until the device has permission to communicate.
|
||||||
print("READING CP Vers.")
|
print("READING CP Vers.")
|
||||||
wifiTransferService.getRequest(read: "boot_out.txt") { result in
|
wifiTransferService.getRequest(read: "boot_out.txt") { result in
|
||||||
|
|
||||||
if result.contains("CircuitPython 7") {
|
let boardID = self.boardDataProvider.getBoardID(from: result) ?? "Unrecognized Board"
|
||||||
WifiCPVersion.versionNumber = 7
|
// Board default version is set to 8
|
||||||
print("WifiCPVersion.versionNumber set to: \(WifiCPVersion.versionNumber)")
|
let boardVersion = self.boardDataProvider.getCircuitPythonMajorVersion(from: result) ?? "8"
|
||||||
}
|
|
||||||
|
|
||||||
if result.contains("CircuitPython 8") {
|
Board.shared.name = boardID
|
||||||
WifiCPVersion.versionNumber = 8
|
Board.shared.versionNumber = boardVersion
|
||||||
print("WifiCPVersion.versionNumber set to: \(WifiCPVersion.versionNumber)")
|
dump(Board.shared)
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private weak var invalidIPObserver: NSObjectProtocol?
|
private weak var invalidIPObserver: NSObjectProtocol?
|
||||||
|
|
||||||
private weak var testObserver: NSObjectProtocol?
|
private weak var testObserver: NSObjectProtocol?
|
||||||
|
|
@ -146,11 +166,6 @@ class WifiViewModel: ObservableObject {
|
||||||
connectionStatus = .connected
|
connectionStatus = .connected
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Published var connectionStatus: ConnectionStatus = AppEnvironment.isRunningTests ? .connected : .noConnection
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func printStoredInfo() {
|
func printStoredInfo() {
|
||||||
print("======Stored UserDefaults======")
|
print("======Stored UserDefaults======")
|
||||||
53
PyLeap/Helpers/BoardDataProvider.swift
Normal file
53
PyLeap/Helpers/BoardDataProvider.swift
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
//
|
||||||
|
// BoardDataProvider.swift
|
||||||
|
// PyLeap
|
||||||
|
//
|
||||||
|
// Created by Trevor Beaton on 5/17/23.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
final class BoardDataProvider {
|
||||||
|
|
||||||
|
|
||||||
|
func getBoardID(from prompt: String) -> String? {
|
||||||
|
print("getBoardID function: \(prompt)")
|
||||||
|
|
||||||
|
let boardIDPrefix = "Board ID:"
|
||||||
|
let uidSuffix = "UID"
|
||||||
|
|
||||||
|
if let startRange = prompt.range(of: boardIDPrefix) {
|
||||||
|
let start = startRange.upperBound
|
||||||
|
var end = prompt.endIndex
|
||||||
|
if let endRange = prompt.range(of: uidSuffix) {
|
||||||
|
end = endRange.lowerBound
|
||||||
|
}
|
||||||
|
|
||||||
|
let range = start..<end
|
||||||
|
let boardID = prompt[range].trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
|
||||||
|
let boardIDWithSpaces = boardID.replacingOccurrences(of: "_", with: " ")
|
||||||
|
|
||||||
|
let capitalizedBoardID = boardIDWithSpaces.capitalized
|
||||||
|
print("Outgoing: \(capitalizedBoardID)")
|
||||||
|
return capitalizedBoardID
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCircuitPythonMajorVersion(from prompt: String) -> String? {
|
||||||
|
print("From getCircuitPythonMajorVersion function: \(prompt)")
|
||||||
|
let regexPattern = "CircuitPython (\\d+)"
|
||||||
|
if let regex = try? NSRegularExpression(pattern: regexPattern) {
|
||||||
|
let range = NSRange(location: 0, length: prompt.utf16.count)
|
||||||
|
if let match = regex.firstMatch(in: prompt, options: [], range: range) {
|
||||||
|
if let range = Range(match.range(at: 1), in: prompt) {
|
||||||
|
return String(prompt[range])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ import Foundation
|
||||||
/// This is a DataStore class that is used for saving and loading data to/from the file system using the FileManager class.
|
/// This is a DataStore class that is used for saving and loading data to/from the file system using the FileManager class.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class DataStore {
|
public class DataStore: ObservableObject {
|
||||||
|
|
||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
|
|
||||||
|
|
@ -27,8 +27,8 @@ public class DataStore {
|
||||||
/// This method writes it to a file named "StandardPyLeapProjects.json" in the documents directory.
|
/// This method writes it to a file named "StandardPyLeapProjects.json" in the documents directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func save(content: [ResultItem], completion: @escaping () -> Void) {
|
func save(content: [PyProject], completion: @escaping () -> Void) {
|
||||||
|
print(#function)
|
||||||
let encoder = JSONEncoder()
|
let encoder = JSONEncoder()
|
||||||
if let encodedProjectData = try? encoder.encode(content) {
|
if let encodedProjectData = try? encoder.encode(content) {
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ public class DataStore {
|
||||||
/// This method reads the "StandardPyLeapProjects.json" file in the documents directory and decodes it as an array of ResultItem objects, and then appends the customProjects array to it and saves it back to the file.
|
/// This method reads the "StandardPyLeapProjects.json" file in the documents directory and decodes it as an array of ResultItem objects, and then appends the customProjects array to it and saves it back to the file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func save(customProjects: [ResultItem], completion: @escaping () -> Void) {
|
func save(customProjects: [PyProject], completion: @escaping () -> Void) {
|
||||||
|
|
||||||
var temp = customProjects
|
var temp = customProjects
|
||||||
|
|
||||||
|
|
@ -55,7 +55,7 @@ public class DataStore {
|
||||||
let savedData = try? Data(contentsOf: fileURL)
|
let savedData = try? Data(contentsOf: fileURL)
|
||||||
|
|
||||||
if let savedData = savedData,
|
if let savedData = savedData,
|
||||||
let savedProjects = try? JSONDecoder().decode([ResultItem].self, from: savedData) {
|
let savedProjects = try? JSONDecoder().decode([PyProject].self, from: savedData) {
|
||||||
NotificationCenter.default.post(name: .didCollectCustomProject, object: nil, userInfo: nil)
|
NotificationCenter.default.post(name: .didCollectCustomProject, object: nil, userInfo: nil)
|
||||||
temp.append(contentsOf: savedProjects)
|
temp.append(contentsOf: savedProjects)
|
||||||
|
|
||||||
|
|
@ -76,24 +76,24 @@ public class DataStore {
|
||||||
let savedData = try? Data(contentsOf: fileURL)
|
let savedData = try? Data(contentsOf: fileURL)
|
||||||
|
|
||||||
if let savedData = savedData,
|
if let savedData = savedData,
|
||||||
let savedProjects = try? JSONDecoder().decode([ResultItem].self, from: savedData) {
|
let savedProjects = try? JSONDecoder().decode([PyProject].self, from: savedData) {
|
||||||
loadCustomProjectList(contents: savedProjects)
|
loadCustomProjectList(contents: savedProjects)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
/// : This method reads the "StandardPyLeapProjects.json" file in the documents directory, decodes it as an array of ResultItem objects, and returns it.
|
/// This method reads the "StandardPyLeapProjects.json" file in the documents directory, decodes it as an array of ResultItem objects, and returns it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func loadDefaultList() -> [ResultItem] {
|
func loadDefaultList() -> [PyProject] {
|
||||||
|
|
||||||
var result = [ResultItem]()
|
var result = [PyProject]()
|
||||||
let fileURL = documentsDirectory.appendingPathComponent("StandardPyLeapProjects.json")
|
let fileURL = documentsDirectory.appendingPathComponent("StandardPyLeapProjects.json")
|
||||||
|
|
||||||
let savedData = try? Data(contentsOf: fileURL)
|
let savedData = try? Data(contentsOf: fileURL)
|
||||||
|
|
||||||
if let savedData = savedData,
|
if let savedData = savedData,
|
||||||
let savedProjects = try? JSONDecoder().decode([ResultItem].self, from: savedData) {
|
let savedProjects = try? JSONDecoder().decode([PyProject].self, from: savedData) {
|
||||||
result = savedProjects
|
result = savedProjects
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
@ -107,14 +107,14 @@ public class DataStore {
|
||||||
/// This method reads the "CustomProjects.json" file in the documents directory, decodes it as an array of ResultItem objects, appends it to the input array, and then calls
|
/// This method reads the "CustomProjects.json" file in the documents directory, decodes it as an array of ResultItem objects, appends it to the input array, and then calls
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func loadCustomProjectList(contents: [ResultItem]) {
|
func loadCustomProjectList(contents: [PyProject]) {
|
||||||
var temp = contents
|
var temp = contents
|
||||||
|
|
||||||
let fileURL = documentsDirectory.appendingPathComponent("CustomProjects.json")
|
let fileURL = documentsDirectory.appendingPathComponent("CustomProjects.json")
|
||||||
let savedData = try? Data(contentsOf: fileURL)
|
let savedData = try? Data(contentsOf: fileURL)
|
||||||
|
|
||||||
if let savedData = savedData,
|
if let savedData = savedData,
|
||||||
let savedProjects = try? JSONDecoder().decode([ResultItem].self, from: savedData) {
|
let savedProjects = try? JSONDecoder().decode([PyProject].self, from: savedData) {
|
||||||
temp.append(contentsOf: savedProjects)
|
temp.append(contentsOf: savedProjects)
|
||||||
removeDuplicates(projectList: temp)
|
removeDuplicates(projectList: temp)
|
||||||
|
|
||||||
|
|
@ -129,9 +129,9 @@ public class DataStore {
|
||||||
/// This method uses the reduce(into:_:) method to iterate over the array, and it builds a new array that only contains unique ResultItem objects based on their bundleLink property. It then calls the save(content:completion:) method to save the new array to "StandardPyLeapProjects.json" file.
|
/// This method uses the reduce(into:_:) method to iterate over the array, and it builds a new array that only contains unique ResultItem objects based on their bundleLink property. It then calls the save(content:completion:) method to save the new array to "StandardPyLeapProjects.json" file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func removeDuplicates(projectList: [ResultItem]) {
|
func removeDuplicates(projectList: [PyProject]) {
|
||||||
|
|
||||||
let combinedLists = projectList.reduce(into: [ResultItem]()) { (result, projectList) in
|
let combinedLists = projectList.reduce(into: [PyProject]()) { (result, projectList) in
|
||||||
|
|
||||||
if !result.contains(where: { $0.bundleLink == projectList.bundleLink }) {
|
if !result.contains(where: { $0.bundleLink == projectList.bundleLink }) {
|
||||||
result.append(projectList)
|
result.append(projectList)
|
||||||
|
|
@ -146,7 +146,7 @@ public class DataStore {
|
||||||
let savedData = try? Data(contentsOf: fileURL)
|
let savedData = try? Data(contentsOf: fileURL)
|
||||||
|
|
||||||
if let savedData = savedData,
|
if let savedData = savedData,
|
||||||
let savedProjects = try? JSONDecoder().decode([ResultItem].self, from: savedData) {
|
let savedProjects = try? JSONDecoder().decode([PyProject].self, from: savedData) {
|
||||||
|
|
||||||
for project in savedProjects {
|
for project in savedProjects {
|
||||||
print("CustomProjects name: \(project.projectName)")
|
print("CustomProjects name: \(project.projectName)")
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,24 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct RootResults: Decodable {
|
|
||||||
let projects: [ResultItem]
|
struct RootResults: Codable {
|
||||||
|
let formatVersion: Int
|
||||||
|
let fileVersion: Int
|
||||||
|
let projects: [PyProject]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ResultItem: Codable, Identifiable, Equatable {
|
struct PyProject: Codable, Identifiable, Equatable {
|
||||||
|
var id: UUID = UUID()
|
||||||
|
let projectName: String
|
||||||
|
let projectImage: String
|
||||||
|
let description: String
|
||||||
|
let bundleLink: String
|
||||||
|
let learnGuideLink: String
|
||||||
|
let compatibility: [String]
|
||||||
|
let bluetoothCompatible: Bool
|
||||||
|
let wifiCompatible: Bool
|
||||||
|
|
||||||
enum CodingKeys: CodingKey {
|
enum CodingKeys: CodingKey {
|
||||||
case projectName
|
case projectName
|
||||||
case projectImage
|
case projectImage
|
||||||
|
|
@ -20,15 +33,21 @@ struct ResultItem: Codable, Identifiable, Equatable {
|
||||||
case bundleLink
|
case bundleLink
|
||||||
case learnGuideLink
|
case learnGuideLink
|
||||||
case compatibility
|
case compatibility
|
||||||
|
case bluetoothCompatible
|
||||||
|
case wifiCompatible
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = UUID()
|
init(from decoder: Decoder) throws {
|
||||||
let projectName: String
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
let projectImage: String
|
self.projectName = try container.decode(String.self, forKey: .projectName)
|
||||||
let description: String
|
self.projectImage = try container.decode(String.self, forKey: .projectImage)
|
||||||
let bundleLink: String
|
self.description = try container.decode(String.self, forKey: .description)
|
||||||
let learnGuideLink: String
|
self.bundleLink = try container.decode(String.self, forKey: .bundleLink)
|
||||||
let compatibility: [String]
|
self.learnGuideLink = try container.decode(String.self, forKey: .learnGuideLink)
|
||||||
|
self.compatibility = try container.decode([String].self, forKey: .compatibility)
|
||||||
|
self.bluetoothCompatible = try container.decode(Bool.self, forKey: .bluetoothCompatible)
|
||||||
|
self.wifiCompatible = try container.decode(Bool.self, forKey: .wifiCompatible)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import Foundation
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
class NetworkService: ObservableObject {
|
class NetworkService: ObservableObject {
|
||||||
|
|
||||||
let dataStore = DataStore()
|
let dataStore = DataStore()
|
||||||
|
|
||||||
let thirdPartyBackgroundQueue = DispatchQueue(label: "com.PyLeap.thirdPartyBackgroundQueue", qos: .background, attributes: .concurrent)
|
let thirdPartyBackgroundQueue = DispatchQueue(label: "com.PyLeap.thirdPartyBackgroundQueue", qos: .background, attributes: .concurrent)
|
||||||
|
|
@ -34,39 +35,40 @@ class NetworkService: ObservableObject {
|
||||||
|
|
||||||
func fetch(completion: @escaping() -> Void) {
|
func fetch(completion: @escaping() -> Void) {
|
||||||
print("Attempting Network Request")
|
print("Attempting Network Request")
|
||||||
let request = URLRequest(url: URL(string: AdafruitInfo.baseURL)!, cachePolicy: URLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: 60.0)
|
let request = URLRequest(url: URL(string: AdafruitInfo.baseURL)!)
|
||||||
let task = session.dataTask(with: request) { data, response, error in
|
let task = session.dataTask(with: request) { data, response, error in
|
||||||
|
|
||||||
if let error = error {
|
if let error = error {
|
||||||
print("error: \(error)")
|
print("error: \(error)")
|
||||||
}
|
|
||||||
|
|
||||||
if let data = data {
|
|
||||||
|
|
||||||
print("Updating UIList with new data...")
|
|
||||||
if let projectData = try? JSONDecoder().decode(RootResults.self, from: data) {
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
|
|
||||||
self.dataStore.save(content: projectData.projects, completion: self.dataStore.loadDefaultProjectList)
|
|
||||||
|
|
||||||
completion()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print("No data found")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
print("Updating UIList with Cached data...")
|
print("Updating UIList with Cached data...")
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.dataStore.loadDefaultProjectList()
|
self.dataStore.loadDefaultProjectList()
|
||||||
completion()
|
completion()
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let data = data {
|
||||||
|
print("Updating storage with new data.")
|
||||||
|
do {
|
||||||
|
let projectData = try JSONDecoder().decode(RootResults.self, from: data)
|
||||||
|
dump(projectData.projects)
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.dataStore.save(content: projectData.projects, completion: self.dataStore.loadDefaultProjectList)
|
||||||
|
completion()
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
print("Decoding error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
task.resume()
|
task.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func fetchThirdPartyProject(urlString: String?) {
|
func fetchThirdPartyProject(urlString: String?) {
|
||||||
|
|
||||||
thirdPartyBackgroundQueue.async {
|
thirdPartyBackgroundQueue.async {
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,9 @@ Find more information on adding your own project here:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extension View {
|
extension View {
|
||||||
|
|
||||||
func comfirmationAlertMessage(title: String, exitTitle: String, primaryTitle: String,disconnect: @escaping() -> (),cancel: @escaping() -> ()){
|
func comfirmationAlertMessage(title: String, exitTitle: String, primaryTitle: String,disconnect: @escaping() -> (),cancel: @escaping() -> ()){
|
||||||
|
|
@ -31,5 +31,10 @@ extension View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatDeviceName(_ name: String) -> String {
|
||||||
|
let replaced = name.replacingOccurrences(of: "_", with: " ").replacingOccurrences(of: "-", with: " ")
|
||||||
|
let formatted = replaced.capitalized
|
||||||
|
return formatted
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
PyLeap/Views/.DS_Store
vendored
BIN
PyLeap/Views/.DS_Store
vendored
Binary file not shown.
|
|
@ -1,246 +0,0 @@
|
||||||
//
|
|
||||||
// MainSelectionView.swift
|
|
||||||
// PyLeap
|
|
||||||
//
|
|
||||||
// Created by Trevor Beaton on 10/16/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import FileTransferClient
|
|
||||||
|
|
||||||
enum AdafruitDevices {
|
|
||||||
case clue_nrf52840_express
|
|
||||||
case circuitplayground_bluefruit
|
|
||||||
case esp32s2
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MainSelectionView: View {
|
|
||||||
|
|
||||||
@State private var showWebViewPopover: Bool = false
|
|
||||||
|
|
||||||
@State private var inConnectedInSelectionView = true
|
|
||||||
@State private var boardBootInfo = ""
|
|
||||||
@EnvironmentObject var expandedState : ExpandedBLECellState
|
|
||||||
|
|
||||||
@ObservedObject var viewModel = MainSelectionViewModel()
|
|
||||||
|
|
||||||
|
|
||||||
@State private var isConnected = false
|
|
||||||
|
|
||||||
@State private var test = ""
|
|
||||||
|
|
||||||
@State private var nilBinder = DownloadState.idle
|
|
||||||
@EnvironmentObject var rootViewModel: RootViewModel
|
|
||||||
|
|
||||||
@AppStorage("shouldShowOnboarding") var shouldShowOnboarding: Bool = true
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
|
|
||||||
VStack(alignment: .center, spacing: 0) {
|
|
||||||
MainHeaderView()
|
|
||||||
|
|
||||||
HStack(alignment: .center, spacing: 8, content: {
|
|
||||||
Text("Not Connected to a Device.")
|
|
||||||
.font(Font.custom("ReadexPro-Regular", size: 16))
|
|
||||||
Button {
|
|
||||||
rootViewModel.goToSelection()
|
|
||||||
} label: {
|
|
||||||
Text("Connect Now")
|
|
||||||
.font(Font.custom("ReadexPro-Regular", size: 16))
|
|
||||||
.underline()
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.padding(.all, 0.0)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.frame(maxHeight: 40)
|
|
||||||
.background(Color("pyleap_burg"))
|
|
||||||
.foregroundColor(.white)
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
|
|
||||||
MainSubHeaderView(device: "Adafruit device")
|
|
||||||
|
|
||||||
if viewModel.pdemos.isEmpty {
|
|
||||||
HStack{
|
|
||||||
Spacer()
|
|
||||||
ProgressView()
|
|
||||||
.scaleEffect(2)
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.padding(0)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollViewReader { scroll in
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ForEach(viewModel.pdemos) { demo in
|
|
||||||
|
|
||||||
if demo.bundleLink == expandedState.currentCell {
|
|
||||||
|
|
||||||
DemoViewCell(result: demo, isExpanded: true, isConnected: $inConnectedInSelectionView, deviceInfo: $boardBootInfo, onViewGeometryChanged: {
|
|
||||||
})
|
|
||||||
.onAppear(){
|
|
||||||
print("Cell Appeared")
|
|
||||||
withAnimation {
|
|
||||||
scroll.scrollTo(demo.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
DemoViewCell(result: demo, isExpanded: false, isConnected: $inConnectedInSelectionView, deviceInfo: $boardBootInfo, onViewGeometryChanged: {
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.onDisappear() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// **Pull down to Refresh feature**
|
|
||||||
// ScrollRefreshableView(title: "Refresh", tintColor: .purple) {
|
|
||||||
// HStack{
|
|
||||||
// Spacer()
|
|
||||||
// MainSubHeaderView()
|
|
||||||
// Spacer()
|
|
||||||
// }
|
|
||||||
// .padding(0)
|
|
||||||
//
|
|
||||||
// if networkModel.pdemos.isEmpty {
|
|
||||||
// HStack{
|
|
||||||
// Spacer()
|
|
||||||
// ProgressView()
|
|
||||||
// .scaleEffect(2)
|
|
||||||
// Spacer()
|
|
||||||
// }
|
|
||||||
// .padding(0)
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }// } onRefresh: {
|
|
||||||
// self.networkModel.fetch()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
.onChange(of: viewModel.pdemos, perform: { newValue in
|
|
||||||
print("Update")
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
.onAppear() {
|
|
||||||
|
|
||||||
|
|
||||||
print("Opened MainSelectionView")
|
|
||||||
}
|
|
||||||
|
|
||||||
.fullScreenCover(isPresented: $shouldShowOnboarding, content: {
|
|
||||||
ExampleView(shouldShowOnboarding: $shouldShowOnboarding)
|
|
||||||
})
|
|
||||||
.preferredColorScheme(.light)
|
|
||||||
.background(Color.white)
|
|
||||||
.navigationBarColor(UIColor(named: "pyleap_gray"))
|
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//struct MainSelectionView_Previews: PreviewProvider {
|
|
||||||
// static var previews: some View {
|
|
||||||
// MainSelectionView()
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//struct MainSelectionView: View {
|
|
||||||
//
|
|
||||||
// @State private var showWebViewPopover: Bool = false
|
|
||||||
// @ObservedObject var networkModel = NetworkService()
|
|
||||||
// @ObservedObject var viewModel = MainSelectionViewModel()
|
|
||||||
// @State private var test = ""
|
|
||||||
// @State private var nilBinder = DownloadState.idle
|
|
||||||
// @EnvironmentObject var rootViewModel: RootViewModel
|
|
||||||
// @AppStorage("shouldShowOnboarding") var shouldShowOnboarding: Bool = true
|
|
||||||
//
|
|
||||||
// var body: some View {
|
|
||||||
// VStack(alignment: .center, spacing: 0) {
|
|
||||||
// MainHeaderView()
|
|
||||||
// connectionMessageView()
|
|
||||||
// ScrollView {
|
|
||||||
// MainSubHeaderView(device: "Adafruit device")
|
|
||||||
// if networkModel.pdemos.isEmpty {
|
|
||||||
// loadingIndicatorView()
|
|
||||||
// }
|
|
||||||
// ScrollViewReader { scroll in
|
|
||||||
// ForEach(networkModel.pdemos) { demo in
|
|
||||||
// demoViewCell(demo: demo, scroll: scroll)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private func connectionMessageView() -> some View {
|
|
||||||
// HStack(alignment: .center, spacing: 8) {
|
|
||||||
// Text("Not Connected to a Device.")
|
|
||||||
// .font(Font.custom("ReadexPro-Regular", size: 16))
|
|
||||||
// Button {
|
|
||||||
// rootViewModel.goToSelection()
|
|
||||||
// } label: {
|
|
||||||
// Text("Connect Now")
|
|
||||||
// .font(Font.custom("ReadexPro-Regular", size: 16))
|
|
||||||
// .underline()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// .padding(.all, 0.0)
|
|
||||||
// .frame(maxWidth: .infinity)
|
|
||||||
// .frame(maxHeight: 40)
|
|
||||||
// .background(Color("pyleap_burg"))
|
|
||||||
// .foregroundColor(.white)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private func loadingIndicatorView() -> some View {
|
|
||||||
// HStack{
|
|
||||||
// Spacer()
|
|
||||||
// ProgressView()
|
|
||||||
// .scaleEffect(2)
|
|
||||||
// Spacer()
|
|
||||||
// }
|
|
||||||
// .padding(0)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private func demoViewCell(demo: Demo, scroll: ScrollViewProxy) -> some View {
|
|
||||||
// if demo.bundleLink == expandedState.currentCell {
|
|
||||||
// DemoViewCell(result: demo, isExpanded: true, isConnected: $inConnectedInSelectionView, deviceInfo: $boardBootInfo, onViewGeometryChanged: {
|
|
||||||
// })
|
|
||||||
// .onAppear(){
|
|
||||||
// print("Cell Appeared")
|
|
||||||
// withAnimation {
|
|
||||||
// scroll.scrollTo(demo.id)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// DemoViewCell(result: demo, isExpanded: false, isConnected: $inConnectedInSelectionView, deviceInfo: $boardBootInfo, onViewGeometryChanged: {
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in a new issue