Blue dot for unread articles
This commit is contained in:
@@ -30,6 +30,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- *UI:* Interface builder files replaced with code equivalent
|
- *UI:* Interface builder files replaced with code equivalent
|
||||||
|
- *UI:* Mark unread articles with blue dot, instead of tick mark
|
||||||
- *Settings, Feeds:* Single add button for feeds, groups, and separators
|
- *Settings, Feeds:* Single add button for feeds, groups, and separators
|
||||||
- *Settings, Feeds:* Always append new items at the end
|
- *Settings, Feeds:* Always append new items at the end
|
||||||
- *Adding feed:* Display error reason if user cancels the creation of a new feed item
|
- *Adding feed:* Display error reason if user cancels the creation of a new feed item
|
||||||
|
|||||||
@@ -31,6 +31,29 @@
|
|||||||
/// UTI type used for opml files
|
/// UTI type used for opml files
|
||||||
static const NSPasteboardType UTI_OPML = @"org.opml";
|
static const NSPasteboardType UTI_OPML = @"org.opml";
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - NSImageName constants
|
||||||
|
|
||||||
|
|
||||||
|
/// Default RSS icon (with border, with gradient, orange)
|
||||||
|
static NSImageName const RSSImageDefaultRSSIcon = @"RSSImageDefaultRSSIcon";
|
||||||
|
/// Settings, global icon (menu bar, black)
|
||||||
|
static NSImageName const RSSImageSettingsGlobal = @"RSSImageSettingsGlobal";
|
||||||
|
/// Settings, group icon (folder, black)
|
||||||
|
static NSImageName const RSSImageSettingsGroup = @"RSSImageSettingsGroup";
|
||||||
|
/// Settings, feed icon (RSS, no border, no gradient, black)
|
||||||
|
static NSImageName const RSSImageSettingsFeed = @"RSSImageSettingsFeed";
|
||||||
|
/// Menu bar, bar icon (RSS, with border, no gradient, orange)
|
||||||
|
static NSImageName const RSSImageMenuBarIconActive = @"RSSImageMenuBarIconActive";
|
||||||
|
/// Menu bar, bar icon (RSS, with border, no gradient, paused, orange)
|
||||||
|
static NSImageName const RSSImageMenuBarIconPaused = @"RSSImageMenuBarIconPaused";
|
||||||
|
/// Menu item, unread state icon (blue dot)
|
||||||
|
static NSImageName const RSSImageMenuItemUnread = @"RSSImageMenuItemUnread";
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - NSNotificationName constants
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@c notification.object is @c NSNumber of type @c NSUInteger.
|
@c notification.object is @c NSNumber of type @c NSUInteger.
|
||||||
Represents number of feeds that are proccessed in background update. Sends @c 0 when all downloads are finished.
|
Represents number of feeds that are proccessed in background update. Sends @c 0 when all downloads are finished.
|
||||||
@@ -64,6 +87,9 @@ static const NSNotificationName kNotificationTotalUnreadCountChanged = @"baRSS-n
|
|||||||
static const NSNotificationName kNotificationTotalUnreadCountReset = @"baRSS-notification-total-unread-count-reset";
|
static const NSNotificationName kNotificationTotalUnreadCountReset = @"baRSS-notification-total-unread-count-reset";
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Internal
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Internal developer method for benchmarking purposes.
|
Internal developer method for benchmarking purposes.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
#import "Feed+Ext.h"
|
#import "Feed+Ext.h"
|
||||||
#import "Constants.h"
|
#import "Constants.h"
|
||||||
#import "UserPrefs.h"
|
#import "UserPrefs.h"
|
||||||
#import "DrawImage.h"
|
|
||||||
#import "FeedMeta+Ext.h"
|
#import "FeedMeta+Ext.h"
|
||||||
#import "FeedGroup+Ext.h"
|
#import "FeedGroup+Ext.h"
|
||||||
#import "FeedArticle+Ext.h"
|
#import "FeedArticle+Ext.h"
|
||||||
|
|||||||
@@ -67,6 +67,8 @@
|
|||||||
item.title = [self shortArticleName];
|
item.title = [self shortArticleName];
|
||||||
item.enabled = (self.link.length > 0);
|
item.enabled = (self.link.length > 0);
|
||||||
item.state = (self.unread && [UserPrefs defaultYES:@"feedTickMark"] ? NSControlStateValueOn : NSControlStateValueOff);
|
item.state = (self.unread && [UserPrefs defaultYES:@"feedTickMark"] ? NSControlStateValueOn : NSControlStateValueOff);
|
||||||
|
item.onStateImage = [NSImage imageNamed:RSSImageMenuItemUnread];
|
||||||
|
item.accessibilityLabel = (self.unread ? NSLocalizedString(@"article: unread", @"accessibility label, feed menu item") : NSLocalizedString(@"article: read", @"accessibility label, feed menu item"));
|
||||||
item.toolTip = (self.abstract ? self.abstract : self.body); // fall back to body (html)
|
item.toolTip = (self.abstract ? self.abstract : self.body); // fall back to body (html)
|
||||||
item.representedObject = self.objectID;
|
item.representedObject = self.objectID;
|
||||||
item.target = [self class];
|
item.target = [self class];
|
||||||
|
|||||||
@@ -36,11 +36,4 @@ IB_DESIGNABLE
|
|||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
static NSImageName const RSSImageSettingsGlobal = @"RSSImageSettingsGlobal";
|
|
||||||
static NSImageName const RSSImageSettingsGroup = @"RSSImageSettingsGroup";
|
|
||||||
static NSImageName const RSSImageSettingsFeed = @"RSSImageSettingsFeed";
|
|
||||||
static NSImageName const RSSImageDefaultRSSIcon = @"RSSImageDefaultRSSIcon";
|
|
||||||
static NSImageName const RSSImageMenuBarIconActive = @"RSSImageMenuBarIconActive";
|
|
||||||
static NSImageName const RSSImageMenuBarIconPaused = @"RSSImageMenuBarIconPaused";
|
|
||||||
|
|
||||||
void RegisterImageViewNames(void);
|
void RegisterImageViewNames(void);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
// SOFTWARE.
|
// SOFTWARE.
|
||||||
|
|
||||||
#import "DrawImage.h"
|
#import "DrawImage.h"
|
||||||
|
#import "Constants.h"
|
||||||
|
|
||||||
@implementation NSColor (RandomColor)
|
@implementation NSColor (RandomColor)
|
||||||
/// @return Color with random R, G, B values for testing purposes
|
/// @return Color with random R, G, B values for testing purposes
|
||||||
@@ -72,6 +73,12 @@ NS_INLINE void PathAddCircle(CGMutablePathRef path, CGFloat radius) {
|
|||||||
CGPathAddArc(path, NULL, radius, radius, radius, 0, M_PI * 2, YES);
|
CGPathAddArc(path, NULL, radius, radius, radius, 0, M_PI * 2, YES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add ring with @c radius and @c innerRadius
|
||||||
|
NS_INLINE void PathAddRing(CGMutablePathRef path, CGFloat radius, CGFloat innerRadius) {
|
||||||
|
CGPathAddArc(path, NULL, radius, radius, radius, 0, M_PI * 2, YES);
|
||||||
|
CGPathAddArc(path, NULL, radius, radius, innerRadius, 0, M_PI * -2, YES);
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a single RSS icon radio wave
|
/// Add a single RSS icon radio wave
|
||||||
NS_INLINE void PathAddRSSArc(CGMutablePathRef path, CGFloat radius, CGFloat thickness) {
|
NS_INLINE void PathAddRSSArc(CGMutablePathRef path, CGFloat radius, CGFloat thickness) {
|
||||||
CGPathMoveToPoint(path, NULL, 0, radius + thickness);
|
CGPathMoveToPoint(path, NULL, 0, radius + thickness);
|
||||||
@@ -285,6 +292,25 @@ NS_INLINE void DrawRSSGradientIcon(CGRect r) {
|
|||||||
CGContextEOFillPath(c);
|
CGContextEOFillPath(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Draw unread icon (blue dot for unread menu item)
|
||||||
|
NS_INLINE void DrawUnreadIcon(CGRect r, NSColor *color) {
|
||||||
|
CGFloat size = ShorterSide(r.size) / 2.0;
|
||||||
|
CGContextRef c = NSGraphicsContext.currentContext.CGContext;
|
||||||
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
|
SetContentScale(c, r.size, 0.8);
|
||||||
|
|
||||||
|
CGContextSetFillColorWithColor(c, color.CGColor);
|
||||||
|
PathAddRing(path, size, size * 0.7);
|
||||||
|
CGContextAddPath(c, path);
|
||||||
|
CGContextEOFillPath(c);
|
||||||
|
|
||||||
|
CGContextSetFillColorWithColor(c, [color colorWithAlphaComponent:0.5].CGColor);
|
||||||
|
PathAddCircle(path, size);
|
||||||
|
CGContextAddPath(c, path);
|
||||||
|
CGContextFillPath(c);
|
||||||
|
CGPathRelease(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - NSImage Name Registration
|
#pragma mark - NSImage Name Registration
|
||||||
|
|
||||||
@@ -299,10 +325,11 @@ NS_INLINE void Register(CGFloat size, NSImageName name, NSString *description, B
|
|||||||
/// Register all icons that require custom drawing in @c ImageNamed cache
|
/// Register all icons that require custom drawing in @c ImageNamed cache
|
||||||
void RegisterImageViewNames(void) {
|
void RegisterImageViewNames(void) {
|
||||||
const CGColorRef black = [NSColor controlTextColor].CGColor;
|
const CGColorRef black = [NSColor controlTextColor].CGColor;
|
||||||
|
Register(16, RSSImageDefaultRSSIcon, NSLocalizedString(@"RSS icon", nil), ^(NSRect r) { DrawRSSGradientIcon(r); return YES; });
|
||||||
Register(16, RSSImageSettingsGlobal, NSLocalizedString(@"Global settings", nil), ^(NSRect r) { DrawGlobalIcon(r, black, NO); return YES; });
|
Register(16, RSSImageSettingsGlobal, NSLocalizedString(@"Global settings", nil), ^(NSRect r) { DrawGlobalIcon(r, black, NO); return YES; });
|
||||||
Register(16, RSSImageSettingsGroup, NSLocalizedString(@"Group settings", nil), ^(NSRect r) { DrawGroupIcon(r, black, NO); return YES; });
|
Register(16, RSSImageSettingsGroup, NSLocalizedString(@"Group settings", nil), ^(NSRect r) { DrawGroupIcon(r, black, NO); return YES; });
|
||||||
Register(16, RSSImageSettingsFeed, NSLocalizedString(@"Feed settings", nil), ^(NSRect r) { DrawRSSIcon(r, black, NO, YES); return YES; });
|
Register(16, RSSImageSettingsFeed, NSLocalizedString(@"Feed settings", nil), ^(NSRect r) { DrawRSSIcon(r, black, NO, YES); return YES; });
|
||||||
Register(16, RSSImageDefaultRSSIcon, NSLocalizedString(@"RSS icon", nil), ^(NSRect r) { DrawRSSGradientIcon(r); return YES; });
|
|
||||||
Register(16, RSSImageMenuBarIconActive, NSLocalizedString(@"RSS menu bar icon", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor rssOrange].CGColor, YES, YES); return YES; });
|
Register(16, RSSImageMenuBarIconActive, NSLocalizedString(@"RSS menu bar icon", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor rssOrange].CGColor, YES, YES); return YES; });
|
||||||
Register(16, RSSImageMenuBarIconPaused, NSLocalizedString(@"RSS menu bar icon, paused", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor rssOrange].CGColor, YES, NO); return YES; });
|
Register(16, RSSImageMenuBarIconPaused, NSLocalizedString(@"RSS menu bar icon, paused", nil), ^(NSRect r) { DrawRSSIcon(r, [NSColor rssOrange].CGColor, YES, NO); return YES; });
|
||||||
|
Register(12, RSSImageMenuItemUnread, NSLocalizedString(@"Unread icon", nil), ^(NSRect r) { DrawUnreadIcon(r, [NSColor systemBlueColor]); return YES; });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>9750</string>
|
<string>9859</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.news</string>
|
<string>public.app-category.news</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#import "SettingsAppearanceView.h"
|
#import "SettingsAppearanceView.h"
|
||||||
#import "NSView+Ext.h"
|
#import "NSView+Ext.h"
|
||||||
#import "DrawImage.h"
|
#import "Constants.h"
|
||||||
#import "UserPrefs.h"
|
#import "UserPrefs.h"
|
||||||
|
|
||||||
@interface SettingsAppearanceView()
|
@interface SettingsAppearanceView()
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#import "BarStatusItem.h"
|
#import "BarStatusItem.h"
|
||||||
#import "Constants.h"
|
#import "Constants.h"
|
||||||
#import "DrawImage.h"
|
|
||||||
#import "FeedDownload.h"
|
#import "FeedDownload.h"
|
||||||
#import "StoreCoordinator.h"
|
#import "StoreCoordinator.h"
|
||||||
#import "UserPrefs.h"
|
#import "UserPrefs.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user