8 Commits

Author SHA1 Message Date
relikd
e0dec3adf9 Change matching order 2020-12-18 10:59:08 +01:00
relikd
f7eb63bed9 update changelog and bump version 2020-12-18 10:43:13 +01:00
relikd
23f4f125db Support for yt /c/channel-name URLs 2020-12-18 10:37:36 +01:00
relikd
b3940f103a Workaround for issue #7 2020-11-27 17:51:27 +01:00
relikd
239527908f Fix colorUnreadIndicator not being used 2020-11-27 17:42:13 +01:00
relikd
7df70a7936 update changelog 2020-08-31 21:26:44 +02:00
relikd
e8c4c06d33 Fix an issue where indices weren't updated, related to #6 2020-08-31 21:14:13 +02:00
relikd
a9c0e64689 Fix error log 'extractOptions unknown hint identifier' 2020-08-31 20:44:41 +02:00
15 changed files with 87 additions and 31 deletions

View File

@@ -8,7 +8,23 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
## [Unreleased]
## [1.1.0] - 2020-01-17
## [1.1.3] 2020-12-18
### Fixed
- Recognize YouTube channel URLs in the format `/c/channel-name`
## [1.1.2] 2020-11-27
### Fixed
- Fixes hidden color option for marking unread entries. Unread menu entries did use `colorStatusIconTint` instead of `colorUnreadIndicator` (thanks @tchek)
- Workaround for not displaying status bar highlight color in macOS 11.0 (issue #7)
## [1.1.1] 2020-08-31
### Fixed
- Feed indices weren't updated properly which resulted in empty feed menus (issue: #6)
## [1.1.0] 2020-01-17
### Added
- *QuickLook*: Thumbnail previews for OPML files (QLOPML v1.3)
- *Status Bar Menu*: Tint menu bar icon with Accent color (macOS 10.14+)
@@ -17,19 +33,19 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
- Resolved Xcode warnings in Xcode 11
## [1.0.2] - 2019-10-25
## [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
## [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
- App Signing
- Sandboxing & hardened runtime environment
@@ -86,7 +102,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
- *UI:* Mark unread articles with blue dot, instead of tick mark
## [0.9.4] - 2019-04-02
## [0.9.4] 2019-04-02
### Fixed
- Article order got mixed up for some feeds (issue: #4)
- If multiple consecutive items reappear in the middle of the feed mark them read
@@ -95,7 +111,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
- *UI:* Removed checkbox `Start on login`. Use Preferences > Users > Login Items instead.
## [0.9.3] - 2019-03-14
## [0.9.3] 2019-03-14
### Added
- Changelog
- *UI:* Show body tag in article tooltip if abstract tag is empty
@@ -105,7 +121,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
- Fixed update for feeds where all article URLs point to the same resource (issue: #3)
## [0.9.2] - 2019-03-07
## [0.9.2] 2019-03-07
### Added
- Limit number of articles that are displayed in feed menu (issue: #2)
@@ -115,7 +131,7 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
- libxml2 will ignore lower ascii characters (`0x00``0x1F`)
## [0.9.1] - 2019-02-14
## [0.9.1] 2019-02-14
### Added
- Mark single article as un/read (hold down option key and click on article)
@@ -133,11 +149,14 @@ and this project does adhere to [Semantic Versioning](https://semver.org/spec/v2
- Remove html tags from abstract on save (not on display)
## [0.9] - 2019-02-11
## [0.9] 2019-02-11
Initial release
[Unreleased]: https://github.com/relikd/baRSS/compare/v1.1.0...HEAD
[Unreleased]: https://github.com/relikd/baRSS/compare/v1.1.3...HEAD
[1.1.3]: https://github.com/relikd/baRSS/compare/v1.1.2...v1.1.3
[1.1.2]: https://github.com/relikd/baRSS/compare/v1.1.1...v1.1.2
[1.1.1]: https://github.com/relikd/baRSS/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/relikd/baRSS/compare/v1.0.2...v1.1.0
[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

View File

@@ -108,7 +108,7 @@ ToDo
The following list is not exhaustive but rather a collection of nice things that will be added eventually.
I may postpone some until demand increases …
- [ ] Localizations
- [ ] Localizations
- [ ] Feed generator for websites without feeds
- [ ] Automatically choose best update interval (e.g., avg)
- [ ] Sync with online services
@@ -180,7 +180,7 @@ This project uses a modified version of Brent Simmons' [RSXML](https://github.co
##### Trivia
- Start of project: __July 19, 2018__
- Estimated development time: __1953h+__
- Estimated development time: __1965h+__
- First prototype used __feedparser python__ library

View File

@@ -462,7 +462,7 @@
54ACC27421061B3B0020715F /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0940;
LastUpgradeCheck = 1200;
ORGANIZATIONNAME = relikd;
TargetAttributes = {
54ACC27B21061B3B0020715F = {
@@ -647,6 +647,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -702,6 +703,7 @@
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1000"
LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -196,7 +196,8 @@
if (self.articles.count == 0) {
img = [NSImage imageNamed:NSImageNameCaution];
} else if (self.hasIcon) {
img = [[NSImage alloc] initByReferencingURL:[self iconPath]];
NSData* data = [[NSData alloc] initWithContentsOfURL:[self iconPath]];
img = [[NSImage alloc] initWithData:data];
} else {
img = [NSImage imageNamed:RSSImageDefaultRSSIcon];
}

View File

@@ -89,11 +89,12 @@
- (void)setSortIndexIfChanged:(int32_t)sortIndex {
if (self.sortIndex != sortIndex) {
self.sortIndex = sortIndex;
}
// Otherwise move from 0.0 -> 0 will not trigger index path update
[self iterateSorted:NO overDescendantFeeds:^(Feed *feed, BOOL *cancel) {
[feed calculateAndSetIndexPathString];
}];
}
}
/// Set @c name attribute but only if value differs.
- (void)setNameIfChanged:(nullable NSString*)name {

View File

@@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
// TODO: Make plugins extensible? community extensions.
@interface YouTubePlugin : NSObject
+ (NSString*)feedURL:(NSURL*)url;
+ (NSString*)feedURL:(NSURL*)url data:(NSData*)html;
+ (NSString*)videoImage:(NSString*)videoid;
+ (NSString*)videoImageHQ:(NSString*)videoid;
@end

View File

@@ -33,12 +33,13 @@
@return @c nil if @c url is not properly formatted, YouTube feed URL otherwise.
*/
+ (NSString*)feedURL:(NSURL*)url {
+ (NSString*)feedURL:(NSURL*)url data:(NSData*)html {
if (![url.host hasSuffix:@"youtube.com"]) // 'youtu.be' & 'youtube-nocookie.com' will redirect
return nil;
// https://www.youtube.com/channel/[channel-id]
// https://www.youtube.com/user/[user-name]
// https://www.youtube.com/playlist?list=[playlist-id]
// https://www.youtube.com/c/[channel-name]
#if DEBUG && ENV_LOG_YOUTUBE
printf("resolving YouTube url:\n");
printf(" ↳ %s\n", url.absoluteString.UTF8String);
@@ -62,6 +63,23 @@
break;
}
}
} else if ([type isEqualToString:@"c"]) {
NSData *m_head = [@"<meta itemprop=\"channelId\" content=\"" dataUsingEncoding:NSUTF8StringEncoding];
NSRange tmp = [html rangeOfData:m_head options:0 range:NSMakeRange(0, html.length)];
if (tmp.location == NSNotFound) {
NSData *m_json = [@"\"channelId\":\"" dataUsingEncoding:NSUTF8StringEncoding];
tmp = [html rangeOfData:m_json options:0 range:NSMakeRange(0, html.length)];
}
NSUInteger start = tmp.location + tmp.length;
NSUInteger end = html.length - start;
if (end > 50) end = 50; // no need to search till the end
NSString *substr = [[NSString alloc] initWithData:[html subdataWithRange:NSMakeRange(start, end)] encoding:NSUTF8StringEncoding];
if (substr) {
NSUInteger to = [substr rangeOfString:@"\""].location;
if (to != NSNotFound) {
found = [ytBase stringByAppendingFormat:@"?channel_id=%@", [substr substringToIndex:to]];
}
}
}
}
#if DEBUG && ENV_LOG_YOUTUBE

View File

@@ -147,7 +147,13 @@
return;
self.currentDownload = [[NSURLRequest requestWithURL:self.remoteURL] downloadTask:^(NSURL * _Nullable path, NSError * _Nullable error) {
if (error) path = nil; // will also nullify img
NSImage *img = path ? [[NSImage alloc] initByReferencingURL:path] : nil;
NSImage *img;
if (path) {
NSData* data = [[NSData alloc] initWithContentsOfURL:path];
img = [[NSImage alloc] initWithData:data];
} else {
img = nil;
}
if (img.valid) {
// move image to temporary destination, otherwise dataTask: will delete it.
NSString *tmpFile = NSProcessInfo.processInfo.globallyUniqueString;
@@ -166,7 +172,8 @@
if (self.canceled)
return;
NSURL *path = self.fileURL;
NSImage *img = [[NSImage alloc] initByReferencingURL:path];
NSData* data = [[NSData alloc] initWithContentsOfURL:path];
NSImage* img = [[NSImage alloc] initWithData:data];
if (!img.valid) { path = nil; img = nil; }
#if DEBUG && ENV_LOG_DOWNLOAD
printf("ICON %1.0fx%1.0f %s\n", img.size.width, img.size.height, self.remoteURL.absoluteString.UTF8String);

View File

@@ -178,7 +178,7 @@
}
else if (!meta || meta.feedLinks.count == 0) {
if ([xml.url.host hasSuffix:@"youtube.com"])
feedURL = [YouTubePlugin feedURL:xml.url];
feedURL = [YouTubePlugin feedURL:xml.url data:xml.data];
if (feedURL.length == 0)
self.error = [NSError feedURLNotFound:xml.url];
}

View File

@@ -45,7 +45,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.1.0</string>
<string>1.1.3</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
@@ -70,7 +70,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>14603</string>
<string>14644</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.news</string>
<key>LSMinimumSystemVersion</key>
@@ -83,7 +83,7 @@
<true/>
</dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2019 relikd. Public Domain.</string>
<string>Copyright © 2020 relikd.</string>
<key>NSPrincipalClass</key>
<string>AppHook</string>
<key>UTImportedTypeDeclarations</key>

View File

@@ -52,9 +52,9 @@
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (@available(macOS 10.14, *)) {
color = UserPrefsColor(Pref_colorStatusIconTint, [NSColor controlAccentColor]);
color = UserPrefsColor(Pref_colorUnreadIndicator, [NSColor controlAccentColor]);
} else {
color = UserPrefsColor(Pref_colorStatusIconTint, [NSColor systemBlueColor]);
color = UserPrefsColor(Pref_colorUnreadIndicator, [NSColor systemBlueColor]);
}
});
return color;

View File

@@ -216,7 +216,13 @@
*/
- (void)faviconDownload:(FaviconDownload*)sender didFinish:(nullable NSURL*)path {
// Create image from favicon temporary file location or default icon if no favicon exists.
NSImage *img = path ? [[NSImage alloc] initByReferencingURL:path] : [NSImage imageNamed:RSSImageDefaultRSSIcon];
NSImage *img;
if (path) {
NSData* data = [[NSData alloc] initWithContentsOfURL:path];
img = [[NSImage alloc] initWithData:data];
} else {
img = [NSImage imageNamed:RSSImageDefaultRSSIcon];
}
self.view.favicon.image = img;
self.faviconFile = path;
[self downloadComplete];

View File

@@ -44,7 +44,7 @@
[content setFrameSize: NSMakeSize(w, h)];
// after content size, increase to window size
w += 2 * PAD_WIN;
w += 2 * (NSInteger)PAD_WIN;
h += PAD_WIN + contentOffsetY; // the second PAD_WIN is already in contentOffsetY
NSWindowStyleMask style = NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskFullSizeContentView;

View File

@@ -121,7 +121,9 @@
BOOL tint = (self.unreadCountTotal > 0 && hasNet && UserPrefsBool(Pref_globalTintMenuIcon));
self.statusItem.button.image = [NSImage imageNamed:(hasNet ? RSSImageMenuBarIconActive : RSSImageMenuBarIconPaused)];
if (@available(macOS 10.14, *)) {
if (@available(macOS 11, *)) {
self.statusItem.button.image.template = !tint;
} else if (@available(macOS 10.14, *)) {
// There is no proper way to display tinted icon WITHOUT tinted text!
// - using alternate image instead of tint:
// icon & text stays black on highlight (but only in light mode)