forked from mirrors/linphone-iphone
Merge remote-tracking branch 'public/master' into dev_cmake
This commit is contained in:
commit
f9cfdbe8aa
82 changed files with 187 additions and 122 deletions
|
|
@ -64,7 +64,7 @@
|
|||
|
||||
[linkLabel setText:NSLocalizedString(@"http://www.linphone.org", nil)];
|
||||
[licenseLabel setText:NSLocalizedString(@"GNU General Public License V2 ", nil)];
|
||||
[copyrightLabel setText:NSLocalizedString(@"© 2010-2012 Belledonne Communications ", nil)];
|
||||
[copyrightLabel setText:NSLocalizedString(@"© 2010 Belledonne Communications ", nil)];
|
||||
|
||||
[linkLabel addGestureRecognizer:linkTapGestureRecognizer];
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,14 @@ typedef NSString* IAPPurchaseNotificationStatus;
|
|||
//paid_account_id=test.autorenew_7days
|
||||
//receipt_validation_url=https://www.linphone.org/inapp.php
|
||||
//products_list=test.autorenew_7days
|
||||
// Note: in Sandbox mode (test), autorenewal expire time is speed up (see http://stackoverflow.com/questions/8815271/what-expiry-date-should-i-see-for-in-app-purchase-in-the-application-sandbox) so that 7 days renewal is only 3 minutes!
|
||||
// Note: in Sandbox mode (test), autorenewal expire time is speed up (see http://stackoverflow.com/questions/8815271/what-expiry-date-should-i-see-for-in-app-purchase-in-the-application-sandbox) so that 7 days renewal is only 3 minutes and:
|
||||
//1 week = 3 minutes
|
||||
//1 month = 5 minutes
|
||||
//2 months = 10 minutes
|
||||
//3 months = 15 minutes
|
||||
//6 months = 30 minutes
|
||||
//1 year = 1 hour
|
||||
|
||||
|
||||
@interface InAppProductsManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver> {
|
||||
NSString *latestReceiptMD5;
|
||||
|
|
@ -64,11 +71,16 @@ typedef NSString* IAPPurchaseNotificationStatus;
|
|||
// TRUE if manager is available for usage - will be FALSE if an operation is already in progress or if not initialized or not enabled
|
||||
@property (readonly) BOOL available;
|
||||
|
||||
// TRUE if accountActivate was started but we did not receive response from server yet
|
||||
@property (readonly) BOOL accountActivationInProgress;
|
||||
|
||||
- (BOOL)isPurchasedWithID:(NSString*)productId;
|
||||
// Purchase an account. You should not use this if manager is not available yet.
|
||||
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString*)email;
|
||||
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString*)email monthly:(BOOL)monthly;
|
||||
// Purchase a product. You should not use this if manager is not available yet.
|
||||
- (BOOL)purchaseWitID:(NSString *)productID;
|
||||
// Activate purchased account.
|
||||
- (BOOL)activateAccount:(NSString *)phoneNumber;
|
||||
|
||||
// restore user purchases. You should not use this if manager is not available yet. Must be at a user action ONLY.
|
||||
- (BOOL)restore;
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@
|
|||
#import "InAppProductsViewController.h"
|
||||
|
||||
@interface InAppProductsManager()
|
||||
@property (retain, nonatomic) NSDictionary *accountCreationData;
|
||||
// needed because request:didFailWithError method is already used by SKProductsRequestDelegate...
|
||||
@property (nonatomic, retain) InAppProductsXMLRPCDelegate *xmlrpc;
|
||||
@property (retain, nonatomic) NSDate *expirationDate;
|
||||
@property (retain, nonatomic) NSDictionary *accountCreationData;
|
||||
// needed because request:didFailWithError method is already used by SKProductsRequestDelegate...
|
||||
@property (nonatomic, retain) InAppProductsXMLRPCDelegate *xmlrpc;
|
||||
@end
|
||||
|
||||
@implementation InAppProductsManager
|
||||
|
|
@ -47,7 +48,7 @@
|
|||
_enabled = (([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) && ([SKPaymentQueue canMakePayments]) && ([[LinphoneManager instance] lpConfigBoolForKey:@"enabled" forSection:@"in_app_purchase"]));
|
||||
_initialized = false;
|
||||
_available = false;
|
||||
|
||||
_accountActivationInProgress = false;
|
||||
if (_enabled) {
|
||||
self.xmlrpc = [[InAppProductsXMLRPCDelegate alloc] init];
|
||||
_status = kIAPNotReady;
|
||||
|
|
@ -64,7 +65,9 @@
|
|||
if (!_enabled) return FALSE;
|
||||
|
||||
for (NSString *prod in _productsIDPurchased) {
|
||||
if ([prod isEqual: productID]) {
|
||||
NSDate *now = [[[NSDate alloc] init] autorelease];
|
||||
// since multiple ID represent the same product, we must not check it
|
||||
if (/*[prod isEqual: productID] &&*/[self.expirationDate earlierDate:now] == now) {
|
||||
bool isBought = true;
|
||||
LOGE(@"%@ is %s bought.", prod, isBought?"":"NOT");
|
||||
return isBought;
|
||||
|
|
@ -75,7 +78,7 @@
|
|||
|
||||
- (BOOL)purchaseWitID:(NSString *)productID {
|
||||
if (!_enabled||!_initialized||!_available) {
|
||||
NSDictionary* dict = @{@"product_id":productID, @"error_msg": NSLocalizedString(@"In apps not ready yet", nil)};
|
||||
NSDictionary* dict = @{@"product_id":productID, @"error_msg": NSLocalizedString(@"Cannot purchase anything yet, please try again later.", nil)};
|
||||
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -95,9 +98,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString*)email {
|
||||
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString*)email monthly:(BOOL)monthly {
|
||||
if (phoneNumber) {
|
||||
NSString* productID = [[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id" forSection:@"in_app_purchase"];
|
||||
NSString* productID = [[LinphoneManager instance] lpConfigStringForKey:(monthly?@"paid_account_id_monthly":@"paid_account_id") forSection:@"in_app_purchase"];
|
||||
self.accountCreationData = @{ @"phoneNumber":[phoneNumber retain], @"password":[password retain], @"email":[email retain] };
|
||||
|
||||
if (![self purchaseWitID:productID]) {
|
||||
|
|
@ -108,6 +111,34 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
- (BOOL)activateAccount:(NSString *)phoneNumber {
|
||||
if (phoneNumber) {
|
||||
NSString *receiptBase64 = [self getReceipt];
|
||||
if (receiptBase64) {
|
||||
NSURL *URL = [NSURL URLWithString:[[LinphoneManager instance] lpConfigStringForKey:@"receipt_validation_url" forSection:@"in_app_purchase"]];
|
||||
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithURL: URL];
|
||||
//buying for the first time: need to create the account
|
||||
//if ([transaction.transactionIdentifier isEqualToString:transaction.originalTransaction.transactionIdentifier]) {
|
||||
[request setMethod: @"activate_account" withParameters:[NSArray arrayWithObjects:
|
||||
@"",
|
||||
phoneNumber,
|
||||
receiptBase64,
|
||||
@"",
|
||||
@"apple",
|
||||
nil]];
|
||||
_accountActivationInProgress = YES;
|
||||
XMLRPCConnectionManager *manager = [XMLRPCConnectionManager sharedManager];
|
||||
[manager spawnConnectionWithXMLRPCRequest: request delegate: self.xmlrpc];
|
||||
LOGI(@"XMLRPC query %@", [request method]);
|
||||
[request release];
|
||||
return true;
|
||||
} else {
|
||||
LOGE(@"Trying to activate account but no receipt available yet (probably doing it too soon)");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
-(BOOL)restore {
|
||||
if (!_enabled||!_initialized||!_available) {
|
||||
NSDictionary* dict = @{@"error_msg": NSLocalizedString(@"In apps not ready yet", nil)};
|
||||
|
|
@ -197,70 +228,66 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)validateReceipt: (SKPaymentTransaction*)transaction {
|
||||
NSString *receiptBase64 = nil;
|
||||
- (NSString*) getReceipt {
|
||||
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
|
||||
|
||||
// Test whether the receipt is present at the above URL
|
||||
if(![[NSFileManager defaultManager] fileExistsAtPath:[receiptURL path]]) {
|
||||
// We are probably in sandbox environment, trying to retrieve it...
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *receiptBase64 = [[NSData dataWithContentsOfURL:receiptURL] base64EncodedStringWithOptions:0];
|
||||
LOGI(@"Found appstore receipt %@", [receiptBase64 md5]);
|
||||
return receiptBase64;
|
||||
}
|
||||
|
||||
- (void)validateReceipt: (SKPaymentTransaction*)transaction {
|
||||
NSString *receiptBase64 = [self getReceipt];
|
||||
if (receiptBase64 == nil) {
|
||||
SKRequest* req = [[SKReceiptRefreshRequest alloc] init];
|
||||
LOGI(@"Receipt not found yet, trying to retrieve it...");
|
||||
req.delegate = self;
|
||||
[req start];
|
||||
return;
|
||||
}
|
||||
|
||||
receiptBase64 = [[NSData dataWithContentsOfURL:receiptURL] base64EncodedStringWithOptions:0];
|
||||
LOGI(@"Found appstore receipt %@", [receiptBase64 md5]);
|
||||
|
||||
//only check the receipt if it has changed
|
||||
if (latestReceiptMD5 == nil || ![latestReceiptMD5 isEqualToString:[receiptBase64 md5]]) {
|
||||
// transaction is null when restoring user purchases at application start or if user clicks the "restore" button
|
||||
// We must validate the receipt on our server
|
||||
NSURL *URL = [NSURL URLWithString:[[LinphoneManager instance] lpConfigStringForKey:@"receipt_validation_url" forSection:@"in_app_purchase"]];
|
||||
|
||||
XMLRPCRequest *request = [[XMLRPCRequest alloc] initWithURL: URL];
|
||||
|
||||
// transaction is null when restoring user purchases at application start or if user clicks the "restore" button
|
||||
if (!transaction || [transaction.payment.productIdentifier isEqualToString:[[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id" forSection:@"in_app_purchase"]]) {
|
||||
//buying for the first time: need to create the account
|
||||
//if ([transaction.transactionIdentifier isEqualToString:transaction.originalTransaction.transactionIdentifier]) {
|
||||
if (self.accountCreationData.count == 3) {
|
||||
[request setMethod: @"create_account_from_in_app_purchase" withParameters:[NSArray arrayWithObjects:
|
||||
@"",
|
||||
[_accountCreationData objectForKey:@"phoneNumber"],
|
||||
receiptBase64,
|
||||
@"",
|
||||
@"apple",
|
||||
[_accountCreationData objectForKey:@"email"],
|
||||
nil]];
|
||||
self.accountCreationData = nil;
|
||||
// otherwise simply renewing
|
||||
} else {
|
||||
if ([[self getPhoneNumber] length] > 0) {
|
||||
//buying for the first time: need to create the account
|
||||
//if ([transaction.transactionIdentifier isEqualToString:transaction.originalTransaction.transactionIdentifier]) {
|
||||
if (self.accountCreationData.count == 3) {
|
||||
[request setMethod: @"create_account_from_in_app_purchase" withParameters:[NSArray arrayWithObjects:
|
||||
@"",
|
||||
[_accountCreationData objectForKey:@"phoneNumber"],
|
||||
receiptBase64,
|
||||
@"",
|
||||
@"apple",
|
||||
[_accountCreationData objectForKey:@"email"],
|
||||
nil]];
|
||||
self.accountCreationData = nil;
|
||||
// otherwise simply renewing
|
||||
} else {
|
||||
if ([[self getPhoneNumber] length] > 0) {
|
||||
[request setMethod: @"get_expiration_date" withParameters:[NSArray arrayWithObjects:
|
||||
[self getPhoneNumber],
|
||||
receiptBase64,
|
||||
@"",
|
||||
@"apple",
|
||||
nil]];
|
||||
} else {
|
||||
LOGW(@"No SIP URI configured, doing nothing");
|
||||
_available = true;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOGW(@"No SIP URI configured, doing nothing");
|
||||
_available = true;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOGE(@"Hum, not handling product with ID %@", transaction.payment.productIdentifier);
|
||||
_available = true;
|
||||
return;
|
||||
}
|
||||
|
||||
latestReceiptMD5 = [[receiptBase64 md5] retain];
|
||||
|
||||
XMLRPCConnectionManager *manager = [XMLRPCConnectionManager sharedManager];
|
||||
[manager spawnConnectionWithXMLRPCRequest: request delegate: self.xmlrpc];
|
||||
LOGI(@"XMLRPC query %@: %@", [request method], [request body]);
|
||||
LOGI(@"XMLRPC query %@", [request method]);
|
||||
[request release];
|
||||
} else {
|
||||
LOGW(@"Not checking receipt since it has already been done!");
|
||||
|
|
@ -311,7 +338,7 @@
|
|||
NSDictionary* dict = @{@"product_id": transaction.payment.productIdentifier};
|
||||
[self postNotificationforStatus:kIAPPurchaseCancelled withDict:dict];
|
||||
} else {
|
||||
NSString* errlast = [NSString stringWithFormat:@"Purchase of %@ failed: %@.",transaction.payment.productIdentifier,transaction.error.localizedDescription];
|
||||
NSString* errlast = [NSString stringWithFormat:@"Purchase failed: %@.",transaction.error.localizedDescription];
|
||||
LOGE(@"SKPaymentTransactionStateFailed: %@", errlast);
|
||||
NSDictionary* dict = @{@"product_id": transaction.payment.productIdentifier, @"error_msg": errlast};
|
||||
[self postNotificationforStatus:kIAPPurchaseFailed withDict:dict];
|
||||
|
|
@ -324,7 +351,7 @@
|
|||
|
||||
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions {
|
||||
for(SKPaymentTransaction * transaction in transactions) {
|
||||
LOGI(@"%@ was removed from the payment queue.", transaction.payment.productIdentifier);
|
||||
LOGD(@"%@ was removed from the payment queue.", transaction.payment.productIdentifier);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +377,10 @@
|
|||
|
||||
_available = true;
|
||||
|
||||
if ([[request method] isEqualToString:@"activate_account"]) {
|
||||
_accountActivationInProgress = NO;
|
||||
}
|
||||
|
||||
LOGI(@"XMLRPC response %@: %@", [request method], [response body]);
|
||||
NSString* productID = [[LinphoneManager instance] lpConfigStringForKey:@"paid_account_id" forSection:@"in_app_purchase"];
|
||||
|
||||
|
|
@ -361,22 +392,26 @@
|
|||
// response object can either be expiration date (long long number or an error string)
|
||||
double timeinterval = [[response object] doubleValue];
|
||||
if (timeinterval != 0.0f) {
|
||||
NSDate *expirationDate = [NSDate dateWithTimeIntervalSince1970:timeinterval/1000];
|
||||
NSDate *now = [[NSDate alloc] init];
|
||||
NSDictionary* dict = @{@"product_id": productID, @"expires_date": expirationDate};
|
||||
if ([expirationDate earlierDate:now] == expirationDate) {
|
||||
self.expirationDate = [NSDate dateWithTimeIntervalSince1970:timeinterval/1000];
|
||||
NSDate *now = [[[NSDate alloc] init] autorelease];
|
||||
NSDictionary* dict = @{@"product_id": productID, @"expires_date": self.expirationDate};
|
||||
if ([self.expirationDate earlierDate:now] == self.expirationDate) {
|
||||
LOGW(@"Account has expired");
|
||||
[self postNotificationforStatus:kIAPPurchaseExpired withDict:dict];
|
||||
} else {
|
||||
LOGI(@"Account valid until %@", self.expirationDate);
|
||||
[_productsIDPurchased addObject:productID];
|
||||
[self postNotificationforStatus:kIAPPurchaseSucceeded withDict:dict];
|
||||
}
|
||||
} else {
|
||||
self.expirationDate = nil;
|
||||
NSString *error = [response object];
|
||||
LOGE(@"Failed with error %@", error);
|
||||
NSString *errorMsg;
|
||||
if ([error isEqualToString:@"ERROR_ACCOUNT_ALREADY_EXISTS"]) {
|
||||
errorMsg=NSLocalizedString(@"You have already registered an account.", nil);
|
||||
errorMsg=NSLocalizedString(@"This account is already registered.", nil);
|
||||
} else if ([error isEqualToString:@"ERROR_UID_ALREADY_IN_USE"]) {
|
||||
errorMsg=NSLocalizedString(@"You already own an account.", nil);
|
||||
} else if ([error isEqualToString:@"ERROR_ACCOUNT_DOESNT_EXIST"]) {
|
||||
errorMsg=NSLocalizedString(@"You have already purchased an account but it does not exist anymore.", nil);
|
||||
} else if ([error isEqualToString:@"ERROR_PURCHASE_CANCELLED"]) {
|
||||
|
|
@ -415,6 +450,10 @@
|
|||
|
||||
_available = true;
|
||||
|
||||
if ([[request method] isEqualToString:@"activate_account"]) {
|
||||
_accountActivationInProgress = NO;
|
||||
}
|
||||
|
||||
LOGE(@"Communication issue (%@)", [error localizedDescription]);
|
||||
NSString *errorString = [NSString stringWithFormat:NSLocalizedString(@"Communication issue (%@)", nil), [error localizedDescription]];
|
||||
UIAlertView* errorView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Communication issue", nil)
|
||||
|
|
@ -434,7 +473,7 @@
|
|||
[[NSNotificationCenter defaultCenter] postNotificationName:status object:self userInfo:nil];
|
||||
LOGE(@"Not supported, triggering %@", status);
|
||||
}
|
||||
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString*)email { [self postNotificationforStatus:kIAPPurchaseFailed]; return false; }
|
||||
- (BOOL)purchaseAccount:(NSString *)phoneNumber withPassword:(NSString *)password andEmail:(NSString *)email monthly:(BOOL)monthly { [self postNotificationforStatus:kIAPPurchaseFailed]; return false; }
|
||||
- (BOOL)restore { [self postNotificationforStatus:kIAPRestoreFailed]; return false; }
|
||||
- (BOOL)retrievePurchases { [self postNotificationforStatus:kIAPRestoreFailed]; return false; }
|
||||
- (BOOL)purchaseWitID:(NSString *)productID { [self postNotificationforStatus:kIAPPurchaseFailed]; return FALSE; }
|
||||
|
|
@ -444,6 +483,7 @@
|
|||
- (void)XMLRPCRequest:(XMLRPCRequest *)request didReceiveResponse:(XMLRPCResponse *)response { }
|
||||
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { }
|
||||
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { }
|
||||
- (BOOL)activateAccount:(NSString *)phoneNumber { return FALSE; }
|
||||
#endif
|
||||
@end
|
||||
|
||||
|
|
@ -470,6 +510,6 @@
|
|||
}
|
||||
|
||||
- (void)request:(XMLRPCRequest *)request didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
|
||||
|
||||
|
||||
}
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -194,11 +194,7 @@ struct codec_name_pref_table codec_pref_table[]={
|
|||
}
|
||||
|
||||
+ (BOOL)runningOnIpad {
|
||||
#ifdef UI_USER_INTERFACE_IDIOM
|
||||
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
|
||||
#else
|
||||
return NO;
|
||||
#endif
|
||||
return ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad);
|
||||
}
|
||||
|
||||
+ (BOOL)isRunningTests {
|
||||
|
|
@ -299,8 +295,6 @@ struct codec_name_pref_table codec_pref_table[]={
|
|||
#endif
|
||||
}
|
||||
|
||||
_iapManager = [[InAppProductsManager alloc] init];
|
||||
|
||||
[self migrateFromUserPrefs];
|
||||
}
|
||||
return self;
|
||||
|
|
@ -1403,6 +1397,8 @@ static BOOL libStarted = FALSE;
|
|||
// create linphone core
|
||||
[self createLinphoneCore];
|
||||
|
||||
_iapManager = [[InAppProductsManager alloc] init];
|
||||
|
||||
linphone_core_migrate_to_multi_transport(theLinphoneCore);
|
||||
|
||||
// init audio session (just getting the instance will init)
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@
|
|||
// Set selected+over background: IB lack !
|
||||
[speakerButton setBackgroundImage:[UIImage imageNamed:@"speaker_on_over.png"]
|
||||
forState:(UIControlStateHighlighted | UIControlStateSelected)];
|
||||
[speakerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"sspeaker_on_over_landscape.png"]
|
||||
[speakerButtonLandscape setBackgroundImage:[UIImage imageNamed:@"speaker_on_over_landscape.png"]
|
||||
forState:(UIControlStateHighlighted | UIControlStateSelected)];
|
||||
|
||||
[LinphoneUtils buttonFixStates:speakerButton];
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -626,7 +626,7 @@ static RootViewManager* rootViewManagerInstance = nil;
|
|||
}
|
||||
|
||||
if (linphone_call_get_reason(call) == LinphoneReasonNotFound) {
|
||||
lMessage = [NSString stringWithFormat : NSLocalizedString(@"'%@' not registered", nil), lUserName];
|
||||
lMessage = [NSString stringWithFormat : NSLocalizedString(@"%@ not registered", nil), lUserName];
|
||||
} else {
|
||||
if (message != nil) {
|
||||
lMessage = [NSString stringWithFormat : NSLocalizedString(@"%@\nReason was: %@", nil), lMessage, message];
|
||||
|
|
|
|||
|
|
@ -595,6 +595,10 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
LinphoneManager* lm = [LinphoneManager instance];
|
||||
NSMutableSet *hiddenKeys = [NSMutableSet set];
|
||||
|
||||
#ifndef HAVE_SSL
|
||||
[hiddenKeys addObject:@"media_encryption_preference"];
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG
|
||||
[hiddenKeys addObject:@"release_button"];
|
||||
[hiddenKeys addObject:@"clear_cache_button"];
|
||||
|
|
|
|||
|
|
@ -933,7 +933,7 @@ static UICompositeViewDescription *compositeDescription = nil;
|
|||
NSString *identity = [self identityFromUsername:username];
|
||||
[self checkUserExist:identity];
|
||||
} else {
|
||||
[iapm purchaseAccount:username withPassword:password andEmail:email];
|
||||
[iapm purchaseAccount:username withPassword:password andEmail:email monthly:FALSE];
|
||||
// inAppPurchaseNotification will take care of bringing us to the next view now
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Classes/zh_TW.lproj/FirstLoginViewController.strings
Normal file
BIN
Classes/zh_TW.lproj/FirstLoginViewController.strings
Normal file
Binary file not shown.
BIN
Classes/zh_TW.lproj/WizardViews.strings
Normal file
BIN
Classes/zh_TW.lproj/WizardViews.strings
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -16,7 +16,7 @@
|
|||
<key>Key</key>
|
||||
<string>speex_16k_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Speex 16Khz</string>
|
||||
<string>Speex 16kHz</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
<key>Key</key>
|
||||
<string>speex_8k_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Speex 8Khz</string>
|
||||
<string>Speex 8kHz</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
<key>Key</key>
|
||||
<string>silk_24k_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Silk 24Khz</string>
|
||||
<string>Silk 24kHz</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
<key>Key</key>
|
||||
<string>silk_16k_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Silk 16Khz</string>
|
||||
<string>Silk 16kHz</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
@ -128,7 +128,7 @@
|
|||
<key>Key</key>
|
||||
<string>g722_preference</string>
|
||||
<key>Title</key>
|
||||
<string>G722</string>
|
||||
<string>G.722</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
<key>Key</key>
|
||||
<string>g729_preference</string>
|
||||
<key>Title</key>
|
||||
<string>G729</string>
|
||||
<string>G.729</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
@ -158,7 +158,7 @@
|
|||
<key>Key</key>
|
||||
<string>ilbc_preference</string>
|
||||
<key>Title</key>
|
||||
<string>ILBC</string>
|
||||
<string>iLBC</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
<key>Key</key>
|
||||
<string>substitute_+_by_00_preference</string>
|
||||
<key>Title</key>
|
||||
<string>Substitue + by 00</string>
|
||||
<string>Substitute + by 00</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
<key>Key</key>
|
||||
<string>mp4v-es_preference</string>
|
||||
<key>Title</key>
|
||||
<string>mpeg4</string>
|
||||
<string>MPEG-4</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
<key>Key</key>
|
||||
<string>h264_preference</string>
|
||||
<key>Title</key>
|
||||
<string>h264</string>
|
||||
<string>H.264</string>
|
||||
<key>Type</key>
|
||||
<string>PSToggleSwitchSpecifier</string>
|
||||
</dict>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Settings/InAppSettings.bundle/de.lproj/Audio.strings
Normal file
BIN
Settings/InAppSettings.bundle/de.lproj/Audio.strings
Normal file
Binary file not shown.
BIN
Settings/InAppSettings.bundle/de.lproj/Call.strings
Normal file
BIN
Settings/InAppSettings.bundle/de.lproj/Call.strings
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Settings/InAppSettings.bundle/de.lproj/Video.strings
Normal file
BIN
Settings/InAppSettings.bundle/de.lproj/Video.strings
Normal file
Binary file not shown.
|
|
@ -1,19 +1,19 @@
|
|||
"Codecs" = "Codecs";
|
||||
"Speex 16Khz" = "Speex 16Khz";
|
||||
"Speex 8Khz" = "Speex 8Khz";
|
||||
"Speex 16kHz" = "Speex 16kHz";
|
||||
"Speex 8kHz" = "Speex 8kHz";
|
||||
"Opus 48kHz" = "Opus 48kHz";
|
||||
"Silk 24Khz" = "Silk 24Khz";
|
||||
"Silk 16Khz" = "Silk 16Khz";
|
||||
"Silk 24kHz" = "Silk 24kHz";
|
||||
"Silk 16kHz" = "Silk 16kHz";
|
||||
"AAC-ELD 16kHz" = "AAC-ELD 16kHz";
|
||||
"AAC-ELD 22kHz" = "AAC-ELD 22kHz";
|
||||
"AAC-ELD 32kHz" = "AAC-ELD 32kHz";
|
||||
"AAC-ELD 44kHz" = "AAC-ELD 44kHz";
|
||||
"AAC-ELD 48kHz" = "AAC-ELD 48kHz";
|
||||
"AMR" = "AMR";
|
||||
"G722" = "G722";
|
||||
"G729" = "G729";
|
||||
"G.722" = "G.722";
|
||||
"G.729" = "G.729";
|
||||
"GSM" = "GSM";
|
||||
"ILBC" = "ILBC";
|
||||
"iLBC" = "iLBC";
|
||||
"PCMU" = "PCMU";
|
||||
"PCMA" = "PCMA";
|
||||
"Advanced" = "Advanced";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
"Prefix" = "Prefix";
|
||||
"Substitue + by 00" = "Substitue + by 00";
|
||||
"Substitute + by 00" = "Substitute + by 00";
|
||||
"Send inband DTMFs" = "Send inband DTMFs";
|
||||
"Send SIP INFO DTMFs" = "Send SIP INFO DTMFs";
|
||||
"Incoming call timeout" = "Incoming call timeout";
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
"Network" = "Network";
|
||||
"Tunnel" = "Tunnel";
|
||||
"Advanced" = "Advanced";
|
||||
"Extra features" = "Extra features";
|
||||
"Development debug actions" = "Development debug actions";
|
||||
"About" = "About";
|
||||
"Quit" = "Quit";
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
"Show preview" = "Show preview";
|
||||
"Preferred video size" = "Preferred video size";
|
||||
"Codecs" = "Codecs";
|
||||
"mpeg4" = "mpeg4";
|
||||
"h264" = "h264";
|
||||
"MPEG-4" = "MPEG-4";
|
||||
"H.264" = "H.264";
|
||||
"VP8" = "VP8";
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Settings/InAppSettings.bundle/ja.lproj/Audio.strings
Normal file
BIN
Settings/InAppSettings.bundle/ja.lproj/Audio.strings
Normal file
Binary file not shown.
Binary file not shown.
BIN
Settings/InAppSettings.bundle/ja.lproj/Video.strings
Normal file
BIN
Settings/InAppSettings.bundle/ja.lproj/Video.strings
Normal file
Binary file not shown.
BIN
Settings/InAppSettings.bundle/nl.lproj/Audio.strings
Normal file
BIN
Settings/InAppSettings.bundle/nl.lproj/Audio.strings
Normal file
Binary file not shown.
BIN
Settings/InAppSettings.bundle/nl.lproj/Call.strings
Normal file
BIN
Settings/InAppSettings.bundle/nl.lproj/Call.strings
Normal file
Binary file not shown.
Binary file not shown.
BIN
Settings/InAppSettings.bundle/nl.lproj/Video.strings
Normal file
BIN
Settings/InAppSettings.bundle/nl.lproj/Video.strings
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Settings/InAppSettings.bundle/zh_TW.lproj/Advanced.strings
Normal file
BIN
Settings/InAppSettings.bundle/zh_TW.lproj/Advanced.strings
Normal file
Binary file not shown.
BIN
Settings/InAppSettings.bundle/zh_TW.lproj/Audio.strings
Normal file
BIN
Settings/InAppSettings.bundle/zh_TW.lproj/Audio.strings
Normal file
Binary file not shown.
Binary file not shown.
BIN
Settings/InAppSettings.bundle/zh_TW.lproj/Video.strings
Normal file
BIN
Settings/InAppSettings.bundle/zh_TW.lproj/Video.strings
Normal file
Binary file not shown.
|
|
@ -1,39 +1,39 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/bash -x
|
||||
|
||||
# Install underscore-cli for hacking
|
||||
if ! which underscore &> /dev/null; then
|
||||
npm install -g underscore-cli
|
||||
npm install -g underscore-cli
|
||||
fi
|
||||
|
||||
cd Screens
|
||||
|
||||
# Prepare location to collect delete commands
|
||||
if test "$TRAVIS_BUILD_NUMBER" = ""; then
|
||||
TRAVIS_BUILD_NUMBER="dev"
|
||||
fi
|
||||
output_dir="Screens"
|
||||
download_cmds=""
|
||||
if "*.png" 2>/dev/null; then
|
||||
# Prepare location to collect delete commands
|
||||
if test "$TRAVIS_BUILD_NUMBER" = ""; then
|
||||
TRAVIS_BUILD_NUMBER="dev"
|
||||
fi
|
||||
output_dir="Screens"
|
||||
download_cmds=""
|
||||
|
||||
# curl from http://imgur.com/tools/imgurbash.sh via http://imgur.com/tools
|
||||
# Documentation: http://code.google.com/p/imgur-api/source/browse/wiki/ImageUploading.wiki?r=82
|
||||
api_key=$IMGUR_KEY
|
||||
oIFS=$IFS
|
||||
IFS=$'\n'
|
||||
for filepath in $(find . -name '*.png'); do
|
||||
# echo "File $filepath"
|
||||
# echo "Command: curl https://api.imgur.com/3/upload.json -H \"Authorization: Client-ID $api_key\" -F "image=@\"$filepath\"""
|
||||
result="$(curl https://api.imgur.com/3/upload.json -H "Authorization: Client-ID $api_key" -F "image=@\"$filepath\"" )"
|
||||
# result='{"rsp":{"stat":"ok","image":{"image_hash":"dKZ0YK9","delete_hash":"r0MsZp11K9vawLf","original_image":"http:\/\/i.imgur.com\/dKZ0YK9.png","large_thumbnail":"http:\/\/i.imgur.com\/dKZ0YK9l.jpg","small_thumbnail":"http:\/\/i.imgur.com\/dKZ0YK9s.jpg","imgur_page":"http:\/\/imgur.com\/dKZ0YK9","delete_page":"http:\/\/imgur.com\/delete\/r0MsZp11K9vawLf"}}}'
|
||||
lol="$(echo $result | underscore extract success)"
|
||||
if test $lol != "true"; then
|
||||
echo "There was a problem uploading \"$filepath\"" 1>&2
|
||||
echo "$result" 1>&2
|
||||
else
|
||||
download_cmds="${download_cmds}wget $(echo "$result" | underscore extract 'data.link')\n"
|
||||
fi
|
||||
done
|
||||
IFS=$oIFS
|
||||
echo "All uploads complete!"
|
||||
echo ""
|
||||
echo "Download via:"
|
||||
echo -e " $download_cmds"
|
||||
# curl from http://imgur.com/tools/imgurbash.sh via http://imgur.com/tools
|
||||
# Documentation: http://code.google.com/p/imgur-api/source/browse/wiki/ImageUploading.wiki?r=82
|
||||
api_key=$IMGUR_KEY
|
||||
for filepath in *.png; do
|
||||
# echo "File $filepath"
|
||||
# echo "Command: curl https://api.imgur.com/3/upload.json -H \"Authorization: Client-ID $api_key\" -F "image=@\"$filepath\"""
|
||||
result="$(curl https://api.imgur.com/3/upload.json -H "Authorization: Client-ID $api_key" -F "image=@\"$filepath\"" )"
|
||||
|
||||
# result='{"rsp":{"stat":"ok","image":{"image_hash":"dKZ0YK9","delete_hash":"r0MsZp11K9vawLf","original_image":"http:\/\/i.imgur.com\/dKZ0YK9.png","large_thumbnail":"http:\/\/i.imgur.com\/dKZ0YK9l.jpg","small_thumbnail":"http:\/\/i.imgur.com\/dKZ0YK9s.jpg","imgur_page":"http:\/\/imgur.com\/dKZ0YK9","delete_page":"http:\/\/imgur.com\/delete\/r0MsZp11K9vawLf"}}}'
|
||||
succeeded="$(echo $result | underscore extract success)"
|
||||
if [ "$succeeded" != "true" ]; then
|
||||
echo "There was a problem uploading \"$filepath\": $result"
|
||||
else
|
||||
download_cmds="${download_cmds}wget $(echo "$result" | underscore extract 'data.link')\n"
|
||||
fi
|
||||
done
|
||||
echo "All uploads complete!"
|
||||
echo ""
|
||||
echo "Download via: $download_cmds"
|
||||
else
|
||||
echo "Could not find any PNG in $PWD, something must be broken!"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -47,15 +47,19 @@ already_sync=$(mktemp -t tag_missing_resources)
|
|||
to_sync=$(mktemp -t tag_missing_resources)
|
||||
|
||||
grep -oE '([^ /"])*.png' ../linphone.xcodeproj/project.pbxproj | sort -u > $already_sync
|
||||
find ../Resources/ -name *.png -exec basename {} \; | sort -u > $to_sync
|
||||
find ../Resources/ -not -path '*/Images.xcassets/*' -name '*.png' -exec basename {} \; | sort -u > $to_sync
|
||||
|
||||
# clean red tags
|
||||
cd ../Resources && tag -r red $(cat $to_sync $already_sync) && cd - 1>/dev/null
|
||||
for file in $to_sync $already_sync; do
|
||||
find ../Resources -name $file -exec tag -r red {} \;
|
||||
done
|
||||
|
||||
# 'comm' command output files contained in second file but not in first nor in common
|
||||
non_synced_files=$(comm -13 $already_sync $to_sync)
|
||||
|
||||
cd ../Resources/ && tag -a red $non_synced_files && cd - 1>/dev/null
|
||||
for file in $non_synced_files; do
|
||||
find ../Resources -name $file -exec tag -a red {} \;
|
||||
done
|
||||
|
||||
rm $already_sync $to_sync
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,8 @@
|
|||
639CEB061A1DF4F1004DE38F /* UIChatRoomCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB081A1DF4F1004DE38F /* UIChatRoomCell.xib */; };
|
||||
639CEB091A1DF4FA004DE38F /* UIChatCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 639CEB0B1A1DF4FA004DE38F /* UIChatCell.xib */; };
|
||||
63CD4B4F1A5AAC8C00B84282 /* DTAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */; };
|
||||
63D2680F1B174A5E00A2CC11 /* numpad_one_voicemail_default.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D2680D1B174A5E00A2CC11 /* numpad_one_voicemail_default.png */; };
|
||||
63D268101B174A5E00A2CC11 /* numpad_one_voicemail_over.png in Resources */ = {isa = PBXBuildFile; fileRef = 63D2680E1B174A5E00A2CC11 /* numpad_one_voicemail_over.png */; };
|
||||
63E59A3F1ADE70D900646FB3 /* InAppProductsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */; };
|
||||
63FB30351A680E73008CA393 /* UIRoundedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FB30341A680E73008CA393 /* UIRoundedImageView.m */; };
|
||||
70571E1A13FABCB000CDD3C2 /* rootca.pem in Resources */ = {isa = PBXBuildFile; fileRef = 70571E1913FABCB000CDD3C2 /* rootca.pem */; };
|
||||
|
|
@ -1045,6 +1047,8 @@
|
|||
639CEB0D1A1DF52C004DE38F /* ru */ = {isa = PBXFileReference; fileEncoding = 2483028224; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/UICallCell.strings; sourceTree = "<group>"; };
|
||||
63CD4B4D1A5AAC8C00B84282 /* DTAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTAlertView.h; sourceTree = "<group>"; };
|
||||
63CD4B4E1A5AAC8C00B84282 /* DTAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DTAlertView.m; sourceTree = "<group>"; };
|
||||
63D2680D1B174A5E00A2CC11 /* numpad_one_voicemail_default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = numpad_one_voicemail_default.png; path = Resources/numpad_one_voicemail_default.png; sourceTree = "<group>"; };
|
||||
63D2680E1B174A5E00A2CC11 /* numpad_one_voicemail_over.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = numpad_one_voicemail_over.png; path = Resources/numpad_one_voicemail_over.png; sourceTree = "<group>"; };
|
||||
63E59A3D1ADE6ECB00646FB3 /* InAppProductsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InAppProductsManager.h; sourceTree = "<group>"; };
|
||||
63E59A3E1ADE70D900646FB3 /* InAppProductsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InAppProductsManager.m; sourceTree = "<group>"; };
|
||||
63EF7FDC1A24B5810017A416 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/AboutViewController.strings; sourceTree = "<group>"; };
|
||||
|
|
@ -2806,6 +2810,8 @@
|
|||
D3F83F3F1582223B00336684 /* numpad_nine_over.png */,
|
||||
D3F83F2E1582223B00336684 /* numpad_one_default.png */,
|
||||
D3F83F2F1582223B00336684 /* numpad_one_over.png */,
|
||||
63D2680D1B174A5E00A2CC11 /* numpad_one_voicemail_default.png */,
|
||||
63D2680E1B174A5E00A2CC11 /* numpad_one_voicemail_over.png */,
|
||||
D3F83F3A1582223B00336684 /* numpad_seven_default.png */,
|
||||
D3F83F3B1582223B00336684 /* numpad_seven_over.png */,
|
||||
D3F83F401582223B00336684 /* numpad_sharp_default.png */,
|
||||
|
|
@ -3328,6 +3334,7 @@
|
|||
70571E1A13FABCB000CDD3C2 /* rootca.pem in Resources */,
|
||||
D347347E1580E5F8003C7B8C /* history_default.png in Resources */,
|
||||
D347347F1580E5F8003C7B8C /* history_selected.png in Resources */,
|
||||
63D268101B174A5E00A2CC11 /* numpad_one_voicemail_over.png in Resources */,
|
||||
D38327F31580FE3A00FA0D23 /* contacts_default.png in Resources */,
|
||||
D38327F41580FE3A00FA0D23 /* contacts_selected.png in Resources */,
|
||||
D38327F51580FE3A00FA0D23 /* dialer_default.png in Resources */,
|
||||
|
|
@ -3528,6 +3535,7 @@
|
|||
639CEB061A1DF4F1004DE38F /* UIChatRoomCell.xib in Resources */,
|
||||
D3A8BB7B15A6CC3200F96BE5 /* chat_bubble_outgoing.png in Resources */,
|
||||
D3A8BB7D15A6CC3200F96BE5 /* chat_bubble_incoming.png in Resources */,
|
||||
63D2680F1B174A5E00A2CC11 /* numpad_one_voicemail_default.png in Resources */,
|
||||
F0C1F9101A28781F009402C9 /* corner-left-bottom.png in Resources */,
|
||||
D3A8BB7F15A6CC3200F96BE5 /* setup_back_disabled.png in Resources */,
|
||||
D3A8BB8115A6CC3200F96BE5 /* setup_cancel_disabled.png in Resources */,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 97bdfd1f51c441c441e713de8c1d50cd037cda5d
|
||||
Subproject commit 1ffd890571879bba9a58251dfe7dd5249c011517
|
||||
Loading…
Add table
Reference in a new issue