Merge "Added an uploader progress view."

This commit is contained in:
Nick O'Neill 2013-12-29 03:01:24 +00:00 committed by Gerrit Code Review
commit f676cc3374
10 changed files with 171 additions and 25 deletions

View File

@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
D0180BEA185007C000E3487F /* credentials.plist in Resources */ = {isa = PBXBuildFile; fileRef = D0180BE9185007C000E3487F /* credentials.plist */; };
D059B88F186944F2006BE899 /* ProgressViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D059B88E186944F2006BE899 /* ProgressViewController.m */; };
D075B282184944330054FED3 /* LACamliUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D075B281184944330054FED3 /* LACamliUtil.m */; };
D075B28518494DB20054FED3 /* LACamliUploadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D075B28418494DB20054FED3 /* LACamliUploadOperation.m */; };
D095AE131814AF10008163F2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D095AE121814AF10008163F2 /* Foundation.framework */; };
@ -43,7 +43,8 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
D0180BE9185007C000E3487F /* credentials.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = credentials.plist; sourceTree = "<group>"; };
D059B88D186944F2006BE899 /* ProgressViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProgressViewController.h; sourceTree = "<group>"; };
D059B88E186944F2006BE899 /* ProgressViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProgressViewController.m; sourceTree = "<group>"; };
D075B280184944330054FED3 /* LACamliUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LACamliUtil.h; sourceTree = "<group>"; };
D075B281184944330054FED3 /* LACamliUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LACamliUtil.m; sourceTree = "<group>"; };
D075B28318494DB20054FED3 /* LACamliUploadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LACamliUploadOperation.h; sourceTree = "<group>"; };
@ -146,11 +147,12 @@
D0AC217018503A8E004BD4F3 /* CamliCollectionCell.m */,
D0D45E9F185FE2BE00EBC0A2 /* SettingsViewController.h */,
D0D45EA0185FE2BE00EBC0A2 /* SettingsViewController.m */,
D059B88D186944F2006BE899 /* ProgressViewController.h */,
D059B88E186944F2006BE899 /* ProgressViewController.m */,
D095AE241814AF10008163F2 /* Main_iPhone.storyboard */,
D095AE271814AF10008163F2 /* Main_iPad.storyboard */,
D095AE2D1814AF10008163F2 /* Images.xcassets */,
D095AE191814AF10008163F2 /* Supporting Files */,
D0180BE9185007C000E3487F /* credentials.plist */,
);
path = photobackup;
sourceTree = "<group>";
@ -286,7 +288,6 @@
buildActionMask = 2147483647;
files = (
D095AE291814AF10008163F2 /* Main_iPad.storyboard in Resources */,
D0180BEA185007C000E3487F /* credentials.plist in Resources */,
D095AE2E1814AF10008163F2 /* Images.xcassets in Resources */,
D095AE261814AF10008163F2 /* Main_iPhone.storyboard in Resources */,
D095AE1D1814AF10008163F2 /* InfoPlist.strings in Resources */,
@ -311,6 +312,7 @@
D095AE1F1814AF10008163F2 /* main.m in Sources */,
D095AE511814B1B9008163F2 /* LACamliClient.m in Sources */,
D0AC217118503A8E004BD4F3 /* CamliCollectionCell.m in Sources */,
D059B88F186944F2006BE899 /* ProgressViewController.m in Sources */,
D095AE501814B1B9008163F2 /* LACamliFile.m in Sources */,
D075B282184944330054FED3 /* LACamliUtil.m in Sources */,
D095AE231814AF10008163F2 /* LAAppDelegate.m in Sources */,

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4514" systemVersion="13A598" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="SoI-nq-iat">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="SoI-nq-iat">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
</dependencies>
@ -102,7 +102,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<collectionView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" minimumZoomScale="0.0" maximumZoomScale="0.0" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="KRb-uW-c9w">
<rect key="frame" x="0.0" y="109" width="320" height="459"/>
<rect key="frame" x="0.0" y="65" width="320" height="503"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="Ruf-Wi-cOY">
<size key="itemSize" width="100" height="100"/>
@ -170,6 +170,46 @@
</objects>
<point key="canvasLocation" x="-50" y="112"/>
</scene>
<!--Progress View Controller-->
<scene sceneID="kwd-3V-dLT">
<objects>
<viewController storyboardIdentifier="uploadBar" autoresizesArchivedViewToFullSize="NO" id="LJZ-RN-5bL" customClass="ProgressViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="ONX-4l-VhG"/>
<viewControllerLayoutGuide type="bottom" id="gTv-HF-xIn"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="W6C-gu-ahl">
<rect key="frame" x="0.0" y="0.0" width="320" height="60"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Uploading..." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vPS-27-7Lj">
<rect key="frame" x="14" y="13" width="286" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lXC-3o-YxX">
<rect key="frame" x="14" y="46" width="286" height="2"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</progressView>
</subviews>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
</view>
<extendedEdge key="edgesForExtendedLayout"/>
<nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="uploadLabel" destination="vPS-27-7Lj" id="PpL-8N-Py3"/>
<outlet property="uploadProgress" destination="lXC-3o-YxX" id="hT7-gd-9XR"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="I8e-te-vX5" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="321" y="620"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>

View File

@ -23,7 +23,10 @@
[self loadCredentials];
self.library = [[ALAssetsLibrary alloc] init];
// TODO: request access to the library first
[[NSNotificationCenter defaultCenter] addObserverForName:CamliNotificationUploadProgress object:nil queue:nil usingBlock:^(NSNotification *note) {
[UIApplication sharedApplication].applicationIconBadgeNumber = [note.userInfo[@"remain"] intValue];
}];
return YES;
}
@ -68,9 +71,7 @@
if (![weakSelf.client fileAlreadyUploaded:file]) {
filesToUpload++;
[weakSelf.client addFile:file withCompletion:^{
[UIApplication sharedApplication].applicationIconBadgeNumber--;
}];
[weakSelf.client addFile:file withCompletion:nil];
} else {
LALog(@"file already uploaded: %@",file.blobRef);
}

View File

@ -11,15 +11,20 @@
@interface LACamliClient : NSObject <NSURLSessionDelegate>
extern NSString *const CamliNotificationUploadStart;
extern NSString *const CamliNotificationUploadProgress;
extern NSString *const CamliNotificationUploadEnd;
extern NSString *const CamliBlobRootComponent;
@property NSURLSession *session;
@property NSURL *serverURL;
@property NSString *username;
@property NSString *password;
@property NSString *blobRoot;
@property NSURL *uploadUrl;
@property NSOperationQueue *uploadQueue;
@property NSUInteger totalUploads;
@property NSMutableArray *uploadedBlobRefs;
@property UIBackgroundTaskIdentifier backgroundID;

View File

@ -12,6 +12,11 @@
@implementation LACamliClient
NSString *const CamliNotificationUploadStart = @"camli-upload-start";
NSString *const CamliNotificationUploadProgress = @"camli-upload-progress";
NSString *const CamliNotificationUploadEnd = @"camli-upload-end";
NSString *const CamliBlobRootComponent = @"bs-recv";
- (id)initWithServer:(NSURL *)server username:(NSString *)username andPassword:(NSString *)password
{
NSParameterAssert(server);
@ -32,6 +37,7 @@
self.uploadQueue = [[NSOperationQueue alloc] init];
self.uploadQueue.maxConcurrentOperationCount = 1;
self.totalUploads = 0;
self.isAuthorized = false;
self.authorizing = false;
@ -63,7 +69,6 @@
#pragma mark - discovery
// if we don't have blobroot with which to make these requests, we need to find it first
- (void)discoveryWithUsername:(NSString *)user andPassword:(NSString *)pass
{
self.authorizing = YES;
@ -86,10 +91,6 @@
if (res.statusCode != 200) {
LALog(@"error with discovery: %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
} else {
NSError *parseError;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
self.blobRoot = json[@"blobRoot"];
self.isAuthorized = YES;
[self.uploadQueue setSuspended:NO];
@ -118,6 +119,12 @@
- (void)addFile:(LACamliFile *)file withCompletion:(void (^)())completion
{
NSParameterAssert(file);
if (self.totalUploads == 0) {
[[NSNotificationCenter defaultCenter] postNotificationName:CamliNotificationUploadStart object:nil];
}
self.totalUploads++;
if (![self isAuthorized]) {
[self.uploadQueue setSuspended:YES];
@ -133,7 +140,16 @@
[self.uploadedBlobRefs addObject:file.blobRef];
[self.uploadedBlobRefs writeToFile:[self uploadedBlobRefArchivePath] atomically:YES];
completion();
// let others know about upload progress
[[NSNotificationCenter defaultCenter] postNotificationName:CamliNotificationUploadProgress object:nil userInfo:@{@"total": @(self.totalUploads), @"remain": @([self.uploadQueue operationCount])}];
if (![self.uploadQueue operationCount]) {
self.totalUploads = 0;
[[NSNotificationCenter defaultCenter] postNotificationName:CamliNotificationUploadEnd object:nil];
}
if (completion) {
completion();
}
};
[self.uploadQueue addOperation:op];
@ -141,7 +157,7 @@
- (NSURL *)statUrl
{
return [[self.serverURL URLByAppendingPathComponent:self.blobRoot] URLByAppendingPathComponent:@"camli/stat"];
return [[self blobRoot] URLByAppendingPathComponent:@"camli/stat"];
}
#pragma mark - getting stuff
@ -173,6 +189,11 @@
#pragma mark - utility
- (NSURL *)blobRoot
{
return [self.serverURL URLByAppendingPathComponent:CamliBlobRootComponent];
}
- (NSString *)encodedAuth
{
NSString *auth = [NSString stringWithFormat:@"%@:%@",self.username,self.password];

View File

@ -64,7 +64,7 @@ static NSString *const multipartBoundary = @"Qe43VdbVVaGtkkMd";
for (NSString *key in params) {
formValues = [formValues stringByAppendingString:[NSString stringWithFormat:@"%@=%@&",key,params[key]]];
}
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[self.client statUrl]];
[req setHTTPMethod:@"POST"];
[req setHTTPBody:[formValues dataUsingEncoding:NSUTF8StringEncoding]];

View File

@ -8,11 +8,12 @@
#import <UIKit/UIKit.h>
@class LACamliClient;
@class LACamliClient,ProgressViewController;
@interface LAViewController : UIViewController
@property LACamliClient *client;
@property ProgressViewController *progress;
- (void)dismissSettings;

View File

@ -11,10 +11,7 @@
#import "LAAppDelegate.h"
#import "LACamliUtil.h"
#import "SettingsViewController.h"
@interface LAViewController ()
@end
#import "ProgressViewController.h"
@implementation LAViewController
@ -26,7 +23,6 @@
[self.navigationItem setRightBarButtonItem:settingsItem];
// show the
NSURL *serverURL = [NSURL URLWithString:[[NSUserDefaults standardUserDefaults] stringForKey:CamliServerKey]];
NSString *username = [[NSUserDefaults standardUserDefaults] stringForKey:CamliUsernameKey];
@ -39,6 +35,41 @@
[self showSettings];
}
self.progress = [[self storyboard] instantiateViewControllerWithIdentifier:@"uploadBar"];
self.progress.view.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height+self.progress.view.frame.size.height, self.progress.view.frame.size.width, self.progress.view.frame.size.height);
[self.view addSubview:self.progress.view];
[[NSNotificationCenter defaultCenter] addObserverForName:CamliNotificationUploadStart object:nil queue:nil usingBlock:^(NSNotification *note) {
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1.0 animations:^{
self.progress.view.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height-self.progress.view.frame.size.height, self.progress.view.frame.size.width, self.progress.view.frame.size.height);
}];
});
}];
[[NSNotificationCenter defaultCenter] addObserverForName:CamliNotificationUploadProgress object:nil queue:nil usingBlock:^(NSNotification *note) {
LALog(@"got progress %@ %@",note.userInfo[@"total"],note.userInfo[@"remain"]);
NSUInteger total = [note.userInfo[@"total"] intValue];
NSUInteger remain = [note.userInfo[@"remain"] intValue];
dispatch_async(dispatch_get_main_queue(), ^{
self.progress.uploadLabel.text = [NSString stringWithFormat:@"Uploading %d of %d",total-remain,total];
self.progress.uploadProgress.progress = (float)(total-remain)/(float)total;
});
}];
[[NSNotificationCenter defaultCenter] addObserverForName:CamliNotificationUploadEnd object:nil queue:nil usingBlock:^(NSNotification *note) {
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1.0 animations:^{
self.progress.view.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height+self.progress.view.frame.size.height, self.progress.view.frame.size.width, self.progress.view.frame.size.height);
}];
});
}];
// [self.client getRecentItemsWithCompletion:^(NSArray *objects) {
// LALog(@"got objects: %@",objects);
// }];
@ -86,4 +117,9 @@
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
@end

View File

@ -0,0 +1,16 @@
//
// ProgressViewController.h
// photobackup
//
// Created by Nick O'Neill on 12/23/13.
// Copyright (c) 2013 The Camlistore Authors. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ProgressViewController : UIViewController
@property IBOutlet UILabel *uploadLabel;
@property IBOutlet UIProgressView *uploadProgress;
@end

View File

@ -0,0 +1,24 @@
//
// ProgressViewController.m
// photobackup
//
// Created by Nick O'Neill on 12/23/13.
// Copyright (c) 2013 The Camlistore Authors. All rights reserved.
//
#import "ProgressViewController.h"
@implementation ProgressViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end