mirror of
https://github.com/zhigang1992/transshift.git
synced 2026-05-28 22:32:14 +08:00
412 lines
15 KiB
Objective-C
412 lines
15 KiB
Objective-C
//
|
|
// AppDelegate.m
|
|
// TransmissionRPCClient
|
|
//
|
|
// Created by Alexey Chechetkin on 23.06.15.
|
|
// Copyright (c) 2015 Alexey Chechetkin. All rights reserved.
|
|
//
|
|
|
|
#import "AppDelegate.h"
|
|
#import "GlobalConsts.h"
|
|
#import "RPCServerConfigDB.h"
|
|
#import "RPCConnector.h"
|
|
#import "ServerListController.h"
|
|
#import "ChooseServerToAddTorrentController.h"
|
|
#import "TorrentListController.h"
|
|
#import "InfoMessage.h"
|
|
#import "FSDirectory.h"
|
|
#import "Bencoding.h"
|
|
#import "TRFileInfo.h"
|
|
|
|
@interface AppDelegate() <RPCConnectorDelegate>
|
|
|
|
@property(atomic) TRInfos* bgTRInfos;
|
|
|
|
@end
|
|
|
|
@implementation AppDelegate
|
|
|
|
{
|
|
ServerListController *_serverList;
|
|
NSData *_torrentFileDataToAdd;
|
|
UINavigationController *_chooseNav;
|
|
RPCServerConfig *_selectedConfig;
|
|
|
|
NSString *_magnetURLString;
|
|
|
|
NSArray *_unwantedFilesIdx;
|
|
|
|
// flag showing - that we use background fetching
|
|
BOOL _isBackgroundFetching;
|
|
|
|
// background fetch complition handler
|
|
void (^_bgComplitionHandler)(UIBackgroundFetchResult);
|
|
}
|
|
|
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
|
{
|
|
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
|
|
|
// Load db config
|
|
[[RPCServerConfigDB sharedDB] loadDB];
|
|
|
|
_serverList = instantiateController( CONTROLLER_ID_SERVERLIST );
|
|
|
|
UINavigationController *leftNav = [[UINavigationController alloc] initWithRootViewController:_serverList];
|
|
|
|
UIViewController *rootController = leftNav;
|
|
|
|
// create split view controller on iPad
|
|
if( [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad )
|
|
{
|
|
TorrentListController *trc = instantiateController( CONTROLLER_ID_TORRENTLIST );
|
|
trc.infoMessage = NSLocalizedString(@"There is no selected server. Select server from list of servers.", @"");
|
|
trc.title = NSLocalizedString(@"Transmission remote client", @"TorrentList start title");
|
|
trc.popoverButtonTitle = NSLocalizedString(@"Servers", @"ServerListController title");//SERVERLIST_CONTROLLER_TITLE;
|
|
|
|
UINavigationController *rightNav = [[UINavigationController alloc] initWithRootViewController:trc];
|
|
|
|
UISplitViewController *splitView = [[UISplitViewController alloc] init];
|
|
splitView.viewControllers = @[ leftNav, rightNav ];
|
|
splitView.delegate = trc;
|
|
rootController = splitView;
|
|
}
|
|
|
|
self.window.rootViewController = rootController;
|
|
// set background fetch interval
|
|
|
|
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
|
|
|
|
// show main window
|
|
self.window.backgroundColor = [UIColor whiteColor];
|
|
[self.window makeKeyAndVisible];
|
|
return YES;
|
|
}
|
|
|
|
// this method is launched when user selects a torrent file to process
|
|
// after this will be launced ApplicationFinishedWithOptions
|
|
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
|
|
{
|
|
// handle url - it is a .torrent file or magnet url
|
|
if( url )
|
|
{
|
|
// FIX: when user tryes to load file serveral times in a row
|
|
if( _chooseNav )
|
|
{
|
|
[_chooseNav dismissViewControllerAnimated:NO completion:nil];
|
|
}
|
|
|
|
//NSLog(@"URL Scheme: %@, desc:%@", url.scheme, url );
|
|
_torrentFileDataToAdd = nil;
|
|
_magnetURLString = nil;
|
|
|
|
NSString *trName = nil;
|
|
NSString *trSize = nil;
|
|
FSDirectory *fs = nil;
|
|
|
|
if( ![url.scheme isEqualToString:@"magnet"] )
|
|
{
|
|
_torrentFileDataToAdd = [NSData dataWithContentsOfURL:url];
|
|
|
|
//NSString *sizeStr = formatByteCount(_torrentFileDataToAdd.length);
|
|
|
|
NSDictionary *trData = decodeObjectFromBencodedData(_torrentFileDataToAdd);
|
|
|
|
if (trData)
|
|
{
|
|
fs = [FSDirectory directory];
|
|
|
|
// get name
|
|
trName = trData[@"info"][@"name"];
|
|
|
|
long long c = 0;
|
|
int idx = 0;
|
|
|
|
for( NSDictionary *fileDesc in trData[@"info"][@"files"] )
|
|
{
|
|
long long fileLength = [fileDesc[@"length"] longLongValue];
|
|
c += fileLength;
|
|
|
|
NSMutableString *fileFullPath = [NSMutableString string];
|
|
|
|
for( NSString *path in fileDesc[@"path"] )
|
|
[fileFullPath appendFormat:@"/%@", path];
|
|
|
|
FSItem *item = [fs addFilePath:fileFullPath withIndex:idx];
|
|
TRFileInfo *info = [[TRFileInfo alloc] init];
|
|
info.length = fileLength;
|
|
info.lengthString = formatByteCount(fileLength);
|
|
info.wanted = YES;
|
|
info.downloadProgress = 0.1;
|
|
info.downloadProgressString = @"";
|
|
item.info = info;
|
|
|
|
idx++;
|
|
}
|
|
|
|
[fs sort];
|
|
|
|
trSize = formatByteCount(c);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_magnetURLString = url.description;
|
|
}
|
|
|
|
if( [RPCServerConfigDB sharedDB].db.count > 0 &&
|
|
( _torrentFileDataToAdd || _magnetURLString ) )
|
|
{
|
|
// presenting view controller to choose from several remote servers
|
|
ChooseServerToAddTorrentController *chooseServerController = instantiateController( CONTROLLER_ID_CHOOSESERVER );
|
|
|
|
if( fs )
|
|
chooseServerController.files = fs;
|
|
|
|
chooseServerController.headerInfoMessage = _magnetURLString ?
|
|
[NSString stringWithFormat: NSLocalizedString(@"Add torrent with magnet link:\n%@", @""), _magnetURLString] :
|
|
[NSString stringWithFormat: NSLocalizedString(@"Add torrent with file size: %@", @""), trName, trSize ];
|
|
|
|
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", @"")
|
|
style:UIBarButtonItemStylePlain
|
|
target:self
|
|
action:@selector(dismissChooseServerController)];
|
|
|
|
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"OK", @"")
|
|
style:UIBarButtonItemStylePlain
|
|
target:self
|
|
action:@selector(addTorrentToSelectedServer)];
|
|
|
|
chooseServerController.navigationItem.leftBarButtonItem = leftButton;
|
|
chooseServerController.navigationItem.rightBarButtonItem = rightButton;
|
|
|
|
|
|
_chooseNav = [[UINavigationController alloc] initWithRootViewController:chooseServerController];
|
|
_chooseNav.modalPresentationStyle = UIModalPresentationFormSheet;
|
|
|
|
[self.window.rootViewController presentViewController:_chooseNav animated:YES completion:nil];
|
|
}
|
|
else // show message
|
|
{
|
|
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@""
|
|
message:NSLocalizedString(@"There is no servers avalable", @"AlerView message OpenURL")
|
|
delegate:nil
|
|
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
|
otherButtonTitles:nil, nil];
|
|
[alert show];
|
|
}
|
|
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (void)applicationWillEnterForeground:(UIApplication *)application
|
|
{
|
|
_isBackgroundFetching = NO;
|
|
}
|
|
|
|
- (void)addTorrentToServerWithRPCConfig:(RPCServerConfig*)config priority:(int)priority startNow:(BOOL)startNow
|
|
{
|
|
RPCConnector *connector = [[RPCConnector alloc] initWithConfig:config andDelegate:self];
|
|
|
|
if( _torrentFileDataToAdd )
|
|
{
|
|
if( _unwantedFilesIdx )
|
|
[connector addTorrentWithData:_torrentFileDataToAdd priority:priority startImmidiately:startNow indexesUnwanted:_unwantedFilesIdx];
|
|
else
|
|
[connector addTorrentWithData:_torrentFileDataToAdd priority:priority startImmidiately:startNow];
|
|
}
|
|
else if( _magnetURLString )
|
|
[connector addTorrentWithMagnet:_magnetURLString priority:priority startImmidiately:startNow];
|
|
}
|
|
|
|
- (void)gotTorrentAdded
|
|
{
|
|
InfoMessage *msg = [InfoMessage infoMessageWithSize:CGSizeMake(300, 50)];
|
|
[msg showInfo:NSLocalizedString(@"New torrent has been added", @"AppDelegate float message")
|
|
fromView:self.window.rootViewController.view];
|
|
}
|
|
|
|
// error handler
|
|
- (void)connector:(RPCConnector *)cn complitedRequestName:(NSString *)requestName withError:(NSString *)errorMessage
|
|
{
|
|
if( !_isBackgroundFetching )
|
|
{
|
|
|
|
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Can't add torrent", @"Alert view title")
|
|
message:[NSString stringWithFormat:@"%@", errorMessage]
|
|
delegate:nil
|
|
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
|
otherButtonTitles:nil, nil];
|
|
[alert show];
|
|
}
|
|
else
|
|
{
|
|
//NSLog(@"BackgroundFetch: connector request error, %@", errorMessage);
|
|
_bgComplitionHandler(UIBackgroundFetchResultFailed);
|
|
}
|
|
}
|
|
|
|
- (void)addTorrentToSelectedServer
|
|
{
|
|
ChooseServerToAddTorrentController *csc = (ChooseServerToAddTorrentController*)_chooseNav.viewControllers[0];
|
|
|
|
if( csc.files )
|
|
{
|
|
NSArray *tmp = csc.files.rootItem.fileIndexesUnwanted;
|
|
_unwantedFilesIdx = ( tmp && tmp.count > 0 ) ? tmp : nil;
|
|
}
|
|
|
|
[self addTorrentToServerWithRPCConfig:csc.rpcConfig priority:csc.bandwidthPriority startNow:csc.startImmidiately];
|
|
|
|
[self dismissChooseServerController];
|
|
}
|
|
|
|
- (void)dismissChooseServerController
|
|
{
|
|
[_chooseNav dismissViewControllerAnimated:YES completion:nil];
|
|
_chooseNav = nil;
|
|
}
|
|
|
|
- (void)applicationWillResignActive:(UIApplication *)application
|
|
{
|
|
// Save db changes
|
|
[[RPCServerConfigDB sharedDB] saveDB];
|
|
|
|
// Save settings changes
|
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
[defaults synchronize];
|
|
}
|
|
|
|
- (void)gotAllTorrents:(TRInfos *)trInfos
|
|
{
|
|
if( _isBackgroundFetching )
|
|
{
|
|
//NSLog(@"BackgroundFetch: got all torrents");
|
|
|
|
// fetch is complite
|
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
NSArray *downIds = [defaults arrayForKey:USERDEFAULTS_BGFETCH_KEY_DOWNTORRENTIDS];
|
|
|
|
// update current downloading torrents ids
|
|
// in NSUserDefaults
|
|
NSArray *curDownIds = trInfos.downloadingTorrents;
|
|
|
|
//NSLog(@"curDownIds from NsUserDefaults: %i", (int)curDownIds.count );
|
|
|
|
if( curDownIds && curDownIds.count > 0 )
|
|
{
|
|
//NSLog(@"Updating NsUserDefaults with curDownIds ...");
|
|
|
|
NSMutableArray *downIds = [NSMutableArray array];
|
|
|
|
for ( TRInfo* t in curDownIds )
|
|
[downIds addObject:@(t.trId)];
|
|
|
|
//NSLog( @"Setting updated array with Ids count :%i", (int)downIds.count );
|
|
[defaults setObject:downIds forKey:USERDEFAULTS_BGFETCH_KEY_DOWNTORRENTIDS];
|
|
[defaults synchronize];
|
|
}
|
|
else // there is no ids, remove key
|
|
{
|
|
[defaults removeObjectForKey:USERDEFAULTS_BGFETCH_KEY_DOWNTORRENTIDS];
|
|
[defaults synchronize];
|
|
}
|
|
|
|
|
|
if( !downIds )
|
|
{
|
|
//NSLog(@"No previous downloading torrent ids found. Exit");
|
|
// there is downIds - try to create new and return
|
|
_bgComplitionHandler(UIBackgroundFetchResultNoData);
|
|
}
|
|
else
|
|
{
|
|
//NSLog(@"There are downloading torrents, %i ", (int)downIds.count);
|
|
// info string
|
|
NSMutableString *infoStr = [NSMutableString string];
|
|
|
|
// searching finished torrents
|
|
NSArray* seedTrs = trInfos.seedingTorrents;
|
|
for ( NSNumber* trId in downIds )
|
|
{
|
|
int torrentId = [trId intValue];
|
|
|
|
for( TRInfo* info in seedTrs )
|
|
{
|
|
if( torrentId == info.trId )
|
|
{
|
|
// we have found torrent that is finished
|
|
[infoStr appendString: [NSString stringWithFormat:NSLocalizedString( @"Torrent: %@, has finished downloading\n", @""), info.name] ];
|
|
}
|
|
}
|
|
} // end for searching
|
|
|
|
if( infoStr.length > 0 )
|
|
{
|
|
//NSLog(@"Found finished torrents: %@", infoStr);
|
|
// we should show
|
|
// show local notification
|
|
UILocalNotification *notification = [[UILocalNotification alloc] init];
|
|
|
|
/* supported only on iOS > 8.1
|
|
notification.alertTitle = @"Torrent(s) downloaded";
|
|
*/
|
|
|
|
notification.alertBody = infoStr;
|
|
notification.soundName = UILocalNotificationDefaultSoundName;
|
|
|
|
[[UIApplication sharedApplication] presentLocalNotificationNow:notification];
|
|
|
|
_bgComplitionHandler(UIBackgroundFetchResultNewData);
|
|
}
|
|
else
|
|
{
|
|
//NSLog(@"No finished torrents found. Exit.");
|
|
_bgComplitionHandler(UIBackgroundFetchResultNoData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
|
|
{
|
|
|
|
// // just for test
|
|
// UILocalNotification *notification = [[UILocalNotification alloc] init];
|
|
// notification.soundName = UILocalNotificationDefaultSoundName;
|
|
// notification.alertBody = @"Background fetch!";
|
|
// [application presentLocalNotificationNow:notification];
|
|
//
|
|
|
|
// peform fetch in background
|
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
NSDictionary *plist = [defaults dictionaryForKey: USERDEFAULTS_BGFETCH_KEY_RPCCONFG];
|
|
|
|
if( plist )
|
|
{
|
|
//NSLog(@"BackgroundFetch: - GETTING DATA .... ");
|
|
|
|
RPCServerConfig *config = [[RPCServerConfig alloc] initFromPList:plist];
|
|
// try to get update on this torrents
|
|
|
|
self.bgTRInfos = nil;
|
|
// set request timeout max to 5 seconds
|
|
config.requestTimeout = 5;
|
|
RPCConnector *connector = [[RPCConnector alloc] initWithConfig:config andDelegate:self];
|
|
_isBackgroundFetching = YES;
|
|
_bgComplitionHandler = completionHandler;
|
|
// try to get all torrents
|
|
[connector getAllTorrents];
|
|
}
|
|
else
|
|
{
|
|
//NSLog(@"BackgroundFetch: - NO DATA FETCHED");
|
|
completionHandler( UIBackgroundFetchResultNoData );
|
|
}
|
|
}
|
|
|
|
|
|
@end
|