mirror of
https://github.com/nicoverbruggen/phpmon.git
synced 2025-08-07 20:10:08 +02:00
🏗 SwiftUI experiments
This commit is contained in:
@ -143,6 +143,18 @@
|
|||||||
C4570C3B28FC355300D18420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C473319E2470923A009A0597 /* Localizable.strings */; };
|
C4570C3B28FC355300D18420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C473319E2470923A009A0597 /* Localizable.strings */; };
|
||||||
C4570C3C28FC355400D18420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C473319E2470923A009A0597 /* Localizable.strings */; };
|
C4570C3C28FC355400D18420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = C473319E2470923A009A0597 /* Localizable.strings */; };
|
||||||
C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */; };
|
C459B4BD27F6093700E9B4B4 /* nginx-proxy.test in Resources */ = {isa = PBXBuildFile; fileRef = C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */; };
|
||||||
|
C45B9149295607F400F4EC78 /* ServiceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B9148295607F400F4EC78 /* ServiceWrapper.swift */; };
|
||||||
|
C45B914A295607F400F4EC78 /* ServiceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B9148295607F400F4EC78 /* ServiceWrapper.swift */; };
|
||||||
|
C45B914B295607F400F4EC78 /* ServiceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B9148295607F400F4EC78 /* ServiceWrapper.swift */; };
|
||||||
|
C45B914C295607F400F4EC78 /* ServiceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B9148295607F400F4EC78 /* ServiceWrapper.swift */; };
|
||||||
|
C45B914E295608E300F4EC78 /* ValetServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B914D295608E300F4EC78 /* ValetServicesManager.swift */; };
|
||||||
|
C45B914F295608E300F4EC78 /* ValetServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B914D295608E300F4EC78 /* ValetServicesManager.swift */; };
|
||||||
|
C45B9150295608E300F4EC78 /* ValetServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B914D295608E300F4EC78 /* ValetServicesManager.swift */; };
|
||||||
|
C45B9151295608E300F4EC78 /* ValetServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B914D295608E300F4EC78 /* ValetServicesManager.swift */; };
|
||||||
|
C45B91532956123A00F4EC78 /* FakeServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B91522956123A00F4EC78 /* FakeServicesManager.swift */; };
|
||||||
|
C45B91542956123A00F4EC78 /* FakeServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B91522956123A00F4EC78 /* FakeServicesManager.swift */; };
|
||||||
|
C45B91552956123A00F4EC78 /* FakeServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B91522956123A00F4EC78 /* FakeServicesManager.swift */; };
|
||||||
|
C45B91562956123A00F4EC78 /* FakeServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45B91522956123A00F4EC78 /* FakeServicesManager.swift */; };
|
||||||
C45E2A7529199248005C7CFD /* InternalSwitcherTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C471E7AF28F9B4940021E251 /* InternalSwitcherTest.swift */; };
|
C45E2A7529199248005C7CFD /* InternalSwitcherTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C471E7AF28F9B4940021E251 /* InternalSwitcherTest.swift */; };
|
||||||
C45E2A77291992DA005C7CFD /* FeatureTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E2A76291992DA005C7CFD /* FeatureTestCase.swift */; };
|
C45E2A77291992DA005C7CFD /* FeatureTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E2A76291992DA005C7CFD /* FeatureTestCase.swift */; };
|
||||||
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
|
C45E76142854A65300B4FE0C /* ServicesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C45E76132854A65300B4FE0C /* ServicesManager.swift */; };
|
||||||
@ -786,6 +798,9 @@
|
|||||||
C44F868D2835BD8D005C353A /* phpmon-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "phpmon-config.json"; sourceTree = "<group>"; };
|
C44F868D2835BD8D005C353A /* phpmon-config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "phpmon-config.json"; sourceTree = "<group>"; };
|
||||||
C450C8C528C919EC002A2B4B /* PreferenceName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceName.swift; sourceTree = "<group>"; };
|
C450C8C528C919EC002A2B4B /* PreferenceName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceName.swift; sourceTree = "<group>"; };
|
||||||
C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-proxy.test"; sourceTree = "<group>"; };
|
C459B4BC27F6093700E9B4B4 /* nginx-proxy.test */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "nginx-proxy.test"; sourceTree = "<group>"; };
|
||||||
|
C45B9148295607F400F4EC78 /* ServiceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServiceWrapper.swift; sourceTree = "<group>"; };
|
||||||
|
C45B914D295608E300F4EC78 /* ValetServicesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetServicesManager.swift; sourceTree = "<group>"; };
|
||||||
|
C45B91522956123A00F4EC78 /* FakeServicesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakeServicesManager.swift; sourceTree = "<group>"; };
|
||||||
C45E2A76291992DA005C7CFD /* FeatureTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureTestCase.swift; sourceTree = "<group>"; };
|
C45E2A76291992DA005C7CFD /* FeatureTestCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureTestCase.swift; sourceTree = "<group>"; };
|
||||||
C45E76132854A65300B4FE0C /* ServicesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesManager.swift; sourceTree = "<group>"; };
|
C45E76132854A65300B4FE0C /* ServicesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServicesManager.swift; sourceTree = "<group>"; };
|
||||||
C463E37F284930EE00422731 /* PresetHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetHelper.swift; sourceTree = "<group>"; };
|
C463E37F284930EE00422731 /* PresetHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PresetHelper.swift; sourceTree = "<group>"; };
|
||||||
@ -1275,6 +1290,17 @@
|
|||||||
path = php;
|
path = php;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
C45B9147295607E200F4EC78 /* Services */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
C45E76132854A65300B4FE0C /* ServicesManager.swift */,
|
||||||
|
C45B914D295608E300F4EC78 /* ValetServicesManager.swift */,
|
||||||
|
C45B9148295607F400F4EC78 /* ServiceWrapper.swift */,
|
||||||
|
C45B91522956123A00F4EC78 /* FakeServicesManager.swift */,
|
||||||
|
);
|
||||||
|
path = Services;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
C464ADAA275A7A25003FCD53 /* DomainList */ = {
|
C464ADAA275A7A25003FCD53 /* DomainList */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -1423,6 +1449,7 @@
|
|||||||
C4B13B1D25C4915000548C3A /* App */ = {
|
C4B13B1D25C4915000548C3A /* App */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
C45B9147295607E200F4EC78 /* Services */,
|
||||||
C41C1B3C22B0098000E7CF16 /* Main.storyboard */,
|
C41C1B3C22B0098000E7CF16 /* Main.storyboard */,
|
||||||
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */,
|
C41C1B3622B0097F00E7CF16 /* AppDelegate.swift */,
|
||||||
C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */,
|
C4B97B74275CF08C003F3378 /* AppDelegate+MenuOutlets.swift */,
|
||||||
@ -1436,7 +1463,6 @@
|
|||||||
C495F5AE28A42E080087F70A /* EnvironmentCheck.swift */,
|
C495F5AE28A42E080087F70A /* EnvironmentCheck.swift */,
|
||||||
C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */,
|
C46E206C28299B3800D909D6 /* AppUpdateChecker.swift */,
|
||||||
C40FE736282ABA4F00A302C2 /* AppVersion.swift */,
|
C40FE736282ABA4F00A302C2 /* AppVersion.swift */,
|
||||||
C45E76132854A65300B4FE0C /* ServicesManager.swift */,
|
|
||||||
C4A6957528D23EE300A14CF8 /* EnvironmentManager.swift */,
|
C4A6957528D23EE300A14CF8 /* EnvironmentManager.swift */,
|
||||||
);
|
);
|
||||||
path = App;
|
path = App;
|
||||||
@ -1954,8 +1980,10 @@
|
|||||||
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */,
|
5420395926135DC100FB00FA /* PrefsVC.swift in Sources */,
|
||||||
C4C8900328F0E28800CE5E97 /* FileSystemProtocol.swift in Sources */,
|
C4C8900328F0E28800CE5E97 /* FileSystemProtocol.swift in Sources */,
|
||||||
C43603A0275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
|
C43603A0275E67610028EFC6 /* AppDelegate+Notifications.swift in Sources */,
|
||||||
|
C45B9149295607F400F4EC78 /* ServiceWrapper.swift in Sources */,
|
||||||
5489625828312FAD004F647A /* CreatedFromFile.swift in Sources */,
|
5489625828312FAD004F647A /* CreatedFromFile.swift in Sources */,
|
||||||
C4068CA727B07A1300544CD5 /* SelectPreferenceView.swift in Sources */,
|
C4068CA727B07A1300544CD5 /* SelectPreferenceView.swift in Sources */,
|
||||||
|
C45B91532956123A00F4EC78 /* FakeServicesManager.swift in Sources */,
|
||||||
C41C708D28AA7F7900E8D498 /* NoWarningsView.swift in Sources */,
|
C41C708D28AA7F7900E8D498 /* NoWarningsView.swift in Sources */,
|
||||||
C4080FF627BD8C6400BF2C6B /* BetterAlert.swift in Sources */,
|
C4080FF627BD8C6400BF2C6B /* BetterAlert.swift in Sources */,
|
||||||
C4E0F7ED27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */,
|
C4E0F7ED27BEBDA9007475F2 /* NSWindowExtension.swift in Sources */,
|
||||||
@ -1967,6 +1995,7 @@
|
|||||||
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */,
|
C4E4404627C56F4700D225E1 /* ValetSite.swift in Sources */,
|
||||||
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
|
C4F2E43A2752F7D00020E974 /* PhpInstallation.swift in Sources */,
|
||||||
C4D9F24B280B69E100DCD39A /* AddProxyVC.swift in Sources */,
|
C4D9F24B280B69E100DCD39A /* AddProxyVC.swift in Sources */,
|
||||||
|
C45B914E295608E300F4EC78 /* ValetServicesManager.swift in Sources */,
|
||||||
C4E49DED28F764A00026AC4E /* TestableCommand.swift in Sources */,
|
C4E49DED28F764A00026AC4E /* TestableCommand.swift in Sources */,
|
||||||
C4A6957628D23EE300A14CF8 /* EnvironmentManager.swift in Sources */,
|
C4A6957628D23EE300A14CF8 /* EnvironmentManager.swift in Sources */,
|
||||||
C41E871A2763D42300161EE0 /* DomainListVC+ContextMenu.swift in Sources */,
|
C41E871A2763D42300161EE0 /* DomainListVC+ContextMenu.swift in Sources */,
|
||||||
@ -2155,6 +2184,7 @@
|
|||||||
C471E86328F9BB650021E251 /* PMTableView.swift in Sources */,
|
C471E86328F9BB650021E251 /* PMTableView.swift in Sources */,
|
||||||
C471E86428F9BB650021E251 /* Warning.swift in Sources */,
|
C471E86428F9BB650021E251 /* Warning.swift in Sources */,
|
||||||
C40175BA2903108900763A68 /* ValetInteractor.swift in Sources */,
|
C40175BA2903108900763A68 /* ValetInteractor.swift in Sources */,
|
||||||
|
C45B9150295608E300F4EC78 /* ValetServicesManager.swift in Sources */,
|
||||||
C471E86528F9BB650021E251 /* WarningManager.swift in Sources */,
|
C471E86528F9BB650021E251 /* WarningManager.swift in Sources */,
|
||||||
C471E86628F9BB650021E251 /* WarningsWindowController.swift in Sources */,
|
C471E86628F9BB650021E251 /* WarningsWindowController.swift in Sources */,
|
||||||
C471E86728F9BB650021E251 /* OnboardingWindowController.swift in Sources */,
|
C471E86728F9BB650021E251 /* OnboardingWindowController.swift in Sources */,
|
||||||
@ -2196,6 +2226,7 @@
|
|||||||
C471E88E28F9BB650021E251 /* KeyCombo.swift in Sources */,
|
C471E88E28F9BB650021E251 /* KeyCombo.swift in Sources */,
|
||||||
C471E88F28F9BB650021E251 /* ModifierFlagsExtension.swift in Sources */,
|
C471E88F28F9BB650021E251 /* ModifierFlagsExtension.swift in Sources */,
|
||||||
C471E7E928F9BAC20021E251 /* Paths.swift in Sources */,
|
C471E7E928F9BAC20021E251 /* Paths.swift in Sources */,
|
||||||
|
C45B91552956123A00F4EC78 /* FakeServicesManager.swift in Sources */,
|
||||||
C471E7FE28F9BACE0021E251 /* HomebrewPackage.swift in Sources */,
|
C471E7FE28F9BACE0021E251 /* HomebrewPackage.swift in Sources */,
|
||||||
C471E7D828F9BA8F0021E251 /* FileSystemProtocol.swift in Sources */,
|
C471E7D828F9BA8F0021E251 /* FileSystemProtocol.swift in Sources */,
|
||||||
C471E7F328F9BAC70021E251 /* PhpHelper.swift in Sources */,
|
C471E7F328F9BAC70021E251 /* PhpHelper.swift in Sources */,
|
||||||
@ -2225,6 +2256,7 @@
|
|||||||
C471E7F228F9BAC70021E251 /* PhpEnv.swift in Sources */,
|
C471E7F228F9BAC70021E251 /* PhpEnv.swift in Sources */,
|
||||||
C471E7E628F9BAC20021E251 /* Process.swift in Sources */,
|
C471E7E628F9BAC20021E251 /* Process.swift in Sources */,
|
||||||
C471E81928F9BAE80021E251 /* NSMenuItemExtension.swift in Sources */,
|
C471E81928F9BAE80021E251 /* NSMenuItemExtension.swift in Sources */,
|
||||||
|
C45B914B295607F400F4EC78 /* ServiceWrapper.swift in Sources */,
|
||||||
C471E7D928F9BA8F0021E251 /* TestableShell.swift in Sources */,
|
C471E7D928F9BA8F0021E251 /* TestableShell.swift in Sources */,
|
||||||
C471E81428F9BAE80021E251 /* NSWindowExtension.swift in Sources */,
|
C471E81428F9BAE80021E251 /* NSWindowExtension.swift in Sources */,
|
||||||
C471E7D328F9BA8F0021E251 /* ActiveShell.swift in Sources */,
|
C471E7D328F9BA8F0021E251 /* ActiveShell.swift in Sources */,
|
||||||
@ -2277,6 +2309,7 @@
|
|||||||
C471E8A528F9BB8F0021E251 /* AppDelegate+InterApp.swift in Sources */,
|
C471E8A528F9BB8F0021E251 /* AppDelegate+InterApp.swift in Sources */,
|
||||||
C471E8A628F9BB8F0021E251 /* App.swift in Sources */,
|
C471E8A628F9BB8F0021E251 /* App.swift in Sources */,
|
||||||
C471E8A728F9BB8F0021E251 /* App+ActivationPolicy.swift in Sources */,
|
C471E8A728F9BB8F0021E251 /* App+ActivationPolicy.swift in Sources */,
|
||||||
|
C45B914C295607F400F4EC78 /* ServiceWrapper.swift in Sources */,
|
||||||
C471E8A828F9BB8F0021E251 /* App+GlobalHotkey.swift in Sources */,
|
C471E8A828F9BB8F0021E251 /* App+GlobalHotkey.swift in Sources */,
|
||||||
C471E8A928F9BB8F0021E251 /* InterAppHandler.swift in Sources */,
|
C471E8A928F9BB8F0021E251 /* InterAppHandler.swift in Sources */,
|
||||||
C471E8AA28F9BB8F0021E251 /* Startup.swift in Sources */,
|
C471E8AA28F9BB8F0021E251 /* Startup.swift in Sources */,
|
||||||
@ -2309,6 +2342,7 @@
|
|||||||
C4D36618291160A1006BD146 /* WIP.swift in Sources */,
|
C4D36618291160A1006BD146 /* WIP.swift in Sources */,
|
||||||
C471E8C328F9BB8F0021E251 /* SelectionVC.swift in Sources */,
|
C471E8C328F9BB8F0021E251 /* SelectionVC.swift in Sources */,
|
||||||
C471E8C428F9BB8F0021E251 /* AddSiteVC.swift in Sources */,
|
C471E8C428F9BB8F0021E251 /* AddSiteVC.swift in Sources */,
|
||||||
|
C45B91562956123A00F4EC78 /* FakeServicesManager.swift in Sources */,
|
||||||
C471E8C528F9BB8F0021E251 /* AddProxyVC.swift in Sources */,
|
C471E8C528F9BB8F0021E251 /* AddProxyVC.swift in Sources */,
|
||||||
C471E8C628F9BB8F0021E251 /* PMTableView.swift in Sources */,
|
C471E8C628F9BB8F0021E251 /* PMTableView.swift in Sources */,
|
||||||
C471E8C728F9BB8F0021E251 /* Warning.swift in Sources */,
|
C471E8C728F9BB8F0021E251 /* Warning.swift in Sources */,
|
||||||
@ -2347,6 +2381,7 @@
|
|||||||
C471E8EA28F9BB8F0021E251 /* SectionHeaderView.swift in Sources */,
|
C471E8EA28F9BB8F0021E251 /* SectionHeaderView.swift in Sources */,
|
||||||
C4D36604291132B7006BD146 /* ValetScanners.swift in Sources */,
|
C4D36604291132B7006BD146 /* ValetScanners.swift in Sources */,
|
||||||
C471E8EB28F9BB8F0021E251 /* HeaderView.swift in Sources */,
|
C471E8EB28F9BB8F0021E251 /* HeaderView.swift in Sources */,
|
||||||
|
C45B9151295608E300F4EC78 /* ValetServicesManager.swift in Sources */,
|
||||||
C471E8EC28F9BB8F0021E251 /* SwiftUIHelper.swift in Sources */,
|
C471E8EC28F9BB8F0021E251 /* SwiftUIHelper.swift in Sources */,
|
||||||
C471E8EE28F9BB8F0021E251 /* HotKey.swift in Sources */,
|
C471E8EE28F9BB8F0021E251 /* HotKey.swift in Sources */,
|
||||||
C471E8EF28F9BB8F0021E251 /* HotKeysController.swift in Sources */,
|
C471E8EF28F9BB8F0021E251 /* HotKeysController.swift in Sources */,
|
||||||
@ -2465,6 +2500,7 @@
|
|||||||
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */,
|
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */,
|
||||||
C4C1019C27C65C6F001FACC2 /* Process.swift in Sources */,
|
C4C1019C27C65C6F001FACC2 /* Process.swift in Sources */,
|
||||||
C4F780C025D80B6E000DBC97 /* Startup.swift in Sources */,
|
C4F780C025D80B6E000DBC97 /* Startup.swift in Sources */,
|
||||||
|
C45B914A295607F400F4EC78 /* ServiceWrapper.swift in Sources */,
|
||||||
C4C0E8E327F88B13002D32A9 /* ValetDomainScanner.swift in Sources */,
|
C4C0E8E327F88B13002D32A9 /* ValetDomainScanner.swift in Sources */,
|
||||||
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */,
|
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */,
|
||||||
C4B5635F276AB09000F12CCB /* VersionExtractor.swift in Sources */,
|
C4B5635F276AB09000F12CCB /* VersionExtractor.swift in Sources */,
|
||||||
@ -2530,6 +2566,7 @@
|
|||||||
C4D3660C29113F20006BD146 /* System.swift in Sources */,
|
C4D3660C29113F20006BD146 /* System.swift in Sources */,
|
||||||
C4D936CA27E3EB6100BD69FE /* PhpHelper.swift in Sources */,
|
C4D936CA27E3EB6100BD69FE /* PhpHelper.swift in Sources */,
|
||||||
C4D36611291140BE006BD146 /* TestableFileSystemTest.swift in Sources */,
|
C4D36611291140BE006BD146 /* TestableFileSystemTest.swift in Sources */,
|
||||||
|
C45B91542956123A00F4EC78 /* FakeServicesManager.swift in Sources */,
|
||||||
C4E2E84B28FC1E70003B070C /* DataExtension.swift in Sources */,
|
C4E2E84B28FC1E70003B070C /* DataExtension.swift in Sources */,
|
||||||
C449B4F127EE7FC200C47E8A /* DomainListNameCell.swift in Sources */,
|
C449B4F127EE7FC200C47E8A /* DomainListNameCell.swift in Sources */,
|
||||||
C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */,
|
C4F780BA25D80B62000DBC97 /* AppDelegate.swift in Sources */,
|
||||||
@ -2559,6 +2596,7 @@
|
|||||||
C4B585452770FE3900DA4FBE /* RealCommand.swift in Sources */,
|
C4B585452770FE3900DA4FBE /* RealCommand.swift in Sources */,
|
||||||
C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */,
|
C4F780C525D80B75000DBC97 /* MenuBarImageGenerator.swift in Sources */,
|
||||||
C4F780B725D80B5D000DBC97 /* App.swift in Sources */,
|
C4F780B725D80B5D000DBC97 /* App.swift in Sources */,
|
||||||
|
C45B914F295608E300F4EC78 /* ValetServicesManager.swift in Sources */,
|
||||||
C4927F0C27B2DFC200C55AFD /* Errors.swift in Sources */,
|
C4927F0C27B2DFC200C55AFD /* Errors.swift in Sources */,
|
||||||
C485707628BF455100539B36 /* SectionHeaderView.swift in Sources */,
|
C485707628BF455100539B36 /* SectionHeaderView.swift in Sources */,
|
||||||
C46EBC4828DB9644007ACC74 /* RealShell.swift in Sources */,
|
C46EBC4828DB9644007ACC74 /* RealShell.swift in Sources */,
|
||||||
|
@ -109,7 +109,7 @@
|
|||||||
<EnvironmentVariable
|
<EnvironmentVariable
|
||||||
key = "PAINT_PHPMON_SWIFTUI_VIEWS"
|
key = "PAINT_PHPMON_SWIFTUI_VIEWS"
|
||||||
value = ""
|
value = ""
|
||||||
isEnabled = "NO">
|
isEnabled = "YES">
|
||||||
</EnvironmentVariable>
|
</EnvironmentVariable>
|
||||||
</EnvironmentVariables>
|
</EnvironmentVariables>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
|
@ -69,7 +69,7 @@ class Actions {
|
|||||||
public static func stopService(name: String) async {
|
public static func stopService(name: String) async {
|
||||||
await brew(
|
await brew(
|
||||||
"services stop \(name)",
|
"services stop \(name)",
|
||||||
sudo: ServicesManager.shared.services[name]?.formula.elevated ?? false
|
sudo: ServicesManager.shared[name]?.formula.elevated ?? false
|
||||||
)
|
)
|
||||||
await ServicesManager.loadHomebrewServices()
|
await ServicesManager.loadHomebrewServices()
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ class Actions {
|
|||||||
public static func startService(name: String) async {
|
public static func startService(name: String) async {
|
||||||
await brew(
|
await brew(
|
||||||
"services start \(name)",
|
"services start \(name)",
|
||||||
sudo: ServicesManager.shared.services[name]?.formula.elevated ?? false
|
sudo: ServicesManager.shared[name]?.formula.elevated ?? false
|
||||||
)
|
)
|
||||||
await ServicesManager.loadHomebrewServices()
|
await ServicesManager.loadHomebrewServices()
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,18 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
class Homebrew {
|
class Homebrew {
|
||||||
|
static var fake: Bool = false
|
||||||
|
|
||||||
struct Formulae {
|
struct Formulae {
|
||||||
static var php: HomebrewFormula {
|
static var php: HomebrewFormula {
|
||||||
|
if Homebrew.fake {
|
||||||
|
return HomebrewFormula("php", elevated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
if PhpEnv.shared.homebrewPackage == nil {
|
||||||
|
fatalError("You must either load the HomebrewPackage object or call `fake` on the Homebrew class.")
|
||||||
|
}
|
||||||
|
|
||||||
return HomebrewFormula(PhpEnv.phpInstall.formula, elevated: true)
|
return HomebrewFormula(PhpEnv.phpInstall.formula, elevated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +36,7 @@ class Homebrew {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HomebrewFormula {
|
class HomebrewFormula: Equatable, Hashable {
|
||||||
let name: String
|
let name: String
|
||||||
let elevated: Bool
|
let elevated: Bool
|
||||||
|
|
||||||
@ -34,4 +44,13 @@ class HomebrewFormula {
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.elevated = elevated
|
self.elevated = elevated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func == (lhs: HomebrewFormula, rhs: HomebrewFormula) -> Bool {
|
||||||
|
return lhs.elevated == rhs.elevated && lhs.name == rhs.name
|
||||||
|
}
|
||||||
|
|
||||||
|
public func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(name)
|
||||||
|
hasher.combine(elevated)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct HomebrewService: Decodable, Equatable {
|
struct HomebrewService: Decodable, Equatable, Hashable {
|
||||||
let name: String
|
let name: String
|
||||||
let service_name: String
|
let service_name: String
|
||||||
let running: Bool
|
let running: Bool
|
||||||
@ -35,4 +35,10 @@ struct HomebrewService: Decodable, Equatable {
|
|||||||
error_log_path: nil
|
error_log_path: nil
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(name)
|
||||||
|
hasher.combine(service_name)
|
||||||
|
hasher.combine(pid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ class PhpEnv {
|
|||||||
var cachedPhpInstallations: [String: PhpInstallation] = [:]
|
var cachedPhpInstallations: [String: PhpInstallation] = [:]
|
||||||
|
|
||||||
/** Information about the currently linked PHP installation. */
|
/** Information about the currently linked PHP installation. */
|
||||||
var currentInstall: ActivePhpInstallation
|
var currentInstall: ActivePhpInstallation!
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The version that the `php` formula via Brew is aliased to on the current system.
|
The version that the `php` formula via Brew is aliased to on the current system.
|
||||||
|
33
phpmon/Domain/App/Services/FakeServicesManager.swift
Normal file
33
phpmon/Domain/App/Services/FakeServicesManager.swift
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// FakeServicesManager.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 23/12/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class FakeServicesManager: ServicesManager {
|
||||||
|
override init() {
|
||||||
|
Log.warn("A fake services manager is being used, so Homebrew formula resolver is set to act in fake mode.")
|
||||||
|
Log.warn("If you do not want this behaviour, never instantiate FakeServicesManager!")
|
||||||
|
Homebrew.fake = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override var formulae: [HomebrewFormula] {
|
||||||
|
var formulae = [
|
||||||
|
Homebrew.Formulae.php,
|
||||||
|
Homebrew.Formulae.nginx,
|
||||||
|
Homebrew.Formulae.dnsmasq
|
||||||
|
]
|
||||||
|
|
||||||
|
let additionalFormulae = ["mailhog", "coolio"].map({ name in
|
||||||
|
return HomebrewFormula(name, elevated: false)
|
||||||
|
})
|
||||||
|
|
||||||
|
formulae.append(contentsOf: additionalFormulae)
|
||||||
|
|
||||||
|
return formulae
|
||||||
|
}
|
||||||
|
}
|
59
phpmon/Domain/App/Services/ServiceWrapper.swift
Normal file
59
phpmon/Domain/App/Services/ServiceWrapper.swift
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// ServiceWrapper.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 23/12/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/**
|
||||||
|
Whether a given service is active, inactive or PHP Monitor is still busy determining the status.
|
||||||
|
*/
|
||||||
|
public enum ServiceStatus: String {
|
||||||
|
case active
|
||||||
|
case inactive
|
||||||
|
case loading
|
||||||
|
case missing
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Service wrapper, that contains the Homebrew JSON output (if determined) and the formula.
|
||||||
|
This helps the app determine whether a service should run as an administrator or not.
|
||||||
|
*/
|
||||||
|
public class ServiceWrapper: ObservableObject, Identifiable, Hashable {
|
||||||
|
var formula: HomebrewFormula
|
||||||
|
var service: HomebrewService?
|
||||||
|
|
||||||
|
var isBusy: Bool = false
|
||||||
|
|
||||||
|
public var name: String {
|
||||||
|
return formula.name
|
||||||
|
}
|
||||||
|
|
||||||
|
public var status: ServiceStatus {
|
||||||
|
if isBusy {
|
||||||
|
return .loading
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let service = self.service else {
|
||||||
|
return .missing
|
||||||
|
}
|
||||||
|
|
||||||
|
return service.running ? .active : .inactive
|
||||||
|
}
|
||||||
|
|
||||||
|
init(formula: HomebrewFormula) {
|
||||||
|
self.formula = formula
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func == (lhs: ServiceWrapper, rhs: ServiceWrapper) -> Bool {
|
||||||
|
return lhs.service == rhs.service && lhs.formula == rhs.formula
|
||||||
|
}
|
||||||
|
|
||||||
|
public func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(formula)
|
||||||
|
hasher.combine(service)
|
||||||
|
}
|
||||||
|
}
|
57
phpmon/Domain/App/Services/ServicesManager.swift
Normal file
57
phpmon/Domain/App/Services/ServicesManager.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// ServicesManager.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 11/06/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
class ServicesManager: ObservableObject {
|
||||||
|
|
||||||
|
@ObservedObject static var shared: ServicesManager = ValetServicesManager()
|
||||||
|
|
||||||
|
@Published private(set) var services = [ServiceWrapper]()
|
||||||
|
|
||||||
|
subscript(name: String) -> ServiceWrapper? {
|
||||||
|
return self.services.first { wrapper in
|
||||||
|
wrapper.name == name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(*, deprecated, message: "Use a more specific method instead")
|
||||||
|
static func loadHomebrewServices() {
|
||||||
|
print(self.shared)
|
||||||
|
print("This method must be updated")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateServices() {
|
||||||
|
fatalError("Must be implemented in child class")
|
||||||
|
}
|
||||||
|
|
||||||
|
var formulae: [HomebrewFormula] {
|
||||||
|
var formulae = [
|
||||||
|
Homebrew.Formulae.php,
|
||||||
|
Homebrew.Formulae.nginx,
|
||||||
|
Homebrew.Formulae.dnsmasq
|
||||||
|
]
|
||||||
|
|
||||||
|
let additionalFormulae = (Preferences.custom.services ?? []).map({ item in
|
||||||
|
return HomebrewFormula(item, elevated: false)
|
||||||
|
})
|
||||||
|
|
||||||
|
formulae.append(contentsOf: additionalFormulae)
|
||||||
|
|
||||||
|
return formulae
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
Log.info("The services manager will determine which Valet services exist on this system.")
|
||||||
|
|
||||||
|
services = formulae.map {
|
||||||
|
ServiceWrapper(formula: $0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
phpmon/Domain/App/Services/ValetServicesManager.swift
Normal file
70
phpmon/Domain/App/Services/ValetServicesManager.swift
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
//
|
||||||
|
// ValetServicesManager.swift
|
||||||
|
// PHP Monitor
|
||||||
|
//
|
||||||
|
// Created by Nico Verbruggen on 23/12/2022.
|
||||||
|
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class ValetServicesManager: ServicesManager {
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
// Load the initial services state
|
||||||
|
self.updateServices()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func updateServices() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
/*
|
||||||
|
public static func loadHomebrewServices() async {
|
||||||
|
await Self.shared.updateServicesList()
|
||||||
|
|
||||||
|
Task {
|
||||||
|
let rootServiceNames = Self.shared.formulae
|
||||||
|
.filter { $0.elevated }
|
||||||
|
.map { $0.name }
|
||||||
|
|
||||||
|
let rootJson = await Shell
|
||||||
|
.pipe("sudo \(Paths.brew) services info --all --json")
|
||||||
|
.out.data(using: .utf8)!
|
||||||
|
|
||||||
|
let rootServices = try! JSONDecoder()
|
||||||
|
.decode([HomebrewService].self, from: rootJson)
|
||||||
|
.filter({ return rootServiceNames.contains($0.name) })
|
||||||
|
|
||||||
|
Task { @MainActor in
|
||||||
|
for service in rootServices {
|
||||||
|
Self.shared.services[service.name]!.service = service
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Task {
|
||||||
|
let userServiceNames = Self.shared.formulae
|
||||||
|
.filter { !$0.elevated }
|
||||||
|
.map { $0.name }
|
||||||
|
|
||||||
|
let normalJson = await Shell
|
||||||
|
.pipe("\(Paths.brew) services info --all --json")
|
||||||
|
.out.data(using: .utf8)!
|
||||||
|
|
||||||
|
let userServices = try! JSONDecoder()
|
||||||
|
.decode([HomebrewService].self, from: normalJson)
|
||||||
|
.filter({ return userServiceNames.contains($0.name) })
|
||||||
|
|
||||||
|
Task { @MainActor in
|
||||||
|
for service in userServices {
|
||||||
|
Self.shared.services[service.name]!.service = service
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
@ -1,125 +0,0 @@
|
|||||||
//
|
|
||||||
// ServicesManager.swift
|
|
||||||
// PHP Monitor
|
|
||||||
//
|
|
||||||
// Created by Nico Verbruggen on 11/06/2022.
|
|
||||||
// Copyright © 2022 Nico Verbruggen. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
class ServicesManager: ObservableObject {
|
|
||||||
|
|
||||||
static var shared = ServicesManager()
|
|
||||||
|
|
||||||
@Published private(set) var formulae: [HomebrewFormula]
|
|
||||||
|
|
||||||
@Published private(set) var services: [String: ServiceWrapper] = [:]
|
|
||||||
|
|
||||||
init() {
|
|
||||||
Log.info("Initializing ServicesManager...")
|
|
||||||
|
|
||||||
formulae = [
|
|
||||||
Homebrew.Formulae.php,
|
|
||||||
Homebrew.Formulae.nginx,
|
|
||||||
Homebrew.Formulae.dnsmasq
|
|
||||||
]
|
|
||||||
|
|
||||||
let additionalFormulae = (Preferences.custom.services ?? []).map({ item in
|
|
||||||
return HomebrewFormula(item, elevated: false)
|
|
||||||
})
|
|
||||||
|
|
||||||
formulae.append(contentsOf: additionalFormulae)
|
|
||||||
|
|
||||||
services = Dictionary(uniqueKeysWithValues: formulae.map { ($0.name, ServiceWrapper(formula: $0)) })
|
|
||||||
}
|
|
||||||
|
|
||||||
public func updateServicesList() async {
|
|
||||||
Task { @MainActor in
|
|
||||||
formulae = [
|
|
||||||
Homebrew.Formulae.php,
|
|
||||||
Homebrew.Formulae.nginx,
|
|
||||||
Homebrew.Formulae.dnsmasq
|
|
||||||
]
|
|
||||||
|
|
||||||
let additionalFormulae = (Preferences.custom.services ?? []).map({ item in
|
|
||||||
return HomebrewFormula(item, elevated: false)
|
|
||||||
})
|
|
||||||
|
|
||||||
formulae.append(contentsOf: additionalFormulae)
|
|
||||||
|
|
||||||
services = Dictionary(uniqueKeysWithValues: formulae.map { ($0.name, ServiceWrapper(formula: $0)) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static func loadHomebrewServices() async {
|
|
||||||
await Self.shared.updateServicesList()
|
|
||||||
|
|
||||||
Task {
|
|
||||||
let rootServiceNames = Self.shared.formulae
|
|
||||||
.filter { $0.elevated }
|
|
||||||
.map { $0.name }
|
|
||||||
|
|
||||||
let rootJson = await Shell
|
|
||||||
.pipe("sudo \(Paths.brew) services info --all --json")
|
|
||||||
.out.data(using: .utf8)!
|
|
||||||
|
|
||||||
let rootServices = try! JSONDecoder()
|
|
||||||
.decode([HomebrewService].self, from: rootJson)
|
|
||||||
.filter({ return rootServiceNames.contains($0.name) })
|
|
||||||
|
|
||||||
Task { @MainActor in
|
|
||||||
for service in rootServices {
|
|
||||||
Self.shared.services[service.name]!.service = service
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Task {
|
|
||||||
let userServiceNames = Self.shared.formulae
|
|
||||||
.filter { !$0.elevated }
|
|
||||||
.map { $0.name }
|
|
||||||
|
|
||||||
let normalJson = await Shell
|
|
||||||
.pipe("\(Paths.brew) services info --all --json")
|
|
||||||
.out.data(using: .utf8)!
|
|
||||||
|
|
||||||
let userServices = try! JSONDecoder()
|
|
||||||
.decode([HomebrewService].self, from: normalJson)
|
|
||||||
.filter({ return userServiceNames.contains($0.name) })
|
|
||||||
|
|
||||||
Task { @MainActor in
|
|
||||||
for service in userServices {
|
|
||||||
Self.shared.services[service.name]!.service = service
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Service wrapper, that contains the Homebrew JSON output (if determined) and the formula.
|
|
||||||
This helps the app determine whether a service should run as an administrator or not.
|
|
||||||
*/
|
|
||||||
public struct ServiceWrapper {
|
|
||||||
public var formula: HomebrewFormula
|
|
||||||
public var service: HomebrewService?
|
|
||||||
|
|
||||||
init(formula: HomebrewFormula) {
|
|
||||||
self.formula = formula
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Dummy data for preview purposes.
|
|
||||||
*/
|
|
||||||
func withDummyServices(_ services: [String: Bool]) -> Self {
|
|
||||||
for (service, enabled) in services {
|
|
||||||
var item = ServiceWrapper(formula: HomebrewFormula(service))
|
|
||||||
item.service = HomebrewService.dummy(named: service, enabled: enabled)
|
|
||||||
self.services[service] = item
|
|
||||||
}
|
|
||||||
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
}
|
|
@ -96,7 +96,7 @@ extension MainMenu {
|
|||||||
Valet.notifyAboutUnsupportedTLD()
|
Valet.notifyAboutUnsupportedTLD()
|
||||||
|
|
||||||
// Find out which services are active
|
// Find out which services are active
|
||||||
await ServicesManager.loadHomebrewServices()
|
Log.info("The services manager knows about \(ServicesManager.shared.services.count) services.")
|
||||||
|
|
||||||
// Start the background refresh timer
|
// Start the background refresh timer
|
||||||
startSharedTimer()
|
startSharedTimer()
|
||||||
|
@ -10,44 +10,129 @@ import Foundation
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct ServicesView: View {
|
struct ServicesView: View {
|
||||||
static func asMenuItem(perRow: Int = 3) -> NSMenuItem {
|
static func asMenuItem(perRow: Int = 4) -> NSMenuItem {
|
||||||
let item = NSMenuItem()
|
let item = NSMenuItem()
|
||||||
|
|
||||||
let view = NSHostingView(
|
let manager = ServicesManager.shared
|
||||||
rootView: Self()
|
|
||||||
|
let rootView = Self(
|
||||||
|
manager: manager,
|
||||||
|
perRow: perRow
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let view = NSHostingView(rootView: rootView)
|
||||||
view.autoresizingMask = [.width, .height]
|
view.autoresizingMask = [.width, .height]
|
||||||
|
view.setFrameSize(
|
||||||
|
CGSize(width: view.frame.width, height: rootView.height)
|
||||||
|
)
|
||||||
|
view.focusRingType = .none
|
||||||
|
|
||||||
let height = CGFloat(45 * ["a", "b", "c", "d", "e", "f"]
|
|
||||||
.chunked(by: perRow).count)
|
|
||||||
|
|
||||||
view.setFrameSize(CGSize(width: view.frame.width, height: height))
|
|
||||||
item.view = view
|
item.view = view
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ObservedObject var manager: ServicesManager
|
||||||
|
var perRow: Int
|
||||||
|
var height: CGFloat
|
||||||
|
var chunkCount: Int
|
||||||
|
|
||||||
|
init(manager: ServicesManager, perRow: Int, height: CGFloat? = nil) {
|
||||||
|
self.manager = manager
|
||||||
|
self.perRow = perRow
|
||||||
|
self.chunkCount = manager.services.chunked(by: perRow).count
|
||||||
|
self.height = CGFloat((50 * chunkCount) + (5 * perRow))
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text("WIP")
|
GeometryReader { geometry in
|
||||||
.padding(10)
|
VStack {
|
||||||
.frame(minWidth: 0, maxWidth: .infinity)
|
ForEach(manager.services.chunked(by: perRow), id: \.self) { chunk in
|
||||||
|
HStack {
|
||||||
|
ForEach(chunk) { service in
|
||||||
|
ServiceView(service: service)
|
||||||
|
.frame(width: abs((geometry.size.width - 15) / CGFloat(perRow)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.top, 10)
|
||||||
|
}
|
||||||
|
.frame(height: self.height)
|
||||||
.background(Color.debug)
|
.background(Color.debug)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ServiceView: View {
|
||||||
|
@ObservedObject var service: ServiceWrapper
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
Text(service.name.uppercased())
|
||||||
|
.font(.system(size: 10))
|
||||||
|
.frame(minWidth: 0, maxWidth: .infinity)
|
||||||
|
.padding(.bottom, 4)
|
||||||
|
.background(Color.debug)
|
||||||
|
if service.status == .loading {
|
||||||
|
ProgressView()
|
||||||
|
.scaleEffect(x: 0.5, y: 0.5, anchor: .center)
|
||||||
|
.frame(width: 16.0, height: 20.0)
|
||||||
|
}
|
||||||
|
if service.status == .missing {
|
||||||
|
Button { print("we pressed da button ")} label: {
|
||||||
|
Text("?")
|
||||||
|
}
|
||||||
|
.buttonStyle(BlueButton())
|
||||||
|
}
|
||||||
|
if service.status == .active {
|
||||||
|
Button {
|
||||||
|
// TODO
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 12.0, height: 12.0)
|
||||||
|
.foregroundColor(Color("IconColorGreen"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if service.status == .inactive {
|
||||||
|
Button {
|
||||||
|
// TODO
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "xmark")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 12.0, height: 12.0)
|
||||||
|
.foregroundColor(Color("IconColorRed"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct BlueButton: ButtonStyle {
|
||||||
|
public func makeBody(configuration: Configuration) -> some View {
|
||||||
|
configuration.label
|
||||||
|
.padding(.bottom, 5)
|
||||||
|
.padding(.top, 5)
|
||||||
|
.padding(.leading, 10)
|
||||||
|
.padding(.trailing, 10)
|
||||||
|
.background(Color(red: 0, green: 0, blue: 0.5))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.clipShape(Capsule())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ServicesView_Previews: PreviewProvider {
|
struct ServicesView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
ServicesView()
|
ServicesView(manager: FakeServicesManager(), perRow: 3)
|
||||||
.frame(width: 330.0)
|
.frame(width: 330.0)
|
||||||
.previewDisplayName("Loading")
|
.previewDisplayName("Loading")
|
||||||
|
|
||||||
ServicesView()
|
ServicesView(manager: FakeServicesManager(), perRow: 3)
|
||||||
.frame(width: 330.0)
|
.frame(width: 330.0)
|
||||||
.previewDisplayName("Light Mode")
|
.previewDisplayName("Light Mode")
|
||||||
|
|
||||||
ServicesView()
|
ServicesView(manager: FakeServicesManager(), perRow: 3)
|
||||||
.frame(width: 330.0)
|
.frame(width: 330.0)
|
||||||
.previewDisplayName("Dark Mode")
|
.previewDisplayName("Dark Mode")
|
||||||
.preferredColorScheme(.dark)
|
.preferredColorScheme(.dark)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user