Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recents window + error handling refactor #35

Merged
merged 14 commits into from
Sep 10, 2014
147 changes: 60 additions & 87 deletions Base.lproj/UI.xib

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion CTCFeedParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

@interface CTCFeedParser : NSObject

+ (NSArray*)parseFiles:(NSXMLDocument*)feed;
+ (NSArray*)parseFiles:(NSXMLDocument*)feed
error:(NSError * __autoreleasing *)error;

@end
5 changes: 3 additions & 2 deletions CTCFeedParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

@implementation CTCFeedParser

+ (NSArray*)parseFiles:(NSXMLDocument*)feed {
+ (NSArray*)parseFiles:(NSXMLDocument*)feed
error:(NSError * __autoreleasing *)outError {
NSLog(@"Parsing feed");

NSError *error = nil;
Expand All @@ -12,7 +13,7 @@ + (NSArray*)parseFiles:(NSXMLDocument*)feed {
NSArray *fileNodes = [feed nodesForXPath:@"//rss/channel/item" error:&error];

if (!fileNodes) {
NSLog(@"Parsing for URLs failed: %@", error);
*outError = error;
return nil;
}

Expand Down
6 changes: 6 additions & 0 deletions CTCFileUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@

@interface CTCFileUtils : NSObject

+ (NSData *)bookmarkForURL:(NSURL *)url
error:(NSError * __autoreleasing *)error;

+ (NSURL *)URLFromBookmark:(NSData *)bookmark
error:(NSError * __autoreleasing *)error;

+ (NSString *)computeFilenameFromURL:(NSURL*)fileURL;

+ (NSString *)addTorrentExtensionTo:(NSString*)filename;
Expand Down
36 changes: 36 additions & 0 deletions CTCFileUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,42 @@

@implementation CTCFileUtils

+ (NSData *)bookmarkForURL:(NSURL *)url
error:(NSError * __autoreleasing *)outError {
// Create a bookmark so we can transfer access to the downloads path
// to the feed checker service
NSError *error = nil;
NSData *downloadFolderBookmark = [url bookmarkDataWithOptions:NSURLBookmarkCreationMinimalBookmark
includingResourceValuesForKeys:@[]
relativeToURL:nil
error:&error];
if (!downloadFolderBookmark || error) {
*outError = error;
return nil;
}

return downloadFolderBookmark;
}

+ (NSURL *)URLFromBookmark:(NSData *)bookmark
error:(NSError * __autoreleasing *)outError {
NSError *error = nil;
BOOL isStale = NO;
NSURL *URL = [NSURL URLByResolvingBookmarkData:bookmark
options:kNilOptions
relativeToURL:nil
bookmarkDataIsStale:&isStale
error:&error];

if (!URL || error) {
NSLog(@"Could not get URL from bookmark: %@", error);
*outError = error;
return nil;
}

return URL;
}

+ (NSString *)computeFilenameFromURL:(NSURL*)fileURL {
// Compute destination filename
NSString *filename = fileURL.path.pathComponents.lastObject;
Expand Down
33 changes: 14 additions & 19 deletions CTCMenuController.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@ @interface CTCMenuController ()

@property (strong, nonatomic) NSStatusItem *menuBarItem;

@property (strong, nonatomic) NSDateFormatter *lastUpdateDateFormatter;

@end


@implementation CTCMenuController

- (void)awakeFromNib {
// Create a date formatter for "last update" dates
self.lastUpdateDateFormatter = NSDateFormatter.new;
self.lastUpdateDateFormatter.timeStyle = NSDateFormatterShortStyle;

[self setupMenuItem];

// Update UI with initial values
Expand Down Expand Up @@ -95,27 +101,16 @@ - (void)refreshSchedulerStatus {

- (void)setLastUpdateStatus:(BOOL)lastUpdateWasSuccessful time:(NSDate *)time {
// Create something like "Last update: 3:45 AM" and place it in the menu
NSString *baseLastUpdateString = nil;
NSString *lastUpdateString = nil;
NSString *lastUpdateStatusFormat = lastUpdateWasSuccessful ?
NSLocalizedString(@"lastupdate", @"Title for the last update time") :
NSLocalizedString(@"lastupdatefailed", @"Title for the last update time if it fails");

if (lastUpdateWasSuccessful) {
baseLastUpdateString = NSLocalizedString(@"lastupdate", @"Title for the last update time");
}
else {
baseLastUpdateString = NSLocalizedString(@"lastupdatefailed", @"Title for the last update time if it fails");
}

if (time) {
NSDateFormatter *dateFormatter = NSDateFormatter.new;
dateFormatter.timeStyle = NSDateFormatterShortStyle;
NSString *lastUpdateTime = [dateFormatter stringFromDate:time];
lastUpdateString = [NSString stringWithFormat:baseLastUpdateString, lastUpdateTime];
}
else {
lastUpdateString = [NSString stringWithFormat:baseLastUpdateString, NSLocalizedString(@"never", @"Never happened")];
}
NSString *lastUpdateStatus = time ?
[NSString stringWithFormat:lastUpdateStatusFormat,
[self.lastUpdateDateFormatter stringFromDate:time]] :
[NSString stringWithFormat:lastUpdateStatusFormat, NSLocalizedString(@"never", @"Never happened")];

[self.menuLastUpdate setTitle:lastUpdateString];
[self.menuLastUpdate setTitle:lastUpdateStatus];
}

- (void)setIdle {
Expand Down
9 changes: 9 additions & 0 deletions CTCRecentsCellView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#import <Cocoa/Cocoa.h>


@interface CTCRecentsCellView : NSTableCellView

@property (weak, nonatomic) IBOutlet NSTextField *downloadDateTextField;
@property (weak, nonatomic) IBOutlet NSButton *downloadAgainButton;

@end
4 changes: 4 additions & 0 deletions CTCRecentsCellView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#import "CTCRecentsCellView.h"


@implementation CTCRecentsCellView @end
93 changes: 34 additions & 59 deletions CTCRecentsController.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "CTCRecentsController.h"
#import "CTCDefaults.h"
#import "CTCScheduler.h"
#import "CTCRecentsCellView.h"


@interface CTCRecentsController ()
Expand All @@ -20,8 +21,6 @@ - (void)awakeFromNib {
self.downloadDateFormatter.dateStyle = NSDateFormatterShortStyle;
self.downloadDateFormatter.doesRelativeDateFormatting = YES;

self.table.selectionHighlightStyle = NSTableViewSelectionHighlightStyleSourceList;

[self setupObservers];
}

Expand All @@ -46,66 +45,42 @@ - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return CTCDefaults.downloadHistory.count;
}

- (IBAction)downloadRecentItemAgain:(id)sender {
NSLog(@"download again");
- (IBAction)downloadRecentItemAgain:(NSButton *)senderButton {
NSUInteger clickedRow = [self.table rowForView:senderButton];
NSDictionary *recentToDownload = CTCDefaults.downloadHistory[clickedRow];
if (!recentToDownload) return;

BOOL isMagnetLink = [recentToDownload[@"isMagnetLink"] boolValue];
if (isMagnetLink) {
[NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:recentToDownload[@"url"]]];
}
else {
[CTCScheduler.sharedScheduler downloadFile:recentToDownload
completion:^(NSDictionary *downloadedFile, NSError *error) {
if (downloadedFile && CTCDefaults.shouldOpenTorrentsAutomatically) {
[NSWorkspace.sharedWorkspace openFile:downloadedFile[@"torrentFilePath"]];
}
}];
}
}

- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
NSDictionary *recent = CTCDefaults.downloadHistory[row];

// // Also refresh the list of recently downloaded torrents
// // Get the full list
// NSArray *downloadHistory = CTCDefaults.downloadHistory;
//
// // Get last 9 elements (changed from 10 so everything aligns nicer in the menu.. small tweak)
// NSUInteger recentsCount = MIN(downloadHistory.count, 9U);
// NSArray *recents = [downloadHistory subarrayWithRange:NSMakeRange(0U, recentsCount)];
//
// // Clear menu
// [self.menuRecentTorrents.submenu removeAllItems];
//
// // Add new items
// [recents enumerateObjectsUsingBlock:^(NSDictionary *recent, NSUInteger index, BOOL *stop) {
// NSString *menuTitle = [NSString stringWithFormat:@"%lu %@", index + 1, recent[@"title"]];
// NSMenuItem *recentMenuItem = [[NSMenuItem alloc] initWithTitle:menuTitle
// action:NULL
// keyEquivalent:@""];
//
// recentMenuItem.submenu = [self submenuForRecentItem:recent atIndex:index];
// [self.menuRecentTorrents.submenu addItem:recentMenuItem];
// }];
//
// // Put the Show in finder menu back
// [self.menuRecentTorrents.submenu addItem:self.menuShowInFinder];
CTCRecentsCellView *cell = [tableView makeViewWithIdentifier:@"RecentCell" owner:self];

// // Create a "download again" item
// NSMenuItem *downloadAgainItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"redownload", @"Button to download a downloaded torrent file again")
// action:@selector(downloadRecentItemAgain:)
// keyEquivalent:@""];
// downloadAgainItem.target = self;
// downloadAgainItem.tag = index;
// [submenu addItem:downloadAgainItem];
//
// // Create a disabled item with the download date, if available
// NSDate *downloadDate = (NSDate *)recent[@"date"];
// if (downloadDate) {
// // it may be interesting to have a bit more structure or intelligence to showing the dates for recent
// // items (just stuff this week based on preference?), or show the date in the list.. this solves
// // the problem of "how recent was recent?" tho with the tooltip.
// NSString *relativeDownloadDateDescription = [self.downloadDateFormatter stringFromDate:downloadDate];
// NSMenuItem *downloadDateItem = [[NSMenuItem alloc] initWithTitle:relativeDownloadDateDescription
// action:NULL
// keyEquivalent:@""];
// downloadAgainItem.enabled = NO;
// [submenu addItem:downloadDateItem];
// }
cell.textField.stringValue = recent[@"title"];

// NSDictionary *recentToDownload = CTCDefaults.downloadHistory[senderMenuItem.tag];
// if (!recentToDownload) return;
//
// BOOL isMagnetLink = [recentToDownload[@"isMagnetLink"] boolValue];
// if (isMagnetLink) {
// [NSWorkspace.sharedWorkspace openURL:[NSURL URLWithString:recentToDownload[@"url"]]];
// }
// else {
// [CTCScheduler.sharedScheduler downloadFile:recentToDownload];
// }
NSDate *downloadDate = (NSDate *)recent[@"date"];
cell.downloadDateTextField.stringValue = downloadDate ? [self.downloadDateFormatter stringFromDate:downloadDate] : @"";

return cell;
}

- (BOOL)selectionShouldChangeInTableView:(NSTableView *)tableView {
return NO;
}

- (void)dealloc {
Expand Down
3 changes: 2 additions & 1 deletion CTCScheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern NSString * const kCTCSchedulerLastUpdateStatusNotificationName;

- (void)forceCheck;

- (void)downloadFile:(NSDictionary *)file;
- (void)downloadFile:(NSDictionary *)file
completion:(void (^)(NSDictionary *downloadedFile, NSError *error))completion;

@end
35 changes: 20 additions & 15 deletions CTCScheduler.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "CTCScheduler.h"
#import "CTCFeedChecker.h"
#import "CTCDefaults.h"
#import "CTCFileUtils.h"
#import "NSDate+TimeOfDayMath.h"


Expand Down Expand Up @@ -81,6 +82,7 @@ - (void)setChecking:(BOOL)checking {

- (void)setPolling:(BOOL)polling {
_polling = polling;

[self reportStatus];
}

Expand Down Expand Up @@ -108,23 +110,17 @@ - (void)checkFeed {
}

- (NSData *)downloadFolderBookmark {
NSString *downloadPath = CTCDefaults.torrentsSavePath;
NSError *error;
NSURL *url = [NSURL fileURLWithPath:CTCDefaults.torrentsSavePath];
NSData *bookmark = [CTCFileUtils bookmarkForURL:url error:&error];

// Create a bookmark so we can transfer access to the downloads path
// to the feed checker service
NSURL *downloadFolderURL = [NSURL fileURLWithPath:downloadPath];
NSError *error = nil;
NSData *downloadFolderBookmark = [downloadFolderURL bookmarkDataWithOptions:NSURLBookmarkCreationMinimalBookmark
includingResourceValuesForKeys:@[]
relativeToURL:nil
error:&error];
if (!downloadFolderBookmark || error) {
// Not really handling this error
if (!bookmark) {
// Not really handling this at all
[NSException raise:@"Couldn't create bookmark for downloads folder"
format:@"Error: %@", error];
}

return downloadFolderBookmark;
return bookmark;
}

- (void)callFeedCheckerWithReplyHandler:(CTCFeedCheckCompletionHandler)replyHandler {
Expand All @@ -143,6 +139,9 @@ - (void)callFeedCheckerWithReplyHandler:(CTCFeedCheckCompletionHandler)replyHand
organizingByFolder:CTCDefaults.shouldOrganizeTorrentsInFolders
skippingURLs:previouslyDownloadedURLs
withReply:^(NSArray *downloadedFeedFiles, NSError *error) {
if (error) {
NSLog(@"Feed Checker error (checking feed): %@", error);
}
dispatch_async(dispatch_get_main_queue(), ^{
replyHandler(downloadedFeedFiles, error);
});
Expand Down Expand Up @@ -181,14 +180,20 @@ - (void)forceCheck {
[self checkFeed];
}

- (void)downloadFile:(NSDictionary *)file {
- (void)downloadFile:(NSDictionary *)file
completion:(void (^)(NSDictionary *downloadedFile, NSError *error))completion {
// Call feed checker service
CTCFeedChecker *feedChecker = [self.feedCheckerConnection remoteObjectProxy];
[feedChecker downloadFile:file
toBookmark:[self downloadFolderBookmark]
organizingByFolder:CTCDefaults.shouldOrganizeTorrentsInFolders
withReply:^(NSError *error) {
// TODO
withReply:^(NSDictionary *downloadedFile, NSError *error) {
if (error) {
NSLog(@"Feed Checker error (downloading file): %@", error);
}
dispatch_async(dispatch_get_main_queue(), ^{
completion(downloadedFile, error);
});
}];
}

Expand Down
Loading