- Readme + ToDo list

- Preferences: Browser list and config
- Preferences: Default RSS reader application
- Open and handle 'feed://' urls
This commit is contained in:
relikd
2018-09-22 02:09:28 +02:00
parent 7d68a25de2
commit 0f90705781
10 changed files with 324 additions and 39 deletions

View File

@@ -31,8 +31,14 @@
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
- (void)applicationWillFinishLaunching:(NSNotification *)notification {
_barMenu = [BarMenu new];
NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager];
[appleEventManager setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass andEventID:kAEGetURL];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
printf("up and running\n");
// https://feeds.feedburner.com/simpledesktops
}
@@ -41,6 +47,12 @@
}
- (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
NSString *url = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
// TODO: Open feed edit sheet in preferences
NSLog(@"%@", url);
}
#pragma mark - Core Data stack

View File

@@ -2,36 +2,49 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>NSPrincipalClass</key>
<string>AppHook</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string></string>
<key>LSUIElement</key>
<true/>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 relikd. All rights reserved.</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>de.relikd.baRSS.url.feed</string>
<key>CFBundleURLSchemes</key>
<array>
<string>feed</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 relikd. Public Domain.</string>
<key>NSPrincipalClass</key>
<string>AppHook</string>
</dict>
</plist>

View File

@@ -23,13 +23,42 @@
#import "SettingsGeneral.h"
#import "AppHook.h"
#import "BarMenu.h"
#import "UserPrefs.h"
@interface SettingsGeneral()
@property (weak) IBOutlet NSPopUpButton *popupHttpApplication;
@property (weak) IBOutlet NSPopUpButton *popupDefaultRSSReader;
@end
@implementation SettingsGeneral
- (void)viewDidLoad {
[super viewDidLoad];
// Default http application for opening the feed urls
[self generateMenuForPopup:self.popupHttpApplication withScheme:@"https"];
[self.popupHttpApplication insertItemWithTitle:NSLocalizedString(@"System Default", @"Default web browser application") atIndex:0];
[self selectBundleID:[UserPrefs getHttpApplication] inPopup:self.popupHttpApplication];
// Default RSS Reader application
[self generateMenuForPopup:self.popupDefaultRSSReader withScheme:@"feed"];
[self selectBundleID:[self defaultBundleIdForScheme:@"feed"] inPopup:self.popupDefaultRSSReader];
}
#pragma mark - UI interaction with IBAction
- (IBAction)changeHttpApplication:(NSPopUpButton *)sender {
[UserPrefs setHttpApplication:sender.selectedItem.representedObject];
}
- (IBAction)changeDefaultRSSReader:(NSPopUpButton *)sender {
if ([self setDefaultRSSApplication:sender.selectedItem.representedObject] == NO) {
// in case anything went wrong, restore previous selection
[self selectBundleID:[self defaultBundleIdForScheme:@"feed"] inPopup:sender];
}
}
// TODO: add self to login items
- (IBAction)checkmarkClicked:(NSButton*)sender {
// TODO: Could be optimized by updating only the relevant parts
[[(AppHook*)NSApp barMenu] rebuildMenu];
@@ -48,11 +77,111 @@
[[(AppHook*)NSApp barMenu] updateMenuHeaders:recursive];
}
- (IBAction)changeMenuItemUpdateAllHidden:(NSButton*)sender {
- (IBAction)changeMenuItemUpdateAll:(NSButton*)sender {
BOOL checked = (sender.state == NSControlStateValueOn);
[[(AppHook*)NSApp barMenu] setItemUpdateAllHidden:!checked];
}
// TODO: show list of installed browsers and make menu choosable
#pragma mark - Helper methods
/**
Populate @c NSPopUpButton menu with all available application for that scheme.
@param scheme URL scheme like @c 'feed' or @c 'https'
*/
- (void)generateMenuForPopup:(NSPopUpButton*)popup withScheme:(NSString*)scheme {
[popup removeAllItems];
NSArray<NSString*> *apps = [self listOfBundleIdsForScheme:scheme];
for (NSString *bundleID in apps) {
NSString *appName = [self applicationNameForBundleId:bundleID];
if (!appName)
appName = bundleID;
[popup addItemWithTitle:appName];
popup.lastItem.representedObject = bundleID;
}
}
/**
For a given @c NSPopUpButton select the item which represents the @c bundleID.
*/
- (void)selectBundleID:(NSString*)bundleID inPopup:(NSPopUpButton*)popup {
[popup selectItemAtIndex:[popup indexOfItemWithRepresentedObject:bundleID]];
}
/**
Get human readable, application name from @c bundleID.
@param bundleID as defined in @c Info.plist
@return Application name such as 'Safari' or 'baRSS'
*/
- (NSString*)applicationNameForBundleId:(NSString*)bundleID {
CFStringRef bundleIDRef = CFBridgingRetain(bundleID);
if (!bundleIDRef)
return nil;
CFArrayRef arr = LSCopyApplicationURLsForBundleIdentifier(bundleIDRef, NULL);
CFRelease(bundleIDRef);
if (!arr)
return nil;
CFDictionaryRef infoDict = NULL;
if (CFArrayGetCount(arr) > 0)
infoDict = CFBundleCopyInfoDictionaryForURL(CFArrayGetValueAtIndex(arr, 0));
CFRelease(arr);
if (!infoDict)
return nil;
NSString *name = CFDictionaryGetValue(infoDict, kCFBundleNameKey);
CFRelease(infoDict);
return name;
}
/**
Get a list of all installed applications supporting that URL scheme.
@param scheme URL scheme like @c 'feed' or @c 'https'
@return Array of @c bundleIDs of installed applications supporting that url scheme.
*/
- (NSArray<NSString*>*)listOfBundleIdsForScheme:(NSString*)scheme {
CFStringRef schemeRef = CFBridgingRetain(scheme);
if (!schemeRef)
return nil;
CFArrayRef allHandlers = LSCopyAllHandlersForURLScheme(schemeRef);
CFRelease(schemeRef);
return (NSArray*)CFBridgingRelease(allHandlers);
}
/**
Get current default application for provided URL scheme. (e.g., )
@param scheme URL scheme like @c 'feed' or @c 'https'
@return @c bundleID of default application
*/
- (NSString*)defaultBundleIdForScheme:(NSString*)scheme {
CFStringRef schemeRef = CFBridgingRetain(scheme);
if (!schemeRef)
return nil;
CFStringRef defaultHandler = LSCopyDefaultHandlerForURLScheme(schemeRef);
CFRelease(schemeRef);
return (NSString*)CFBridgingRelease(defaultHandler);
}
/**
Sets the default application for @c feed:// urls. (system wide)
@param bundleID as defined in @c Info.plist
@return Return @c YES if operation was successfull. @c NO otherwise.
*/
- (BOOL)setDefaultRSSApplication:(NSString*)bundleID {
CFStringRef bundleIDRef = CFBridgingRetain(bundleID);
if (!bundleIDRef)
return NO;
CFStringRef schemeRef = CFBridgingRetain(@"feed");
if (!schemeRef) {
CFRelease(bundleIDRef);
return NO;
}
OSStatus s = LSSetDefaultHandlerForURLScheme(schemeRef, bundleIDRef);
CFRelease(schemeRef);
CFRelease(bundleIDRef);
return s == 0;
}
@end

View File

@@ -8,6 +8,8 @@
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SettingsGeneral">
<connections>
<outlet property="popupDefaultRSSReader" destination="tJe-jL-nUu" id="DUq-ti-Drf"/>
<outlet property="popupHttpApplication" destination="BcN-gW-jBg" id="X2r-Nn-igN"/>
<outlet property="view" destination="mbb-wD-pDD" id="Syb-4w-ekh"/>
</connections>
</customObject>
@@ -42,7 +44,7 @@
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="changeMenuItemUpdateAllHidden:" target="-2" id="12D-ge-tzs"/>
<action selector="changeMenuItemUpdateAll:" target="-2" id="Zb8-Oi-JVr"/>
<binding destination="iU7-KA-nY5" name="value" keyPath="values.globalUpdateAll" id="FrQ-u0-lFo">
<dictionary key="options">
<bool key="NSAllowsEditingMultipleValuesSelection" value="NO"/>
@@ -327,7 +329,7 @@
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="36q-Dv-PLf">
<rect key="frame" x="18" y="49" width="133" height="17"/>
<rect key="frame" x="18" y="76" width="133" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Menu bar icon:" id="Mkr-3d-gmN">
<font key="font" metaFont="system"/>
@@ -336,33 +338,34 @@
</textFieldCell>
</textField>
<imageView focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="usG-bX-431">
<rect key="frame" x="156" y="42" width="32" height="32"/>
<rect key="frame" x="156" y="69" width="32" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<imageCell key="cell" selectable="YES" editable="YES" focusRingType="none" alignment="left" imageScaling="proportionallyDown" imageFrameStyle="grayBezel" image="NSBookmarksTemplate" id="QxY-0c-aDo"/>
</imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2sG-NO-OJz">
<rect key="frame" x="18" y="22" width="133" height="17"/>
<rect key="frame" x="18" y="49" width="133" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Open URL in:" id="vNb-i3-dvE">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Open URLs with:" id="vNb-i3-dvE">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BcN-gW-jBg">
<rect key="frame" x="155" y="17" width="148" height="26"/>
<rect key="frame" x="155" y="44" width="148" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Default" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="qW6-vv-pdE" id="R91-En-pHg">
<popUpButtonCell key="cell" type="push" title="-- list --" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="qW6-vv-pdE" id="R91-En-pHg">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="M0i-AE-1LS">
<items>
<menuItem title="Default" state="on" id="qW6-vv-pdE"/>
<menuItem title="Safari" id="RTt-ZJ-ZHv"/>
<menuItem title="other …" id="hSc-D3-fq8"/>
<menuItem title="-- list --" state="on" id="qW6-vv-pdE"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="changeHttpApplication:" target="-2" id="Cyb-ab-VNu"/>
</connections>
</popUpButton>
<customView toolTip="Show in menu bar" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="P4Y-i1-MGE" customClass="SettingsIconGlobal">
<rect key="frame" x="20" y="260" width="18" height="18"/>
@@ -401,7 +404,7 @@
</userDefinedRuntimeAttributes>
</customView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Tec-F3-9cE">
<rect key="frame" x="201" y="48" width="46" height="18"/>
<rect key="frame" x="201" y="75" width="46" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Tint" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="19k-mc-RLe">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@@ -417,6 +420,31 @@
</binding>
</connections>
</button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="TC5-cu-zUi">
<rect key="frame" x="18" y="22" width="133" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Default RSS Reader:" id="wvK-Oz-Kk3">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tJe-jL-nUu">
<rect key="frame" x="155" y="17" width="148" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="-- list --" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="4Gg-hZ-mh4" id="saR-9h-TWE">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/>
<menu key="menu" id="8gY-aZ-fCb">
<items>
<menuItem title="-- list --" state="on" id="4Gg-hZ-mh4"/>
</items>
</menu>
</popUpButtonCell>
<connections>
<action selector="changeDefaultRSSReader:" target="-2" id="ul1-1K-oJb"/>
</connections>
</popUpButton>
</subviews>
<point key="canvasLocation" x="140" y="-155.5"/>
</customView>

View File

@@ -25,4 +25,6 @@
@interface UserPrefs : NSObject
+ (BOOL)defaultYES:(NSString*)key;
+ (BOOL)defaultNO:(NSString*)key;
+ (NSString*)getHttpApplication;
+ (void)setHttpApplication:(NSString*)bundleID;
@end

View File

@@ -35,4 +35,12 @@
return [[NSUserDefaults standardUserDefaults] boolForKey:key];
}
+ (NSString*)getHttpApplication {
return [[NSUserDefaults standardUserDefaults] stringForKey:@"defaultHttpApplication"];
}
+ (void)setHttpApplication:(NSString*)bundleID {
[[NSUserDefaults standardUserDefaults] setObject:bundleID forKey:@"defaultHttpApplication"];
}
@end

View File

@@ -78,7 +78,7 @@
Update menu bar icon and text according to unread count and user preferences.
*/
- (void)updateBarIcon {
// TODO: Option: unread count in menubar, Option: highlight color, Option: icon choice
// TODO: Option: icon choice
dispatch_async(dispatch_get_main_queue(), ^{
if (self.unreadCountTotal > 0 && [UserPrefs defaultYES:@"globalUnreadCount"]) {
self.barItem.title = [NSString stringWithFormat:@"%d", self.unreadCountTotal];
@@ -394,9 +394,8 @@
@param urls A list of @c NSURL objects that will be opened immediatelly in bulk.
*/
- (void)openURLsWithPreferredBrowser:(NSArray<NSURL*>*)urls {
// TODO: lookup preferred browser in user preferences
if (urls.count == 0) return;
// [[NSWorkspace sharedWorkspace] openURLs:urls withAppBundleIdentifier:@"com.apple.Safari" options:NSWorkspaceLaunchDefault additionalEventParamDescriptor:nil launchIdentifiers:nil];
[[NSWorkspace sharedWorkspace] openURLs:urls withAppBundleIdentifier:[UserPrefs getHttpApplication] options:NSWorkspaceLaunchDefault additionalEventParamDescriptor:nil launchIdentifiers:nil];
}