Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c9362b42e | ||
|
|
9af191834e | ||
|
|
8d2e4e4383 | ||
|
|
473d4b6057 |
17
CHANGELOG.md
17
CHANGELOG.md
@@ -7,6 +7,19 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.2] - 2019-10-25
|
||||||
|
### Fixed
|
||||||
|
- *Status Bar Menu*: Preferences could not be opened on macOS 10.15
|
||||||
|
- *Status Bar Menu*: Menu flickering resulting in a hang on macOS 10.15
|
||||||
|
- *UI*: Text color in `About` tab
|
||||||
|
|
||||||
|
|
||||||
|
## [1.0.1] - 2019-10-04
|
||||||
|
### Fixed
|
||||||
|
- Crash on macOS 10.14 due to a `CGColorRef` null pointer
|
||||||
|
|
||||||
|
|
||||||
## [1.0.0] - 2019-10-03
|
## [1.0.0] - 2019-10-03
|
||||||
### Added
|
### Added
|
||||||
- App Signing
|
- App Signing
|
||||||
@@ -115,7 +128,9 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
|
|||||||
Initial release
|
Initial release
|
||||||
|
|
||||||
|
|
||||||
[Unreleased]: https://github.com/relikd/baRSS/compare/v1.0.0...HEAD
|
[Unreleased]: https://github.com/relikd/baRSS/compare/v1.0.2...HEAD
|
||||||
|
[1.0.2]: https://github.com/relikd/baRSS/compare/v1.0.1...v1.0.2
|
||||||
|
[1.0.1]: https://github.com/relikd/baRSS/compare/v1.0.0...v1.0.1
|
||||||
[1.0.0]: https://github.com/relikd/baRSS/compare/v0.9.4...v1.0.0
|
[1.0.0]: https://github.com/relikd/baRSS/compare/v0.9.4...v1.0.0
|
||||||
[0.9.4]: https://github.com/relikd/baRSS/compare/v0.9.3...v0.9.4
|
[0.9.4]: https://github.com/relikd/baRSS/compare/v0.9.3...v0.9.4
|
||||||
[0.9.3]: https://github.com/relikd/baRSS/compare/v0.9.2...v0.9.3
|
[0.9.3]: https://github.com/relikd/baRSS/compare/v0.9.2...v0.9.3
|
||||||
|
|||||||
95
README.md
95
README.md
@@ -31,39 +31,6 @@ But it will reuse `ETag` and `Last-Modified` headers to avoid unnecessary transm
|
|||||||
Further, tuning the update frequently will decrease the traffic even more.
|
Further, tuning the update frequently will decrease the traffic even more.
|
||||||
|
|
||||||
|
|
||||||
### Why create something that already existed?
|
|
||||||
|
|
||||||
First, open source is awesome!
|
|
||||||
Secondly, RSS Menu made some design decisions I didn't like.
|
|
||||||
For example, the new integrated browser window.
|
|
||||||
|
|
||||||
One thing I liked most, was the fact that feeds were opened in the default browser.
|
|
||||||
Not like 99% of the other feed readers on the market that show a separate HTML viewer window.
|
|
||||||
No rendering issues, no broken links, no content that is different from the actual news article.
|
|
||||||
|
|
||||||
I know, the whole purpose of RSS is to deliver content without the need of opening a webpage.
|
|
||||||
But for me RSS is more about being informed whenever a blog or news feed has some updated content.
|
|
||||||
E.g, subscribing to video channels without having to have an account.
|
|
||||||
|
|
||||||
|
|
||||||
### 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.
|
|
||||||
The working alpha version, written in Objective-C, had only 500 Kb.
|
|
||||||
The reason being that Swift frameworks are always packed into the final application.
|
|
||||||
|
|
||||||
Sadly, this was before Swift 5 and ABI stability.
|
|
||||||
Had I only started the project a year later…
|
|
||||||
But on the other hand, now it is macOS 10.12 compatible.
|
|
||||||
|
|
||||||
|
|
||||||
### 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).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Download & Install
|
Download & Install
|
||||||
------------------
|
------------------
|
||||||
@@ -71,19 +38,19 @@ Download & Install
|
|||||||
Requires macOS Sierra (10.12) or higher.
|
Requires macOS Sierra (10.12) or higher.
|
||||||
|
|
||||||
### Easy way
|
### Easy way
|
||||||
Go to [releases](https://github.com/relikd/baRSS/releases) and downloaded the latest version.
|
Go to [releases](https://github.com/relikd/baRSS/releases) and downloaded the latest version.
|
||||||
|
Searching for the App Store release? Read this [notice](#app-store-notice).
|
||||||
|
|
||||||
### Build from source
|
### Build from source
|
||||||
|
|
||||||
You'll need Xcode and [Carthage](https://github.com/Carthage/Carthage#installing-carthage).
|
You'll need Xcode and [Carthage](https://github.com/Carthage/Carthage#installing-carthage).
|
||||||
The latter is optional, you can build the [RSXML2](https://github.com/relikd/RSXML2) library from source instead.
|
The latter is optional, you can build the [RSXML2] library from source instead.
|
||||||
Carthage just makes it more convenient.
|
Carthage just makes it more convenient.
|
||||||
Download and unzip this project, navigate to the root folder and run `carthage bootstrap --platform macOS`.
|
Download and unzip this project, navigate to the root folder and run `carthage bootstrap --platform macOS`.
|
||||||
|
|
||||||
Next, you need to clone [QLOPML](https://github.com/relikd/QLOPML) in the same folder where this project is.
|
Next, you need to clone [QLOPML](https://github.com/relikd/QLOPML) in the same folder where this project is.
|
||||||
Alternatively, you can simply delete the `QLOPML` project reference without much harm.
|
Alternatively, you can simply delete the `QLOPML` project reference without much harm.
|
||||||
`QLOPML` is a Quick Look plugin for `.opml` files.
|
`QLOPML` is a Quick Look plugin for `.opml` files.
|
||||||
It will display the file contents whenever you hit space.
|
It will display the file contents whenever you hit spacebar.
|
||||||
|
|
||||||
That's it.
|
That's it.
|
||||||
Open Xcode and build the project.
|
Open Xcode and build the project.
|
||||||
@@ -160,9 +127,61 @@ I may postpone some until demand increases …
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
FAQ / Q&A
|
||||||
|
---------
|
||||||
|
|
||||||
|
### App Store Notice
|
||||||
|
|
||||||
|
In the last couple of months I prepared baRSS to be released on the App Store.
|
||||||
|
With sandboxing enabled and hardened runtime environment, etc.
|
||||||
|
|
||||||
|
But, for the time being, I decided to not publish this app for political reasons.
|
||||||
|
I was not happy about some decisions made in the last weeks.
|
||||||
|
Decisions that were evaluated on monetary aspects and not on ethical considerations.
|
||||||
|
I won't support this conduct with my own money.
|
||||||
|
|
||||||
|
If you find this app somewhere on the App Store, you can be sure that it is a counterfeit.
|
||||||
|
As long as you can read this very notice, I am not responsible for the publication.
|
||||||
|
Further, I can't guarantee the App Store version wasn't modified by a malicious actor to spy on you.
|
||||||
|
|
||||||
|
|
||||||
|
### Why create something that already existed?
|
||||||
|
|
||||||
|
First, open source is awesome!
|
||||||
|
Secondly, RSS Menu made some design decisions I didn't like.
|
||||||
|
For example, the new integrated browser window.
|
||||||
|
|
||||||
|
One thing I liked most, was the fact that feeds were opened in the default browser.
|
||||||
|
Not like 99% of the other feed readers on the market that show a separate HTML viewer window.
|
||||||
|
No rendering issues, no broken links, no content that is different from the actual news article.
|
||||||
|
|
||||||
|
I know, the whole purpose of RSS is to deliver content without the need of opening a webpage.
|
||||||
|
But for me RSS is more about being informed whenever a blog or news feed has some updated content.
|
||||||
|
E.g, subscribing to video channels without having to have an account.
|
||||||
|
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
The working alpha version, written in Objective-C, had only 500 Kb.
|
||||||
|
The reason being that Swift frameworks are always packed into the final application.
|
||||||
|
|
||||||
|
Sadly, this was before Swift 5 and ABI stability.
|
||||||
|
Had I only started the project a year later…
|
||||||
|
But on the other hand, now it is macOS 10.12 compatible.
|
||||||
|
|
||||||
|
### 3rd Party Libraries
|
||||||
|
|
||||||
|
This project uses a modified version of Brent Simmons' [RSXML](https://github.com/brentsimmons/RSXML) for feed parsing.
|
||||||
|
[RSXML2] is licensed under a MIT license (same as this project).
|
||||||
|
|
||||||
|
|
||||||
##### Trivia
|
##### Trivia
|
||||||
|
|
||||||
- Start of project: __July 19, 2018__
|
- Start of project: __July 19, 2018__
|
||||||
- Estimated development time: __1940h+__
|
- Estimated development time: __1953h+__
|
||||||
- First prototype used __feedparser python__ library
|
- First prototype used __feedparser python__ library
|
||||||
|
|
||||||
|
|
||||||
|
[RSXML2]: https://github.com/relikd/RSXML2
|
||||||
|
|||||||
@@ -702,6 +702,7 @@
|
|||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
|||||||
@@ -80,5 +80,10 @@
|
|||||||
return [NSString stringWithFormat:@"http://i.ytimg.com/vi/%@/hqdefault.jpg", videoid];
|
return [NSString stringWithFormat:@"http://i.ytimg.com/vi/%@/hqdefault.jpg", videoid];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return @c http://i.ytimg.com/vi/<videoid>/maxresdefault.jpg
|
||||||
|
+ (NSString*)videoImage4k:(NSString*)videoid {
|
||||||
|
return [NSString stringWithFormat:@"http://i.ytimg.com/vi/%@/maxresdefault.jpg", videoid];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0.1</string>
|
<string>1.0.2</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>14405</string>
|
<string>14471</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>
|
||||||
|
|||||||
@@ -74,7 +74,8 @@
|
|||||||
/// Helper method to insert attributed (bold) text
|
/// Helper method to insert attributed (bold) text
|
||||||
- (void)str:(NSMutableAttributedString*)parent add:(NSString*)text bold:(BOOL)flag {
|
- (void)str:(NSMutableAttributedString*)parent add:(NSString*)text bold:(BOOL)flag {
|
||||||
NSFont *font = [NSFont systemFontOfSize:NSFont.systemFontSize weight:(flag ? NSFontWeightMedium : NSFontWeightLight)];
|
NSFont *font = [NSFont systemFontOfSize:NSFont.systemFontSize weight:(flag ? NSFontWeightMedium : NSFontWeightLight)];
|
||||||
[parent appendAttributedString:[[NSAttributedString alloc] initWithString:NonLocalized(text) attributes:@{ NSFontAttributeName : font }]];
|
NSDictionary *style = @{ NSFontAttributeName: font, NSForegroundColorAttributeName: [NSColor controlTextColor] };
|
||||||
|
[parent appendAttributedString:[[NSAttributedString alloc] initWithString:NonLocalized(text) attributes:style]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper method to insert attributed hyperlink text
|
/// Helper method to insert attributed hyperlink text
|
||||||
|
|||||||
@@ -24,20 +24,20 @@
|
|||||||
@class ModalFeedEdit;
|
@class ModalFeedEdit;
|
||||||
|
|
||||||
@interface ModalFeedEditView : NSView
|
@interface ModalFeedEditView : NSView
|
||||||
@property (weak) IBOutlet NSTextField *url;
|
@property (strong) IBOutlet NSTextField *url;
|
||||||
@property (weak) IBOutlet NSProgressIndicator *spinnerURL;
|
@property (strong) IBOutlet NSProgressIndicator *spinnerURL;
|
||||||
@property (weak) IBOutlet NSImageView *favicon;
|
@property (strong) IBOutlet NSImageView *favicon;
|
||||||
|
|
||||||
@property (weak) IBOutlet NSTextField *name;
|
@property (strong) IBOutlet NSTextField *name;
|
||||||
@property (weak) IBOutlet NSProgressIndicator *spinnerName;
|
@property (strong) IBOutlet NSProgressIndicator *spinnerName;
|
||||||
|
|
||||||
@property (weak) IBOutlet NSTextField *refreshNum;
|
@property (strong) IBOutlet NSTextField *refreshNum;
|
||||||
@property (weak) IBOutlet NSPopUpButton *refreshUnit;
|
@property (strong) IBOutlet NSPopUpButton *refreshUnit;
|
||||||
|
|
||||||
@property (weak) IBOutlet NSButton *warningButton;
|
@property (strong) IBOutlet NSButton *warningButton;
|
||||||
@property NSPopover *warningPopover;
|
@property NSPopover *warningPopover;
|
||||||
@property (weak) IBOutlet NSTextField *warningText;
|
@property (strong) IBOutlet NSTextField *warningText;
|
||||||
@property (weak) IBOutlet NSButton *warningReload;
|
@property (strong) IBOutlet NSButton *warningReload;
|
||||||
|
|
||||||
- (instancetype)initWithController:(ModalFeedEdit*)controller NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithController:(ModalFeedEdit*)controller NS_DESIGNATED_INITIALIZER;
|
||||||
- (instancetype)initWithFrame:(NSRect)frameRect NS_UNAVAILABLE;
|
- (instancetype)initWithFrame:(NSRect)frameRect NS_UNAVAILABLE;
|
||||||
|
|||||||
@@ -24,9 +24,9 @@
|
|||||||
@class SettingsFeeds;
|
@class SettingsFeeds;
|
||||||
|
|
||||||
@interface SettingsFeedsView : NSView
|
@interface SettingsFeedsView : NSView
|
||||||
@property (weak) IBOutlet NSOutlineView *outline;
|
@property (strong) IBOutlet NSOutlineView *outline;
|
||||||
@property (weak) IBOutlet NSTextField *status;
|
@property (strong) IBOutlet NSTextField *status;
|
||||||
@property (weak) IBOutlet NSProgressIndicator *spinner;
|
@property (strong) IBOutlet NSProgressIndicator *spinner;
|
||||||
|
|
||||||
- (instancetype)initWithController:(SettingsFeeds*)delegate NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithController:(SettingsFeeds*)delegate NS_DESIGNATED_INITIALIZER;
|
||||||
- (instancetype)initWithFrame:(NSRect)frameRect NS_UNAVAILABLE;
|
- (instancetype)initWithFrame:(NSRect)frameRect NS_UNAVAILABLE;
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
@class SettingsGeneral;
|
@class SettingsGeneral;
|
||||||
|
|
||||||
@interface SettingsGeneralView : NSView
|
@interface SettingsGeneralView : NSView
|
||||||
@property (weak) IBOutlet NSPopUpButton* popupHttpApplication;
|
@property (strong) IBOutlet NSPopUpButton* popupHttpApplication;
|
||||||
@property (weak) IBOutlet NSTextField *defaultReader;
|
@property (strong) IBOutlet NSTextField *defaultReader;
|
||||||
|
|
||||||
- (instancetype)initWithController:(SettingsGeneral*)controller NS_DESIGNATED_INITIALIZER;
|
- (instancetype)initWithController:(SettingsGeneral*)controller NS_DESIGNATED_INITIALIZER;
|
||||||
- (instancetype)initWithFrame:(NSRect)frameRect NS_UNAVAILABLE;
|
- (instancetype)initWithFrame:(NSRect)frameRect NS_UNAVAILABLE;
|
||||||
|
|||||||
@@ -82,11 +82,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get rid of everything that is not needed.
|
|
||||||
- (void)menuDidClose:(NSMenu*)menu {
|
|
||||||
[menu cleanup];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate items for @c FeedGroup menu.
|
/// Generate items for @c FeedGroup menu.
|
||||||
- (void)setFeedGroups:(NSArray<FeedGroup*>*)sortedList forMenu:(NSMenu*)menu {
|
- (void)setFeedGroups:(NSArray<FeedGroup*>*)sortedList forMenu:(NSMenu*)menu {
|
||||||
[menu insertDefaultHeader];
|
[menu insertDefaultHeader];
|
||||||
@@ -125,17 +120,21 @@
|
|||||||
Fetch @c Feed from core data and find deepest visible @c NSMenuItem.
|
Fetch @c Feed from core data and find deepest visible @c NSMenuItem.
|
||||||
@warning @c item and @c feed will often mismatch.
|
@warning @c item and @c feed will often mismatch.
|
||||||
*/
|
*/
|
||||||
- (void)updateFeedMenuItem:(NSManagedObjectID*)oid withBlock:(void(^)(Feed *feed, NSMenuItem *item))block {
|
- (BOOL)findDeepest:(NSManagedObjectID*)oid feed:(Feed*__autoreleasing*)feed menuItem:(NSMenuItem*__autoreleasing*)item {
|
||||||
Feed *feed = [[StoreCoordinator getMainContext] objectWithID:oid];
|
Feed *f = [[StoreCoordinator getMainContext] objectWithID:oid];
|
||||||
if ([feed isKindOfClass:[Feed class]]) {
|
if (![f isKindOfClass:[Feed class]]) return NO;
|
||||||
NSMenuItem *item = [self.statusItem.mainMenu deepestItemWithPath:feed.indexPath];
|
NSMenuItem *mi = [self.statusItem.mainMenu deepestItemWithPath:f.indexPath];
|
||||||
if (item) block(feed, item);
|
if (!mi) return NO;
|
||||||
}
|
*feed = f;
|
||||||
|
*item = mi;
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Callback method fired when feed has been updated in the background.
|
/// Callback method fired when feed has been updated in the background.
|
||||||
- (void)articlesUpdated:(NSNotification*)notify {
|
- (void)articlesUpdated:(NSNotification*)notify {
|
||||||
[self updateFeedMenuItem:notify.object withBlock:^(Feed *feed, NSMenuItem *item) {
|
Feed *feed;
|
||||||
|
NSMenuItem *item;
|
||||||
|
if ([self findDeepest:notify.object feed:&feed menuItem:&item]) {
|
||||||
// 1. update in-memory unread count
|
// 1. update in-memory unread count
|
||||||
UnreadTotal *updated = [UnreadTotal new];
|
UnreadTotal *updated = [UnreadTotal new];
|
||||||
updated.total = feed.articles.count;
|
updated.total = feed.articles.count;
|
||||||
@@ -160,15 +159,17 @@
|
|||||||
[item setTitleCount:uct.unread];
|
[item setTitleCount:uct.unread];
|
||||||
item = item.parentItem;
|
item = item.parentItem;
|
||||||
}
|
}
|
||||||
}];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Callback method fired when feed icon has changed.
|
/// Callback method fired when feed icon has changed.
|
||||||
- (void)feedIconUpdated:(NSNotification*)notify {
|
- (void)feedIconUpdated:(NSNotification*)notify {
|
||||||
[self updateFeedMenuItem:notify.object withBlock:^(Feed *feed, NSMenuItem *item) {
|
Feed *feed;
|
||||||
|
NSMenuItem *item;
|
||||||
|
if ([self findDeepest:notify.object feed:&feed menuItem:&item]) {
|
||||||
if (item.submenu.isFeedMenu)
|
if (item.submenu.isFeedMenu)
|
||||||
item.image = [feed iconImage16];
|
item.image = [feed iconImage16];
|
||||||
}];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
- (NSMenuItem*)insertFeedGroupItem:(FeedGroup*)fg;
|
- (NSMenuItem*)insertFeedGroupItem:(FeedGroup*)fg;
|
||||||
- (void)insertDefaultHeader;
|
- (void)insertDefaultHeader;
|
||||||
// Update menu
|
// Update menu
|
||||||
- (void)cleanup;
|
|
||||||
- (void)setHeaderHasUnread:(BOOL)hasUnread hasRead:(BOOL)hasRead;
|
- (void)setHeaderHasUnread:(BOOL)hasUnread hasRead:(BOOL)hasRead;
|
||||||
- (NSMenuItem*)deepestItemWithPath:(nonnull NSString*)path;
|
- (NSMenuItem*)deepestItemWithPath:(nonnull NSString*)path;
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -104,12 +104,6 @@ typedef NS_ENUM(NSInteger, MenuItemTag) {
|
|||||||
|
|
||||||
#pragma mark - Update Menu
|
#pragma mark - Update Menu
|
||||||
|
|
||||||
/// Replace this menu with a clean @c NSMenu. Copy old @c title and @c delegate to new menu. @b Won't work without supermenu!
|
|
||||||
- (void)cleanup {
|
|
||||||
NSMenu *m = [[NSMenu alloc] initWithTitle:self.title];
|
|
||||||
m.delegate = self.delegate;
|
|
||||||
self.parentItem.submenu = m;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Loop over default header and enable 'OpenAllUnread' and 'TagMarkAllRead' based on unread count.
|
/// Loop over default header and enable 'OpenAllUnread' and 'TagMarkAllRead' based on unread count.
|
||||||
- (void)setHeaderHasUnread:(BOOL)hasUnread hasRead:(BOOL)hasRead {
|
- (void)setHeaderHasUnread:(BOOL)hasUnread hasRead:(BOOL)hasRead {
|
||||||
|
|||||||
Reference in New Issue
Block a user