diff --git a/baRSS-Helper/Info.plist b/baRSS-Helper/Info.plist new file mode 100644 index 0000000..acac651 --- /dev/null +++ b/baRSS-Helper/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2018 relikd. Public Domain. + LSBackgroundOnly + + + diff --git a/baRSS-Helper/main.m b/baRSS-Helper/main.m new file mode 100644 index 0000000..5de221e --- /dev/null +++ b/baRSS-Helper/main.m @@ -0,0 +1,46 @@ +// +// The MIT License (MIT) +// Copyright (c) 2018 Oleg Geier +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#import + +int main(int argc, const char * argv[]) { + @autoreleasepool { + // see: http://martiancraft.com/blog/2015/01/login-items/ + NSArray *arr = [NSRunningApplication runningApplicationsWithBundleIdentifier:@"de.relikd.baRSS"]; + if (arr.count == 0) { // if not already running + NSArray *pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents]; + pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)]; + NSString *path = [NSString pathWithComponents:pathComponents]; + [[NSWorkspace sharedWorkspace] launchApplication:path]; + } + /* + Important: If your daemon shuts down too quickly after being launched, + launchd may think it has crashed. Daemons that continue this behavior may + be suspended and not launched again when future requests arrive. To avoid + this behavior, do not shut down for at least 10 seconds after launch. + */ + // https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html + sleep(10); // Not sure if this is necessary. However, it doesnt hurt. + [NSApp terminate:nil]; + } + return 0; +} diff --git a/baRSS.xcodeproj/project.pbxproj b/baRSS.xcodeproj/project.pbxproj index 2cdea8f..f61aa49 100644 --- a/baRSS.xcodeproj/project.pbxproj +++ b/baRSS.xcodeproj/project.pbxproj @@ -26,9 +26,12 @@ 54ACC28C21061B3C0020715F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC28B21061B3C0020715F /* main.m */; }; 54ACC29521061E270020715F /* FeedDownload.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC29421061E270020715F /* FeedDownload.m */; }; 54ACC29821061FBA0020715F /* Preferences.m in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC29721061FBA0020715F /* Preferences.m */; }; + 54CC04382162532A00A48795 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 54CC04372162532A00A48795 /* main.m */; }; + 54CC043E2162566900A48795 /* baRSS-Helper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 54CC042C2162532800A48795 /* baRSS-Helper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 54E88320211B509D00064188 /* ModalFeedEdit.m in Sources */ = {isa = PBXBuildFile; fileRef = 54E8831E211B509D00064188 /* ModalFeedEdit.m */; }; 54E88321211B509D00064188 /* ModalFeedEdit.xib in Resources */ = {isa = PBXBuildFile; fileRef = 54E8831F211B509D00064188 /* ModalFeedEdit.xib */; }; 54F39C2E210BE1F700AEE730 /* DBv1.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 54ACC28221061B3B0020715F /* DBv1.xcdatamodeld */; }; + 54F518782162CA4F00EE856C /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54F518772162CA4F00EE856C /* ServiceManagement.framework */; }; 54FE73D021220DEC003EAC65 /* StoreCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FE73CF21220DEC003EAC65 /* StoreCoordinator.m */; }; 54FE73D3212316CD003EAC65 /* BarMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 54FE73D2212316CD003EAC65 /* BarMenu.m */; }; /* End PBXBuildFile section */ @@ -55,6 +58,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 54CC043D2162565F00A48795 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = Contents/Library/LoginItems; + dstSubfolderSpec = 1; + files = ( + 54CC043E2162566900A48795 /* baRSS-Helper.app in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -90,9 +103,13 @@ 54ACC29421061E270020715F /* FeedDownload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FeedDownload.m; sourceTree = ""; }; 54ACC29621061FBA0020715F /* Preferences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Preferences.h; sourceTree = ""; }; 54ACC29721061FBA0020715F /* Preferences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Preferences.m; sourceTree = ""; }; + 54CC042C2162532800A48795 /* baRSS-Helper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "baRSS-Helper.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 54CC04362162532A00A48795 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 54CC04372162532A00A48795 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 54E8831D211B509D00064188 /* ModalFeedEdit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModalFeedEdit.h; sourceTree = ""; }; 54E8831E211B509D00064188 /* ModalFeedEdit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ModalFeedEdit.m; sourceTree = ""; }; 54E8831F211B509D00064188 /* ModalFeedEdit.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ModalFeedEdit.xib; sourceTree = ""; }; + 54F518772162CA4F00EE856C /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; 54FE73CE21220DEC003EAC65 /* StoreCoordinator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StoreCoordinator.h; sourceTree = ""; }; 54FE73CF21220DEC003EAC65 /* StoreCoordinator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = StoreCoordinator.m; sourceTree = ""; }; 54FE73D1212316CD003EAC65 /* BarMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BarMenu.h; sourceTree = ""; }; @@ -104,10 +121,18 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 54F518782162CA4F00EE856C /* ServiceManagement.framework in Frameworks */, 544DCCB9212A2B4D002DBC46 /* RSXML.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; + 54CC04292162532800A48795 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -127,6 +152,7 @@ 544FBD4321064AEB008A260C /* Frameworks */ = { isa = PBXGroup; children = ( + 54F518772162CA4F00EE856C /* ServiceManagement.framework */, 544DCCB8212A2B4D002DBC46 /* RSXML.framework */, 544DCCBD212A2B6F002DBC46 /* RSXML.framework.dSYM */, ); @@ -165,6 +191,7 @@ isa = PBXGroup; children = ( 54ACC27E21061B3B0020715F /* baRSS */, + 54CC042D2162532800A48795 /* baRSS-Helper */, 54ACC27D21061B3B0020715F /* Products */, 544FBD4321064AEB008A260C /* Frameworks */, ); @@ -174,6 +201,7 @@ isa = PBXGroup; children = ( 54ACC27C21061B3B0020715F /* baRSS.app */, + 54CC042C2162532800A48795 /* baRSS-Helper.app */, ); name = Products; sourceTree = ""; @@ -199,6 +227,15 @@ path = baRSS; sourceTree = ""; }; + 54CC042D2162532800A48795 /* baRSS-Helper */ = { + isa = PBXGroup; + children = ( + 54CC04362162532A00A48795 /* Info.plist */, + 54CC04372162532A00A48795 /* main.m */, + ); + path = "baRSS-Helper"; + sourceTree = ""; + }; 54E88323211B542E00064188 /* Feeds Tab */ = { isa = PBXGroup; children = ( @@ -224,6 +261,7 @@ 54ACC27A21061B3B0020715F /* Resources */, 544DCCBB212A2B4D002DBC46 /* Embed Frameworks */, 544DCCBC212A2B5A002DBC46 /* CopyFiles */, + 54CC043D2162565F00A48795 /* CopyFiles */, ); buildRules = ( ); @@ -234,6 +272,23 @@ productReference = 54ACC27C21061B3B0020715F /* baRSS.app */; productType = "com.apple.product-type.application"; }; + 54CC042B2162532800A48795 /* baRSS-Helper */ = { + isa = PBXNativeTarget; + buildConfigurationList = 54CC043C2162532A00A48795 /* Build configuration list for PBXNativeTarget "baRSS-Helper" */; + buildPhases = ( + 54CC04282162532800A48795 /* Sources */, + 54CC04292162532800A48795 /* Frameworks */, + 54CC042A2162532800A48795 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "baRSS-Helper"; + productName = "baRSS-Helper"; + productReference = 54CC042C2162532800A48795 /* baRSS-Helper.app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -255,6 +310,14 @@ }; }; }; + 54CC042B2162532800A48795 = { + CreatedOnToolsVersion = 9.4.1; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 0; + }; + }; + }; }; }; buildConfigurationList = 54ACC27721061B3B0020715F /* Build configuration list for PBXProject "baRSS" */; @@ -271,6 +334,7 @@ projectRoot = ""; targets = ( 54ACC27B21061B3B0020715F /* baRSS */, + 54CC042B2162532800A48795 /* baRSS-Helper */, ); }; /* End PBXProject section */ @@ -288,6 +352,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 54CC042A2162532800A48795 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -314,6 +385,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 54CC04282162532800A48795 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 54CC04382162532A00A48795 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ @@ -350,7 +429,6 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -409,7 +487,6 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -444,7 +521,6 @@ CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; - CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = ""; @@ -495,7 +571,6 @@ CLANG_WARN_OBJC_EXPLICIT_OWNERSHIP_TYPE = YES; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; - CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = ""; @@ -529,6 +604,44 @@ }; name = Release; }; + 54CC043A2162532A00A48795 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "baRSS-Helper/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_BUNDLE_IDENTIFIER = "de.relikd.baRSS-Helper"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 54CC043B2162532A00A48795 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "baRSS-Helper/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.12; + PRODUCT_BUNDLE_IDENTIFIER = "de.relikd.baRSS-Helper"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -550,6 +663,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 54CC043C2162532A00A48795 /* Build configuration list for PBXNativeTarget "baRSS-Helper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 54CC043A2162532A00A48795 /* Debug */, + 54CC043B2162532A00A48795 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ /* Begin XCVersionGroup section */ diff --git a/baRSS/Preferences/General Tab/SettingsGeneral.m b/baRSS/Preferences/General Tab/SettingsGeneral.m index a8ae63f..d832862 100644 --- a/baRSS/Preferences/General Tab/SettingsGeneral.m +++ b/baRSS/Preferences/General Tab/SettingsGeneral.m @@ -24,6 +24,7 @@ #import "AppHook.h" #import "BarMenu.h" #import "UserPrefs.h" +#import @interface SettingsGeneral() @@ -46,6 +47,16 @@ #pragma mark - UI interaction with IBAction +- (IBAction)changeStartOnLogin:(NSButton *)sender { + // launchctl list | grep de.relikd + CFStringRef helperIdentifier = CFBridgingRetain(@"de.relikd.baRSS-Helper"); + Boolean setOnLogin = (sender.state == NSControlStateValueOn); + if (!helperIdentifier || !SMLoginItemSetEnabled(helperIdentifier, setOnLogin)) + sender.state = (setOnLogin ? NSControlStateValueOff : NSControlStateValueOn); // restore prev state + if (helperIdentifier) + CFRelease(helperIdentifier); +} + - (IBAction)changeHttpApplication:(NSPopUpButton *)sender { [UserPrefs setHttpApplication:sender.selectedItem.representedObject]; } @@ -170,6 +181,7 @@ @return Return @c YES if operation was successfull. @c NO otherwise. */ - (BOOL)setDefaultRSSApplication:(NSString*)bundleID { + // TODO: Does not work with sandboxing. CFStringRef bundleIDRef = CFBridgingRetain(bundleID); if (!bundleIDRef) return NO; diff --git a/baRSS/Preferences/General Tab/SettingsGeneral.xib b/baRSS/Preferences/General Tab/SettingsGeneral.xib index e061e72..dd9721b 100644 --- a/baRSS/Preferences/General Tab/SettingsGeneral.xib +++ b/baRSS/Preferences/General Tab/SettingsGeneral.xib @@ -28,6 +28,7 @@ +