Compare commits
6 commits
master
...
Add-pull-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51e7ef0573 | ||
|
|
2ecc9a2ec9 | ||
|
|
0646453175 | ||
|
|
a34e2bf6d3 | ||
|
|
e5bb6df771 | ||
|
|
976bf512fa |
76 changed files with 871 additions and 1168 deletions
|
|
@ -9,13 +9,13 @@
|
|||
/* Begin PBXBuildFile section */
|
||||
D505B99C2755323C00386E9F /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D505B99B2755323C00386E9F /* NetworkMonitor.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 */; };
|
||||
D5199A2F28DD16F100ACC34C /* BleContentTransfer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5199A2E28DD16F100ACC34C /* BleContentTransfer.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 */; };
|
||||
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 */; };
|
||||
D52A926D29071DF400973B6B /* SelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A926C29071DF400973B6B /* SelectionView.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 */; };
|
||||
D58E1C8828A2B10B00AB683E /* WifiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1C8728A2B10B00AB683E /* WifiView.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 */; };
|
||||
D595FC2E2812C23D00569D8C /* Image Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D595FC2D2812C23D00569D8C /* Image Extension.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 */; };
|
||||
D5BA1F8128B66F920012FC62 /* CircuitPythonService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5BA1F8028B66F920012FC62 /* CircuitPythonService.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 */; };
|
||||
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 */; };
|
||||
|
|
@ -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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
|
@ -177,7 +179,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
|
@ -194,6 +195,8 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
|
@ -218,7 +221,6 @@
|
|||
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>"; };
|
||||
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>"; };
|
||||
D5F53CEC2694B7A9007634C2 /* OnboardingBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
|
@ -278,9 +280,11 @@
|
|||
D59DFDB5268CD052001737F6 /* AppEnvironment.swift */,
|
||||
D534F3FB280B59090053699C /* ExampleView.swift */,
|
||||
D544A2502822D4730038D483 /* Spotlight Extension.swift */,
|
||||
D5BBD12A2A15389400961B68 /* Helpers */,
|
||||
D567E2B428B80DC10009F768 /* Outline.md */,
|
||||
D567E2DD28C8D3E20009F768 /* SettingsView */,
|
||||
D5C74DF027EB92E900730505 /* Model */,
|
||||
D59DFDB2268CCEAC001737F6 /* Views */,
|
||||
D59DFDB2268CCEAC001737F6 /* Features */,
|
||||
D5C74DEE27EB91D600730505 /* Networking */,
|
||||
D5C74DED27EB919200730505 /* Resource */,
|
||||
D5C41D6726C5F509004C38E3 /* Download View */,
|
||||
|
|
@ -376,23 +380,29 @@
|
|||
path = BLESetttings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D58E1C8628A2B0DE00AB683E /* Wifi View */ = {
|
||||
D56FFE1C2A2A4ED500EF1E3B /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D567E2DD28C8D3E20009F768 /* SettingsView */,
|
||||
D58E1C8728A2B10B00AB683E /* WifiView.swift */,
|
||||
D567E2B728C137880009F768 /* WifiCell.swift */,
|
||||
D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */,
|
||||
D567E2B928C1382E0009F768 /* WifiSubViewCell.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D58E1C8628A2B0DE00AB683E /* Wifi Module */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D56FFE1C2A2A4ED500EF1E3B /* Views */,
|
||||
D51D1412293A53BD0028AEDD /* WifiCellViewModel.swift */,
|
||||
D58E1C8928A2B15E00AB683E /* WifiViewModel.swift */,
|
||||
D5269C07291AB75800C0CE4B /* WifiPairingView.swift */,
|
||||
D52A926E29078E0A00973B6B /* WifiServiceSelectionView.swift */,
|
||||
D5269BFF291960A300C0CE4B /* WifiSelection.swift */,
|
||||
D5269C01291997DE00C0CE4B /* WifiServiceCellView.swift */,
|
||||
D5269C032919985400C0CE4B /* WifiServiceCellSubView.swift */,
|
||||
D520D68F29D4C9380022048D /* WifiServiceCellView.swift */,
|
||||
D5BA1F7E28B66F280012FC62 /* WifiServiceManager.swift */,
|
||||
D5DD39A628D11817000FAEB8 /* WifiFileTransfer.swift */,
|
||||
D5DD39A828D11962000FAEB8 /* WifiTransferService.swift */,
|
||||
D520D69129D4C9900022048D /* WifiServiceCellSubView.swift */,
|
||||
D5AA27F728CA785B001CCE25 /* CircuitPythonType.swift */,
|
||||
D5482F4A28E75053000B0C8E /* LocalNetworkAuth.swift */,
|
||||
D5AA27F928CA8D46001CCE25 /* WifiStatusHeaderBarView.swift */,
|
||||
|
|
@ -402,17 +412,17 @@
|
|||
D5BA1F8028B66F920012FC62 /* CircuitPythonService.swift */,
|
||||
D58E1C8E28A30A5300AB683E /* WifiNetworkService.swift */,
|
||||
D5BA1F8228B68ED40012FC62 /* NetworkPeripheral.swift */,
|
||||
D50887622A2E35510002B798 /* Wifi_ifaddrs.m */,
|
||||
D50887612A2E35490002B798 /* PyLeap-Bridging-Header.h */,
|
||||
D5D7DF2A28B3E321008552D1 /* BasicCredentials.swift */,
|
||||
D58E1C8C28A2B32C00AB683E /* Wifi_ifaddrs.m */,
|
||||
D5ECF4B828C8E3C600FBF93D /* PyLeap-Bridging-Header.h */,
|
||||
);
|
||||
path = "Wifi View";
|
||||
path = "Wifi Module";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D59DFDB2268CCEAC001737F6 /* Views */ = {
|
||||
D59DFDB2268CCEAC001737F6 /* Features */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D58E1C8628A2B0DE00AB683E /* Wifi View */,
|
||||
D58E1C8628A2B0DE00AB683E /* Wifi Module */,
|
||||
D5507ACE26C668BC00512BAA /* UI Components */,
|
||||
D59DFDB3268CCEB9001737F6 /* Onboarding Views */,
|
||||
D5C474AA27E1746F002DD160 /* WebView */,
|
||||
|
|
@ -424,7 +434,7 @@
|
|||
D517F68026C5771D002996E8 /* FillerView.swift */,
|
||||
D5D1F4AC27ECFD200040E2BF /* Startup View */,
|
||||
);
|
||||
path = Views;
|
||||
path = Features;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D59DFDB3268CCEB9001737F6 /* Onboarding Views */ = {
|
||||
|
|
@ -438,6 +448,14 @@
|
|||
path = "Onboarding Views";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D5BBD12A2A15389400961B68 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D5BBD12B2A1538C100961B68 /* BoardDataProvider.swift */,
|
||||
);
|
||||
path = Helpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D5C41D6726C5F509004C38E3 /* Download View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -535,6 +553,7 @@
|
|||
children = (
|
||||
D59E31A9281B8DD300D24211 /* DownloadState.swift */,
|
||||
D5507ACB26C668BC00512BAA /* BleModuleView.swift */,
|
||||
D5BBD12D2A1C6AB300961B68 /* BleBannerView.swift */,
|
||||
D5507ACC26C668BC00512BAA /* BleModuleViewModel.swift */,
|
||||
D5199A2E28DD16F100ACC34C /* BleContentTransfer.swift */,
|
||||
D5D5BB3828DD19F000E5D93F /* BleContentCommands.swift */,
|
||||
|
|
@ -659,6 +678,7 @@
|
|||
D5D1F4B827ED2F4F0040E2BF /* FileManagerCheck.swift in Sources */,
|
||||
D52BE82A26A0660200630900 /* KeyboardUtils.swift in Sources */,
|
||||
D58182FB27F732E40091C43B /* SubCellViewModel.swift in Sources */,
|
||||
D520D69229D4C9900022048D /* WifiServiceCellSubView.swift in Sources */,
|
||||
D5D5BB3928DD19F000E5D93F /* BleContentCommands.swift in Sources */,
|
||||
D544A1D2281B9BB70038D483 /* Buttons.swift in Sources */,
|
||||
D5D1F4AE27ECFDA10040E2BF /* GifImage.swift in Sources */,
|
||||
|
|
@ -678,9 +698,9 @@
|
|||
D56F640C270242CA000E5975 /* UIColor+LightAndDark.swift in Sources */,
|
||||
D5F53CED2694B7A9007634C2 /* OnboardingBackgroundView.swift in Sources */,
|
||||
D5D1F4B227ECFF760040E2BF /* ProjectsModel.swift in Sources */,
|
||||
D5269C02291997DE00C0CE4B /* WifiServiceCellView.swift in Sources */,
|
||||
D5BA1F7A28B52A490012FC62 /* WifiListDetailView.swift in Sources */,
|
||||
D52F7E742672F4C400911D43 /* PyLeapApp.swift in Sources */,
|
||||
D5BBD12E2A1C6AB300961B68 /* BleBannerView.swift in Sources */,
|
||||
D567E2B628B81B730009F768 /* Queue.swift in Sources */,
|
||||
D534F3FC280B59090053699C /* ExampleView.swift in Sources */,
|
||||
D57858ED28327E18008E8BE4 /* PairingTutorialView.swift in Sources */,
|
||||
|
|
@ -702,7 +722,6 @@
|
|||
D5DD39A728D11817000FAEB8 /* WifiFileTransfer.swift in Sources */,
|
||||
D5AA27FA28CA8D46001CCE25 /* WifiStatusHeaderBarView.swift in Sources */,
|
||||
D5F53CEB2694B524007634C2 /* Blinka Animation.swift in Sources */,
|
||||
D5269C00291960A300C0CE4B /* WifiSelection.swift in Sources */,
|
||||
D5597BF826A9E14B00DF17C0 /* AppDelegate.swift in Sources */,
|
||||
D56F640E270242CA000E5975 /* String+DeletingPrefix.swift in Sources */,
|
||||
D57858F328333CBC008E8BE4 /* TroubleshootView.swift in Sources */,
|
||||
|
|
@ -739,18 +758,19 @@
|
|||
D567E2B828C137880009F768 /* WifiCell.swift in Sources */,
|
||||
D5D1F4B027ECFDE00040E2BF /* NavBarModifier.swift in Sources */,
|
||||
D5597C0C26AF018800DF17C0 /* View+If.swift in Sources */,
|
||||
D58E1C8D28A2B32C00AB683E /* Wifi_ifaddrs.m in Sources */,
|
||||
D56B75D4294BAAB400D008E7 /* BLESettingsView.swift in Sources */,
|
||||
D50887632A2E35510002B798 /* Wifi_ifaddrs.m in Sources */,
|
||||
D52BE7EE269DF36E00630900 /* DownloadViewModel.swift in Sources */,
|
||||
D59E31AA281B8DD300D24211 /* DownloadState.swift in Sources */,
|
||||
D520D69029D4C9380022048D /* WifiServiceCellView.swift in Sources */,
|
||||
D5BA1F7F28B66F280012FC62 /* WifiServiceManager.swift in Sources */,
|
||||
D5C74DF327EB92FA00730505 /* View+Extensions.swift in Sources */,
|
||||
D5AA27F828CA785B001CCE25 /* CircuitPythonType.swift in Sources */,
|
||||
D5199A2F28DD16F100ACC34C /* BleContentTransfer.swift in Sources */,
|
||||
D535E21628E1FA910096E548 /* ScrollRefreshableView.swift in Sources */,
|
||||
D5640216271B54BF00AE1519 /* MainSelectionView.swift in Sources */,
|
||||
D5269C042919985400C0CE4B /* WifiServiceCellSubView.swift in Sources */,
|
||||
D505B99C2755323C00386E9F /* NetworkMonitor.swift in Sources */,
|
||||
D5BBD12C2A1538C100961B68 /* BoardDataProvider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -881,22 +901,22 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = PyLeap/PyLeap.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 0;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"PyLeap/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = PyLeap/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.1.1;
|
||||
MARKETING_VERSION = 2.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.PyLeap;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "PyLeap/Views/Wifi View/PyLeap-Bridging-Header.h";
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
@ -911,22 +931,22 @@
|
|||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = PyLeap/PyLeap.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 0;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"PyLeap/Preview Content\"";
|
||||
DEVELOPMENT_TEAM = 2X94RM7457;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
INFOPLIST_FILE = PyLeap/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.1.1;
|
||||
MARKETING_VERSION = 2.2;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.adafruit.PyLeap;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "PyLeap/Views/Wifi View/PyLeap-Bridging-Header.h";
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
|
|
|
|||
Binary file not shown.
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?
|
||||
@Published var transmissionProgress: TransmissionProgress?
|
||||
|
||||
@Published var isTransmiting = false
|
||||
@Published var bootUpInfo = String()
|
||||
@Published var counter = 0
|
||||
|
||||
enum ProjectViewError: LocalizedError {
|
||||
|
|
@ -63,7 +63,6 @@ class BleContentCommands: ObservableObject {
|
|||
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
||||
|
||||
|
||||
@Published var activeAlert: ActiveAlert?
|
||||
|
||||
// Data
|
||||
private let bleManager = BleManager.shared
|
||||
|
|
@ -102,10 +101,7 @@ class BleContentCommands: ObservableObject {
|
|||
case .success(let data):
|
||||
self.lastTransmit = TransmissionLog(type: .read(data: data))
|
||||
let str = String(decoding: data, as: UTF8.self)
|
||||
print("Read: \(str)")
|
||||
self.bootUpInfo = str
|
||||
sharedBootinfo = str
|
||||
|
||||
print("Read: \(str)")
|
||||
|
||||
case .failure(let error):
|
||||
self.lastTransmit = TransmissionLog(type: .error(message: error.localizedDescription))
|
||||
|
|
@ -8,7 +8,24 @@
|
|||
import SwiftUI
|
||||
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?
|
||||
|
||||
|
|
@ -22,7 +39,6 @@ class BleContentTransfer: ObservableObject {
|
|||
|
||||
@Published var downloadState: DownloadState = .idle
|
||||
|
||||
@State var circuitPythonVersion = String()
|
||||
|
||||
@Published var isTransmiting = false
|
||||
|
||||
|
|
@ -31,19 +47,14 @@ class BleContentTransfer: ObservableObject {
|
|||
@Published var transferError = false
|
||||
|
||||
@Published var downloaderror = false
|
||||
|
||||
@Published var bootUpInfo = ""
|
||||
|
||||
|
||||
|
||||
|
||||
@Published var contentCommands = BleContentCommands()
|
||||
// CLEAN UP
|
||||
var projectDirectories: [URL] = []
|
||||
var projectFiles: [URL] = []
|
||||
var returnedArray = [[String]]()
|
||||
var fileTransferArray : [URL] = []
|
||||
|
||||
var filesReadyForTransfer : [URL] = []
|
||||
|
||||
@Published var sendingBundle = false
|
||||
@Published var didCompleteTranfer = false
|
||||
|
|
@ -57,11 +68,13 @@ class BleContentTransfer: ObservableObject {
|
|||
|
||||
@Published var isConnectedToInternet = false
|
||||
@Published var showAlert = false
|
||||
|
||||
var downloadPhases: String = ""
|
||||
|
||||
|
||||
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 {
|
||||
case fileTransferUndefined
|
||||
|
|
@ -77,25 +90,9 @@ class BleContentTransfer: ObservableObject {
|
|||
}
|
||||
|
||||
init() {
|
||||
getCPVersion()
|
||||
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 didEncounterTransferError: NSObjectProtocol?
|
||||
private weak var downloadErrorDidOccur: NSObjectProtocol?
|
||||
|
|
@ -310,14 +307,7 @@ class BleContentTransfer: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// filterCPVersion(incomingArray: regularFileUrls)
|
||||
// filterCPFiles(filesArray: regularFileUrls)
|
||||
|
||||
|
||||
// pathManipulation(arrayOfAny: filterCPVersion(incomingArray: projectDirectories), regularArray: filterCPVersion(incomingArray: projectFiles))
|
||||
|
||||
|
||||
projectDirectories.removeFirst()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
|
@ -336,70 +326,28 @@ class BleContentTransfer: ObservableObject {
|
|||
|
||||
|
||||
func filterCPVersion(incomingArray: [URL]) -> [URL] {
|
||||
print("project name \(projectName)")
|
||||
|
||||
|
||||
for i in incomingArray {
|
||||
print("incoming Array \(i.absoluteString)")
|
||||
|
||||
let filteredList = incomingArray.filter {
|
||||
let lastPathComponent = $0.lastPathComponent
|
||||
return lastPathComponent != "CircuitPython 8.x"
|
||||
&& lastPathComponent != "CircuitPython 7.x"
|
||||
&& lastPathComponent != "CircuitPython_Templates"
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
if sharedBootinfo.contains("CircuitPython 7") {
|
||||
|
||||
let listForCurrentCPVersion = listWithoutCP7Folder.filter {
|
||||
!$0.absoluteString.contains("CircuitPython%208.x")
|
||||
}
|
||||
|
||||
for i in listForCurrentCPVersion {
|
||||
print("listForCurrentCPVersion :- \(i.absoluteString)")
|
||||
}
|
||||
let listForCurrentCPVersion = filteredList.filter {
|
||||
$0.absoluteString.contains("CircuitPython%20\(Board.shared.versionNumber).x")
|
||||
}
|
||||
|
||||
return listForCurrentCPVersion
|
||||
}
|
||||
|
||||
return listWithoutCP7Folder
|
||||
}
|
||||
|
||||
|
||||
func makeDirectory(directoryArray: [URL], regularFilesArray: [URL]) {
|
||||
print("\(#function) @Line: \(#line)")
|
||||
var recursiveArray = directoryArray
|
||||
|
||||
for i in recursiveArray {
|
||||
print("recursiveArray \(i.absoluteString)")
|
||||
}
|
||||
|
||||
|
||||
if directoryArray.isEmpty {
|
||||
print("Array is empty. makeDirectory is done - Ready for file transfer!")
|
||||
newTransfer(listOf: regularFilesArray)
|
||||
} else {
|
||||
|
||||
|
|
@ -490,10 +438,7 @@ class BleContentTransfer: ObservableObject {
|
|||
|
||||
}
|
||||
|
||||
enum ListCommandError: Error {
|
||||
case belowMinimum
|
||||
case isPrime
|
||||
}
|
||||
|
||||
|
||||
func checkIfFilesExistOnBoard(url: URL) {
|
||||
|
||||
|
|
@ -527,29 +472,16 @@ class BleContentTransfer: ObservableObject {
|
|||
var tempPathComponents = url.pathComponents
|
||||
print("Incoming URL for makeFileString: \(url.absoluteString)")
|
||||
|
||||
|
||||
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")!
|
||||
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython \(Board.shared.versionNumber).x")!
|
||||
tempPathComponents.removeSubrange(0...indexOfCP)
|
||||
tempPathComponents.removeLast()
|
||||
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
||||
print("\(#function) @Line: \(#line)")
|
||||
print("Outgoing makeFileString: \(joinedArrayPath) for CP 8")
|
||||
return joinedArrayPath
|
||||
}
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -561,256 +493,81 @@ class BleContentTransfer: ObservableObject {
|
|||
|
||||
print("Incoming URL: \(url.absoluteString) ")
|
||||
|
||||
|
||||
|
||||
if sharedBootinfo.contains("CircuitPython 7") {
|
||||
print(tempPathComponents)
|
||||
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython 7.x")!
|
||||
print(tempPathComponents)
|
||||
indexOfCP = tempPathComponents.firstIndex(of: "CircuitPython \(Board.shared.versionNumber).x")!
|
||||
|
||||
|
||||
tempPathComponents.removeSubrange(0...indexOfCP)
|
||||
var joinedArrayPath = tempPathComponents.joined(separator: "/")
|
||||
print("\(#function) @Line: \(#line)")
|
||||
print("Outgoing String: \(joinedArrayPath) for CP 7")
|
||||
print("Outgoing Directory String: \(joinedArrayPath) for CP \(Board.shared.versionNumber)")
|
||||
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]) {
|
||||
print("\(#function) @Line: \(#line)")
|
||||
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 {
|
||||
guard !urls.isEmpty else {
|
||||
print("All Files Transferred! 👍")
|
||||
self.completedTransfer()
|
||||
|
||||
completedTransfer()
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2){
|
||||
self.sendingBundle = false
|
||||
self.completedTransfer()
|
||||
self.numOfFiles = 0
|
||||
self.counter = 0
|
||||
self.contentList.removeAll()
|
||||
self.resetTransferParameters()
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
guard let data = try? Data(contentsOf: URL(string: copiedFiles.first!.absoluteString)!) else {
|
||||
print("File not found")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
if copiedFiles.first?.lastPathComponent == "code.py" || copiedFiles.first?.lastPathComponent == "README.txt" {
|
||||
|
||||
print("Input for writeFileCommand: \(copiedFiles.first?.absoluteString)")
|
||||
|
||||
|
||||
self.contentCommands.writeFileCommand(path: copiedFiles.first!.lastPathComponent, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
print("Checking... 🫥")
|
||||
// print("makeDirectoryString transfer \(makeDirectoryString(url: copiedFiles.first!))")
|
||||
|
||||
let directoryPath = makeDirectoryString(url: copiedFiles.first!)
|
||||
|
||||
print("Input writeFileCommand: \(directoryPath)")
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
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 url = urls.first,
|
||||
let data = try? Data(contentsOf: url) else {
|
||||
print("File not found")
|
||||
return
|
||||
}
|
||||
|
||||
let path = isDirectFile(name: url.lastPathComponent) ? url.lastPathComponent : makeDirectoryString(url: url)
|
||||
|
||||
contentCommands.writeFileCommand(path: path, data: data) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
print("Success ✅")
|
||||
self.newTransfer(listOf: Array(urls.dropFirst()))
|
||||
case .failure(let error):
|
||||
print("Transfer Failure \(error)")
|
||||
self.handleTransferError(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func filePathMod(listOf files: [URL]) {
|
||||
var indexOfCP = 0
|
||||
|
||||
for i in files {
|
||||
print("-\(i.absoluteString)-\n")
|
||||
}
|
||||
|
||||
var tempArray = files
|
||||
|
||||
if files.isEmpty {
|
||||
// Continue
|
||||
|
||||
private func handleTransferError(_ error: Error) {
|
||||
DispatchQueue.main.async {
|
||||
print("\(#function) @Line: \(#line)")
|
||||
print("Done!")
|
||||
// print("RETURNED PATHS: \(returnedArray)\n")
|
||||
|
||||
for i in filesReadyForTransfer {
|
||||
print("\(i)")
|
||||
print(error)
|
||||
self.downloadState = .failed
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
self.downloadState = .idle
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
NotificationCenter.default.post(name: .didEncounterTransferError, object: nil, userInfo: nil)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private func resetTransferParameters() {
|
||||
sendingBundle = false
|
||||
completedTransfer()
|
||||
numOfFiles = 0
|
||||
counter = 0
|
||||
contentList.removeAll()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private func isDirectFile(name: String) -> Bool {
|
||||
return name == "code.py" || name == "README.txt"
|
||||
}
|
||||
|
||||
|
||||
func completedTransfer() {
|
||||
|
||||
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.downloadState = .complete
|
||||
self.didCompleteTranfer = true
|
||||
|
|
@ -824,186 +581,7 @@ 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
|
||||
|
||||
struct TransmissionProgress {
|
||||
|
|
@ -1047,7 +625,6 @@ class BleContentTransfer: ObservableObject {
|
|||
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
||||
|
||||
|
||||
@Published var activeAlert: ActiveAlert?
|
||||
|
||||
// Data
|
||||
private let bleManager = BleManager.shared
|
||||
|
|
@ -1088,8 +665,7 @@ class BleContentTransfer: ObservableObject {
|
|||
let str = String(decoding: data, as: UTF8.self)
|
||||
print("\(#function) @Line: \(#line)")
|
||||
print("Read: \(str)")
|
||||
//self.readMyStatus()
|
||||
self.bootUpInfo = str
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -12,28 +12,36 @@ class ExpandedBLECellState: ObservableObject {
|
|||
@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 {
|
||||
|
||||
// Data
|
||||
enum ActiveAlert: Identifiable {
|
||||
case confirmUnpair(blePeripheral: BlePeripheral)
|
||||
|
||||
var id: Int {
|
||||
switch self {
|
||||
case .confirmUnpair: return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@State var boardInfoForView: Board?
|
||||
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
@EnvironmentObject var expandedState : ExpandedBLECellState
|
||||
@ObservedObject var connectionManager = FileTransferConnectionManager.shared
|
||||
|
||||
|
||||
@State var unknownBoardName: String?
|
||||
|
||||
let selectedPeripheral = FileTransferConnectionManager.shared.selectedPeripheral
|
||||
|
||||
@StateObject var viewModel = BleModuleViewModel()
|
||||
@StateObject var vm = BleModuleViewModel()
|
||||
@EnvironmentObject var rootViewModel: RootViewModel
|
||||
|
||||
|
||||
|
|
@ -44,7 +52,6 @@ struct BleModuleView: View {
|
|||
@State var isExpanded = true
|
||||
|
||||
@State private var scrollViewID = UUID()
|
||||
@State private var activeAlert: ActiveAlert?
|
||||
@State private var boardBootInfo = ""
|
||||
@State private var inConnectedInSelectionView = true
|
||||
|
||||
|
|
@ -118,12 +125,7 @@ struct BleModuleView: View {
|
|||
.lineLimit(2)
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
if boardBootInfo == "clue_nrf52840_express" {
|
||||
} else if boardBootInfo == "clue_nrf52840_express" {
|
||||
Image("clue")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
|
|
@ -138,6 +140,20 @@ struct BleModuleView: View {
|
|||
.lineLimit(2)
|
||||
.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)
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -170,89 +186,14 @@ struct BleModuleView: View {
|
|||
|
||||
HeaderView()
|
||||
|
||||
|
||||
|
||||
VStack {
|
||||
|
||||
BleBannerView(deviceName: boardInfoForView?.name ?? "Unknown Device", disconnectAction: {
|
||||
showConfirmationPrompt()
|
||||
})
|
||||
|
||||
|
||||
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()
|
||||
} 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)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
|
@ -270,14 +211,32 @@ struct BleModuleView: View {
|
|||
MainSubHeaderView(device: "Adafruit CLUE")
|
||||
}
|
||||
|
||||
if boardBootInfo == "circuitplayground_bluefruit" {
|
||||
else if boardInfoForView?.name == "Circuitplayground Bluefruit" {
|
||||
MainSubHeaderView(device: "Circuit Playground")
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
MainSubHeaderView(device: unknownBoardName ?? "device")
|
||||
}
|
||||
|
||||
let check = viewModel.pdemos.filter {
|
||||
$0.compatibility.contains(boardBootInfo)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -311,6 +270,9 @@ struct BleModuleView: View {
|
|||
.id(self.scrollViewID)
|
||||
}
|
||||
.environmentObject(expandedState)
|
||||
.refreshable {
|
||||
vm.fetchAndLoadProjectsFromStorage()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -318,50 +280,37 @@ struct BleModuleView: View {
|
|||
.background(Color.white)
|
||||
|
||||
|
||||
.onChange(of: viewModel.bootUpInfo, perform: { newValue in
|
||||
viewModel.readMyStatus()
|
||||
.onChange(of: vm.bootUpInfo, perform: { newValue in
|
||||
vm.readMyStatus()
|
||||
|
||||
print("newValue \(newValue)")
|
||||
boardBootInfo = newValue
|
||||
})
|
||||
|
||||
.onChange(of: connectionManager.selectedClient) { selectedClient in
|
||||
viewModel.setup(fileTransferClient: selectedClient)
|
||||
vm.setup(fileTransferClient: selectedClient)
|
||||
}
|
||||
|
||||
.onChange(of: vm.connectedBoard, perform: { newValue in
|
||||
dump(newValue)
|
||||
boardInfoForView = newValue
|
||||
unknownBoardName = newValue?.name
|
||||
})
|
||||
|
||||
.onAppear(){
|
||||
print("Opened BleModuleView")
|
||||
// networkServiceModel.fetch()
|
||||
|
||||
viewModel.setup(fileTransferClient:connectionManager.selectedClient)
|
||||
|
||||
vm.setup(fileTransferClient:connectionManager.selectedClient)
|
||||
|
||||
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")) {})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ViewHeightKey: PreferenceKey {
|
||||
|
|
@ -10,30 +10,57 @@ import Zip
|
|||
import FileTransferClient
|
||||
|
||||
class BleModuleViewModel: ObservableObject {
|
||||
|
||||
|
||||
weak var delegate: BoardInfoDelegate?
|
||||
|
||||
@Published var boardInfoForView: Board? {
|
||||
didSet {
|
||||
print("Changed")
|
||||
delegate?.boardInfoDidUpdate(to: boardInfoForView)
|
||||
}
|
||||
}
|
||||
|
||||
private weak var fileTransferClient: FileTransferClient?
|
||||
@StateObject var contentTransfer = BleContentTransfer()
|
||||
@State var contentTransfer = BleContentTransfer()
|
||||
|
||||
@Published var entries = [BlePeripheral.DirectoryEntry]()
|
||||
@Published var isTransmiting = false
|
||||
@Published var bootUpInfo = ""
|
||||
|
||||
|
||||
|
||||
var boardDataProvider = BoardDataProvider()
|
||||
var connectedBoard: Board?
|
||||
|
||||
let dataStore = DataStore()
|
||||
@ObservedObject var networkModel = NetworkService()
|
||||
|
||||
|
||||
@Published var pdemos : [ResultItem] = []
|
||||
|
||||
init() {
|
||||
pdemos = dataStore.loadDefaultList()
|
||||
func loadProjectsFromStorage() {
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
}
|
||||
|
||||
|
||||
func fetchAndLoadProjectsFromStorage() {
|
||||
self.networkModel.fetch {
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init() {
|
||||
loadProjectsFromStorage()
|
||||
self.delegate = contentTransfer
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum ProjectViewError: LocalizedError {
|
||||
case fileTransferUndefined
|
||||
}
|
||||
|
||||
|
||||
func readMyStatus() {
|
||||
|
||||
|
||||
print("BOOT INFO: \(bootUpInfo)")
|
||||
|
||||
switch bootUpInfo.description {
|
||||
|
|
@ -41,11 +68,11 @@ class BleModuleViewModel: ObservableObject {
|
|||
case let str where str.contains("circuitplayground_bluefruit"):
|
||||
print("Circuit Playground Bluefruit device")
|
||||
bootUpInfo = "circuitplayground_bluefruit"
|
||||
|
||||
|
||||
case let str where str.contains("clue_nrf52840_express"):
|
||||
print("Clue device")
|
||||
bootUpInfo = "clue_nrf52840_express"
|
||||
|
||||
|
||||
default:
|
||||
print("Unknown Device")
|
||||
}
|
||||
|
|
@ -71,7 +98,6 @@ class BleModuleViewModel: ObservableObject {
|
|||
|
||||
@Published var transmissionProgress: TransmissionProgress?
|
||||
@Published var lastTransmit: TransmissionLog? = TransmissionLog(type: .write(size: 334))
|
||||
@Published var activeAlert: ActiveAlert?
|
||||
// Data
|
||||
private let bleManager = BleManager.shared
|
||||
|
||||
|
|
@ -100,7 +126,7 @@ class BleModuleViewModel: ObservableObject {
|
|||
return modeText
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Setup
|
||||
func onAppear() {
|
||||
//registerNotifications(enabled: true)
|
||||
|
|
@ -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
|
||||
|
||||
func readFile(filename: String) {
|
||||
|
|
@ -135,8 +183,10 @@ class BleModuleViewModel: ObservableObject {
|
|||
let str = String(decoding: data, as: UTF8.self)
|
||||
|
||||
print("Read: \(str)")
|
||||
self.bootUpInfo = str
|
||||
sharedBootinfo = str
|
||||
|
||||
self.connectedBoard = self.setupBoardInfoForDisplay(str)
|
||||
self.boardInfoForView = self.connectedBoard
|
||||
|
||||
|
||||
case .failure(let error):
|
||||
self.lastTransmit = TransmissionLog(type: .error(message: error.localizedDescription))
|
||||
|
|
@ -344,18 +394,4 @@ class BleModuleViewModel: ObservableObject {
|
|||
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 {
|
||||
|
||||
@Binding var bindingString: String
|
||||
|
||||
let result: ResultItem
|
||||
|
||||
@EnvironmentObject var rootViewModel: RootViewModel
|
||||
@StateObject var viewModel = SubCellViewModel()
|
||||
@StateObject var contentTransfer = BleContentTransfer()
|
||||
//@StateObject var contentTransfer = BleContentTransfer()
|
||||
@StateObject var contentTransfer = BleContentTransfer.shared
|
||||
|
||||
|
||||
@ObservedObject var connectionManager = FileTransferConnectionManager.shared
|
||||
|
||||
|
|
@ -150,16 +150,7 @@ Try again later
|
|||
|
||||
if isConnected {
|
||||
|
||||
if result.compatibility.contains(bindingString) {
|
||||
|
||||
// Button {
|
||||
// viewModel.deleteStoredFilesInFM()
|
||||
// } label: {
|
||||
// Text("Delete File Manager Contents")
|
||||
// .bold()
|
||||
// .padding(12)
|
||||
// }
|
||||
|
||||
|
||||
if contentTransfer.downloadState == .idle {
|
||||
|
||||
Button(action: {
|
||||
|
|
@ -210,7 +201,7 @@ Try again later
|
|||
CompleteButton()
|
||||
.padding(.top, 20)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -231,9 +222,7 @@ Try again later
|
|||
|
||||
print("On Appear")
|
||||
contentTransfer.contentCommands.setup(fileTransferClient: connectionManager.selectedClient)
|
||||
|
||||
// viewModel.readFile(filename: "boot_out.txt")
|
||||
}
|
||||
}
|
||||
|
||||
.onChange(of: contentTransfer.transferError, perform: { newValue in
|
||||
if newValue {
|
||||
|
|
@ -246,15 +235,9 @@ Try again later
|
|||
showDownloadErrorMessage()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// .onChange(of: connectionManager.selectedClient) { selectedClient in
|
||||
// viewModel.setup(fileTransferClient: selectedClient)
|
||||
// }
|
||||
|
||||
|
||||
.onAppear(perform: {
|
||||
|
||||
contentTransfer.readMyStatus()
|
||||
viewModel.searchPathForProject(nameOf: result.projectName)
|
||||
|
||||
if viewModel.projectDownloaded {
|
||||
|
|
@ -36,7 +36,7 @@ struct DemoViewCell: View {
|
|||
if isExpanded {
|
||||
|
||||
Group {
|
||||
DemoSubview(bindingString: $deviceInfo, result: result, isConnected: $isConnected)
|
||||
DemoSubview(result: result, isConnected: $isConnected)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -54,8 +54,7 @@ struct RootView: View {
|
|||
case .selection:
|
||||
SelectionView()
|
||||
|
||||
case .wifiSelection:
|
||||
WifiSelection()
|
||||
|
||||
|
||||
case .wifiPairingTutorial:
|
||||
WifiPairingView()
|
||||
|
|
@ -47,7 +47,7 @@ public class RootViewModel: ObservableObject {
|
|||
}
|
||||
|
||||
func goToWiFiSelection() {
|
||||
destination = .wifiSelection
|
||||
destination = .wifiServiceSelection
|
||||
}
|
||||
|
||||
func goToWifiView() {
|
||||
|
|
@ -16,8 +16,6 @@ struct WifiHeaderView: View {
|
|||
|
||||
VStack {
|
||||
|
||||
|
||||
|
||||
HStack (alignment: .center, spacing: 0) {
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -58,31 +58,42 @@ class MainSelectionViewModel: ObservableObject {
|
|||
let dataStore = DataStore()
|
||||
|
||||
@Published var pdemos : [ResultItem] = []
|
||||
|
||||
var networkMonitorCancellable: AnyCancellable?
|
||||
|
||||
init() {
|
||||
let fileURL = documentsDirectory.appendingPathComponent("StandardPyLeapProjects.json")
|
||||
|
||||
|
||||
startUp()
|
||||
}
|
||||
|
||||
|
||||
func loadProjectsFromStorage() {
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
}
|
||||
|
||||
func fetchAndLoadProjectsFromStorage() {
|
||||
self.networkModel.fetch {
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
}
|
||||
}
|
||||
|
||||
func startUp(){
|
||||
networkMonitorCancellable = networkMonitor.$isConnected.sink { isConnected in
|
||||
if isConnected {
|
||||
print("The device is currently connected to the internet.")
|
||||
// Perform some action when the device is connected to the internet.
|
||||
self.networkModel.fetch {
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
}
|
||||
|
||||
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 {
|
||||
print("The device is not currently connected to the internet.")
|
||||
// Perform some action when the device is not connected to the internet.
|
||||
print("Loading cached remote data.")
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
|
||||
self.loadProjectsFromStorage()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ struct SelectionView: View {
|
|||
Button {
|
||||
rootViewModel.goToWiFiSelection()
|
||||
} label: {
|
||||
Text("Wifi")
|
||||
Text("WiFi")
|
||||
.font(Font.custom("ReadexPro-Regular", size: 25))
|
||||
.foregroundColor(Color.white)
|
||||
.frame(width: 270, height: 50, alignment: .center)
|
||||
|
|
@ -110,6 +110,9 @@ struct SelectionView: View {
|
|||
|
||||
}
|
||||
.padding(.bottom, 60)
|
||||
.onAppear() {
|
||||
print("In Selection view")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import Combine
|
|||
|
||||
struct WifiView: View {
|
||||
|
||||
@StateObject var viewModel = WifiViewModel()
|
||||
@StateObject var vm = WifiViewModel()
|
||||
private let kPrefix = Bundle.main.bundleIdentifier!
|
||||
|
||||
// User Defaults
|
||||
|
|
@ -38,12 +38,12 @@ struct WifiView: View {
|
|||
@State private var showPopover: Bool = false
|
||||
|
||||
func toggleViewModelIP() {
|
||||
viewModel.isInvalidIP.toggle()
|
||||
vm.isInvalidIP.toggle()
|
||||
}
|
||||
|
||||
|
||||
func scanNetworkWifi() {
|
||||
viewModel.wifiServiceManager.findService()
|
||||
vm.wifiServiceManager.findService()
|
||||
}
|
||||
|
||||
func printArray(array: [Any]) {
|
||||
|
|
@ -59,9 +59,9 @@ struct WifiView: View {
|
|||
|
||||
} else {
|
||||
hostName = userDefaults.object(forKey: kPrefix+".storeResolvedAddress.hostName") as! String
|
||||
viewModel.ipAddressStored = true
|
||||
vm.ipAddressStored = true
|
||||
print("storeResolvedAddress - is stored")
|
||||
viewModel.connectionStatus = .connected
|
||||
vm.connectionStatus = .connected
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -71,28 +71,40 @@ struct WifiView: View {
|
|||
hintText: "IP Address...",
|
||||
primaryTitle: "Done",
|
||||
secondaryTitle: "Cancel") { text in
|
||||
viewModel.checkServices(ip: text)
|
||||
vm.checkServices(ip: text)
|
||||
|
||||
} secondaryAction: {
|
||||
print("Cancel")
|
||||
}
|
||||
}
|
||||
|
||||
func showConfirmationPrompt() {
|
||||
comfirmationAlertMessage(title: "Are you sure you want to disconnect?", exitTitle: "Cancel", primaryTitle: "Disconnect") {
|
||||
rootViewModel.goToSelection()
|
||||
} cancel: {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func showAlertMessage() {
|
||||
alertMessage(title: "IP address Not Found", exitTitle: "Ok") {
|
||||
showValidationPrompt()
|
||||
}
|
||||
}
|
||||
|
||||
@State var boardInfoForView = Board.shared
|
||||
|
||||
var body: some View {
|
||||
|
||||
VStack(spacing: 0) {
|
||||
WifiHeaderView()
|
||||
|
||||
Group{
|
||||
switch viewModel.connectionStatus {
|
||||
switch vm.connectionStatus {
|
||||
case .connected:
|
||||
WifiStatusConnectedView(hostName: $hostName)
|
||||
WifiStatusConnectedView(hostName: $hostName, disconnectAction: {
|
||||
showConfirmationPrompt()
|
||||
})
|
||||
case .noConnection:
|
||||
WifiStatusNoConnectionView()
|
||||
case .connecting:
|
||||
|
|
@ -100,65 +112,58 @@ struct WifiView: View {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
|
||||
ScrollViewReader { scroll in
|
||||
|
||||
SubHeaderView()
|
||||
|
||||
|
||||
let check = viewModel.pdemos.filter {
|
||||
$0.compatibility.contains(boardBootInfo)
|
||||
}
|
||||
|
||||
let check = vm.pdemos.filter {
|
||||
$0.compatibility.contains(boardBootInfo)
|
||||
}
|
||||
|
||||
ForEach(check) { demo in
|
||||
|
||||
if demo.bundleLink == test.currentCell {
|
||||
WifiCell(result: demo,isExpanded: trueTog, isConnected: $inConnectedInWifiView, bootOne: $boardBootInfo, stateBinder: $downloadState, onViewGeometryChanged: {
|
||||
|
||||
|
||||
})
|
||||
.onAppear(){
|
||||
|
||||
withAnimation {
|
||||
scroll.scrollTo(demo.id)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
WifiCell(result: demo, isExpanded: falseTog, isConnected: $inConnectedInWifiView, bootOne: $boardBootInfo, stateBinder: $downloadState, onViewGeometryChanged: {
|
||||
withAnimation {
|
||||
// scroll.scrollTo(demo.id)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.id(self.scrollViewID)
|
||||
}
|
||||
.foregroundColor(.black)
|
||||
.environmentObject(test)
|
||||
.refreshable {
|
||||
vm.fetchAndLoadProjectsFromStorage()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.onChange(of: viewModel.connectionStatus, perform: { newValue in
|
||||
.onChange(of: vm.connectionStatus, perform: { newValue in
|
||||
if newValue == .connected {
|
||||
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(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")
|
||||
if newValue {
|
||||
showAlertMessage()
|
||||
|
|
@ -185,8 +190,8 @@ struct WifiView: View {
|
|||
|
||||
.onAppear(){
|
||||
checkForStoredIPAddress()
|
||||
viewModel.printStoredInfo()
|
||||
viewModel.read()
|
||||
vm.printStoredInfo()
|
||||
vm.read()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -17,52 +17,7 @@ struct TestIndex {
|
|||
}
|
||||
|
||||
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 {
|
||||
var count = 0
|
||||
var numberOfFiles = 0
|
||||
|
|
@ -74,13 +29,10 @@ class WifiFileTransfer: ObservableObject {
|
|||
downloadState = .idle
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
var testIndex = TestIndex()
|
||||
|
||||
|
||||
func copy(with zone: NSZone? = nil) -> Any {
|
||||
let copy = WifiFileTransfer()
|
||||
copy.counter = counter
|
||||
|
|
@ -125,6 +77,7 @@ class WifiFileTransfer: ObservableObject {
|
|||
|
||||
func printArray(array: [Any]) {
|
||||
|
||||
print("From print array:")
|
||||
for i in array {
|
||||
print("\(i)")
|
||||
}
|
||||
|
|
@ -339,34 +292,20 @@ class WifiFileTransfer: ObservableObject {
|
|||
|
||||
func filterOutCPDirectories(urls: [URL]) -> [URL] {
|
||||
// Removes - CircuitPython 8.x directory at the lastPathComponent
|
||||
let removingCP8FromArray = urls.filter {
|
||||
$0.lastPathComponent != ("CircuitPython 8.x")
|
||||
let filteredList = urls.filter {
|
||||
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 removingCP7FromArray = removingCP8FromArray.filter {
|
||||
$0.lastPathComponent != ("CircuitPython 7.x")
|
||||
let listForCurrentCPVersion = filteredList.filter {
|
||||
$0.absoluteString.contains("CircuitPython%20\(Board.shared.versionNumber).x")
|
||||
}
|
||||
|
||||
if WifiCPVersion.versionNumber == 8 {
|
||||
let listForCurrentCPVersion = removingCP7FromArray.filter {
|
||||
!$0.absoluteString.contains("CircuitPython%207.x")
|
||||
|
||||
}
|
||||
return listForCurrentCPVersion
|
||||
}
|
||||
printArray(array: listForCurrentCPVersion)
|
||||
|
||||
if WifiCPVersion.versionNumber == 7 {
|
||||
let listForCurrentCPVersion = removingCP7FromArray.filter {
|
||||
!$0.absoluteString.contains("CircuitPython%208.x")
|
||||
|
||||
}
|
||||
return listForCurrentCPVersion
|
||||
}
|
||||
|
||||
|
||||
|
||||
return removingCP7FromArray
|
||||
return listForCurrentCPVersion
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -419,8 +358,6 @@ class WifiFileTransfer: ObservableObject {
|
|||
DispatchQueue.main.async {
|
||||
self.numOfFiles = tempArray.count
|
||||
self.makeFile(files: tempArray)
|
||||
// self.testIndex.numberOfFiles = self.numOfFiles
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -618,7 +555,6 @@ class WifiFileTransfer: ObservableObject {
|
|||
printArray(array: files)
|
||||
var copiedArray = files
|
||||
|
||||
// self.fetchDocumentsq(in: files)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
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)
|
||||
// }
|
||||
//}
|
||||
87
PyLeap/Features/Wifi Module/WifiServiceCellView.swift
Normal file
87
PyLeap/Features/Wifi Module/WifiServiceCellView.swift
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
//
|
||||
// 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() }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//struct WifiServiceCellView_Previews: PreviewProvider {
|
||||
// static var previews: some View {
|
||||
// WifiServiceCellView()
|
||||
// }
|
||||
//}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
// PyLeap
|
||||
//
|
||||
// Created by Trevor Beaton on 10/24/22.
|
||||
//
|
||||
// Testing
|
||||
|
||||
import SwiftUI
|
||||
|
||||
|
|
@ -9,19 +9,16 @@ import SwiftUI
|
|||
import Foundation
|
||||
|
||||
struct WifiStatusConnectedView: View {
|
||||
|
||||
let userDefaults = UserDefaults.standard
|
||||
private let kPrefix = Bundle.main.bundleIdentifier!
|
||||
@EnvironmentObject var rootViewModel: RootViewModel
|
||||
|
||||
@Binding var hostName: String
|
||||
|
||||
var disconnectAction: () -> Void
|
||||
|
||||
func showConfirmationPrompt() {
|
||||
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 {
|
||||
|
|
@ -33,16 +30,13 @@ struct WifiStatusConnectedView: View {
|
|||
.frame(width: 20, height: 20)
|
||||
.padding(5)
|
||||
|
||||
Text("Connected to \(hostName). ")
|
||||
Text("Connected to \(hostName) ")
|
||||
.font(Font.custom("ReadexPro-Regular", size: 14))
|
||||
|
||||
Button {
|
||||
showConfirmationPrompt()
|
||||
} label: {
|
||||
Button(action: disconnectAction) {
|
||||
Text("Disconnect")
|
||||
.font(Font.custom("ReadexPro-Bold", size: 14))
|
||||
.underline()
|
||||
.minimumScaleFactor(0.1)
|
||||
}
|
||||
|
||||
})
|
||||
|
|
@ -69,32 +69,7 @@ class WifiSubViewCellModel: ObservableObject {
|
|||
print("Failure")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// 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()
|
||||
|
||||
// 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)
|
||||
|
||||
request.addValue("application/json", forHTTPHeaderField: "Accept")
|
||||
|
|
@ -226,7 +226,6 @@ class WifiTransferService: ObservableObject {
|
|||
|
||||
let loginData = loginString.data(using: String.Encoding.utf8)
|
||||
|
||||
|
||||
let base64LoginString = loginData!.base64EncodedString()
|
||||
|
||||
print("Host Name: \(hostName)")
|
||||
|
|
@ -27,6 +27,7 @@ class WifiViewModel: ObservableObject {
|
|||
@Published var ipInputValidation = false
|
||||
//Dependencies
|
||||
var networkMonitor = NetworkMonitor()
|
||||
|
||||
var networkAuth = LocalNetworkAuthorization()
|
||||
|
||||
public var wifiNetworkService = WifiNetworkService()
|
||||
|
|
@ -34,7 +35,7 @@ class WifiViewModel: ObservableObject {
|
|||
@Published var wifiTransferService = WifiTransferService()
|
||||
|
||||
@Published var wifiServiceManager = WifiServiceManager()
|
||||
|
||||
@ObservedObject var networkModel = NetworkService()
|
||||
var circuitPythonVersion = Int()
|
||||
|
||||
@Published var webDirectoryInfo = [WebDirectoryModel]()
|
||||
|
|
@ -48,6 +49,16 @@ class WifiViewModel: ObservableObject {
|
|||
@Published var pdemos : [ResultItem] = []
|
||||
|
||||
|
||||
func loadProjectsFromStorage() {
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
}
|
||||
|
||||
func fetchAndLoadProjectsFromStorage() {
|
||||
self.networkModel.fetch {
|
||||
self.pdemos = self.dataStore.loadDefaultList()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// File Manager Data
|
||||
let directoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
|
||||
|
|
@ -59,11 +70,10 @@ class WifiViewModel: ObservableObject {
|
|||
var ipAddressStored = false
|
||||
|
||||
init() {
|
||||
pdemos = dataStore.loadDefaultList()
|
||||
loadProjectsFromStorage()
|
||||
checkIP()
|
||||
registerNotifications(enabled: true)
|
||||
wifiServiceManager.findService()
|
||||
//read()
|
||||
}
|
||||
|
||||
/// Makes a network call to populate our project list
|
||||
|
|
@ -72,26 +82,36 @@ class WifiViewModel: ObservableObject {
|
|||
}
|
||||
|
||||
@Published var pyleapProjects = [ResultItem]()
|
||||
|
||||
|
||||
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() {
|
||||
setBoardToDefault()
|
||||
// This method can't be used until the device has permission to communicate.
|
||||
print("READING CP Vers.")
|
||||
wifiTransferService.getRequest(read: "boot_out.txt") { result in
|
||||
|
||||
let boardID = self.boardDataProvider.getBoardID(from: result) ?? "Unrecognized Board"
|
||||
// Board default version is set to 8
|
||||
let boardVersion = self.boardDataProvider.getCircuitPythonMajorVersion(from: result) ?? "8"
|
||||
|
||||
if result.contains("CircuitPython 7") {
|
||||
WifiCPVersion.versionNumber = 7
|
||||
print("WifiCPVersion.versionNumber set to: \(WifiCPVersion.versionNumber)")
|
||||
}
|
||||
|
||||
if result.contains("CircuitPython 8") {
|
||||
WifiCPVersion.versionNumber = 8
|
||||
print("WifiCPVersion.versionNumber set to: \(WifiCPVersion.versionNumber)")
|
||||
}
|
||||
Board.shared.name = boardID
|
||||
Board.shared.versionNumber = boardVersion
|
||||
dump(Board.shared)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private weak var invalidIPObserver: NSObjectProtocol?
|
||||
|
|
@ -146,12 +166,7 @@ class WifiViewModel: ObservableObject {
|
|||
connectionStatus = .connected
|
||||
}
|
||||
|
||||
// @Published var connectionStatus: ConnectionStatus = AppEnvironment.isRunningTests ? .connected : .noConnection
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func printStoredInfo() {
|
||||
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.
|
||||
*/
|
||||
|
||||
public class DataStore {
|
||||
public class DataStore: ObservableObject {
|
||||
|
||||
let fileManager = FileManager.default
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ public class DataStore {
|
|||
*/
|
||||
|
||||
func save(content: [ResultItem], completion: @escaping () -> Void) {
|
||||
|
||||
print(#function)
|
||||
let encoder = JSONEncoder()
|
||||
if let encodedProjectData = try? encoder.encode(content) {
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ public class DataStore {
|
|||
}
|
||||
|
||||
/**
|
||||
/// : 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] {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import Foundation
|
|||
import SwiftUI
|
||||
|
||||
class NetworkService: ObservableObject {
|
||||
|
||||
let dataStore = DataStore()
|
||||
|
||||
let thirdPartyBackgroundQueue = DispatchQueue(label: "com.PyLeap.thirdPartyBackgroundQueue", qos: .background, attributes: .concurrent)
|
||||
|
|
@ -43,7 +44,7 @@ class NetworkService: ObservableObject {
|
|||
|
||||
if let data = data {
|
||||
|
||||
print("Updating UIList with new data...")
|
||||
print("Updating storage with new data.")
|
||||
if let projectData = try? JSONDecoder().decode(RootResults.self, from: data) {
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
|
|
|||
|
|
@ -175,6 +175,9 @@ Find more information on adding your own project here:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
extension View {
|
||||
|
||||
func comfirmationAlertMessage(title: String, exitTitle: String, primaryTitle: String,disconnect: @escaping() -> (),cancel: @escaping() -> ()){
|
||||
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