Commit a53e2d1d authored by Felix Paul Kühne's avatar Felix Paul Kühne

OneDrive: implement file downloading

Note that we don't use the Live SDK for this, but the existing HTTP downloading class for simplicity and performance reasons
parent 924b63ef
......@@ -146,11 +146,13 @@
}
} else if(_oneDriveFile != nil) {
if (_oneDriveFile.isFolder) {
self.downloadButton.hidden = YES;
self.folderTitleLabel.text = self.oneDriveFile.name;
self.titleLabel.hidden = self.subtitleLabel.hidden = YES;
self.folderTitleLabel.hidden = NO;
self.thumbnailView.image = [UIImage imageNamed:@"folder"];
} else {
self.downloadButton.hidden = NO;
self.titleLabel.text = self.oneDriveFile.name;
NSMutableString *subtitle = [[NSMutableString alloc] init];
if (self.oneDriveFile.size > 0) {
......
......@@ -31,7 +31,7 @@
@interface VLCOneDriveController : NSObject
@property (nonatomic, weak) VLCOneDriveTableViewController *delegate;
@property (nonatomic, weak) UIViewController <VLCOneDriveControllerDelegate>*delegate;
@property (readonly) BOOL activeSession;
@property (readonly) BOOL userAuthenticated;
@property (nonatomic, readonly) VLCOneDriveObject *rootFolder;
......@@ -42,8 +42,8 @@
- (void)login;
- (void)logout;
- (void)downloadObject:(VLCOneDriveObject *)object;
- (void)loadCurrentFolder;
- (void)downloadFileWithPath:(NSString *)path;
- (void)streamFileWithPath:(NSString *)path;
@end
......@@ -21,11 +21,19 @@
/* include private API headers */
#import <LiveSDK/LiveApiHelper.h>
@interface VLCOneDriveController () <LiveAuthDelegate, LiveDownloadOperationDelegate, VLCOneDriveObjectDelegate>
@interface VLCOneDriveController () <LiveAuthDelegate, VLCOneDriveObjectDelegate, VLCOneDriveObjectDownloadDelegate>
{
LiveConnectClient *_liveClient;
NSArray *_liveScopes;
BOOL _activeSession;
NSMutableArray *_pendingDownloads;
BOOL _downloadInProgress;
CGFloat _averageSpeed;
CGFloat _fileSize;
NSTimeInterval _startDL;
NSTimeInterval _lastStatsUpdate;
}
@end
......@@ -85,7 +93,7 @@
- (void)authCompleted:(LiveConnectSessionStatus)status session:(LiveConnectSession *)session userState:(id)userState
{
NSLog(@"authCompleted, status %i, state %@", status, userState);
APLog(@"OneDrive: authCompleted, status %i, state %@", status, userState);
if (status == 1 && session != NULL && [userState isEqualToString:@"init"])
_activeSession = YES;
......@@ -151,40 +159,82 @@
#pragma mark - file handling
- (void)downloadFileWithPath:(NSString *)path
- (void)downloadObject:(VLCOneDriveObject *)object
{
if (object.isFolder)
return;
object.downloadDelegate = self;
if (!_pendingDownloads)
_pendingDownloads = [[NSMutableArray alloc] init];
[_pendingDownloads addObject:object];
[self _triggerNextDownload];
}
- (void)liveDownloadOperationProgressed:(LiveOperationProgress *)progress
data:(NSData *)receivedData
operation:(LiveDownloadOperation *)operation
- (void)_triggerNextDownload
{
if (_pendingDownloads.count > 0 && !_downloadInProgress) {
_downloadInProgress = YES;
[_pendingDownloads[0] saveObjectToDocuments];
[_pendingDownloads removeObjectAtIndex:0];
if ([self.delegate respondsToSelector:@selector(numberOfFilesWaitingToBeDownloadedChanged)])
[self.delegate numberOfFilesWaitingToBeDownloadedChanged];
}
}
- (void)streamFileWithPath:(NSString *)path
- (void)downloadStarted:(VLCOneDriveObject *)object
{
_startDL = [NSDate timeIntervalSinceReferenceDate];
if ([self.delegate respondsToSelector:@selector(operationWithProgressInformationStarted)])
[self.delegate operationWithProgressInformationStarted];
}
#pragma mark - skydrive object delegation
- (void)downloadEnded:(VLCOneDriveObject *)object
{
if ([self.delegate respondsToSelector:@selector(operationWithProgressInformationStopped)])
[self.delegate operationWithProgressInformationStopped];
- (void)folderContentLoaded:(VLCOneDriveObject *)sender
_downloadInProgress = NO;
[self _triggerNextDownload];
}
- (void)progressUpdated:(CGFloat)progress
{
if (self.delegate)
[self.delegate performSelector:@selector(mediaListUpdated)];
if ([self.delegate respondsToSelector:@selector(currentProgressInformation:)])
[self.delegate currentProgressInformation:progress];
}
- (void)folderContentLoadingFailed:(NSError *)error sender:(VLCOneDriveObject *)sender
- (void)calculateRemainingTime:(CGFloat)receivedDataSize expectedDownloadSize:(CGFloat)expectedDownloadSize
{
APLog(@"folder content loading failed %@", error);
CGFloat lastSpeed = receivedDataSize / ([NSDate timeIntervalSinceReferenceDate] - _startDL);
CGFloat smoothingFactor = 0.005;
_averageSpeed = isnan(_averageSpeed) ? lastSpeed : smoothingFactor * lastSpeed + (1 - smoothingFactor) * _averageSpeed;
CGFloat RemainingInSeconds = (expectedDownloadSize - receivedDataSize)/_averageSpeed;
NSDate *date = [NSDate dateWithTimeIntervalSince1970:RemainingInSeconds];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSString *remaingTime = [formatter stringFromDate:date];
if ([self.delegate respondsToSelector:@selector(updateRemainingTime:)])
[self.delegate updateRemainingTime:remaingTime];
}
- (void)fileContentLoaded:(VLCOneDriveObject *)sender
#pragma mark - onedrive object delegation
- (void)folderContentLoaded:(VLCOneDriveObject *)sender
{
if (self.delegate)
[self.delegate performSelector:@selector(mediaListUpdated)];
}
- (void)fileContentLoadingFailed:(NSError *)error sender:(VLCOneDriveObject *)sender
- (void)folderContentLoadingFailed:(NSError *)error sender:(VLCOneDriveObject *)sender
{
APLog(@"file content loading failed %@", error);
APLog(@"folder content loading failed %@", error);
}
- (void)fullFolderTreeLoaded:(VLCOneDriveObject *)sender
......
......@@ -22,12 +22,14 @@
- (void)folderContentLoadingFailed:(NSError *)error
sender:(VLCOneDriveObject *) sender;
@end
- (void)fileContentLoaded:(VLCOneDriveObject *)sender;
- (void)fileContentLoadingFailed:(NSError *)error
sender:(VLCOneDriveObject *) sender;
@protocol VLCOneDriveObjectDownloadDelegate <NSObject>
- (void)downloadStarted:(VLCOneDriveObject *)object;
- (void)downloadEnded:(VLCOneDriveObject *)object;
- (void)progressUpdated:(CGFloat)progress;
- (void)calculateRemainingTime:(CGFloat)receivedDataSize expectedDownloadSize:(CGFloat)expectedDownloadSize;
@end
@interface VLCOneDriveObject : NSObject <LiveOperationDelegate, LiveDownloadOperationDelegate, VLCOneDriveObjectDelegate>
......@@ -53,8 +55,9 @@
@property (strong, nonatomic) LiveConnectClient *liveClient;
@property (strong, nonatomic) id<VLCOneDriveObjectDelegate>delegate;
@property (strong, nonatomic) id<VLCOneDriveObjectDownloadDelegate>downloadDelegate;
- (void)loadFolderContent;
- (void)loadFileContent;
- (void)saveObjectToDocuments;
@end
......@@ -11,6 +11,14 @@
*****************************************************************************/
#import "VLCOneDriveObject.h"
#import "VLCHTTPFileDownloader.h"
@interface VLCOneDriveObject () <VLCHTTPFileDownloader>
{
VLCHTTPFileDownloader *_fileDownloader;
}
@end
@implementation VLCOneDriveObject
......@@ -60,7 +68,6 @@
- (void)loadFolderContent
{
NSLog(@"loadFolderContent");
if (!self.isFolder) {
APLog(@"%@ is no folder, can't load content", self.objectId);
return;
......@@ -85,25 +92,13 @@
}
}
- (void)loadFileContent
{
}
#pragma mark - live operations
- (void)liveOperationSucceeded:(LiveDownloadOperation *)operation
{
NSString *userState = operation.userState;
NSLog(@"liveOperationSucceeded: %@", userState);
if ([userState isEqualToString:@"load-file-content"]) {
// LiveDownloadOperation *downloadOperation = (LiveDownloadOperation *)operation;
//FIXME: handle the incoming data!
[self.delegate fileContentLoaded:self];
} else if ([userState isEqualToString:@"load-folder-content"]) {
if ([userState isEqualToString:@"load-folder-content"]) {
NSMutableArray *subFolders = [[NSMutableArray alloc] init];
NSMutableArray *folderFiles = [[NSMutableArray alloc] init];
NSMutableArray *items = [[NSMutableArray alloc] init];
......@@ -146,14 +141,10 @@
{
NSString *userState = operation.userState;
NSLog(@"liveOperationFailed %@ (%@)", userState, error);
APLog(@"liveOperationFailed %@ (%@)", userState, error);
if ([userState isEqualToString:@"load-folder-content"])
[self.delegate folderContentLoadingFailed:error sender:self];
else if ([userState isEqualToString:@"load-file-content"])
[self.delegate fileContentLoadingFailed:error sender:self];
else
APLog(@"failing live operation with state %@ failed with error %@", userState, error);
}
#pragma mark - delegation
......@@ -173,12 +164,38 @@
[self loadFolderContent];
}
- (void)fileContentLoaded:(VLCOneDriveObject *)sender
#pragma mark - file downloading
- (void)saveObjectToDocuments
{
_fileDownloader = [[VLCHTTPFileDownloader alloc] init];
_fileDownloader.delegate = self;
[_fileDownloader downloadFileFromURLwithFileName:[NSURL URLWithString:self.downloadPath] fileNameOfMedia:self.name];
}
- (void)downloadStarted
{
if ([self.downloadDelegate respondsToSelector:@selector(downloadStarted:)])
[self.downloadDelegate downloadStarted:self];
}
- (void)downloadEnded
{
if ([self.downloadDelegate respondsToSelector:@selector(downloadEnded:)])
[self.downloadDelegate downloadEnded:self];
}
- (void)downloadFailedWithErrorDescription:(NSString *)description
{
APLog(@"download failed (%@)", description);
}
- (void)fileContentLoadingFailed:(NSError *)error sender:(VLCOneDriveObject *)sender
- (void)progressUpdatedTo:(CGFloat)percentage receivedDataSize:(CGFloat)receivedDataSize expectedDownloadSize:(CGFloat)expectedDownloadSize
{
if ([self.downloadDelegate respondsToSelector:@selector(progressUpdated:)])
[self.downloadDelegate progressUpdated:percentage];
if ([self.downloadDelegate respondsToSelector:@selector(calculateRemainingTime:expectedDownloadSize:)])
[self.downloadDelegate calculateRemainingTime:receivedDataSize expectedDownloadSize:expectedDownloadSize];
}
@end
......@@ -16,16 +16,22 @@
#import "VLCCloudStorageTableViewCell.h"
#import "VLCAppDelegate.h"
#import "VLCOneDriveController.h"
#import "VLCProgressView.h"
@interface VLCOneDriveTableViewController () <UITableViewDataSource, UITableViewDelegate, VLCOneDriveControllerDelegate, VLCCloudStorageTableViewCell>
{
UIBarButtonItem *_backButton;
UIBarButtonItem *_logoutButton;
UIBarButtonItem *_numberOfFilesBarButtonItem;
UIBarButtonItem *_progressBarButtonItem;
VLCProgressView *_progressView;
UIActivityIndicatorView *_activityIndicator;
VLCOneDriveController *_oneDriveController;
NSString *_currentPath;
VLCOneDriveObject *_selectedFile;
}
@end
......@@ -50,6 +56,12 @@
self.tableView.separatorColor = [UIColor VLCDarkBackgroundColor];
self.view.backgroundColor = [UIColor VLCDarkBackgroundColor];
_numberOfFilesBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:[NSString stringWithFormat:NSLocalizedString(@"NUM_OF_FILES", nil), 0] style:UIBarButtonItemStylePlain target:nil action:nil];
[_numberOfFilesBarButtonItem setTitleTextAttributes:@{ UITextAttributeFont : [UIFont systemFontOfSize:11.] } forState:UIControlStateNormal];
_progressView = [VLCProgressView new];
_progressBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:_progressView];
self.cloudStorageLogo = nil;
if (!SYSTEM_RUNS_IOS7_OR_LATER) {
self.flatLoginButton.hidden = YES;
......@@ -59,6 +71,10 @@
[self.flatLoginButton setTitle:NSLocalizedString(@"DROPBOX_LOGIN", nil) forState:UIControlStateNormal];
}
[self.navigationController.toolbar setBackgroundImage:[UIImage imageNamed:@"sudHeaderBg"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[self _showProgressInToolbar:NO];
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
_activityIndicator.hidesWhenStopped = YES;
_activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
......@@ -70,6 +86,10 @@
- (void)viewWillAppear:(BOOL)animated
{
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.barStyle = UIBarStyleBlack;
[self.navigationController.toolbar setBackgroundImage:[UIImage imageNamed:@"bottomBlackBar"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[super viewWillAppear:animated];
if (_oneDriveController.activeSession)
......@@ -82,6 +102,12 @@
self.cloudStorageLogo.center = self.view.center;
}
- (void)viewWillDisappear:(BOOL)animated
{
self.navigationController.toolbarHidden = YES;
[super viewWillDisappear:animated];
}
#pragma mark - generic interface interaction
- (IBAction)goBack:(id)sender
......@@ -148,6 +174,14 @@
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
[_oneDriveController downloadObject:_selectedFile];
_selectedFile = nil;
}
#pragma mark - login dialog
- (void)logout
......@@ -175,6 +209,14 @@
[_activityIndicator stopAnimating];
[self.tableView reloadData];
NSUInteger count = _oneDriveController.currentFolder.items.count;
if (count == 0)
_numberOfFilesBarButtonItem.title = NSLocalizedString(@"NO_FILES", nil);
else if (count != 1)
_numberOfFilesBarButtonItem.title = [NSString stringWithFormat:NSLocalizedString(@"NUM_OF_FILES", nil), count];
else
_numberOfFilesBarButtonItem.title = NSLocalizedString(@"ONE_FILE", nil);
}
- (void)sessionWasUpdated
......@@ -182,6 +224,39 @@
[self updateViewAfterSessionChange];
}
#pragma mark - download visualization
- (void)_showProgressInToolbar:(BOOL)value
{
if (!value)
[self setToolbarItems:@[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], _numberOfFilesBarButtonItem, [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]] animated:YES];
else {
_progressView.progressBar.progress = 0.;
[self setToolbarItems:@[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], _progressBarButtonItem, [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]] animated:YES];
}
}
- (void)operationWithProgressInformationStarted
{
[self _showProgressInToolbar:YES];
}
- (void)currentProgressInformation:(float)progress
{
[_progressView.progressBar setProgress:progress animated:YES];
}
- (void)updateRemainingTime:(NSString *)time
{
[_progressView updateTime:time];
}
- (void)operationWithProgressInformationStopped
{
[self _showProgressInToolbar:NO];
}
#pragma mark - app delegate
- (void)updateViewAfterSessionChange
......@@ -206,6 +281,11 @@
- (void)triggerDownloadForCell:(VLCCloudStorageTableViewCell *)cell
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
_selectedFile = _oneDriveController.currentFolder.items[indexPath.row];
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"DROPBOX_DOWNLOAD", nil) message:[NSString stringWithFormat:NSLocalizedString(@"DROPBOX_DL_LONG", nil), _selectedFile.name, [[UIDevice currentDevice] model]] delegate:self cancelButtonTitle:NSLocalizedString(@"BUTTON_CANCEL", nil) otherButtonTitles:NSLocalizedString(@"BUTTON_DOWNLOAD", nil), nil];
[alert show];
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment