- 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

7
LICENSE Normal file
View File

@@ -0,0 +1,7 @@
Copyright 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.

87
README.md Normal file
View File

@@ -0,0 +1,87 @@
# baRSS *Menu Bar RSS Reader*
![screenshot](doc/screenshot.png)
For nearly a decade I've been using the then free version of [RSS Menu](https://itunes.apple.com/us/app/rss-menu/id423069534). However, with the release of macOS Mojave, 32bit applications are no longer supported.
*baRSS* is an open source community project and will be available on the AppStore soon (hopefully); free of charge. Everything is built from the ground up with a minimal footprint in mind.
Why is this project not written in Swift?
-----------------------------------------
Actually, I started this project with Swift. Even without adding much functionality, the app was exceeding the 10 Mb file size. Compared to the nearly finished Alpha version with 500 Kb written in Objective-C. The reason for that, Swift frameworks are always packed into the final application. I decided that this level of encapsulation is a waste of space for such a small application.
3rd Party Libraries
-------------------
This project uses a modified version of Brent Simmons [RSXML](https://github.com/brentsimmons/RSXML) for feed parsing. RSXML is licensed under a MIT license (same as this project).
Current project state
---------------------
The basic functionality is there. Manually added feeds will be downloaded and stored in an SQLite database. The complete management of feeds is there (sorting, grouping, editing, deleting). The bar menu is functional too, including unread count, URL opening and display.
ToDo
----
- [ ] Preferences
- [x] Choose favorite web browser
- [x] Show list of installed browsers
- [ ] Choose status bar icon?
- [ ] Tick mark feed items based on prefs
- [ ] Open a few links (# editable)
- [ ] Performance: Update menu partially
- [ ] Start on login
- [x] Make it system default application
- [ ] Display license info (e.g., RSXML)
- [ ] Short article names
- [ ] Import / Export (all feeds)
- [ ] Support for `.opml` format
- [ ] Append or replace
- [ ] Status menu
- [ ] Update menu header after mark (un)read
- [ ] Pause updates functionality
- [ ] Update all feeds functionality
- [ ] Edit feed
- [ ] Show statistics
- [ ] How often gets the feed updated (min, max, avg)
- [ ] Automatically choose best interval?
- [ ] Auto fix 301 Redirect or ask user
- [ ] Make `feed://` URLs clickable
- [ ] Feeds with authentication
- [ ] Show proper feed icon
- [ ] Download and store icon file
- [ ] Other
- [ ] App Icon
- [ ] Translate text to different languages
- [ ] Automatically update feeds with chosen interval
- [ ] Reuse ETag and Modification date
- [ ] Append only new items, keep sorting
- [ ] Delete old ones eventually
- [ ] Purge cache
- [ ] Manually or automatically
- [ ] Add something to restore a broken state
- [ ] Code Documentation (mostly methods)
- [ ] Add Sandboxing
- [ ] Additional features
- [ ] Sync with online services!
- [ ] Notification Center
- [ ] Sleep timer. (e.g., disable updates during working hours)
- [ ] Pure image feed? (show images directly in menu)
- [ ] Infinite storage. (load more button)
- [ ] Automatically open feed items?
- [ ] Per feed launch application (e.g., for podcasts)
- [ ] Per group setting to exclude unread count from menu bar

View File

@@ -31,8 +31,14 @@
return self; return self;
} }
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - (void)applicationWillFinishLaunching:(NSNotification *)notification {
_barMenu = [BarMenu new]; _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"); printf("up and running\n");
// https://feeds.feedburner.com/simpledesktops // 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 #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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <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> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>NSHumanReadableCopyright</key> <key>CFBundleExecutable</key>
<string>Copyright © 2018 relikd. All rights reserved.</string> <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> <key>CFBundleShortVersionString</key>
<string>1.0</string> <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> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsArbitraryLoads</key> <key>NSAllowsArbitraryLoads</key>
<true/> <true/>
</dict> </dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2018 relikd. Public Domain.</string>
<key>NSPrincipalClass</key>
<string>AppHook</string>
</dict> </dict>
</plist> </plist>

View File

@@ -23,13 +23,42 @@
#import "SettingsGeneral.h" #import "SettingsGeneral.h"
#import "AppHook.h" #import "AppHook.h"
#import "BarMenu.h" #import "BarMenu.h"
#import "UserPrefs.h"
@interface SettingsGeneral()
@property (weak) IBOutlet NSPopUpButton *popupHttpApplication;
@property (weak) IBOutlet NSPopUpButton *popupDefaultRSSReader;
@end
@implementation SettingsGeneral @implementation SettingsGeneral
- (void)viewDidLoad { - (void)viewDidLoad {
[super 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 { - (IBAction)checkmarkClicked:(NSButton*)sender {
// TODO: Could be optimized by updating only the relevant parts // TODO: Could be optimized by updating only the relevant parts
[[(AppHook*)NSApp barMenu] rebuildMenu]; [[(AppHook*)NSApp barMenu] rebuildMenu];
@@ -48,11 +77,111 @@
[[(AppHook*)NSApp barMenu] updateMenuHeaders:recursive]; [[(AppHook*)NSApp barMenu] updateMenuHeaders:recursive];
} }
- (IBAction)changeMenuItemUpdateAllHidden:(NSButton*)sender { - (IBAction)changeMenuItemUpdateAll:(NSButton*)sender {
BOOL checked = (sender.state == NSControlStateValueOn); BOOL checked = (sender.state == NSControlStateValueOn);
[[(AppHook*)NSApp barMenu] setItemUpdateAllHidden:!checked]; [[(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 @end

View File

@@ -8,6 +8,8 @@
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="SettingsGeneral"> <customObject id="-2" userLabel="File's Owner" customClass="SettingsGeneral">
<connections> <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"/> <outlet property="view" destination="mbb-wD-pDD" id="Syb-4w-ekh"/>
</connections> </connections>
</customObject> </customObject>
@@ -42,7 +44,7 @@
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
</buttonCell> </buttonCell>
<connections> <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"> <binding destination="iU7-KA-nY5" name="value" keyPath="values.globalUpdateAll" id="FrQ-u0-lFo">
<dictionary key="options"> <dictionary key="options">
<bool key="NSAllowsEditingMultipleValuesSelection" value="NO"/> <bool key="NSAllowsEditingMultipleValuesSelection" value="NO"/>
@@ -327,7 +329,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="36q-Dv-PLf"> <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"/> <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"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Menu bar icon:" id="Mkr-3d-gmN">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@@ -336,33 +338,34 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<imageView focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="usG-bX-431"> <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"/> <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"/> <imageCell key="cell" selectable="YES" editable="YES" focusRingType="none" alignment="left" imageScaling="proportionallyDown" imageFrameStyle="grayBezel" image="NSBookmarksTemplate" id="QxY-0c-aDo"/>
</imageView> </imageView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2sG-NO-OJz"> <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"/> <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"/> <font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell> </textFieldCell>
</textField> </textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BcN-gW-jBg"> <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"/> <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"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/> <font key="font" metaFont="menu"/>
<menu key="menu" id="M0i-AE-1LS"> <menu key="menu" id="M0i-AE-1LS">
<items> <items>
<menuItem title="Default" state="on" id="qW6-vv-pdE"/> <menuItem title="-- list --" state="on" id="qW6-vv-pdE"/>
<menuItem title="Safari" id="RTt-ZJ-ZHv"/>
<menuItem title="other …" id="hSc-D3-fq8"/>
</items> </items>
</menu> </menu>
</popUpButtonCell> </popUpButtonCell>
<connections>
<action selector="changeHttpApplication:" target="-2" id="Cyb-ab-VNu"/>
</connections>
</popUpButton> </popUpButton>
<customView toolTip="Show in menu bar" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="P4Y-i1-MGE" customClass="SettingsIconGlobal"> <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"/> <rect key="frame" x="20" y="260" width="18" height="18"/>
@@ -401,7 +404,7 @@
</userDefinedRuntimeAttributes> </userDefinedRuntimeAttributes>
</customView> </customView>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Tec-F3-9cE"> <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"/> <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"> <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"/> <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
@@ -417,6 +420,31 @@
</binding> </binding>
</connections> </connections>
</button> </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> </subviews>
<point key="canvasLocation" x="140" y="-155.5"/> <point key="canvasLocation" x="140" y="-155.5"/>
</customView> </customView>

View File

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

View File

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

View File

@@ -78,7 +78,7 @@
Update menu bar icon and text according to unread count and user preferences. Update menu bar icon and text according to unread count and user preferences.
*/ */
- (void)updateBarIcon { - (void)updateBarIcon {
// TODO: Option: unread count in menubar, Option: highlight color, Option: icon choice // TODO: Option: icon choice
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (self.unreadCountTotal > 0 && [UserPrefs defaultYES:@"globalUnreadCount"]) { if (self.unreadCountTotal > 0 && [UserPrefs defaultYES:@"globalUnreadCount"]) {
self.barItem.title = [NSString stringWithFormat:@"%d", self.unreadCountTotal]; 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. @param urls A list of @c NSURL objects that will be opened immediatelly in bulk.
*/ */
- (void)openURLsWithPreferredBrowser:(NSArray<NSURL*>*)urls { - (void)openURLsWithPreferredBrowser:(NSArray<NSURL*>*)urls {
// TODO: lookup preferred browser in user preferences
if (urls.count == 0) return; 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];
} }

BIN
doc/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB