diff --git a/Sources/teaBASE.m b/Sources/teaBASE.m index 437bd82..eaf90dd 100644 --- a/Sources/teaBASE.m +++ b/Sources/teaBASE.m @@ -1,5 +1,10 @@ #import "teaBASE.h" +@interface teaBASE () +@property (nonatomic) BOOL isInitializing; +@property (weak) IBOutlet NSSwitch *testSwitch; +@end + @implementation teaBASE - (void)mainViewDidLoad { @@ -18,22 +23,23 @@ - (void)willSelect { [self.dotfileSyncSwitch setEnabled:NO]; [self.dotfileSyncEditWhitelistButton setEnabled:NO]; [self.dotfileSyncViewRepoButton setEnabled:NO]; - + [self.testSwitch setEnabled:NO]; + dispatch_group_t group = dispatch_group_create(); dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - + // Create containers for async results __block BOOL hasSignedCommits = NO; __block BOOL homebrewInstalled = NO; __block BOOL pkgxInstalled = NO; __block BOOL xcodeCLTInstalled = NO; __block BOOL dotfileSyncEnabled = NO; - + // Perform heavy operations in background dispatch_group_async(group, backgroundQueue, ^{ [self updateSSHStates]; }); - + dispatch_group_async(group, backgroundQueue, ^{ hasSignedCommits = [self gpgSignEnabled]; dispatch_async(dispatch_get_main_queue(), ^{ @@ -41,7 +47,7 @@ - (void)willSelect { [self.gpgSignSwitch setEnabled:YES]; }); }); - + dispatch_group_async(group, backgroundQueue, ^{ [self updateVersions]; dispatch_async(dispatch_get_main_queue(), ^{ @@ -49,30 +55,33 @@ - (void)willSelect { [self.dockerSwitch setEnabled:YES]; }); }); - + dispatch_group_async(group, backgroundQueue, ^{ homebrewInstalled = [self homebrewInstalled]; pkgxInstalled = [self pkgxInstalled]; xcodeCLTInstalled = [self xcodeCLTInstalled]; dotfileSyncEnabled = self.dotfileSyncEnabled; - + + self.isInitializing = YES; + dispatch_async(dispatch_get_main_queue(), ^{ [self.homebrewSwitch setState:homebrewInstalled ? NSControlStateValueOn : NSControlStateValueOff]; [self.pkgxSwitch setState:pkgxInstalled ? NSControlStateValueOn : NSControlStateValueOff]; [self.xcodeCLTSwitch setState:xcodeCLTInstalled ? NSControlStateValueOn : NSControlStateValueOff]; [self.dotfileSyncSwitch setState:dotfileSyncEnabled ? NSControlStateValueOn : NSControlStateValueOff]; - + [self.homebrewSwitch setEnabled:YES]; [self.pkgxSwitch setEnabled:YES]; [self.xcodeCLTSwitch setEnabled:YES]; [self.dotfileSyncSwitch setEnabled:YES]; - + [self.testSwitch setEnabled:YES]; + BOOL dotfileSyncActive = self.dotfileSyncSwitch.state == NSControlStateValueOn; [self.dotfileSyncEditWhitelistButton setEnabled:dotfileSyncActive]; [self.dotfileSyncViewRepoButton setEnabled:dotfileSyncActive]; }); }); - + // Once all background tasks complete, update remaining UI elements dispatch_group_notify(group, dispatch_get_main_queue(), ^{ if ([self.defaultsController.defaults boolForKey:@"xyz.tea.BASE.integrated-GitHub"]) { @@ -81,17 +90,17 @@ - (void)willSelect { if ([self.defaultsController.defaults boolForKey:@"xyz.tea.BASE.printed-GPG-emergency-kit"]) { self.greenCheckGPGBackup.hidden = NO; } - + [self calculateSecurityRating]; [self updateGitGudListing]; [self updateGitIdentity]; - + id v = [[NSBundle bundleForClass:[self class]] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; if (v) { self.selfVersionLabel.stringValue = [NSString stringWithFormat:@"v%@", v]; } }); - + [self updateInstallationStatuses]; } @@ -105,10 +114,10 @@ - (void)calculateSecurityRating { BOOL hasSSH = self.sshSwitch.state == NSControlStateValueOn; BOOL hasGitHubIntegration = self.greenCheckGitHubIntegration.hidden == NO; BOOL hasGPGBackup = self.greenCheckGPGBackup.hidden == NO; - + float rating = hasSignedCommits + hasSSHPassPhrase + hasSSH + hasGitHubIntegration + hasGPGBackup; [self.ratingIndicator setIntValue:rating]; - + if (self.ratingIndicator.intValue >= self.ratingIndicator.maxValue) { [self.ratingIndicator setFillColor:[NSColor systemGreenColor]]; } else if (self.ratingIndicator.intValue <= 1) { @@ -120,35 +129,41 @@ - (void)updateVersions { NSString *brew_out = output(brewPath(), @[@"--version"]); NSString *pkgx_out = output(@"/usr/local/bin/pkgx", @[@"--version"]); NSString *xcode_clt_out = output(@"/usr/sbin/pkgutil", @[@"--pkg-info=com.apple.pkg.CLTools_Executables"]); - + id path = [[[NSBundle bundleForClass:[self class]] bundlePath] stringByAppendingPathComponent:@"Contents/Scripts/docker-version.sh"]; NSString *docker_version = output(path, @[]); - + BOOL has_clt = [self xcodeCLTInstalled]; BOOL has_xcode = [self xcodeInstalled]; - // emulate login shell to ensure PATH contains everything the user has configured - // ∵ GUI apps do not have full user PATH set otherwise + NSString *git_out = nil; if (has_clt || has_xcode) { - // only check if clt or xcode otherwise this may trigger the XcodeCLT installation GUI flow git_out = output(@"/bin/sh", @[@"-l", @"-c", @"git --version"]); } - - brew_out = [[brew_out componentsSeparatedByString:@" "] lastObject]; // Homebrew 1.2.3 - pkgx_out = [[pkgx_out componentsSeparatedByString:@" "] lastObject]; // pkgx 1.2.3 - git_out = [[git_out componentsSeparatedByString:@" "] objectAtIndex:2]; // git version 1.2.3 - xcode_clt_out = [[[[xcode_clt_out componentsSeparatedByString:@"\n"] objectAtIndex:1] componentsSeparatedByString:@" "] objectAtIndex:1]; // Version: 1.2.3 - + + brew_out = [[brew_out componentsSeparatedByString:@" "] lastObject]; + pkgx_out = [[pkgx_out componentsSeparatedByString:@" "] lastObject]; + git_out = [[git_out componentsSeparatedByString:@" "] objectAtIndex:2]; + xcode_clt_out = [[[[xcode_clt_out componentsSeparatedByString:@"\n"] objectAtIndex:1] componentsSeparatedByString:@" "] objectAtIndex:1]; + self.brewVersion.stringValue = brew_out ? [NSString stringWithFormat:@"v%@", brew_out] : @""; self.pkgxVersion.stringValue = pkgx_out ? [NSString stringWithFormat:@"v%@", pkgx_out] : @""; self.gitVersion.stringValue = git_out ? [NSString stringWithFormat:@"v%@", git_out] : @""; self.xcodeCLTVersion.stringValue = xcode_clt_out ? [NSString stringWithFormat:@"v%@", xcode_clt_out] : @""; self.dockerVersion.stringValue = docker_version ? [@"v" stringByAppendingString:docker_version] : @""; - + [self.installGitButton setHidden:git_out != nil]; } +- (IBAction)onTestSwitchChanged:(NSSwitch *)sender { + if (sender.state == NSControlStateValueOn) { + NSLog(@"Test switch is ON"); + } else { + NSLog(@"Test switch is OFF"); + } +} + - (IBAction)openGitHub:(id)sender { NSURL *url = [NSURL URLWithString:@"https://github.com/teaxyz/teaBASE"]; [[NSWorkspace sharedWorkspace] openURL:url]; @@ -157,7 +172,6 @@ - (IBAction)openGitHub:(id)sender { - (IBAction)onShareClicked:(id)sender { const int starCount = self.ratingIndicator.intValue; - // Construct the stars string NSMutableString *stars = [NSMutableString string]; for (int i = 0; i < 5; i++) { if (i < starCount) { @@ -167,33 +181,24 @@ - (IBAction)onShareClicked:(id)sender { } } - // URL encode the message NSString *message = [NSString stringWithFormat:@"I got %@ developer security with @teaprotocol’s teaBASE", stars]; NSString *encodedMessage = [message stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; - // Construct the full URL NSString *urlString = [NSString stringWithFormat:@"https://x.com/intent/tweet?text=%@", encodedMessage]; NSURL *url = [NSURL URLWithString:urlString]; - // Open the URL [NSWorkspace.sharedWorkspace openURL:url]; } @end - @implementation teaBASE (Integration) - (IBAction)integrateWithGitHub:(id)sender { - //TODO not great since we don’t know when we’re finished - //NOTE `gh` fails when uploading an existing GPG key (though is fine for existing ssh keys) - //TODO ^^ report as bug? - //TODO pipe output and handle it so exit code is good - NSString *script_path = [[[NSBundle bundleForClass:[self class]] bundlePath] stringByAppendingPathComponent:@"Contents/Scripts/github-integration.sh"]; - + run_in_terminal(script_path, [NSBundle bundleForClass:self.class]); - + self.greenCheckGitHubIntegration.hidden = NO; [self.defaultsController.defaults setValue:@YES forKey:@"xyz.tea.BASE.integrated-GitHub"]; [self calculateSecurityRating];