Commit 4b4ed8b3 authored by Carola Nitz's avatar Carola Nitz Committed by Felix Paul Kühne

GDrive integration WIP

Signed-off-by: Felix Paul Kühne's avatarFelix Paul Kühne <fkuehne@videolan.org>
parent 502ab6e3
......@@ -4,6 +4,9 @@
<FileRef
location = "group:VLC for iOS.xcodeproj">
</FileRef>
<FileRef
location = "group:ImportedSources/GDrive/GTL.xcodeproj">
</FileRef>
<FileRef
location = "group:ImportedSources/MediaLibraryKit/MediaLibraryKit.xcodeproj">
</FileRef>
......
......@@ -9,6 +9,7 @@
//
#import "VLCDropboxTableViewController.h"
#import "VLCGoogleDriveTableViewController.h"
#import "VLCHTTPUploaderController.h"
#import "GHRevealViewController.h"
#import "VLCMenuTableViewController.h"
......@@ -27,6 +28,7 @@
@property (nonatomic, readonly) VLCPlaylistViewController *playlistViewController;
@property (nonatomic, readonly) VLCDropboxTableViewController *dropboxTableViewController;
@property (nonatomic, readonly) VLCGoogleDriveTableViewController *googleDriveTableViewController;
@property (nonatomic, readonly) VLCDownloadViewController *downloadViewController;
@property (nonatomic, strong) UIWindow *window;
......
......@@ -25,6 +25,7 @@
@interface VLCAppDelegate () <PAPasscodeViewControllerDelegate, VLCMediaFileDiscovererDelegate> {
PAPasscodeViewController *_passcodeLockController;
VLCDropboxTableViewController *_dropboxTableViewController;
VLCGoogleDriveTableViewController *_googleDriveTableViewController;
VLCDownloadViewController *_downloadViewController;
int _idleCounter;
VLCMovieViewController *_movieViewController;
......@@ -175,6 +176,16 @@
return _dropboxTableViewController;
}
- (VLCGoogleDriveTableViewController *)googleDriveTableViewController
{
if (_googleDriveTableViewController == nil) {
_googleDriveTableViewController = [[VLCGoogleDriveTableViewController alloc] initWithNibName:nil bundle:nil];
}
return _googleDriveTableViewController;
}
- (VLCDownloadViewController *)downloadViewController
{
if (_downloadViewController == nil) {
......
//
// VLCGoogleDriveConstants.h
// VLC for iOS
//
// Created by Carola Nitz on 21.09.13.
// Copyright (c) 2013 VideoLAN. All rights reserved.
//
// Refer to the COPYING file of the official project for license.
//
#define kVLCGoogleDriveClientID @"775640710334.apps.googleusercontent.com"
#warning Google Drive app secret missing, login will fail
#define kVLCGoogleDriveClientSecret @""
//#define kVLCGoogleDriveAppKey @"a60fc6qj9zdg7bw"
#warning Google Drive app private key missing, login will fail
#define kVLCGoogleDrivePrivateKey @""
//
// VLCGoogleDriveController.h
// VLC for iOS
//
// Created by Carola Nitz on 21.09.13.
// Copyright (c) 2013 VideoLAN. All rights reserved.
//
// Refer to the COPYING file of the official project for license.
//
#import "GTLDrive.h"
@protocol VLCGoogleDriveController
@required
- (void)mediaListUpdated;
@optional
- (void)operationWithProgressInformationStarted;
- (void)currentProgressInformation:(float)progress;
- (void)operationWithProgressInformationStopped;
- (void)numberOfFilesWaitingToBeDownloadedChanged;
@end
@interface VLCGoogleDriveController : NSObject
@property (nonatomic, retain) id delegate;
@property (nonatomic, readonly) NSArray *currentListFiles;
@property (nonatomic, readwrite) BOOL isAuthorized;
@property (nonatomic, readonly) NSInteger numberOfFilesWaitingToBeDownloaded;
@property (nonatomic, retain) GTLServiceDrive *driveService;
- (void)startSession;
- (void)logout;
- (void)requestDirectoryListingAtPath:(NSString *)path;
//- (void)downloadFileToDocumentFolder:(DBMetadata *)file;
@end
//
// VLCGoogleDriveController.m
// VLC for iOS
//
// Created by Carola Nitz on 21.09.13.
// Copyright (c) 2013 VideoLAN. All rights reserved.
//
// Refer to the COPYING file of the official project for license.
//
#import "VLCGoogleDriveController.h"
#import "NSString+SupportedMedia.h"
#import "VLCAppDelegate.h"
#import "HTTPMessage.h"
#import "VLCGoogleDriveConstants.h"
static NSString *const kKeychainItemName = @"Google Drive Quickstart #2";
@interface VLCGoogleDriveController ()
{
GTLDriveFileList *_fileList;
NSError *_fileListFetchError;
GTLServiceTicket *_fileListTicket;
NSArray *_currentFileList;
NSMutableArray *_listOfGoogleDriveFilesToDownload;
BOOL _downloadInProgress;
NSInteger _outstandingNetworkRequests;
}
@end
@implementation VLCGoogleDriveController
#pragma mark - session handling
- (void)startSession
{
self.driveService = [[GTLServiceDrive alloc] init];
self.driveService.authorizer = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName clientID:kVLCGoogleDriveClientID clientSecret:kVLCGoogleDriveClientSecret];
}
- (void)logout
{
}
- (BOOL)isAuthorized
{
return [((GTMOAuth2Authentication *)self.driveService.authorizer) canAuthorize];;
}
- (void)showAlert:(NSString *)title message:(NSString *)message
{
UIAlertView *alert;
alert = [[UIAlertView alloc] initWithTitle: title
message: message
delegate: nil
cancelButtonTitle: @"OK"
otherButtonTitles: nil];
[alert show];
}
#pragma mark - file management
- (void)requestDirectoryListingAtPath:(NSString *)path
{
if (self.isAuthorized)
[self listFiles];
}
- (void)downloadFileToDocumentFolder:(DBMetadata *)file
{
if (!file.isDirectory) {
if (!_listOfGoogleDriveFilesToDownload)
_listOfGoogleDriveFilesToDownload = [[NSMutableArray alloc] init];
[_listOfGoogleDriveFilesToDownload addObject:file];
if ([self.delegate respondsToSelector:@selector(numberOfFilesWaitingToBeDownloadedChanged)])
[self.delegate numberOfFilesWaitingToBeDownloadedChanged];
[self _triggerNextDownload];
}
}
- (void)listFiles
{
_fileList = nil;
_fileListFetchError = nil;
GTLServiceDrive *service = self.driveService;
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
// maxResults specifies the number of results per page. Since we earlier
// specified shouldFetchNextPages=YES, all results should be fetched,
// though specifying a larger maxResults will reduce the number of fetches
// needed to retrieve all pages.
query.maxResults = 150;
// The Drive API's file entries are chock full of data that the app may not
// care about. Specifying the fields we want here reduces the network
// bandwidth and memory needed for the collection.
//
// For example, leave query.fields as nil during development.
// When ready to test and optimize your app, specify just the fields needed.
// For example, this sample app might use
//
// query.fields = @"kind,etag,items(id,downloadUrl,editable,etag,exportLinks,kind,labels,originalFilename,title)";
//TODO:specify query.fields
_fileListTicket = [service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFileList *fileList,
NSError *error) {
// Callback
_fileList = fileList;
_fileListFetchError = error;
_fileListTicket = nil;
[self listOfGoodFiles];
}];
// [self updateUI];
}
- (void)_triggerNextDownload
{
if (_listOfGoogleDriveFilesToDownload.count > 0 && !_downloadInProgress) {
[self _reallyDownloadFileToDocumentFolder:_listOfGoogleDriveFilesToDownload[0]];
[_listOfGoogleDriveFilesToDownload removeObjectAtIndex:0];
if ([self.delegate respondsToSelector:@selector(numberOfFilesWaitingToBeDownloadedChanged)])
[self.delegate numberOfFilesWaitingToBeDownloadedChanged];
}
}
- (void)_reallyDownloadFileToDocumentFolder:(DBMetadata *)file
{
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [searchPaths[0] stringByAppendingFormat:@"/%@", file.filename];
//[[self restClient] loadFile:file.path intoPath:filePath];
if ([self.delegate respondsToSelector:@selector(operationWithProgressInformationStarted)])
[self.delegate operationWithProgressInformationStarted];
_downloadInProgress = YES;
}
#pragma mark - restClient delegate
- (BOOL)_supportedFileExtension:(NSString *)filename
{
if ([filename isSupportedMediaFormat] || [filename isSupportedAudioMediaFormat] || [filename isSupportedSubtitleFormat])
return YES;
return NO;
}
- (void)listOfGoodFiles
{
NSMutableArray *listOfGoodFilesAndFolders = [[NSMutableArray alloc] init];
for (GTLDriveFile *driveFile in _fileList.items)
{
BOOL isDirectory = [driveFile.mimeType isEqualToString:@"application/vnd.google-apps.folder"];
if (isDirectory || [self _supportedFileExtension:driveFile.fileExtension]) {
[listOfGoodFilesAndFolders addObject:driveFile];
}
}
_currentFileList = [NSArray arrayWithArray:listOfGoodFilesAndFolders];
APLog(@"found filtered metadata for %i files", _currentFileList.count);
if ([self.delegate respondsToSelector:@selector(mediaListUpdated)])
[self.delegate mediaListUpdated];
}
//- (void)restClient:(DBRestClient *)client loadMetadataFailedWithError:(NSError *)error
//{
// APLog(@"DBMetadata download failed with error %i", error.code);
//}
//
//- (void)restClient:(DBRestClient*)client loadedFile:(NSString*)localPath
//{
// /* update library now that we got a file */
// VLCAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
// [appDelegate updateMediaList];
//
// if ([self.delegate respondsToSelector:@selector(operationWithProgressInformationStopped)])
// [self.delegate operationWithProgressInformationStopped];
// _downloadInProgress = NO;
//
// [self _triggerNextDownload];
//}
//
//- (void)restClient:(DBRestClient*)client loadFileFailedWithError:(NSError*)error
//{
// APLog(@"DBFile download failed with error %i", error.code);
// if ([self.delegate respondsToSelector:@selector(operationWithProgressInformationStopped)])
// [self.delegate operationWithProgressInformationStopped];
// _downloadInProgress = NO;
//
// [self _triggerNextDownload];
//}
//
//- (void)restClient:(DBRestClient*)client loadProgress:(CGFloat)progress forFile:(NSString*)destPath
//{
// if ([self.delegate respondsToSelector:@selector(currentProgressInformation:)])
// [self.delegate currentProgressInformation:progress];
//}
//
//#pragma mark - DBSession delegate
//
//- (void)sessionDidReceiveAuthorizationFailure:(DBSession *)session userId:(NSString *)userId
//{
// APLog(@"DriveSession received authorization failure with user ID %@", userId);
//}
//
//#pragma mark - DBNetworkRequest delegate
//- (void)networkRequestStarted
//{
// _outstandingNetworkRequests++;
// if (_outstandingNetworkRequests == 1) {
// [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
// [(VLCAppDelegate*)[UIApplication sharedApplication].delegate disableIdleTimer];
// }
//}
- (void)networkRequestStopped
{
_outstandingNetworkRequests--;
if (_outstandingNetworkRequests == 0) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
[(VLCAppDelegate*)[UIApplication sharedApplication].delegate activateIdleTimer];
}
}
#pragma mark - VLC internal communication and delegate
- (NSArray *)currentListFiles
{
return _currentFileList;
}
- (NSInteger)numberOfFilesWaitingToBeDownloaded
{
if (_listOfGoogleDriveFilesToDownload)
return _listOfGoogleDriveFilesToDownload.count;
return 0;
}
@end
//
// VLCDropboxTableViewCell.h
// VLC for iOS
//
// Created by Carola Nitz on 21.09.13.
// Copyright (c) 2013 VideoLAN. All rights reserved.
//
// Refer to the COPYING file of the official project for license.
//
//#import <DropboxSDK/DropboxSDK.h>
@interface VLCGoogleDriveTableViewCell : UITableViewCell
@property (nonatomic, strong) IBOutlet UILabel *titleLabel;
@property (nonatomic, strong) IBOutlet UILabel *folderTitleLabel;
@property (nonatomic, strong) IBOutlet UILabel *subtitleLabel;
@property (nonatomic, strong) IBOutlet UIImageView *thumbnailView;
//@property (nonatomic, retain) DBMetadata *fileMetadata;
+ (VLCGoogleDriveTableViewCell *)cellWithReuseIdentifier:(NSString *)ident;
+ (CGFloat)heightOfCell;
@end
//
// VLCGoogleDriveTableViewCell.m
// VLC for iOS
//
// Created by Felix Paul Kühne on 24.05.13.
// Copyright (c) 2013 VideoLAN. All rights reserved.
//
// Refer to the COPYING file of the official project for license.
//
#import "VLCGoogleDriveTableViewCell.h"
@implementation VLCGoogleDriveTableViewCell
+ (VLCGoogleDriveTableViewCell *)cellWithReuseIdentifier:(NSString *)ident
{
NSArray *nibContentArray = [[NSBundle mainBundle] loadNibNamed:@"VLCGoogleDriveTableViewCell" owner:nil options:nil];
NSAssert([nibContentArray count] == 1, @"meh");
NSAssert([[nibContentArray lastObject] isKindOfClass:[VLCGoogleDriveTableViewCell class]], @"meh meh");
VLCGoogleDriveTableViewCell *cell = (VLCGoogleDriveTableViewCell *)[nibContentArray lastObject];
return cell;
}
- (void)_updatedDisplayedInformation
{
[self setNeedsDisplay];
}
+ (CGFloat)heightOfCell
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
return 80.;
return 48.;
}
@end
//
// VLCGoogleDriveTableViewController.h
// VLC for iOS
//
// Created by Carola Nitz on 21.09.13.
// Copyright (c) 2013 VideoLAN. All rights reserved.
//
// Refer to the COPYING file of the official project for license.
//
#import "VLCGoogleDriveController.h"
#import "GTMOAuth2ViewControllerTouch.h"
@interface VLCGoogleDriveTableViewController : UIViewController <VLCGoogleDriveController>
@property (nonatomic, strong) IBOutlet UITableView *tableView;
@property (nonatomic, strong) IBOutlet UIView *loginToGoogleDriveView;
@property (nonatomic, strong) IBOutlet UIButton *loginToGoogleDriveButton;
- (IBAction)loginToGoogleDriveAction:(id)sender;
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth:(GTMOAuth2Authentication *)authResult error:(NSError *)error;
- (void)updateViewAfterSessionChange;
@end
//
// VLCGoogleDriveTableViewController.m
// VLC for iOS
//
// Created by Carola Nitz on 21.09.13.
// Copyright (c) 2013 VideoLAN. All rights reserved.
//
// Refer to the COPYING file of the official project for license.
//
#import "VLCGoogleDriveTableViewController.h"
#import "VLCGoogleDriveTableViewCell.h"
#import "VLCGoogleDriveController.h"
#import "VLCAppDelegate.h"
#import "VLCPlaylistViewController.h"
#import "UIBarButtonItem+Theme.h"
#import "VLCGoogleDriveConstants.h"
#import "GTMOAuth2ViewControllerTouch.h"
static NSString *const kKeychainItemName = @"Google Drive Quickstart #3";
@interface VLCGoogleDriveTableViewController ()
{
VLCGoogleDriveController *_googleDriveController;
GTMOAuth2ViewControllerTouch *_authController;
NSString *_currentPath;
UIBarButtonItem *_backButton;
UIBarButtonItem *_backToMenuButton;
UIBarButtonItem *_numberOfFilesBarButtonItem;
UIBarButtonItem *_progressBarButtonItem;
UIBarButtonItem *_downloadingBarLabel;
UIProgressView *_progressView;
UIActivityIndicatorView *_activityIndicator;
}
@end
@implementation VLCGoogleDriveTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.modalPresentationStyle = UIModalPresentationFormSheet;
_googleDriveController = [[VLCGoogleDriveController alloc] init];
_googleDriveController.delegate = self;
[_googleDriveController startSession];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"DriveWhite"]];
self.navigationItem.titleView.contentMode = UIViewContentModeScaleAspectFit;
_backButton = [UIBarButtonItem themedBackButtonWithTarget:self andSelector:@selector(goBack:)];
_backToMenuButton = [UIBarButtonItem themedRevealMenuButtonWithTarget:self andSelector:@selector(goBack:)];
self.navigationItem.leftBarButtonItem = _backToMenuButton;
self.tableView.rowHeight = [VLCGoogleDriveTableViewCell heightOfCell];
self.tableView.separatorColor = [UIColor colorWithWhite:.122 alpha:1.];
self.view.backgroundColor = [UIColor colorWithWhite:.122 alpha:1.];
_numberOfFilesBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:[NSString stringWithFormat:NSLocalizedString(@"NUM_OF_FILES", @""), 0] style:UIBarButtonItemStylePlain target:nil action:nil];
[_numberOfFilesBarButtonItem setTitleTextAttributes:@{ UITextAttributeFont : [UIFont systemFontOfSize:11.] } forState:UIControlStateNormal];
_progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
_progressBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:_progressView];
_downloadingBarLabel = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"DOWNLOADING",@"") style:UIBarButtonItemStylePlain target:nil action:nil];
[_downloadingBarLabel setTitleTextAttributes:@{ UITextAttributeFont : [UIFont systemFontOfSize:11.] } forState:UIControlStateNormal];
[_loginToGoogleDriveButton setTitle:NSLocalizedString(@"DROPBOX_LOGIN", @"") forState:UIControlStateNormal];
[self.navigationController.toolbar setBackgroundImage:[UIImage imageNamed:@"sudHeaderBg"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[self _showProgressInToolbar:NO];
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
_activityIndicator.hidesWhenStopped = YES;
[self.view addSubview:_activityIndicator];
}
- (GTMOAuth2ViewControllerTouch *)createAuthController
{
_authController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDriveFile
clientID:kVLCGoogleDriveClientID
clientSecret:kVLCGoogleDriveClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:@selector(viewController:finishedWithAuth:error:)];
return _authController;
}
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
finishedWithAuth:(GTMOAuth2Authentication *)authResult
error:(NSError *)error
{
if (error != nil)
{
[self showAlert:@"Authentication Error" message:error.localizedDescription];
_googleDriveController.driveService.authorizer = nil;
}
else
{
_googleDriveController.driveService.authorizer = authResult;
}
[self updateViewAfterSessionChange];
}
- (void)showAlert:(NSString *)title message:(NSString *)message
{
UIAlertView *alert;
alert = [[UIAlertView alloc] initWithTitle: title
message: message
delegate: nil
cancelButtonTitle: @"OK"
otherButtonTitles: nil];
[alert show];
}
- (void)viewWillAppear:(BOOL)animated
{
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.barStyle = UIBarStyleBlack;
[self.navigationController.toolbar setBackgroundImage:[UIImage imageNamed:@"bottomBlackBar"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[self updateViewAfterSessionChange];
[super viewWillAppear:animated];
CGRect aiFrame = _activityIndicator.frame;
CGSize tvSize = self.tableView.frame.size;
aiFrame.origin.x = (tvSize.width - aiFrame.size.width) / 2.;
aiFrame.origin.y = (tvSize.height - aiFrame.size.height) / 2.;
_activityIndicator.frame = aiFrame;
}
- (void)viewWillDisappear:(BOOL)animated
{
self.navigationController.toolbarHidden = YES;
[super viewWillDisappear:animated];
}
- (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.progress = 0.;
[self setToolbarItems:@[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], _downloadingBarLabel, _progressBarButtonItem, [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]] animated:YES];
}
}
- (void)_requestInformationForCurrentPath
{
[_activityIndicator startAnimating];
[_googleDriveController requestDirectoryListingAtPath:_currentPath];
self.navigationItem.leftBarButtonItem = ![_currentPath isEqualToString:@"/"] ? _backButton : _backToMenuButton;
}
#pragma mark - interface interaction
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
return NO;
return YES;
}
- (IBAction)goBack:(id)sender
{
if (![_currentPath isEqualToString:@"/"] && [_currentPath length] > 0) {
_currentPath = [_currentPath stringByDeletingLastPathComponent];
[self _requestInformationForCurrentPath];
} else
[[(VLCAppDelegate*)[UIApplication sharedApplication].delegate revealController] toggleSidebar:![(VLCAppDelegate*)[UIApplication sharedApplication].delegate revealController].sidebarShowing duration:kGHRevealSidebarDefaultAnimationDuration];
}