Added override for Google's "New Privacy Policy" alerts to allow continuation of use. Changed SIP to do the opposite with domain fields and registrar as this is how it should have been written. Added note to let users know that most providers use "*" for the domain. Fixed notifications for SMSes. Upgraded Growl to support Mountain Lion's Notification Center. Added account name to Google Voice account verification window. Upgraded PJSIP to 2.1 stable. Updated build scripts for PJSIP and FFmpeg for Mountain Lion and newer Xcode. Upgraded VoiceMob to current position in work. Probably too many changes to mention here. Changed version of VoiceMac to 0.3.

This commit is contained in:
GRMrGecko 2013-07-20 06:56:17 -05:00
parent 13b6d2ac02
commit 610dc8126f
117 changed files with 12348 additions and 4346 deletions

View File

@ -158,7 +158,7 @@ const int MGMCMaxResults = 10;
NSLog(@"Getting Contacts");
[updateConnection setLogQuery:YES];
#endif
[updateConnection query:@"CREATE VIRTUAL TABLE contacts USING fts3(name, company, number, label, photo)"];
[updateConnection query:@"CREATE VIRTUAL TABLE contacts USING fts3(name, company, number INTEGER, label, photo)"];
[updateConnection query:@"CREATE TABLE groups (docid INTEGER PRIMARY KEY AUTOINCREMENT, name)"];
[updateConnection query:@"CREATE TABLE groupMembers (docid INTEGER PRIMARY KEY AUTOINCREMENT, groupid INTEGER, contactid INTEGER)"];
[updateLock unlock];

View File

@ -56,20 +56,19 @@
while (1) {
NSRange rangeToCopy;
NSRange foundRange = [self rangeOfString:targetString options:0 range:rangeInOriginalString];
if (foundRange.length == 0) break;
if (foundRange.length==0) break;
rangeToCopy = NSMakeRange(rangeInOriginalString.location, foundRange.location - rangeInOriginalString.location);
[temp appendString:[self substringWithRange:rangeToCopy]];
[temp appendString:replaceString];
rangeInOriginalString.length -= NSMaxRange(foundRange) -
rangeInOriginalString.location;
rangeInOriginalString.length -= (NSMaxRange(foundRange)-rangeInOriginalString.location);
rangeInOriginalString.location = NSMaxRange(foundRange);
replaced++;
if (replaced % 100 == 0) {
if ((replaced%100)==0) {
[pool drain];
pool = [NSAutoreleasePool new];
}
}
if (rangeInOriginalString.length > 0) [temp appendString:[self substringWithRange:rangeInOriginalString]];
if (rangeInOriginalString.length>0) [temp appendString:[self substringWithRange:rangeInOriginalString]];
[pool drain];
return [temp autorelease];
@ -1309,13 +1308,10 @@
- (NSString *)addPercentEscapes {
NSString *result = [self stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR("!*'();:^@&=+$,/?%#[]|"), kCFStringEncodingUTF8);
if (escapedString) {
result = [NSString stringWithString:(NSString *)escapedString];
CFRelease(escapedString);
}
if (escapedString!=NULL)
result = [(NSString *)escapedString autorelease];
return result;
}

View File

@ -530,8 +530,18 @@ const BOOL MGMInstanceInvisible = YES;
[handler setFinish:@selector(indexDidFinish:)];
[handler setInvisible:MGMInstanceInvisible];
[connectionManager addHandler:handler];
} else {
NSString *string, *guser = @"", *phonesInfo = @"";
} else if ([[[[theHandler request] URL] relativeString] containsString:@"NewPrivacyPolicy"]) {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://accounts.google.com/b/0/NewPrivacyPolicy"]];
[request setHTTPMethod:MGMPostMethod];
[request setValue:MGMURLForm forHTTPHeaderField:MGMContentType];
[request setHTTPBody:[@"service=grandcentral&continue=https://www.google.com/voice&submitbutton=OK,%20got%20it" dataUsingEncoding:NSUTF8StringEncoding]];
MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:request delegate:self];
[handler setFailWithError:@selector(index:didFailWithError:)];
[handler setFinish:@selector(indexDidFinish:)];
[handler setInvisible:MGMInstanceInvisible];
[connectionManager addHandler:handler];
} else {
NSString *string, *guser = @"", *phonesInfo = @"";
NSRange range;
#if MGMInstanceDebug

View File

@ -69,9 +69,9 @@ extern const int MGMSIPAccountDefaultProxyPort;
NSString *lastError;
}
- (id)initWithSettings:(NSDictionary *)theSettings;
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain;
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress;
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress registrar:(NSString *)theRegistrar;
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar;
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress;
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress domain:(NSString *)theDomain;
- (BOOL)informationComplete;
- (id<MGMSIPAccountDelegate>)delegate;
- (void)setDelegate:(id)theDelegate;

View File

@ -44,16 +44,16 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300;
@implementation MGMSIPAccount
- (id)initWithSettings:(NSDictionary *)theSettings {
if ((self = [self init])) {
if ([theSettings objectForKey:MGMSIPAccountUserName]==nil || [[theSettings objectForKey:MGMSIPAccountUserName] isEqual:@""] || [theSettings objectForKey:MGMSIPAccountDomain]==nil || [[theSettings objectForKey:MGMSIPAccountDomain] isEqual:@""]) {
if ([theSettings objectForKey:MGMSIPAccountUserName]==nil || [[theSettings objectForKey:MGMSIPAccountUserName] isEqual:@""] || [theSettings objectForKey:MGMSIPAccountRegistrar]==nil || [[theSettings objectForKey:MGMSIPAccountRegistrar] isEqual:@""]) {
[self release];
self = nil;
} else {
if ([theSettings objectForKey:MGMSIPAccountFullName]!=nil && ![[theSettings objectForKey:MGMSIPAccountFullName] isEqual:@""])
fullName = [[theSettings objectForKey:MGMSIPAccountFullName] copy];
userName = [[theSettings objectForKey:MGMSIPAccountUserName] copy];
domain = [[theSettings objectForKey:MGMSIPAccountDomain] copy];
if ([theSettings objectForKey:MGMSIPAccountRegistrar]!=nil && ![[theSettings objectForKey:MGMSIPAccountRegistrar] isEqual:@""])
registrar = [[theSettings objectForKey:MGMSIPAccountRegistrar] copy];
registrar = [[theSettings objectForKey:MGMSIPAccountRegistrar] copy];
if ([theSettings objectForKey:MGMSIPAccountDomain]!=nil && ![[theSettings objectForKey:MGMSIPAccountDomain] isEqual:@""])
domain = [[theSettings objectForKey:MGMSIPAccountDomain] copy];
if ([theSettings objectForKey:MGMSIPAccountSIPAddress]!=nil && ![[theSettings objectForKey:MGMSIPAccountSIPAddress] isEqual:@""])
SIPAddress = [[theSettings objectForKey:MGMSIPAccountSIPAddress] copy];
if ([theSettings objectForKey:MGMSIPAccountProxy]!=nil && ![[theSettings objectForKey:MGMSIPAccountProxy] isEqual:@""])
@ -76,23 +76,23 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300;
}
return self;
}
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain {
return [self initWithFullName:theFullName userName:theUserName domain:theDomain SIPAddress:nil];
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar {
return [self initWithFullName:theFullName userName:theUserName registrar:theRegistrar SIPAddress:nil];
}
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress {
return [self initWithFullName:theFullName userName:theUserName domain:theDomain SIPAddress:theSIPAddress registrar:nil];
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress {
return [self initWithFullName:theFullName userName:theUserName registrar:theRegistrar SIPAddress:theSIPAddress domain:nil];
}
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName domain:(NSString *)theDomain SIPAddress:(NSString *)theSIPAddress registrar:(NSString *)theRegistrar {
if (theUserName==nil || theDomain==nil) return nil;
- (id)initWithFullName:(NSString *)theFullName userName:(NSString *)theUserName registrar:(NSString *)theRegistrar SIPAddress:(NSString *)theSIPAddress domain:(NSString *)theDomain {
if (theUserName==nil || theRegistrar==nil) return nil;
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
if (theFullName!=nil)
[settings setObject:theFullName forKey:MGMSIPAccountFullName];
[settings setObject:theUserName forKey:MGMSIPAccountUserName];
[settings setObject:theDomain forKey:MGMSIPAccountDomain];
[settings setObject:theRegistrar forKey:MGMSIPAccountRegistrar];
if (theSIPAddress!=nil)
[settings setObject:theSIPAddress forKey:MGMSIPAccountSIPAddress];
if (theRegistrar!=nil)
[settings setObject:theRegistrar forKey:MGMSIPAccountRegistrar];
if (theDomain!=nil)
[settings setObject:theDomain forKey:MGMSIPAccountDomain];
return [self initWithSettings:settings];
}
- (id)init {
@ -118,7 +118,7 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300;
}
- (BOOL)informationComplete {
return ((delegate!=nil && [delegate respondsToSelector:@selector(password)]) && userName!=nil && (domain!=nil || [self SIPAddress]!=nil));
return ((delegate!=nil && [delegate respondsToSelector:@selector(password)]) && userName!=nil && (registrar!=nil || [self SIPAddress]!=nil));
}
- (NSString *)description {
return [NSString stringWithFormat:@"%@ %@", [super description], [self SIPAddress]];
@ -145,6 +145,7 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300;
userName = [theUserName copy];
}
- (NSString *)domain {
if ((domain==nil || [domain isEqual:@""]) && registrar!=nil) return registrar;
return domain;
}
- (void)setDomain:(NSString *)theDomain {
@ -152,7 +153,6 @@ const int MGMSIPAccountReregisterTimeoutDefault = 300;
domain = [theDomain copy];
}
- (NSString *)registrar {
if (registrar==nil && domain!=nil) return domain;
return registrar;
}
- (void)setRegistrar:(NSString *)theRegistrar {

View File

@ -97,7 +97,7 @@ extern NSString * const MGMSAccountType;
//Step 6
- (IBAction)S6UserNameChanged:(id)sender;
- (IBAction)S6DomainChanged:(id)sender;
- (IBAction)S6RegistrarChanged:(id)sender;
- (void)S6Reset;
//Step 7

View File

@ -303,11 +303,11 @@ NSString * const MGMS7SIPWaiting = @"Waiting for Registration Status.";
- (IBAction)S6UserNameChanged:(id)sender {
[[S6FullNameField cell] setPlaceholderString:[S6UserNameField stringValue]];
}
- (IBAction)S6DomainChanged:(id)sender {
if ([[S6DomainField stringValue] isEqual:@""])
[[S6RegistrarField cell] setPlaceholderString:@""];
- (IBAction)S6RegistrarChanged:(id)sender {
if ([[S6RegistrarField stringValue] isEqual:@""])
[[S6DomainField cell] setPlaceholderString:@"Providers usually require *"];
else
[[S6RegistrarField cell] setPlaceholderString:[S6DomainField stringValue]];
[[S6DomainField cell] setPlaceholderString:[S6DomainField stringValue]];
}
- (void)S6Reset {
[S6FullNameField setStringValue:@""];

View File

@ -69,8 +69,9 @@ NSString * const MGMLoading = @"Loading...";
[defaults removeObjectForKey:MGMMakeDefault];
}
NSString *appVersion = [[MGMSystemInfo info] applicationVersion];
if ([defaults objectForKey:MGMVersion]==nil) {
[defaults setObject:[[MGMSystemInfo info] applicationVersion] forKey:MGMVersion];
[defaults setObject:appVersion forKey:MGMVersion];
[defaults removeObjectForKey:@"actionCall"];
[defaults removeObjectForKey:@"googleContact"];
[defaults removeObjectForKey:@"lastPhone"];
@ -85,6 +86,24 @@ NSString * const MGMLoading = @"Loading...";
[defaults removeObjectForKey:@"SMSThemePath"];
[defaults removeObjectForKey:@"SMSThemeVariant"];
}
#if MGMSIPENABLED
if (![[defaults objectForKey:MGMVersion] isEqual:@"0.3"]) {
[defaults setObject:appVersion forKey:MGMVersion];
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSArray *users = [MGMUser users];
for (int i=0; i<[users count]; i++) {
MGMUser *user = [MGMUser userWithID:[users objectAtIndex:i]];
if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) {
if ([user settingForKey:MGMSIPAccountRegistrar]==nil || [[user settingForKey:MGMSIPAccountRegistrar] isEqual:@""])
[user setSetting:[user settingForKey:MGMSIPAccountDomain] forKey:MGMSIPAccountRegistrar];
}
}
[pool drain];
}
#endif
if (![[defaults objectForKey:MGMVersion] isEqual:appVersion]) {
[defaults setObject:appVersion forKey:MGMVersion];
}
[self registerDefaults];
if ([defaults integerForKey:MGMLaunchCount]!=5) {
[defaults setInteger:[defaults integerForKey:MGMLaunchCount]+1 forKey:MGMLaunchCount];

View File

@ -25,6 +25,7 @@
MGMInstance *instance;
IBOutlet NSWindow *window;
IBOutlet NSTextField *accountNameField;
IBOutlet NSTextField *codeField;
}
+ (id)verifyWithInstance:(MGMInstance *)theInstance;

View File

@ -19,6 +19,7 @@
#import "MGMVoiceVerify.h"
#import <VoiceBase/VoiceBase.h>
#import <MGMUsers/MGMUsers.h>
@implementation MGMVoiceVerify
+ (id)verifyWithInstance:(MGMInstance *)theInstance {
@ -33,6 +34,7 @@
self = nil;
} else {
instance = theInstance;
[accountNameField setStringValue:[[instance user] settingForKey:MGMUserName]];
[window makeKeyAndOrderFront:self];
}
}

View File

@ -260,17 +260,17 @@ NSString * const MGMLogout = @"Logout";
[SIPFullNameField setStringValue:[user settingForKey:MGMSIPAccountFullName]];
else
[SIPFullNameField setStringValue:@""];
if ([user settingForKey:MGMSIPAccountDomain]==nil || [[user settingForKey:MGMSIPAccountDomain] isEqual:@""]) {
[[SIPRegistrarField cell] setPlaceholderString:@""];
[SIPDomainField setStringValue:@""];
} else {
[[SIPRegistrarField cell] setPlaceholderString:[user settingForKey:MGMSIPAccountDomain]];
if ([user settingForKey:MGMSIPAccountDomain]!=nil)
[SIPDomainField setStringValue:[user settingForKey:MGMSIPAccountDomain]];
}
if ([user settingForKey:MGMSIPAccountRegistrar]!=nil)
[SIPRegistrarField setStringValue:[user settingForKey:MGMSIPAccountRegistrar]];
else
[SIPDomainField setStringValue:@""];
if ([user settingForKey:MGMSIPAccountRegistrar]==nil || [[user settingForKey:MGMSIPAccountRegistrar] isEqual:@""]) {
[[SIPDomainField cell] setPlaceholderString:@"Usually *"];
[SIPRegistrarField setStringValue:@""];
} else {
[[SIPDomainField cell] setPlaceholderString:[user settingForKey:MGMSIPAccountRegistrar]];
[SIPRegistrarField setStringValue:[user settingForKey:MGMSIPAccountRegistrar]];
}
if ([user settingForKey:MGMSIPAccountUserName]!=nil)
[SIPUserNameField setStringValue:[user settingForKey:MGMSIPAccountUserName]];
else
@ -292,7 +292,7 @@ NSString * const MGMLogout = @"Logout";
[SIPSIPAddressField setStringValue:[user settingForKey:MGMSIPAccountSIPAddress]];
else
[SIPSIPAddressField setStringValue:@""];
[[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountDomain]]];
[[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountRegistrar]]];
if ([user settingForKey:MGMSIPAccountRegisterTimeout]!=nil && [[user settingForKey:MGMSIPAccountRegisterTimeout] intValue]!=0)
[SIPRegistrarTimeoutField setIntValue:[[user settingForKey:MGMSIPAccountRegisterTimeout] intValue]];
else
@ -368,17 +368,17 @@ NSString * const MGMLogout = @"Logout";
#if MGMSIPENABLED
MGMUser *user = [MGMUser userWithID:[[MGMUser users] objectAtIndex:[usersTable selectedRow]]];
[user setSetting:[SIPFullNameField stringValue] forKey:MGMSIPAccountFullName];
if ([[SIPDomainField stringValue] isEqual:@""]) {
[[SIPRegistrarField cell] setPlaceholderString:@""];
[user setSetting:@"" forKey:MGMSIPAccountDomain];
if ([[SIPRegistrarField stringValue] isEqual:@""]) {
[[SIPDomainField cell] setPlaceholderString:@"Usually *"];
[user setSetting:@"" forKey:MGMSIPAccountRegistrar];
} else {
[[SIPRegistrarField cell] setPlaceholderString:[SIPDomainField stringValue]];
[user setSetting:[SIPDomainField stringValue] forKey:MGMSIPAccountDomain];
[[SIPDomainField cell] setPlaceholderString:[SIPRegistrarField stringValue]];
[user setSetting:[SIPRegistrarField stringValue] forKey:MGMSIPAccountRegistrar];
}
if ([[SIPRegistrarField stringValue] isEqual:@""] && [[SIPDomainField stringValue] isEqual:@""])
NSBeep();
else
[user setSetting:[SIPRegistrarField stringValue] forKey:MGMSIPAccountRegistrar];
[user setSetting:[SIPDomainField stringValue] forKey:MGMSIPAccountDomain];
if ([[SIPUserNameField stringValue] isEqual:@""] || [[SIPPasswordField stringValue] isEqual:@""]) {
NSBeep();
if ([user settingForKey:MGMSIPAccountUserName]!=nil) {
@ -396,7 +396,7 @@ NSString * const MGMLogout = @"Logout";
[user setSetting:[SIPProxyHostField stringValue] forKey:MGMSIPAccountProxy];
[user setSetting:[NSNumber numberWithInt:[SIPProxyPortField intValue]] forKey:MGMSIPAccountProxyPort];
[user setSetting:[SIPSIPAddressField stringValue] forKey:MGMSIPAccountSIPAddress];
[[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountDomain]]];
[[SIPSIPAddressField cell] setPlaceholderString:[NSString stringWithFormat:@"%@@%@", [user settingForKey:MGMSIPAccountUserName], [user settingForKey:MGMSIPAccountRegistrar]]];
[user setSetting:[NSNumber numberWithInt:[SIPRegistrarTimeoutField intValue]] forKey:MGMSIPAccountRegisterTimeout];
[user setSetting:[NSNumber numberWithInt:[SIPTransportPopUp indexOfSelectedItem]] forKey:MGMSIPAccountTransport];
[user setSetting:[NSNumber numberWithInt:[SIPToneTypePopUp indexOfSelectedItem]] forKey:MGMSIPAccountDTMFToneType];

View File

@ -97,11 +97,13 @@
}
- (void)sendNotifications {
for (unsigned int i=[messages count]-1; i>=0; i--) {
for (unsigned int i=[messages count]-1;; i--) {
if (![[[messages objectAtIndex:i] objectForKey:MGMIYou] boolValue]) {
[GrowlApplicationBridge notifyWithTitle:[NSString stringWithFormat:@"SMS from %@", [messageInfo objectForKey:MGMTInName]] description:[[[messages objectAtIndex:i] objectForKey:MGMIText] flattenHTML] notificationName:@"SMS" iconData:[[instance contacts] photoDataForNumber:[messageInfo objectForKey:MGMIPhoneNumber]] priority:0 isSticky:NO clickContext:nil];
break;
}
if (i==0)
break;
}
}

View File

@ -29,7 +29,7 @@
}
- (void)addSubview:(NSView *)theView {
subview = theView;
subview = (NSView<MGMViewCellProtocol> *)theView;
}
- (NSView *)view {
return subview;

View File

@ -3,12 +3,12 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/27/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class MGMAccountController, MGMController, MGMAccounts, MGMUser;
@class MGMAccountController, MGMController, MGMAccounts, MGMSettings, MGMSound, MGMUser, MGMInstance;
@protocol MGMAccountProtocol <NSObject>
- (MGMAccountController *)accountController;
@ -18,28 +18,40 @@
- (UIView *)view;
- (void)releaseView;
@end
- (void)showOptionsForNumber:(NSString *)theNumber;
@end
@interface MGMAccountController : NSObject {
MGMController *controller;
NSMutableArray *contactsControllers;
int currentContactsController;
NSMutableDictionary *badgeValues;
MGMAccounts *accounts;
MGMSettings *settings;
MGMSound *soundPlayer;
IBOutlet UIView *view;
IBOutlet UIToolbar *toolbar;
NSArray *accountsItems;
NSArray *accountItems;
IBOutlet UILabel *titleField;
NSArray *settingsItems;
IBOutlet UIButton *phoneButton;
IBOutlet UIView *contentView;
BOOL shouldRefreshSounds;
}
- (id)initWithController:(MGMController *)theController;
- (void)registerDefaults;
- (MGMController *)controller;
- (NSArray *)contactsControllers;
- (id<MGMAccountProtocol>)contactControllerWithUser:(MGMUser *)theUser;
- (NSDictionary *)badgeValues;
- (int)badgeValueForInstance:(MGMInstance *)theInstance;
- (void)setBadge:(int)theBadge forInstance:(MGMInstance *)theInstance;
- (UIView *)view;
- (void)releaseView;
- (UIToolbar *)toolbar;
- (void)setItems:(NSArray *)theItems animated:(BOOL)isAnimated;
- (NSArray *)accountsItems;
@ -50,6 +62,12 @@
- (IBAction)showAccounts:(id)sender;
- (IBAction)showSettings:(id)sender;
- (NSString *)soundTitleForKey:(NSString *)theKey;
- (int)soundSectionForKey:(NSString *)theKey;
- (int)soundSettingRowForKey:(NSString *)theKey;
- (NSDictionary *)soundMenuWithSounds:(NSDictionary *)theSounds key:(NSString *)key;
- (void)showUser:(MGMUser *)theUser;
- (IBAction)phone:(id)sender;
@end

View File

@ -3,85 +3,75 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/27/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMAccounts.h"
#import "MGMGContactUser.h"
#import "MGMVoiceUser.h"
#import "MGMSIPUser.h"
#import "MGMPhotoSelector.h"
#import "MGMVMAddons.h"
#import "MGMAccountSetup.h"
#import "MGMConverter.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
NSString * const MGMLastContactsController = @"MGMLastContactsController";
NSString * const MGMAccountsTitle = @"Accounts";
NSString * const MGMBackTitle = @"Back";
NSString * const MGMLogInOut = @"MGMLogInOut";
NSString * const MGMLogin = @"Login";
NSString * const MGMLogout = @"Logout";
@implementation MGMAccountController
- (id)initWithController:(MGMController *)theController {
if (self = [super init]) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"AccountController"] owner:self options:nil]) {
NSLog(@"Unable to load Account Controller");
[self release];
self = nil;
} else {
controller = theController;
if ((self = [super init])) {
controller = theController;
[self registerDefaults];
[self registerDefaults];
contactsControllers = [NSMutableArray new];
NSArray *lastUsers = [MGMUser lastUsers];
for (int i=0; i<[lastUsers count]; i++) {
MGMUser *user = [MGMUser userWithID:[lastUsers objectAtIndex:i]];
if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) {
[contactsControllers addObject:[MGMVoiceUser voiceUser:user accountController:self]];
}
contactsControllers = [NSMutableArray new];
NSArray *lastUsers = [MGMUser lastUsers];
for (int i=0; i<[lastUsers count]; i++) {
MGMUser *user = [MGMUser userWithID:[lastUsers objectAtIndex:i]];
if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) {
[contactsControllers addObject:[MGMVoiceUser voiceUser:user accountController:self]];
}
#if MGMSIPENABLED
else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) {
if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start];
[contactsControllers addObject:[MGMSIPUser SIPUser:user accountController:self]];
}
else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) {
if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start];
[contactsControllers addObject:[MGMSIPUser SIPUser:user accountController:self]];
}
#endif
}
currentContactsController = [[NSUserDefaults standardUserDefaults] integerForKey:MGMLastContactsController];
accounts = [[MGMAccounts alloc] initWithAccountController:self];
accountsItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addAccount:)] autorelease], nil] retain];
accountItems = [[toolbar items] copy];
if ([contactsControllers count]==0 || currentContactsController==-1) {
[self setItems:accountsItems animated:NO];
[contentView addSubview:[accounts view]];
[self setTitle:MGMAccountsTitle];
} else {
id<MGMAccountProtocol> contactsController = [contactsControllers objectAtIndex:currentContactsController];
[self setItems:accountItems animated:NO];
[contentView addSubview:[contactsController view]];
[self setTitle:[contactsController title]];
}
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:@selector(userStarted:) name:MGMUserStartNotification object:nil];
[notificationCenter addObserver:self selector:@selector(userDone:) name:MGMUserDoneNotification object:nil];
}
currentContactsController = [[NSUserDefaults standardUserDefaults] integerForKey:MGMLastContactsController];
badgeValues = [NSMutableDictionary new];
accounts = [[MGMAccounts alloc] initWithAccountController:self];
shouldRefreshSounds = NO;
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:@selector(userStarted:) name:MGMUserStartNotification object:nil];
[notificationCenter addObserver:self selector:@selector(userDone:) name:MGMUserDoneNotification object:nil];
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (contactsControllers!=nil)
[contactsControllers release];
if (accounts!=nil)
[accounts release];
if (view!=nil)
[view release];
if (accountsItems!=nil)
[accountsItems release];
if (accountItems!=nil)
[accountItems release];
[self releaseView];
[contactsControllers release];
[badgeValues release];
[accounts release];
[accountsItems release];
[accountItems release];
[settingsItems release];
[super dealloc];
}
@ -94,9 +84,88 @@ NSString * const MGMAccountsTitle = @"Accounts";
- (MGMController *)controller {
return controller;
}
- (NSArray *)contactsControllers {
return contactsControllers;
}
- (id<MGMAccountProtocol>)contactControllerWithUser:(MGMUser *)theUser {
for (int i=0; i<[contactsControllers count]; i++) {
if ([[[contactsControllers objectAtIndex:i] user] isEqual:theUser])
return [contactsControllers objectAtIndex:i];
}
return nil;
}
- (NSDictionary *)badgeValues {
return badgeValues;
}
- (int)badgeValueForInstance:(MGMInstance *)theInstance {
return [[badgeValues objectForKey:[theInstance userNumber]] intValue];
}
- (void)setBadge:(int)theBadge forInstance:(MGMInstance *)theInstance {
if (![theInstance isLoggedIn]) return;
if (theBadge==0)
[badgeValues removeObjectForKey:[theInstance userNumber]];
else
[badgeValues setObject:[NSNumber numberWithInt:theBadge] forKey:[theInstance userNumber]];
NSArray *valueKeys = [badgeValues allKeys];
int value = 0;
for (int i=0; i<[valueKeys count]; i++)
value += [[badgeValues objectForKey:[valueKeys objectAtIndex:i]] intValue];
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:value];
if (currentContactsController==-1)
[(UITableView *)[accounts view] reloadData];
}
- (UIView *)view {
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"AccountController"] owner:self options:nil]) {
NSLog(@"Unable to load Account Controller");
} else {
accountsItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:self action:@selector(showSettings:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addAccount:)] autorelease], nil] retain];
accountItems = [[toolbar items] copy];
settingsItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:MGMBackTitle style:UIBarButtonItemStyleBordered target:self action:@selector(goBack:)] autorelease], nil] retain];
if ([contactsControllers count]==0 || currentContactsController==-1) {
[self setItems:accountsItems animated:NO];
CGRect viewFrame = [[accounts view] frame];
viewFrame.size = [contentView frame].size;
[[accounts view] setFrame:viewFrame];
[contentView addSubview:[accounts view]];
[self setTitle:MGMAccountsTitle];
} else {
id<MGMAccountProtocol> contactsController = [contactsControllers objectAtIndex:currentContactsController];
[self setItems:accountItems animated:NO];
CGRect viewFrame = [[contactsController view] frame];
viewFrame.size = [contentView frame].size;
[[contactsController view] setFrame:viewFrame];
[contentView addSubview:[contactsController view]];
[self setTitle:[contactsController title]];
}
}
}
return view;
}
- (void)releaseView {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
if (currentContactsController!=-1)
[[contactsControllers objectAtIndex:currentContactsController] releaseView];
[accounts releaseView];
[view release];
view = nil;
[toolbar release];
toolbar = nil;
[phoneButton release];
phoneButton = nil;
[contentView release];
contentView = nil;
[accountsItems release];
accountsItems = nil;
[accountItems release];
accountItems = nil;
[settingsItems release];
settingsItems = nil;
}
- (UIToolbar *)toolbar {
return toolbar;
}
@ -115,7 +184,7 @@ NSString * const MGMAccountsTitle = @"Accounts";
return ([contactsControllers indexOfObject:theUser]==currentContactsController);
}
- (void)setTitle:(NSString *)theTitle {
[titleField setText:theTitle];
[phoneButton setTitle:theTitle forState:UIControlStateNormal];
}
- (IBAction)addAccount:(id)sender {
@ -123,12 +192,17 @@ NSString * const MGMAccountsTitle = @"Accounts";
}
- (IBAction)showAccounts:(id)sender {
id contactsController = [contactsControllers objectAtIndex:currentContactsController];
currentContactsController = -1;
[[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController];
id contactsController = nil;
if (currentContactsController!=-1) {
contactsController = [contactsControllers objectAtIndex:currentContactsController];
currentContactsController = -1;
[[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController];
}
[self setItems:accountsItems animated:YES];
[self setTitle:MGMAccountsTitle];
CGRect outViewFrame = [[contactsController view] frame];
CGRect inViewFrame = [[accounts view] frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[[accounts view] setFrame:inViewFrame];
[contentView addSubview:[accounts view]];
@ -137,14 +211,560 @@ NSString * const MGMAccountsTitle = @"Accounts";
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(contactsControllerAnimationDidStop:finished:contactsController:)];
[[accounts view] setFrame:[[contactsController view] frame]];
CGRect outViewFrame = [[contactsController view] frame];
[[accounts view] setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[[contactsController view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (IBAction)showSettings:(id)sender {
settings = [[MGMSettings alloc] initWithDisplayView:contentView delegate:self];
if (currentContactsController==-1) {
NSMutableDictionary *settingsDic = [NSPropertyListSerialization propertyListFromData:[NSData dataWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"settings.plist"]] mutabilityOption:NSPropertyListMutableContainersAndLeaves format:nil errorDescription:nil];
NSMutableArray *allSettings = [[[settingsDic objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey];
NSMutableArray *soundSections = [[[allSettings objectAtIndex:0] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey];
NSDictionary *sounds = [[controller themeManager] sounds];
NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil];
for (int i=0; i<[rebuild count]; i++) {
[[[soundSections objectAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] objectForKey:MGMSObjectsKey] replaceObjectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]] withObject:[self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]]];
}
NSMutableArray *themesArray = [[[[[allSettings objectAtIndex:1] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey];
NSMutableArray *themesValue = [NSMutableArray array];
NSArray *themes = [[controller themeManager] themes];
for (int i=0; i<[themes count]; i++) {
[themesValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[themes objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [[[themes objectAtIndex:i] objectForKey:MGMTThemePath] lastPathComponent], MGMSValueKey, nil]];
}
[[themesArray objectAtIndex:0] setObject:themesValue forKey:MGMSValueKey];
NSDictionary *theme = [[controller themeManager] theme];
[[themesArray objectAtIndex:2] setObject:[theme objectForKey:MGMTAuthor] forKey:MGMSValueKey];
[[themesArray objectAtIndex:2] setObject:[theme objectForKey:MGMTSite] forKey:MGMSExtraKey];
NSArray *fonts = [UIFont familyNames];
fonts = [fonts sortedArrayUsingSelector:@selector(compare:)];
NSMutableArray *fontsValue = [NSMutableArray array];
for (int i=0; i<[fonts count]; i++) {
NSString *font = [fonts objectAtIndex:i];
NSArray *fontNames = [UIFont fontNamesForFamilyName:font];
for (int i=0; i<[fontNames count]; i++) {
NSString *fontName = [fontNames objectAtIndex:i];
NSArray *fontComponents = [fontName componentsSeparatedByString:@"-"];
NSString *name = font;
if ([fontComponents count]>=2)
name = [NSString stringWithFormat:@"%@ - %@", name, [fontComponents objectAtIndex:1]];
[fontsValue addObject:[NSDictionary dictionaryWithObjectsAndKeys:name, MGMSTitleKey, fontName, MGMSValueKey, nil]];
}
}
[[themesArray objectAtIndex:6] setObject:fontsValue forKey:MGMSValueKey];
NSArray *variants = [theme objectForKey:MGMTVariants];
NSMutableArray *varientsValue = [NSMutableArray array];
for (int i=0; i<[variants count]; i++) {
[varientsValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[variants objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [NSNumber numberWithInt:i], MGMSValueKey, nil]];
}
[[themesArray objectAtIndex:1] setObject:varientsValue forKey:MGMSValueKey];
NSMutableArray *sipSections = [[[allSettings objectAtIndex:2] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey];
NSArray *codecs = [[[MGMSIP sharedSIP] codecs] allKeys];
codecs = [codecs sortedArrayUsingSelector:@selector(compare:)];
NSMutableArray *codecsValue = [NSMutableArray array];
for (int i=0; i<[codecs count]; i++) {
NSString *codec = [codecs objectAtIndex:i];
[codecsValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:codec, MGMSTitleKey, codec, MGMSValueKey, nil]];
}
[[[[sipSections objectAtIndex:4] objectForKey:MGMSObjectsKey] objectAtIndex:2] setObject:codecsValue forKey:MGMSValueKey];
if (![[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom])
[[[[[[[[[sipSections objectAtIndex:1] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSObjectsKey] objectAtIndex:1] setObject:[NSNumber numberWithInt:MGMSOCheckMark] forKey:MGMSOptionsKey];
[settings setSections:[MGMSettingSections sectionsWithDictionary:settingsDic target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)]];
} else {
NSString *settingsFile = nil;
id<MGMAccountProtocol> account = [contactsControllers objectAtIndex:currentContactsController];
if ([account isKindOfClass:[MGMVoiceUser class]])
settingsFile = @"voicesettings.plist";
else if ([account isKindOfClass:[MGMSIPUser class]])
settingsFile = @"sipsettings.plist";
else if ([account isKindOfClass:[MGMGContactUser class]])
settingsFile = @"gcontactsettings.plist";
NSMutableDictionary *settingsDic = [NSPropertyListSerialization propertyListFromData:[NSData dataWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:settingsFile]] mutabilityOption:NSPropertyListMutableContainersAndLeaves format:nil errorDescription:nil];
NSMutableArray *objects = [settingsDic objectForKey:MGMSObjectsKey];
for (int i=0; i<[objects count]; i++) {
if ([[[[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSKeyKey] isEqual:MGMSContactsSourceKey]) {
NSMutableDictionary *contacts = [[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0];
[contacts removeObjectForKey:MGMSKeyKey];
NSMutableDictionary *extra = [NSMutableDictionary dictionaryWithObject:MGMSContactsSourceKey forKey:MGMSKeyKey];
if ([[[account user] settingForKey:MGMSContactsSourceKey] isEqual:NSStringFromClass([MGMAddressBook class])])
[extra setObject:[[account user] settingForKey:MGMSContactsSourceKey] forKey:MGMSValueKey];
else
[extra setObject:[[account user] settingForKey:MGMCGoogleContactsUser] forKey:MGMSValueKey];
[contacts setValue:extra forKey:MGMSExtraKey];
NSMutableArray *contactSources = [NSMutableArray array];
[contactSources addObject:[NSDictionary dictionaryWithObjectsAndKeys:NSStringFromClass([MGMAddressBook class]), MGMSValueKey, @"Address Book", MGMSTitleKey, nil]];
NSArray *users = [MGMUser users];
for (int i=0; i<[users count]; i++) {
MGMUser *gcUser = [MGMUser userWithID:[users objectAtIndex:i]];
if ([[gcUser settingForKey:MGMSAccountType] isEqual:MGMSGoogleContacts]) {
NSMutableDictionary *contactSource = [NSMutableDictionary dictionary];
[contactSource setObject:[gcUser settingForKey:MGMUserName] forKey:MGMSTitleKey];
[contactSource setObject:[gcUser settingForKey:MGMUserID] forKey:MGMSValueKey];
[contactSources addObject:contactSource];
}
}
[contacts setObject:contactSources forKey:MGMSValueKey];
} else if ([[[[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0] objectForKey:MGMSKeyKey] isEqual:MGMLogInOut]) {
NSMutableDictionary *logInOut = [[[objects objectAtIndex:i] objectForKey:MGMSObjectsKey] objectAtIndex:0];
if ([[account user] isStarted]) {
[logInOut setObject:MGMLogout forKey:MGMSTitleKey];
} else {
[logInOut setObject:MGMLogin forKey:MGMSTitleKey];
}
}
}
[settings setSections:[MGMSettingSections sectionsWithDictionary:settingsDic target:[account user] getter:@selector(settingForKey:) setter:@selector(setSetting:forKey:)]];
}
[self setItems:nil animated:YES];
[self setTitle:[settings title]];
CGRect outViewFrame = [((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) frame];
CGRect inViewFrame = [[settings view] frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[[settings view] setFrame:inViewFrame];
[contentView addSubview:[settings view]];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(showSettingsAnimationDidStop:finished:context:)];
[[settings view] setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) setFrame:outViewFrame];
[UIView commitAnimations];
}
- (NSString *)soundTitleForKey:(NSString *)theKey {
if ([theKey isEqual:MGMTSSMSMessage])
return @"SMS Message";
if ([theKey isEqual:MGMTSVoicemail])
return @"Voicemail";
if ([theKey isEqual:MGMTSSIPRingtone])
return @"Ringtone";
if ([theKey isEqual:MGMTSSIPHoldMusic])
return @"Hold Music";
if ([theKey isEqual:MGMTSSIPConnected])
return @"Connected";
if ([theKey isEqual:MGMTSSIPDisconnected])
return @"Disconnected";
if ([theKey isEqual:MGMTSSIPSound1])
return @"Sound 1";
if ([theKey isEqual:MGMTSSIPSound2])
return @"Sound 2";
if ([theKey isEqual:MGMTSSIPSound3])
return @"Sound 3";
if ([theKey isEqual:MGMTSSIPSound4])
return @"Sound 4";
if ([theKey isEqual:MGMTSSIPSound5])
return @"Sound 5";
return nil;
}
- (int)soundSectionForKey:(NSString *)theKey {
if ([theKey isEqual:MGMTSSMSMessage] || [theKey isEqual:MGMTSVoicemail])
return 0;
if ([theKey isEqual:MGMTSSIPRingtone] || [theKey isEqual:MGMTSSIPHoldMusic])
return 1;
if ([theKey isEqual:MGMTSSIPConnected] || [theKey isEqual:MGMTSSIPDisconnected])
return 2;
if ([theKey isEqual:MGMTSSIPSound1] || [theKey isEqual:MGMTSSIPSound2] || [theKey isEqual:MGMTSSIPSound3] || [theKey isEqual:MGMTSSIPSound4] || [theKey isEqual:MGMTSSIPSound5])
return 3;
return 0;
}
- (int)soundSettingRowForKey:(NSString *)theKey {
if ([theKey isEqual:MGMTSSMSMessage])
return 0;
if ([theKey isEqual:MGMTSVoicemail])
return 1;
if ([theKey isEqual:MGMTSSIPRingtone])
return 0;
if ([theKey isEqual:MGMTSSIPHoldMusic])
return 1;
if ([theKey isEqual:MGMTSSIPConnected])
return 0;
if ([theKey isEqual:MGMTSSIPDisconnected])
return 1;
if ([theKey isEqual:MGMTSSIPSound1])
return 0;
if ([theKey isEqual:MGMTSSIPSound2])
return 1;
if ([theKey isEqual:MGMTSSIPSound3])
return 2;
if ([theKey isEqual:MGMTSSIPSound4])
return 3;
if ([theKey isEqual:MGMTSSIPSound5])
return 4;
return 0;
}
- (NSDictionary *)soundMenuWithSounds:(NSDictionary *)theSounds key:(NSString *)key {
NSMutableDictionary *mainMenu = [NSMutableDictionary dictionary];
[mainMenu setObject:[self soundTitleForKey:key] forKey:MGMSTitleKey];
[mainMenu setObject:[NSNumber numberWithInt:MGMSTitleType] forKey:MGMSTypeKey];
NSString *soundPath = [[controller themeManager] currentSoundPath:key];
if ([soundPath isEqual:MGMTNoSound])
[mainMenu setObject:@"No Sound" forKey:MGMSValueKey];
NSArray *soundKeys = [theSounds allKeys];
NSMutableArray *soundsArray = [NSMutableArray array];
for (int i=0; i<[soundKeys count]; i++) {
NSArray *sounds = [theSounds objectForKey:[soundKeys objectAtIndex:i]];
NSMutableDictionary *sound = [NSMutableDictionary dictionary];
NSMutableDictionary *soundExtra = [NSMutableDictionary dictionary];
[sound setObject:[soundKeys objectAtIndex:i] forKey:MGMSTitleKey];
[soundExtra setObject:[[[sounds objectAtIndex:0] objectForKey:MGMTSPath] stringByDeletingLastPathComponent] forKey:MGMTSPath];
[sound setObject:[NSNumber numberWithInt:MGMSMultiType] forKey:MGMSTypeKey];
BOOL isCurrent = [[soundPath stringByDeletingLastPathComponent] isEqual:[soundExtra objectForKey:MGMTSPath]];
if (isCurrent)
[sound setObject:[MGMTSName stringByAppendingString:key] forKey:MGMSKeyKey];
else
[soundExtra setObject:[MGMTSName stringByAppendingString:key] forKey:MGMSKeyKey];
[sound setObject:soundExtra forKey:MGMSExtraKey];
if ([[soundKeys objectAtIndex:i] isEqual:@"Unknown"] || [[soundKeys objectAtIndex:i] isEqual:@"User Sounds"])
[sound setObject:[NSNumber numberWithInt:8] forKey:MGMSOptionsKey];
else if (![[soundKeys objectAtIndex:i] isEqual:@"System Sounds"] && ![[soundKeys objectAtIndex:i] isEqual:@"VoiceMob"])
[sound setObject:[NSNumber numberWithInt:4] forKey:MGMSOptionsKey];
NSMutableArray *soundArray = [NSMutableArray array];
for (int s=0; s<[sounds count]; s++) {
if (isCurrent && [[[sounds objectAtIndex:s] objectForKey:MGMTSPath] isEqual:soundPath])
[mainMenu setObject:[[sounds objectAtIndex:s] objectForKey:MGMTSName] forKey:MGMSValueKey];
NSMutableDictionary *soundDic = [NSMutableDictionary dictionary];
[soundDic setObject:[[sounds objectAtIndex:s] objectForKey:MGMTSName] forKey:MGMSTitleKey];
[soundDic setObject:[[[sounds objectAtIndex:s] objectForKey:MGMTSPath] lastPathComponent] forKey:MGMSValueKey];
[soundArray addObject:soundDic];
}
[sound setObject:soundArray forKey:MGMSValueKey];
[soundsArray addObject:sound];
}
NSDictionary *soundDicionary = [NSDictionary dictionaryWithObject:soundsArray forKey:MGMSObjectsKey];
NSMutableDictionary *noSoundDic = [NSMutableDictionary dictionary];
[noSoundDic setObject:@"No Sound" forKey:MGMSTitleKey];
[noSoundDic setObject:MGMTNoSound forKey:MGMSExtraKey];
[noSoundDic setObject:[MGMTSName stringByAppendingString:key] forKey:MGMSKeyKey];
[noSoundDic setObject:[NSNumber numberWithInt:MGMSNullType] forKey:MGMSTypeKey];
if ([soundPath isEqual:MGMTNoSound])
[noSoundDic setObject:[NSNumber numberWithInt:MGMSOCheckMark] forKey:MGMSOptionsKey];
NSDictionary *noSoundDicDicionary = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:noSoundDic] forKey:MGMSObjectsKey];
NSArray *soundObject = [NSArray arrayWithObjects:soundDicionary, noSoundDicDicionary, nil];
[mainMenu setObject:[NSDictionary dictionaryWithObjectsAndKeys:[self soundTitleForKey:key], MGMSTitleKey, soundObject, MGMSObjectsKey, nil] forKey:MGMSObjectsKey];
return mainMenu;
}
- (IBAction)goBack:(id)sender {
[soundPlayer stop];
[soundPlayer release];
soundPlayer = nil;
if (![settings goBack]) {
BOOL account = (currentContactsController!=-1 && [(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]);
if (!account)
[[accountsItems objectAtIndex:0] setEnabled:NO];
else
[[accountItems objectAtIndex:0] setEnabled:NO];
[self setItems:(!account ? accountsItems : accountItems) animated:YES];
if (!account)
[self setTitle:MGMAccountsTitle];
else
[self setTitle:[[contactsControllers objectAtIndex:currentContactsController] title]];
CGRect outViewFrame = [[settings view] frame];
CGRect inViewFrame = [(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) setFrame:inViewFrame];
[contentView addSubview:(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view])];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(hideSettingsAnimationDidStop:finished:context:)];
[(!account ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[[settings view] setFrame:outViewFrame];
[UIView commitAnimations];
}
}
- (void)settingsWillTransition {
[[settingsItems objectAtIndex:0] setEnabled:NO];
}
- (void)settingsDidTransition {
if ([settings parentTitle]!=nil)
[[settingsItems objectAtIndex:0] setTitle:[settings parentTitle]];
else
[[settingsItems objectAtIndex:0] setTitle:MGMBackTitle];
[[settingsItems objectAtIndex:0] setEnabled:YES];
if (shouldRefreshSounds) {
shouldRefreshSounds = NO;
NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil];
MGMSettingSections *sections = [[settings sections] parent];
NSDictionary *sounds = [[controller themeManager] sounds];
for (int i=0; i<[rebuild count]; i++) {
NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]];
MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)];
if ([settings sections]==[(MGMSettings *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] sections]) {
[(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setValue:[setting objectForKey:MGMSValueKey]];
[[settings sections] setSections:[settingSections sections]];
} else {
[(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections];
}
}
[(UITableView *)[settings view] reloadData];
}
[self setTitle:[settings title]];
}
- (void)setting:(MGMSetting *)theSetting changedToValue:(id)theValue forKey:(NSString *)theKey {
if ([theKey isEqual:MGMTCurrentThemeName] || [theKey isEqual:@"MGMTDownloader"]) {
if ([theKey isEqual:MGMTCurrentThemeName]) {
int index = 0;
for (int i=0; i<[[theSetting value] count]; i++) {
if ([[[[theSetting value] objectAtIndex:i] objectForKey:MGMSValueKey] isEqual:theValue]) {
index = i;
break;
}
}
[[controller themeManager] setTheme:[[[controller themeManager] themes] objectAtIndex:index]];
}
NSArray *themesArray = [[[settings sections] sectionAtIndex:0] settings];
NSMutableArray *themesValue = [NSMutableArray array];
NSArray *themes = [[controller themeManager] themes];
for (int i=0; i<[themes count]; i++) {
[themesValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[themes objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [[[themes objectAtIndex:i] objectForKey:MGMTThemePath] lastPathComponent], MGMSValueKey, nil]];
}
[(MGMSetting *)[themesArray objectAtIndex:0] setValue:themesValue];
NSDictionary *theme = [[controller themeManager] theme];
[(MGMSetting *)[themesArray objectAtIndex:2] setValue:[theme objectForKey:MGMTAuthor]];
NSArray *variants = [theme objectForKey:MGMTVariants];
NSMutableArray *varientsValue = [NSMutableArray array];
for (int i=0; i<[variants count]; i++) {
[varientsValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[variants objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [NSNumber numberWithInt:i], MGMSValueKey, nil]];
}
[(MGMSetting *)[themesArray objectAtIndex:1] setValue:varientsValue];
} else if ([theKey isEqual:MGMTCurrentThemeName] || [theKey isEqual:@"MGMSDownloader"]) {
NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil];
NSDictionary *sounds = [[controller themeManager] sounds];
for (int i=0; i<[rebuild count]; i++) {
NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]];
MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)];
[(MGMSetting *)[[[[settings sections] sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections];
}
} else if ([theKey hasPrefix:MGMTSName] || ([[theSetting extra] isKindOfClass:[NSDictionary class]] && [[[theSetting extra] objectForKey:MGMSKeyKey] hasPrefix:MGMTSName])) {
NSString *key = nil;
if (theKey!=nil)
key = theKey;
else
key = [[theSetting extra] objectForKey:MGMSKeyKey];
NSString *path = [[[theSetting extra] objectForKey:MGMTSPath] stringByAppendingPathComponent:theValue];
NSString *soundName = [key substringFromIndex:[MGMTSName length]];
[[controller themeManager] setSound:soundName withPath:path];
[soundPlayer stop];
[soundPlayer release];
soundPlayer = nil;
soundPlayer = [[controller themeManager] playSound:soundName];
[soundPlayer setDelegate:self];
#if MGMSIPENABLED
if ([soundName isEqual:MGMTSSIPHoldMusic] || [soundName isEqual:MGMTSSIPSound1] || [soundName isEqual:MGMTSSIPSound2] || [soundName isEqual:MGMTSSIPSound3] || [soundName isEqual:MGMTSSIPSound4] || [soundName isEqual:MGMTSSIPSound5])
[[MGMConverter alloc] initWithSound:soundName file:path];
#endif
NSDictionary *soundDic = [self soundMenuWithSounds:[[controller themeManager] sounds] key:soundName];
[(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[soundDic objectForKey:MGMSValueKey]];
MGMSettingSections *sections = [MGMSettingSections sectionsWithDictionary:[soundDic objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)];
[[settings sections] setSections:[sections sections]];
} else if ([[theSetting extra] isKindOfClass:[NSDictionary class]] && [[[theSetting extra] objectForKey:MGMSKeyKey] isEqual:MGMSContactsSourceKey]) {
if ([theValue isEqual:NSStringFromClass([MGMAddressBook class])]) {
NSString *key = MGMSContactsSourceKey;
NSMethodSignature *signature = [[theSetting target] methodSignatureForSelector:[theSetting action]];
if (signature!=nil) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:[theSetting action]];
[invocation setArgument:&theValue atIndex:2];
[invocation setArgument:&key atIndex:3];
[invocation invokeWithTarget:[theSetting target]];
}
} else {
NSString *key = MGMSContactsSourceKey;
NSString *value = NSStringFromClass([MGMGoogleContacts class]);
NSMethodSignature *signature = [[theSetting target] methodSignatureForSelector:[theSetting action]];
if (signature!=nil) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:[theSetting action]];
[invocation setArgument:&value atIndex:2];
[invocation setArgument:&key atIndex:3];
[invocation invokeWithTarget:[theSetting target]];
}
key = MGMCGoogleContactsUser;
signature = [[theSetting target] methodSignatureForSelector:[theSetting action]];
if (signature!=nil) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:[theSetting action]];
[invocation setArgument:&theValue atIndex:2];
[invocation setArgument:&key atIndex:3];
[invocation invokeWithTarget:[theSetting target]];
}
}
} else if ([[theSetting extra] isKindOfClass:[NSDictionary class]] && [[[theSetting extra] objectForKey:MGMSExtraKey] isEqual:@"MGMCustom"]) {
if ([[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom])
[[[[[settings sections] sectionAtIndex:0] settings] objectAtIndex:1] setOptions:0];
else
[[[[[settings sections] sectionAtIndex:0] settings] objectAtIndex:1] setOptions:MGMSOCheckMark];
}
}
- (void)soundDidFinishPlaying:(MGMSound *)theSound {
[soundPlayer release];
soundPlayer = nil;
}
- (void)didSelectSetting:(MGMSetting *)theSetting {
if ([[theSetting key] isEqual:@"MGMTAuthor"]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[theSetting extra]]];
} else if ([[theSetting extra] isEqual:MGMTNoSound]) {
NSString *soundName = [[theSetting key] substringFromIndex:[MGMTSName length]];
[[controller themeManager] setSound:soundName withPath:MGMTNoSound];
NSDictionary *soundDic = [self soundMenuWithSounds:[[controller themeManager] sounds] key:soundName];
[(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[soundDic objectForKey:MGMSValueKey]];
MGMSettingSections *sections = [MGMSettingSections sectionsWithDictionary:[soundDic objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)];
[[settings sections] setSections:[sections sections]];
[self goBack:self];
} else if ([[theSetting extra] isEqual:@"MGMDefault"]) {
[theSetting setOptions:MGMSOCheckMark];
[[NSUserDefaults standardUserDefaults] setObject:MGMSIPBDefault forKey:MGMSIPBackground];
[[NSFileManager defaultManager] removeItemAtPath:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground]];
[self goBack:self];
} else if ([[theSetting key] isEqual:MGMLogInOut]) {
id<MGMAccountProtocol> account = [[[contactsControllers objectAtIndex:currentContactsController] retain] autorelease];
MGMUser *user = [account user];
[contactsControllers removeObjectAtIndex:currentContactsController];
if ([user isStarted]) {
[user done];
[theSetting setTitle:MGMLogin];
id contactsController = nil;
if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) {
contactsController = [MGMVoiceUser voiceUser:user accountController:self];
[contactsControllers addObject:contactsController];
} else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSGoogleContacts]) {
contactsController = [MGMGContactUser gContactUser:user accountController:self];
[contactsControllers addObject:contactsController];
}
#if MGMSIPENABLED
else if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) {
if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start];
contactsController = [MGMSIPUser SIPUser:user accountController:self];
[contactsControllers addObject:contactsController];
}
#endif
} else {
[user start];
[theSetting setTitle:MGMLogout];
}
currentContactsController = [contactsControllers count]-1;
[(UITableView *)[settings view] reloadData];
}
}
- (void)settingDeleted:(MGMSetting *)theSetting {
NSString *key = [theSetting key];
if (key==nil)
key = [[theSetting extra] objectForKey:MGMSKeyKey];
NSString *path = [[theSetting extra] objectForKey:MGMTSPath];
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil];
MGMSettingSections *sections = [[settings sections] parent];
NSDictionary *sounds = [[controller themeManager] sounds];
for (int i=0; i<[rebuild count]; i++) {
NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]];
MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)];
if ([[MGMTSName stringByAppendingString:[rebuild objectAtIndex:i]] isEqual:key]) {
NSString *soundName = [[theSetting key] substringFromIndex:[MGMTSName length]];
[(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[setting objectForKey:MGMSValueKey]];
[[settings sections] setSections:[settingSections sections]];
} else {
[(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections];
}
}
}
- (void)settingDeleted:(MGMSetting *)theSetting value:(id)theValue {
if ([[theSetting key] isEqual:MGMTCurrentThemeName]) {
int index = 0;
for (int i=0; i<[[theSetting value] count]; i++) {
if ([[[[theSetting value] objectAtIndex:i] objectForKey:MGMSValueKey] isEqual:theValue]) {
index = i;
break;
}
}
NSString *path = [[[[controller themeManager] themes] objectAtIndex:index] objectForKey:MGMTThemePath];
if ([path rangeOfString:[[NSBundle mainBundle] resourcePath]].location!=NSNotFound) {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error Deleting"];
[alert setMessage:@"You cannot delete a built in theme."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
} else if ([([[theSetting extra] isKindOfClass:[NSDictionary class]] ? [[theSetting extra] objectForKey:MGMSValueKey] : [theSetting extra]) isEqual:theValue]) {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error Deleting"];
[alert setMessage:@"You cannot delete the current theme."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
} else {
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
NSMutableArray *themesValue = [NSMutableArray array];
NSArray *themes = [[controller themeManager] themes];
for (int i=0; i<[themes count]; i++) {
[themesValue addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:[[themes objectAtIndex:i] objectForKey:MGMTName], MGMSTitleKey, [[[themes objectAtIndex:i] objectForKey:MGMTThemePath] lastPathComponent], MGMSValueKey, nil]];
}
[theSetting setValue:themesValue];
}
} else {
NSString *key = [theSetting key];
if (key==nil)
key = [[theSetting extra] objectForKey:MGMSKeyKey];
NSString *path = [[[theSetting extra] objectForKey:MGMTSPath] stringByAppendingPathComponent:theValue];
[[NSFileManager defaultManager] removeItemAtPath:path error:nil];
if ([[theSetting value] count]==1) {
[self goBack:self];
shouldRefreshSounds = YES;
} else {
NSArray *rebuild = [NSArray arrayWithObjects:MGMTSSMSMessage, MGMTSVoicemail, MGMTSSIPRingtone, MGMTSSIPHoldMusic, MGMTSSIPConnected, MGMTSSIPDisconnected, MGMTSSIPSound1, MGMTSSIPSound2, MGMTSSIPSound3, MGMTSSIPSound4, MGMTSSIPSound5, nil];
MGMSettingSections *sections = [[settings sections] parent];
NSDictionary *sounds = [[controller themeManager] sounds];
for (int i=0; i<[rebuild count]; i++) {
NSDictionary *setting = [self soundMenuWithSounds:sounds key:[rebuild objectAtIndex:i]];
MGMSettingSections *settingSections = [MGMSettingSections sectionsWithDictionary:[setting objectForKey:MGMSObjectsKey] target:[NSUserDefaults standardUserDefaults] getter:@selector(objectForKey:) setter:@selector(setObject:forKey:)];
if ([[MGMTSName stringByAppendingString:[rebuild objectAtIndex:i]] isEqual:key]) {
NSString *soundName = [[theSetting key] substringFromIndex:[MGMTSName length]];
[(MGMSetting *)[[[[[settings sections] parent] sectionAtIndex:[self soundSectionForKey:soundName]] settings] objectAtIndex:[self soundSettingRowForKey:soundName]] setValue:[setting objectForKey:MGMSValueKey]];
[theSetting setValue:[[[[settingSections sectionAtIndex:0] settings] objectAtIndex:[[[[settings sections] sectionAtIndex:0] settings] indexOfObject:theSetting]] value]];
} else {
[(MGMSetting *)[[[sections sectionAtIndex:[self soundSectionForKey:[rebuild objectAtIndex:i]]] settings] objectAtIndex:[self soundSettingRowForKey:[rebuild objectAtIndex:i]]] setSections:settingSections];
}
}
}
}
}
- (void)showSettingsAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if ([settings parentTitle]!=nil)
[[settingsItems objectAtIndex:0] setTitle:[settings parentTitle]];
else
[[settingsItems objectAtIndex:0] setTitle:MGMBackTitle];
[self setItems:settingsItems animated:YES];
[((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? [accounts view] : [[contactsControllers objectAtIndex:currentContactsController] view]) removeFromSuperview];
[((currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) ? accounts : [contactsControllers objectAtIndex:currentContactsController]) releaseView];
}
- (void)hideSettingsAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[[settings view] removeFromSuperview];
[settings release];
settings = nil;
if (currentContactsController==-1 || ![(MGMUser *)[[contactsControllers objectAtIndex:currentContactsController] user] isStarted]) {
if (currentContactsController!=-1) {
[contactsControllers removeObjectAtIndex:currentContactsController];
currentContactsController = -1;
[[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController];
}
[[NSUserDefaults standardUserDefaults] synchronize];
[[accountsItems objectAtIndex:0] setEnabled:YES];
} else {
[[accountItems objectAtIndex:0] setEnabled:YES];
}
}
- (void)userStarted:(NSNotification *)theNotification {
@ -161,31 +781,16 @@ NSString * const MGMAccountsTitle = @"Accounts";
}
- (void)userDone:(NSNotification *)theNotification {
for (int i=0; i<[contactsControllers count]; i++) {
if ([[contactsControllers objectAtIndex:i] isKindOfClass:[MGMVoiceUser class]]) {
MGMVoiceUser *voiceUser = [contactsControllers objectAtIndex:i];
if ([[voiceUser user] isEqual:[theNotification object]]) {
if (currentContactsController==i) {
currentContactsController = -1;
[[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController];
} else {
[contactsControllers removeObject:voiceUser];
}
break;
id<MGMAccountProtocol> account = [contactsControllers objectAtIndex:i];
if ([[account user] isEqual:[theNotification object]]) {
if (currentContactsController==i) {
currentContactsController = -1;
[[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController];
} else {
[contactsControllers removeObject:account];
}
break;
}
#if MGMSIPENABLED
else if ([[contactsControllers objectAtIndex:i] isKindOfClass:[MGMSIPUser class]]) {
MGMSIPUser *SIPUser = [contactsControllers objectAtIndex:i];
if ([[SIPUser user] isEqual:[theNotification object]]) {
if (currentContactsController==i) {
currentContactsController = -1;
[[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController];
} else {
[contactsControllers removeObject:SIPUser];
}
}
}
#endif
}
}
@ -201,45 +806,60 @@ NSString * const MGMAccountsTitle = @"Accounts";
if ([[theUser settingForKey:MGMSAccountType] isEqual:MGMSGoogleVoice]) {
contactsController = [MGMVoiceUser voiceUser:theUser accountController:self];
[contactsControllers addObject:contactsController];
} else if ([[theUser settingForKey:MGMSAccountType] isEqual:MGMSGoogleContacts]) {
contactsController = [MGMGContactUser gContactUser:theUser accountController:self];
[contactsControllers addObject:contactsController];
}
#if MGMSIPENABLED
else if ([[theUser settingForKey:MGMSAccountType] isEqual:MGMSSIP]) {
NSLog(@"Hello");
if (![[MGMSIP sharedSIP] isStarted]) [[MGMSIP sharedSIP] start];
contactsController = [MGMSIPUser SIPUser:theUser accountController:self];
[contactsControllers addObject:contactsController];
}
#endif
}
if ([theUser isStarted]) {
currentContactsController = [contactsControllers indexOfObject:contactsController];
if (contactsController==nil)
return;
currentContactsController = [contactsControllers indexOfObject:contactsController];
if (![theUser isStarted]) {
[self showSettings:self];
} else if ([contactsController view]!=nil) {
[[NSUserDefaults standardUserDefaults] setInteger:currentContactsController forKey:MGMLastContactsController];
}
[self setItems:nil animated:YES];
[self setTitle:[contactsController title]];
CGRect inViewFrame = [[contactsController view] frame];
inViewFrame.origin.x = +inViewFrame.size.width;
[[contactsController view] setFrame:inViewFrame];
[contentView addSubview:[contactsController view]];
[UIView beginAnimations:nil context:accounts];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(contactsControllerAnimationDidStop:finished:contactsController:)];
[[contactsController view] setFrame:[[accounts view] frame]];
CGRect outViewFrame = [[accounts view] frame];
outViewFrame.origin.x = -outViewFrame.size.width;
[[accounts view] setFrame:outViewFrame];
[UIView commitAnimations];
[self setItems:nil animated:YES];
[self setTitle:[contactsController title]];
CGRect outViewFrame = [[accounts view] frame];
CGRect inViewFrame = [[contactsController view] frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[[contactsController view] setFrame:inViewFrame];
[contentView addSubview:[contactsController view]];
[UIView beginAnimations:nil context:accounts];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(contactsControllerAnimationDidStop:finished:contactsController:)];
[[contactsController view] setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[[accounts view] setFrame:outViewFrame];
[UIView commitAnimations];
}
}
- (void)contactsControllerAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished contactsController:(id<MGMAccountProtocol>)theContactsController {
[[theContactsController view] removeFromSuperview];
[theContactsController releaseView];
if ([theContactsController isKindOfClass:[MGMAccounts class]]) {
[self setItems:accountItems animated:YES];
} else {
if (![[theContactsController user] isStarted])
[contactsControllers removeObject:theContactsController];
}
}
- (IBAction)phone:(id)sender {
if (currentContactsController!=-1) {
id contactsController = [contactsControllers objectAtIndex:currentContactsController];
if (![[phoneButton titleForState:UIControlStateNormal] isEqual:[contactsController title]] && [[phoneButton titleForState:UIControlStateNormal] isPhone])
[contactsController showOptionsForNumber:[[phoneButton titleForState:UIControlStateNormal] phoneFormatWithAreaCode:[contactsController areaCode]]];
}
}
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@ -22,8 +22,6 @@ extern NSString * const MGMSIPDefaultDomain;
BOOL setupOnly;
IBOutlet UIView *setupView;
CGRect setupRect;
CGRect setupKeyboardRect;
IBOutlet UIView *view;
IBOutlet UILabel *titleField;
IBOutlet UIBarButtonItem *backButton;
@ -77,6 +75,8 @@ extern NSString * const MGMSIPDefaultDomain;
IBOutlet UILabel *S7StatusField;
MGMUser *S7CheckUser;
MGMInstance *S7CheckInstance;
UIAlertView *S7VerificationView;
UITextField *S7VerificationField;
MGMURLConnectionManager *S7ConnectionManager;
#if MGMSIPENABLED
MGMSIPAccount *S7CheckSIPAccount;
@ -115,8 +115,6 @@ extern NSString * const MGMSIPDefaultDomain;
- (void)S5Reset;
//Step 6
- (IBAction)S6ShowKeyboard:(id)sender;
- (IBAction)S6CloseKeyboard:(id)sender;
- (IBAction)S6UserNameChanged:(id)sender;
- (IBAction)S6DomainChanged:(id)sender;
- (void)S6Reset;

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMAccountSetup.h"
@ -33,9 +33,11 @@ NSString * const MGMS7SIPWaiting = @"Waiting for Registration Status.";
NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
NSString * const MGMASKeyboardBounds = @"UIKeyboardBoundsUserInfoKey";
@implementation MGMAccountSetup
- (id)initWithController:(MGMController *)theController {
if (self = [super init]) {
if ((self = [super init])) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"AccountSetup"] owner:self options:nil]) {
NSLog(@"Unable to load Account Setup");
[self release];
@ -50,48 +52,60 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
accountType = 0;
accountsCreated = [NSMutableArray new];
S7ConnectionManager = [[MGMURLConnectionManager managerWithCookieStorage:nil] retain];
setupRect = [setupView frame];
setupKeyboardRect = setupRect;
setupKeyboardRect.origin.y = (-(setupKeyboardRect.size.height-45))+246;
NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter];
[notifications addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[notifications addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
}
return self;
}
- (void)dealloc {
if (setupView!=nil)
[setupView release];
if (S1View!=nil)
[S1View release];
if (S2View!=nil)
[S2View release];
if (S3View!=nil)
[S3View release];
if (S4View!=nil)
[S4View release];
if (S5View!=nil)
[S5View release];
if (S6View!=nil)
[S6View release];
if (S7View!=nil)
[S7View release];
if (S8View!=nil)
[S8View release];
if (S9View!=nil)
[S9View release];
if (accountsCreated!=nil)
[accountsCreated release];
if (S7CheckUser!=nil)
[S7CheckUser release];
if (S7CheckInstance!=nil)
[S7CheckInstance release];
if (S7ConnectionManager!=nil)
[S7ConnectionManager release];
#if MGMSIPENABLED
if (S7CheckSIPAccount!=nil)
[S7CheckSIPAccount release];
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
if (S8Message!=nil)
[S8Message release];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[setupView release];
[view release];
[titleField release];
[backButton release];
[continueButton release];
[S1View release];
[S2View release];
[S2GVButton release];
[S2GCButton release];
[S2SIPButton release];
[S3View release];
[S3Browser release];
[S4View release];
[S4EmailField release];
[S4PasswordField release];
[S5View release];
[S5EmailField release];
[S5PasswordField release];
[S6View release];
[S6FullNameField release];
[S6DomainField release];
[S6RegistrarField release];
[S6UserNameField release];
[S6PasswordField release];
[S7View release];
[S7Progress release];
[S7StatusField release];
[S7CheckUser release];
[S7CheckInstance release];
[S7ConnectionManager release];
#if MGMSIPENABLED
[S7CheckSIPAccount release];
[S7SIPRegistrationTimeout invalidate];
[S7SIPRegistrationTimeout release];
#endif
[S8View release];
[S8MessageField release];
[S8Message release];
[S9View release];
[S9MessageField release];
[accountsCreated release];
[super dealloc];
}
@ -104,6 +118,42 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
- (IBAction)closeKeyboard:(id)sender {
}
- (void)keyboardWillShow:(NSNotification *)theNotification {
if (step!=6) return;
CGSize keyboardSize = CGSizeZero;
if ([[theNotification userInfo] objectForKey:MGMASKeyboardBounds]!=nil)
keyboardSize = [[[theNotification userInfo] objectForKey:MGMASKeyboardBounds] CGRectValue].size;
else
keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect setupRect = [setupView frame];
setupRect.origin.y = (-keyboardSize.height)+44;
if (!CGRectEqualToRect([setupView frame], setupRect)) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[setupView setFrame:setupRect];
[UIView commitAnimations];
}
}
- (void)keyboardWillHide:(NSNotification *)theNotification {
if (step!=6) return;
CGSize keyboardSize = CGSizeZero;
if ([[theNotification userInfo] objectForKey:MGMASKeyboardBounds]!=nil)
keyboardSize = [[[theNotification userInfo] objectForKey:MGMASKeyboardBounds] CGRectValue].size;
else
keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect setupRect = [setupView frame];
setupRect.origin.y = 0;
if (!CGRectEqualToRect([setupView frame], setupRect)) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[setupView setFrame:setupRect];
[UIView commitAnimations];
}
}
- (void)setSetupOnly:(BOOL)isSetupOnly {
setupOnly = isSetupOnly;
@ -203,11 +253,17 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
[backButton setEnabled:YES];
[continueButton setTitle:MGMSContinue];
[continueButton setEnabled:NO];
<<<<<<< HEAD
[S8MessageField setText:[NSString stringWithFormat:@"Unable to set up your %@ account, the error we receviced was \"%@\" Please go back and correct the problem.", type, S8Message]];
[S8Message release];
S8Message = nil;
=======
[S8MessageField setText:[NSString stringWithFormat:@"Unable to set up your %@ account, the error we received was \"%@\" Please go back and correct the problem.", type, S8Message]];
if (S8Message!=nil) {
[S8Message release];
S8Message = nil;
}
>>>>>>> 13b6d2ac024f36826fdb6cd6dcb05710e133e842
break;
}
case 9: {
@ -239,7 +295,9 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
[continueButton setEnabled:NO];
displaying = YES;
if (goingBack) {
CGRect outViewFrame = [lastView frame];
CGRect inViewFrame = [nextView frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[nextView setFrame:inViewFrame];
[view addSubview:nextView];
@ -248,13 +306,14 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(displayAnimationDidStop:finished:context:)];
[nextView setFrame:[lastView frame]];
CGRect outViewFrame = [lastView frame];
[nextView setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[lastView setFrame:outViewFrame];
[UIView commitAnimations];
} else {
CGRect outViewFrame = [lastView frame];
CGRect inViewFrame = [nextView frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[nextView setFrame:inViewFrame];
[view addSubview:nextView];
@ -263,8 +322,7 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(displayAnimationDidStop:finished:context:)];
[nextView setFrame:[lastView frame]];
CGRect outViewFrame = [lastView frame];
[nextView setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[lastView setFrame:outViewFrame];
[UIView commitAnimations];
@ -334,11 +392,11 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
#if MGMSIPENABLED
step = 6;
#else
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Unable to Add Account"];
[theAlert setMessage:@"MGMSIP is not compiled with VoiceMob, you can not add a SIP account without first compiling with MGMSIP."];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Unable to Add Account"];
[alert setMessage:@"MGMSIP is not compiled with VoiceMob, you can not add a SIP account without first compiling with MGMSIP."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
return;
#endif
break;
@ -363,11 +421,11 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
emptyFields = YES;
}
if (emptyFields) {
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Missing Information"];
[theAlert setMessage:@"It appears as if you did not fill the required fields, please fill out the required fields and then continue."];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Missing Information"];
[alert setMessage:@"It appears as if you did not fill the required fields, please fill out the required fields and then continue."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
return;
}
step = 7;
@ -412,22 +470,6 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
}
//Step 6
- (IBAction)S6ShowKeyboard:(id)sender {
if (CGRectEqualToRect([setupView frame], setupRect)) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[setupView setFrame:setupKeyboardRect];
[UIView commitAnimations];
}
}
- (IBAction)S6CloseKeyboard:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[setupView setFrame:setupRect];
[UIView commitAnimations];
}
- (IBAction)S6UserNameChanged:(id)sender {
[S6FullNameField setPlaceholder:[S6UserNameField text]];
}
@ -453,21 +495,51 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
S7CheckInstance = [[MGMInstance instanceWithUser:S7CheckUser delegate:self isCheck:YES] retain];
}
- (void)loginError:(NSError *)theError {
if (S7CheckUser!=nil) {
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
}
if (S7CheckInstance!=nil) {
[S7CheckInstance release];
S7CheckInstance = nil;
}
[S7VerificationView release];
S7VerificationView = nil;
[S7VerificationField release];
S7VerificationField = nil;
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
[S7CheckInstance release];
S7CheckInstance = nil;
NSLog(@"Login Failed %@", theError);
S8Message = [[theError localizedDescription] copy];
step = 8;
[self displayStep];
}
- (void)loginVerificationRequested {
[S7VerificationView release];
S7VerificationView = [UIAlertView new];
[S7VerificationView setTitle:@"Account Verification"];
[S7VerificationView setMessage:@" "];
[S7VerificationView addButtonWithTitle:@"Cancel"];
[S7VerificationView addButtonWithTitle:@"Verify"];
[S7VerificationView setCancelButtonIndex:1];
[S7VerificationView setDelegate:self];
[S7VerificationField release];
S7VerificationField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)];
[S7VerificationField setBorderStyle:UITextBorderStyleLine];
[S7VerificationField setBackgroundColor:[UIColor whiteColor]];
[S7VerificationField setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
[S7VerificationView addSubview:S7VerificationField];
[S7VerificationView show];
[S7VerificationField becomeFirstResponder];
}
- (void)alertView:(UIAlertView *)theAlertView clickedButtonAtIndex:(NSInteger)theIndex {
if (theAlertView==S7VerificationView) {
if (theIndex==1)
[S7CheckInstance verifyWithCode:[S7VerificationField text]];
else
[S7CheckInstance cancelVerification];
}
}
- (void)loginSuccessful {
[S7VerificationView release];
S7VerificationView = nil;
[S7VerificationField release];
S7VerificationField = nil;
if (S7CheckUser!=nil) {
[accountsCreated addObject:S7CheckUser];
MGMUser *contactsUser = [MGMUser createUserWithName:[S4EmailField text] password:[S4PasswordField text]];
@ -476,10 +548,8 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
[S7CheckUser release];
S7CheckUser = nil;
}
if (S7CheckInstance!=nil) {
[S7CheckInstance release];
S7CheckInstance = nil;
}
[S7CheckInstance release];
S7CheckInstance = nil;
[self S4Reset];
step = 9;
[self displayStep];
@ -494,44 +564,41 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
NSURLCredential *credentials = [NSURLCredential credentialWithUser:username password:[S7CheckUser password] persistence:NSURLCredentialPersistenceForSession];
[S7ConnectionManager setCookieStorage:[S7CheckUser cookieStorage]];
[S7ConnectionManager setCredentials:credentials];
[S7ConnectionManager setCustomUseragent:MGMGCUseragent];
[S7ConnectionManager setUserAgent:MGMGCUseragent];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:MGMGCAuthenticationURL] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0];
[request setHTTPMethod:MGMPostMethod];
[request setValue:MGMURLForm forHTTPHeaderField:MGMContentType];
[request setHTTPBody:[[NSString stringWithFormat:MGMGCAuthenticationBody, [username addPercentEscapes], [[S7CheckUser password] addPercentEscapes]] dataUsingEncoding:NSUTF8StringEncoding]];
[S7ConnectionManager connectionWithRequest:request delegate:self didFailWithError:@selector(authentication:didFailWithError:) didFinish:@selector(authenticationDidFinish:) invisible:NO object:nil];
MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:request delegate:self];
[handler setFailWithError:@selector(authentication:didFailWithError:)];
[handler setFinish:@selector(authenticationDidFinish:)];
[S7ConnectionManager addHandler:handler];
}
- (void)authentication:(NSDictionary *)theInfo didFailWithError:(NSError *)theError {
if (S7CheckUser!=nil) {
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
}
if (S7ConnectionManager!=nil)
[S7ConnectionManager setCookieStorage:nil];
- (void)authentication:(MGMURLBasicHandler *)theHandler didFailWithError:(NSError *)theError {
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
[S7ConnectionManager setCookieStorage:nil];
NSLog(@"Login Failed %@", theError);
S8Message = [[theError localizedDescription] copy];
step = 8;
[self displayStep];
}
- (void)authenticationDidFinish:(NSDictionary *)theInfo {
NSDictionary *info = [MGMGoogleContacts dictionaryWithData:[theInfo objectForKey:MGMConnectionData]];
if (S7ConnectionManager!=nil)
[S7ConnectionManager setCookieStorage:nil];
if (S7CheckUser!=nil) {
if ([info objectForKey:@"Error"]!=nil) {
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
S8Message = [@"Unable to login. Please check your Credentials." retain];
step = 8;
[self displayStep];
return;
}
[S7CheckUser done];
- (void)authenticationDidFinish:(MGMURLBasicHandler *)theHandler {
NSDictionary *info = [MGMGoogleContacts dictionaryWithString:[theHandler string]];
[S7ConnectionManager setCookieStorage:nil];
if ([info objectForKey:@"Error"]!=nil) {
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
S8Message = [@"Unable to login. Please check your Credentials." retain];
step = 8;
[self displayStep];
return;
}
[S7CheckUser done];
[S7CheckUser release];
S7CheckUser = nil;
[self S5Reset];
step = 9;
@ -557,6 +624,7 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
if (![[S6RegistrarField text] isEqual:@""])
[S7CheckUser setSetting:[S6RegistrarField text] forKey:MGMSIPAccountRegistrar];
S7CheckSIPAccount = [[MGMSIPAccount alloc] initWithSettings:[S7CheckUser settings]];
[S7CheckUser registerSettings:[S7CheckSIPAccount settings]];
[S7CheckSIPAccount setDelegate:self];
S7AccountRegistered = NO;
NSLog(@"Logging in");
@ -567,23 +635,22 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
return [S7CheckUser password];
}
- (void)registrationChanged {
[self performSelector:@selector(S7RegistrationChanged) withObject:nil afterDelay:0.5];
}
- (void)S7RegistrationChanged {
#if MGMSIPENABLED
if (S7SIPRegistrationTimeout!=nil) {
[S7SIPRegistrationTimeout invalidate];
[S7SIPRegistrationTimeout release];
S7SIPRegistrationTimeout = nil;
}
if (S7CheckSIPAccount!=nil) {
if (![S7CheckSIPAccount isRegistered]) {
[S7CheckSIPAccount setLastError:@"Unable to Register with Server. Please check your credentials."];
[self loginErrored];
return;
}
[S7CheckSIPAccount setDelegate:nil];
[S7CheckSIPAccount logout];
[S7CheckSIPAccount release];
S7CheckSIPAccount = nil;
[S7SIPRegistrationTimeout invalidate];
[S7SIPRegistrationTimeout release];
S7SIPRegistrationTimeout = nil;
if (![S7CheckSIPAccount isRegistered]) {
[S7CheckSIPAccount setLastError:@"Unable to Register with Server. Please check your credentials."];
[self loginErrored];
return;
}
[S7CheckSIPAccount setDelegate:nil];
[S7CheckSIPAccount logout];
[S7CheckSIPAccount release];
S7CheckSIPAccount = nil;
if (S7CheckUser!=nil) {
[accountsCreated addObject:S7CheckUser];
[S7CheckUser release];
@ -592,16 +659,14 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
[self S6Reset];
S7AccountRegistered = YES;
step = 9;
[self performSelectorOnMainThread:@selector(displayStep) withObject:nil waitUntilDone:NO];
[self displayStep];
#endif
}
#if MGMSIPENABLED
- (void)S7SIPTimeout {
if (S7SIPRegistrationTimeout!=nil) {
[S7SIPRegistrationTimeout invalidate];
[S7SIPRegistrationTimeout release];
S7SIPRegistrationTimeout = nil;
}
[S7SIPRegistrationTimeout invalidate];
[S7SIPRegistrationTimeout release];
S7SIPRegistrationTimeout = nil;
[S7CheckSIPAccount setLastError:@"Registration Timeout."];
[self loginErrored];
}
@ -614,19 +679,15 @@ NSString * const MGMSIPDefaultDomain = @"proxy01.sipphone.com";
S7SIPRegistrationTimeout = [[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(S7SIPTimeout) userInfo:nil repeats:NO] retain];
}
- (void)loginErrored {
if (S7CheckUser!=nil) {
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
}
if (S7CheckSIPAccount!=nil) {
NSLog(@"Login Failed %@", [S7CheckSIPAccount lastError]);
S8Message = [[S7CheckSIPAccount lastError] copy];
[S7CheckSIPAccount setDelegate:nil];
[S7CheckSIPAccount logout];
[S7CheckSIPAccount release];
S7CheckSIPAccount = nil;
}
[S7CheckUser remove];
[S7CheckUser release];
S7CheckUser = nil;
NSLog(@"Login Failed %@", [S7CheckSIPAccount lastError]);
S8Message = [[S7CheckSIPAccount lastError] copy];
[S7CheckSIPAccount setDelegate:nil];
[S7CheckSIPAccount logout];
[S7CheckSIPAccount release];
S7CheckSIPAccount = nil;
step = 8;
[self performSelectorOnMainThread:@selector(displayStep) withObject:nil waitUntilDone:NO];
}

View File

@ -3,10 +3,10 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/27/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class MGMAccountController;

View File

@ -3,12 +3,14 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/27/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMAccounts.h"
#import "MGMAccountController.h"
#import "MGMBadgeView.h"
#import "MGMAccountSetup.h"
#import "MGMVoiceUser.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
@ -17,12 +19,15 @@ NSString * const MGMAccountCellIdentifier = @"MGMAccountCellIdentifier";
@implementation MGMAccounts
- (id)initWithAccountController:(MGMAccountController *)theAccountController {
if (self = [super init]) {
if ((self = [super init])) {
accountController = theAccountController;
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[super dealloc];
}
@ -31,8 +36,6 @@ NSString * const MGMAccountCellIdentifier = @"MGMAccountCellIdentifier";
if (tableView==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"Accounts"] owner:self options:nil]) {
NSLog(@"Unable to load Accounts");
[self release];
self = nil;
} else {
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:tableView selector:@selector(reloadData) name:MGMUserStartNotification object:nil];
@ -42,32 +45,45 @@ NSString * const MGMAccountCellIdentifier = @"MGMAccountCellIdentifier";
return tableView;
}
- (void)releaseView {
if (tableView!=nil) {
[tableView release];
tableView = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[tableView release];
tableView = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section {
return [[MGMUser users] count];
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MGMAccountCellIdentifier];
MGMBadgeView *cell = (MGMBadgeView *)[tableView dequeueReusableCellWithIdentifier:MGMAccountCellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMAccountCellIdentifier] autorelease];
cell = [[[MGMBadgeView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMAccountCellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
NSArray *users = [MGMUser users];
if ([users count]<=[indexPath indexAtPosition:1]) {
[cell setText:@"Unknown"];
[cell setName:@"Unknown"];
} else {
[cell setText:[[MGMUser userNames] objectAtIndex:[indexPath indexAtPosition:1]]];
[cell setName:[[MGMUser userNames] objectAtIndex:[indexPath indexAtPosition:1]]];
MGMUser *user = [MGMUser userWithID:[users objectAtIndex:[indexPath indexAtPosition:1]]];
id<MGMAccountProtocol> account = [accountController contactControllerWithUser:user];
if ([account isKindOfClass:[MGMVoiceUser class]]) {
int count = [accountController badgeValueForInstance:[(MGMVoiceUser *)account instance]];
if (count!=0)
[cell setBadge:[[NSNumber numberWithInt:count] stringValue]];
else
[cell setBadge:nil];
} else {
[cell setBadge:nil];
}
#if MGMSPENABLED
if ([[user settingForKey:MGMSAccountType] isEqual:MGMSSIP]) {
if ([user settingForKey:MGMSIPAccountFullName]!=nil && ![[user settingForKey:MGMSIPAccountFullName] isEqual:@""])
[cell setText:[user settingForKey:MGMSIPAccountFullName]];
[cell setName:[user settingForKey:MGMSIPAccountFullName]];
}
#endif
}
return cell;
}

View File

@ -3,14 +3,14 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@class MGMAccountController, MGMContacts;
@interface MGMContactsController : NSObject {
@interface MGMContactsController : NSObject <UITableViewDelegate, UITableViewDataSource> {
MGMAccountController *accountController;
IBOutlet UISearchBar *searchBar;
@ -29,6 +29,7 @@
- (void)awakeFromNib;
- (void)releaseView;
- (void)cleanup;
- (MGMContacts *)contacts;
- (NSString *)filterString;

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMContactsController.h"
@ -15,10 +15,8 @@
NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier";
@implementation MGMContactsController
- (id)initWithAccountController:(MGMAccountController *)theAccountController {
if (self = [super init]) {
accountController = theAccountController;
- (id)init {
if ((self = [super init])) {
filterLock = [NSLock new];
filterWaiting = 0;
contactViews = [NSMutableArray new];
@ -26,28 +24,43 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier";
}
return self;
}
- (id)initWithAccountController:(MGMAccountController *)theAccountController {
if ((self = [self init])) {
accountController = theAccountController;
}
return self;
}
- (void)awakeFromNib {
if (contactsMatchString!=nil)
[searchBar setText:contactsMatchString];
[searchBar setText:contactsMatchString];
[self filterContacts];
[searchCancelButton setHidden:YES];
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[filterLock release];
[contactsMatchString release];
[contactViews release];
[super dealloc];
}
- (void)releaseView {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[searchBar release];
searchBar = nil;
[searchCancelButton release];
searchCancelButton = nil;
[contactsTable release];
contactsTable = nil;
[self cleanup];
}
- (void)cleanup {
contactsCount = 0;
[contactViews removeAllObjects];
}
- (void)dealloc {
if (filterLock!=nil)
[filterLock release];
if (contactsMatchString!=nil)
[contactsMatchString release];
if (contactViews!=nil)
[contactViews release];
[super dealloc];
}
- (MGMContacts *)contacts {
return nil;
@ -56,9 +69,12 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier";
return [searchBar text];
}
- (void)updateMatchString {
if (contactsMatchString!=nil) [contactsMatchString release];
[contactsMatchString release];
contactsMatchString = [[self filterString] copy];
}
- (void)scrollToTop {
[contactsTable scrollRectToVisible:CGRectMake(0, 0, [contactsTable frame].size.width, 20) animated:NO];
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)theSearchBar {
[searchCancelButton setHidden:NO];
@ -87,6 +103,7 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier";
cell = [[[MGMContactView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMContactViewCellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[cell setThemeManager:[[accountController controller] themeManager]];
[cell setContacts:[self contacts]];
}
int row = [indexPath indexAtPosition:1];
@ -137,13 +154,13 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier";
contactsVisible.location = 0;
contactsVisible.length = [[self contacts] maxResults];
[contactViews addObjectsFromArray:[[self contacts] contactsMatching:contactsMatchString page:1]];
[contactViews addObjectsFromArray:[[self contacts] contactsMatching:contactsMatchString page:1 includePhoto:NO]];
contactsCount = count;
[filterLock unlock];
if (contactsTable==nil) return;
[contactsTable performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
if (contactsCount!=0)
[contactsTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
[self performSelectorOnMainThread:@selector(scrollToTop) withObject:nil waitUntilDone:NO];
[pool drain];
}
- (void)loadContacts:(BOOL)updatingCount {
@ -161,7 +178,7 @@ NSString * const MGMContactViewCellIdentifier = @"MGMContactViewCellIdentifier";
int times = contactsLoading.length/maxResults;
for (int t=0; t<times; t++) {
page++;
[contactViews addObjectsFromArray:[[self contacts] contactsMatching:contactsMatchString page:page]];
[contactViews addObjectsFromArray:[[self contacts] contactsMatching:contactsMatchString page:page includePhoto:NO]];
}
contactsVisible = contactsLoading;
if (updatingCount)

View File

@ -3,21 +3,40 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@class MGMThemeManager, MGMAccountController, MGMAccountSetup;
@class MGMThemeManager, MGMAccountController, MGMAccountSetup, MGMReverseLookup, MGMInstance, MGMVoiceMultiSMS;
#if MGMSIPENABLED
@class MGMSIPCallView;
#endif
@interface MGMController : UIViewController {
IBOutlet UIWindow *mainWindow;
BOOL inBackground;
MGMThemeManager *themeManager;
MGMAccountController *accountController;
}
- (BOOL)isInBackground;
- (MGMThemeManager *)themeManager;
- (MGMAccountController *)accountController;
- (void)showAccountSetup;
- (void)dismissAccountSetup:(MGMAccountSetup *)theAccountSetup;
- (void)showReverseLookupWithNumber:(NSString *)theNumber;
- (void)dismissReverseLookup:(MGMReverseLookup *)theReverseLookup;
- (void)showMultiSMSWithInstance:(MGMInstance *)theInstance;
- (void)dismissMultiSMS:(MGMVoiceMultiSMS *)theMultiSMS;
#if MGMSIPENABLED
- (void)showCallView:(MGMSIPCallView *)theCallView;
- (void)dismissCallView:(MGMSIPCallView *)theCallView;
#endif
@end

View File

@ -3,37 +3,94 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMController.h"
#import "MGMAccountController.h"
#import "MGMAccountSetup.h"
#import "MGMReverseLookup.h"
#import "MGMVoiceMultiSMS.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
#if MGMSIPENABLED
#import "MGMSIPUser.h"
#import "MGMSIPCallView.h"
#endif
@implementation MGMController
- (void)awakeFromNib {
inBackground = NO;
themeManager = [MGMThemeManager new];
accountController = [[MGMAccountController alloc] initWithController:self];
[[self view] addSubview:[accountController view]];
[mainWindow addSubview:[self view]];
[mainWindow makeKeyAndVisible];
}
- (void)dealloc {
[mainWindow release];
[themeManager release];
[accountController release];
[super dealloc];
}
- (BOOL)isInBackground {
return inBackground;
}
- (MGMThemeManager *)themeManager {
return themeManager;
}
- (MGMAccountController *)accountController {
return accountController;
}
- (void)applicationWillResignActive:(UIApplication *)application {
[accountController releaseView];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
inBackground = NO;
[self performSelector:@selector(clearCalls) withObject:nil afterDelay:0.1];
CGRect viewFrame = [[accountController view] frame];
viewFrame.size = [[self view] frame].size;
[[accountController view] setFrame:viewFrame];
[[self view] addSubview:[accountController view]];
if ([[MGMUser userNames] count]==0) {
MGMAccountSetup *accountSetup = [[MGMAccountSetup alloc] initWithController:self];
[[self view] addSubview:[accountSetup view]];
}
[mainWindow makeKeyAndVisible];
}
- (MGMThemeManager *)themeManager {
return themeManager;
#if MGMSIPENABLED
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
for (int i=0; i<[[accountController contactsControllers] count]; i++) {
if ([[[accountController contactsControllers] objectAtIndex:i] isKindOfClass:[MGMSIPUser class]])
[[[accountController contactsControllers] objectAtIndex:i] answerCall];
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[MGMSIP sharedSIP] performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
[application setKeepAliveTimeout:600 handler: ^{
[[MGMSIP sharedSIP] performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
}];
inBackground = YES;
}
- (void)clearCalls {
for (int i=0; i<[[accountController contactsControllers] count]; i++) {
if ([[[accountController contactsControllers] objectAtIndex:i] isKindOfClass:[MGMSIPUser class]])
[[[accountController contactsControllers] objectAtIndex:i] clearCall];
}
}
#endif
#endif
- (void)showAccountSetup {
MGMAccountSetup *accountSetup = [[MGMAccountSetup alloc] initWithController:self];
[accountSetup setSetupOnly:YES];
CGRect inViewFrame = [[accountSetup view] frame];
inViewFrame.size = [[self view] frame].size;
inViewFrame.origin.y = +inViewFrame.size.height;
[[accountSetup view] setFrame:inViewFrame];
[[self view] addSubview:[accountSetup view]];
@ -60,4 +117,100 @@
[[theAccountSetup view] removeFromSuperview];
[theAccountSetup release];
}
- (void)showReverseLookupWithNumber:(NSString *)theNumber {
MGMReverseLookup *reverseLookup = [[MGMReverseLookup alloc] initWithController:self];
[reverseLookup setNumber:theNumber];
CGRect inViewFrame = [[reverseLookup view] frame];
inViewFrame.size = [[self view] frame].size;
inViewFrame.origin.y = +inViewFrame.size.height;
[[reverseLookup view] setFrame:inViewFrame];
[[self view] addSubview:[reverseLookup view]];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [[reverseLookup view] frame];
outViewFrame.origin.y -= outViewFrame.size.height;
[[reverseLookup view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissReverseLookup:(MGMReverseLookup *)theReverseLookup {
[UIView beginAnimations:nil context:theReverseLookup];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:reverseLookup:)];
CGRect outViewFrame = [[theReverseLookup view] frame];
outViewFrame.origin.y = +outViewFrame.size.height;
[[theReverseLookup view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished reverseLookup:(MGMReverseLookup *)theReverseLookup {
[[theReverseLookup view] removeFromSuperview];
[theReverseLookup release];
}
- (void)showMultiSMSWithInstance:(MGMInstance *)theInstance {
MGMVoiceMultiSMS *multiSMS = [[MGMVoiceMultiSMS alloc] initWithInstance:theInstance controller:self];
CGRect inViewFrame = [[multiSMS view] frame];
inViewFrame.size = [[self view] frame].size;
inViewFrame.origin.y = +inViewFrame.size.height;
[[multiSMS view] setFrame:inViewFrame];
[[self view] addSubview:[multiSMS view]];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [[multiSMS view] frame];
outViewFrame.origin.y -= outViewFrame.size.height;
[[multiSMS view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissMultiSMS:(MGMVoiceMultiSMS *)theMultiSMS {
[UIView beginAnimations:nil context:theMultiSMS];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:reverseLookup:)];
CGRect outViewFrame = [[theMultiSMS view] frame];
outViewFrame.origin.y = +outViewFrame.size.height;
[[theMultiSMS view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished multiSMS:(MGMVoiceMultiSMS *)theMultiSMS {
[[theMultiSMS view] removeFromSuperview];
[theMultiSMS release];
}
#if MGMSIPENABLED
- (void)showCallView:(MGMSIPCallView *)theCallView {
CGRect inViewFrame = [[theCallView view] frame];
inViewFrame.size = [[self view] frame].size;
inViewFrame.origin.y = +inViewFrame.size.height;
[[theCallView view] setFrame:inViewFrame];
[[self view] addSubview:[theCallView view]];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [[theCallView view] frame];
outViewFrame.origin.y -= outViewFrame.size.height;
[[theCallView view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissCallView:(MGMSIPCallView *)theCallView {
[theCallView retain];
[UIView beginAnimations:nil context:theCallView];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:callView:)];
CGRect outViewFrame = [[theCallView view] frame];
outViewFrame.origin.y = +outViewFrame.size.height;
[[theCallView view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished callView:(MGMSIPCallView *)theCallView {
[[theCallView view] removeFromSuperview];
[theCallView release];
}
#endif
@end

View File

@ -0,0 +1,25 @@
//
// MGMGContactUser.h
// VoiceMob
//
// Created by Mr. Gecko on 11/9/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@class MGMAccountController, MGMUser;
@interface MGMGContactUser : NSObject {
MGMAccountController *accountController;
MGMUser *user;
}
+ (id)gContactUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (MGMAccountController *)accountController;
- (MGMUser *)user;
- (UIView *)view;
- (void)releaseView;
@end

View File

@ -0,0 +1,47 @@
//
// MGMGContactUser.m
// VoiceMob
//
// Created by Mr. Gecko on 11/9/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMGContactUser.h"
#import "MGMAccountController.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
@implementation MGMGContactUser
+ (id)gContactUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController {
return [[[self alloc] initWithUser:theUser accountController:theAccountController] autorelease];
}
- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController {
if ((self = [super init])) {
accountController = theAccountController;
user = [theUser retain];
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[user release];
[super dealloc];
}
- (MGMAccountController *)accountController {
return accountController;
}
- (MGMUser *)user {
return user;
}
- (UIView *)view {
return nil;
}
- (void)releaseView {
}
@end

View File

@ -0,0 +1,45 @@
//
// MGMReverseLookup.h
// VoiceMob
//
// Created by Mr. Gecko on 10/5/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
#define MGMMKEnabled 1
@class MGMController, MGMURLConnectionManager, MKMapView;
@interface MGMReverseLookup : NSObject <UIWebViewDelegate> {
MGMController *controller;
MGMURLConnectionManager *connectionManager;
NSString *currentNumber;
#if !MGMMKEnabled
BOOL mapLoaded;
NSString *mapCall;
#endif
IBOutlet UIView *view;
IBOutlet UITextView *RLName;
IBOutlet UITextView *RLAddress;
IBOutlet UITextView *RLCityState;
IBOutlet UITextView *RLZipCode;
IBOutlet UITextView *RLPhoneNumber;
#if MGMMKEnabled
IBOutlet MKMapView *map;
#else
IBOutlet UIWebView *RLMap;
#endif
}
- (id)initWithController:(MGMController *)theController;
- (MGMController *)controller;
- (UIView *)view;
- (void)setNumber:(NSString *)theNumber;
- (IBAction)close:(id)sender;
@end

View File

@ -0,0 +1,237 @@
//
// MGMReverseLookup.m
// VoiceMob
//
// Created by Mr. Gecko on 10/5/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMReverseLookup.h"
#import "MGMController.h"
#import "MGMVMAddons.h"
#if MGMMKEnabled
#import <MapKit/MapKit.h>
#endif
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
#if MGMMKEnabled
@interface MGMMapPin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
- (CLLocationCoordinate2D)coordinate;
- (void)setCoordinate:(CLLocationCoordinate2D)theCoordinate;
- (NSString *)title;
- (void)setTitle:(NSString *)theTitle;
- (NSString *)subtitle;
- (void)setSubtitle:(NSString *)theTitle;
@end
@implementation MGMMapPin
- (void)dealloc {
[title release];
[subtitle release];
[super dealloc];
}
- (CLLocationCoordinate2D)coordinate {
return coordinate;
}
- (void)setCoordinate:(CLLocationCoordinate2D)theCoordinate {
coordinate = theCoordinate;
}
- (NSString *)title {
return title;
}
- (void)setTitle:(NSString *)theTitle {
[title release];
title = [theTitle copy];
}
- (NSString *)subtitle {
return subtitle;
}
- (void)setSubtitle:(NSString *)theTitle {
[subtitle release];
subtitle = [theTitle copy];
}
@end
#endif
NSString * const MGMRLLoading = @"Loading...";
@implementation MGMReverseLookup
- (id)initWithController:(MGMController *)theController {
if ((self = [super init])) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"ReverseLookup"] owner:self options:nil]) {
NSLog(@"Unable to load Reverse Lookup");
[self release];
self = nil;
} else {
controller = theController;
connectionManager = [MGMURLConnectionManager new];
#if !MGMMKEnabled
mapLoaded = NO;
[RLMap setDelegate:self];
[RLMap loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"map" ofType:@"html"]]]];
#endif
}
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[connectionManager cancelAll];
[connectionManager release];
[currentNumber release];
[view release];
[RLName release];
[RLAddress release];
[RLCityState release];
[RLZipCode release];
[RLPhoneNumber release];
#if MGMMKEnabled
[map release];
#else
[RLMap release];
[mapCall release];
#endif
[super dealloc];
}
- (MGMController *)controller {
return controller;
}
- (UIView *)view {
return view;
}
- (void)setNumber:(NSString *)theNumber {
[currentNumber release];
currentNumber = [theNumber copy];
[RLPhoneNumber setText:[currentNumber readableNumber]];
MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:currentNumber delegate:self];
[connectionManager addHandler:handler];
[RLName setText:MGMRLLoading];
[RLAddress setText:MGMRLLoading];
[RLCityState setText:MGMRLLoading];
[RLZipCode setText:MGMRLLoading];
}
- (void)reverseLookup:(MGMWhitePagesHandler *)theHandler didFailWithError:(NSError *)theError {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Reverse Lookup Failed"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (void)reverseLookupDidFindInfo:(MGMWhitePagesHandler *)theHandler {
if ([theHandler name]!=nil) {
[RLName setText:[theHandler name]];
} else {
[RLName setText:@""];
}
if ([theHandler address]!=nil) {
[RLAddress setText:[theHandler address]];
} else {
[RLAddress setText:@""];
}
if ([theHandler location]!=nil) {
[RLCityState setText:[theHandler location]];
} else {
[RLCityState setText:@""];
}
if ([theHandler zip]!=nil) {
[RLZipCode setText:[theHandler zip]];
} else {
[RLZipCode setText:@""];
}
if ([theHandler phoneNumber]!=nil) {
[RLPhoneNumber setText:[[theHandler phoneNumber] readableNumber]];
} else {
[RLPhoneNumber setText:@""];
}
int zoom = 0;
NSString *address = nil;
if ([theHandler address]!=nil) {
address = [NSString stringWithFormat:@"%@, %@", [theHandler address], [theHandler zip]];
zoom = 15;
} else if ([theHandler zip]!=nil) {
address = [theHandler zip];
zoom = 13;
} else if ([theHandler location]!=nil) {
address = [theHandler location];
zoom = 13;
} else if ([theHandler latitude]!=nil && [theHandler longitude]!=nil) {
address = [NSString stringWithFormat:@"%@, %@", [theHandler latitude], [theHandler longitude]];
zoom = 13;
}
#if MGMMKEnabled
double latitude = 0.0;
double longitude = 0.0;
if (address!=nil && [theHandler latitude]==nil) {
NSData *geocodeData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=false", [address addPercentEscapes]]]];
if (geocodeData!=nil) {
NSDictionary *geocode = [geocodeData parseJSON];
if ([[geocode objectForKey:@"status"] isEqual:@"OK"]) {
NSDictionary *location = [[[[geocode objectForKey:@"results"] objectAtIndex:0] objectForKey:@"geometry"] objectForKey:@"location"];
latitude = [[location objectForKey:@"lat"] doubleValue];
longitude = [[location objectForKey:@"lng"] doubleValue];
}
}
} else {
latitude = [[theHandler latitude] doubleValue];
longitude = [[theHandler longitude] doubleValue];
}
if (latitude!=0.0 || longitude!=0.0) {
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitude, longitude);
double span = (zoom==15 ? 0.002 : 0.3);
[map setRegion:MKCoordinateRegionMake(coordinate, MKCoordinateSpanMake(span, span))];
MGMMapPin *pin = [[MGMMapPin new] autorelease];
[pin setCoordinate:coordinate];
if ([theHandler name]!=nil)
[pin setTitle:[theHandler name]];
else if (address!=nil)
[pin setTitle:address];
if ([pin title]!=nil) {
[pin setSubtitle:[currentNumber readableNumber]];
} else {
[pin setTitle:[currentNumber readableNumber]];
[pin setSubtitle:[NSString stringWithFormat:@"%lf, %lf", coordinate.latitude, coordinate.longitude]];
}
[map addAnnotation:pin];
}
#else
if (address!=nil && !mapLoaded) {
[mapCall release];
mapCall = [[NSString stringWithFormat:@"showAddress('%@', %d);", [address javascriptEscape], zoom] retain];
} else if (address!=nil) {
[RLMap stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"showAddress('%@', %d);", [address javascriptEscape], zoom]];
}
#endif
}
#if !MGMMKEnabled
- (void)webViewDidFinishLoad:(UIWebView *)webView {
mapLoaded = YES;
if (mapCall!=nil) {
[RLMap stringByEvaluatingJavaScriptFromString:mapCall];
[mapCall release];
mapCall = nil;
}
}
#endif
- (IBAction)close:(id)sender {
#if !MGMMKEnabled
[RLMap setDelegate:nil];
#endif
[connectionManager cancelAll];
[controller dismissReverseLookup:self];
}
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@ -13,6 +13,10 @@
- (NSString *)appendDeviceSuffixToString:(NSString *)theString;
@end
@interface UIScreen (MGMVMAddons)
- (BOOL)isRetina;
@end
@interface UIColor (MGMVMAddons)
- (UIColor *)colorWithDifference:(CGFloat)theDifference;
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMVMAddons.h"
@ -22,6 +22,12 @@
}
@end
@implementation UIScreen (MGMVMAddons)
- (BOOL)isRetina {
return ([self respondsToSelector:@selector(scale)] && [self scale]==2);
}
@end
@implementation UIColor (MGMVMAddons)
- (UIColor *)colorWithDifference:(CGFloat)theDifference {
CGColorRef colorRef = [self CGColor];

View File

@ -0,0 +1,77 @@
//
// MGMSIPCallView.h
// VoiceMob
//
// Created by Mr. Gecko on 10/9/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import <UIKit/UIKit.h>
@class MGMSIPCall, MGMSIPAccount, MGMSIPUser, MGMURLConnectionManager, MGMSound, MGMMiddleView;
@interface MGMSIPCallView : NSObject {
MGMSIPCall *call;
MGMSIPAccount *account;
MGMSIPUser *SIPUser;
MGMURLConnectionManager *connectionManager;
IBOutlet UIView *backgroundView;
IBOutlet UIImageView *iImageView;
IBOutlet UIView *incomingView;
IBOutlet UILabel *iPhoneField;
IBOutlet UILabel *iNameField;
NSString *fullName;
NSString *phoneNumber;
MGMSound *ringtone;
NSDate *startTime;
NSTimer *durationUpdater;
BOOL answered;
IBOutlet UIView *callView;
IBOutlet UIScrollView *scrollView;
IBOutlet UILabel *phoneField;
IBOutlet UILabel *nameField;
IBOutlet UILabel *durationField;
IBOutlet UILabel *statusField;
IBOutlet MGMMiddleView *optionsView;
IBOutlet MGMMiddleView *keypadView;
IBOutlet UISlider *volumeSlider;
IBOutlet UISlider *micVolumeSlider;
IBOutlet UIButton *sound1Button;
IBOutlet UIButton *sound2Button;
IBOutlet UIButton *sound3Button;
IBOutlet UIButton *sound4Button;
IBOutlet UIButton *sound5Button;
IBOutlet UIButton *holdButton;
}
+ (id)viewWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser;
- (id)initWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser;
- (MGMSIPUser *)SIPUser;
- (MGMSIPCall *)call;
- (BOOL)didAnswer;
- (UIView *)view;
- (void)startDurationTimer;
- (void)fillCallView;
- (IBAction)answer:(id)sender;
- (IBAction)ignore:(id)sender;
- (IBAction)sound:(id)sender;
- (IBAction)volume:(id)sender;
- (IBAction)micVolume:(id)sender;
- (IBAction)hold:(id)sender;
- (IBAction)hangUp:(id)sender;
@end
#endif

View File

@ -0,0 +1,429 @@
//
// MGMSIPCallView.m
// VoiceMob
//
// Created by Mr. Gecko on 10/9/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import "MGMSIPCallView.h"
#import "MGMSIPUser.h"
#import "MGMSIPRecordings.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMMiddleView.h"
#import "MGMPhotoSelector.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
@implementation MGMSIPCallView
+ (id)viewWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser {
return [[[self alloc] initWithCall:theCall SIPUser:theSIPUser] autorelease];
}
- (id)initWithCall:(MGMSIPCall *)theCall SIPUser:(MGMSIPUser *)theSIPUser {
if ((self = [super init])) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPCall"] owner:self options:nil]) {
NSLog(@"Unable to load SIP Call View");
[self release];
self = nil;
} else {
call = [theCall retain];
[call setDelegate:self];
[call setHoldMusicPath:[[[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMTCallSoundsFolder] stringByAppendingPathComponent:MGMTSSIPHoldMusic] stringByAppendingPathExtension:MGMWavExt]];
account = [call account];
SIPUser = theSIPUser;
answered = NO;
UIImage *background = nil;
if ([[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom])
background = [UIImage imageWithContentsOfFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground]];
else
background = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"background" ofType:@"png"]];
[iImageView setImage:background];
CGSize scrollViewSize = [scrollView frame].size;
[scrollView setContentSize:CGSizeMake(scrollViewSize.width * 4, scrollViewSize.height)];
[scrollView scrollRectToVisible:CGRectMake(scrollViewSize.width, 0, scrollViewSize.width, scrollViewSize.height) animated:NO];
[optionsView addButtonWithTitle:@"Keypad" imageName:@"keypad" target:self action:@selector(showKeypad:atIndex:)];
[optionsView addButtonWithTitle:@"Record" imageName:@"record" target:self action:@selector(startRecording:atIndex:)];
[optionsView addButtonWithTitle:@"Speaker" imageName:@"speaker" target:self action:@selector(playThroughSpeakers:atIndex:)];
[optionsView addButtonWithTitle:@"Mute Microphone" imageName:@"mutemicrophone" target:self action:@selector(muteMicrophone:atIndex:)];
[optionsView addButtonWithTitle:@"Mute Speaker" imageName:@"mutespeaker" target:self action:@selector(muteSpeakers:atIndex:)];
[optionsView addButtonWithTitle:@"Sound Effects" imageName:@"soundeffects" target:self action:@selector(showSoundEffects:atIndex:)];
[keypadView addButtonWithTitle:nil imageName:@"n1" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"ABC" imageName:@"n2" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"DEF" imageName:@"n3" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"GHI" imageName:@"n4" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"JKL" imageName:@"n5" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"MNO" imageName:@"n6" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"PQRS" imageName:@"n7" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"TUV" imageName:@"n8" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"WXYZ" imageName:@"n9" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:nil imageName:@"n*" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:@"+" imageName:@"n0" target:self action:@selector(dial:atIndex:)];
[keypadView addButtonWithTitle:nil imageName:@"n#" target:self action:@selector(dial:atIndex:)];
NSString *phoneCalling = [SIPUser phoneCalling];
if (phoneCalling!=nil)
[[call remoteURL] setUserName:phoneCalling];
if ([call isIncoming] && phoneCalling==nil) {
if ([[[call remoteURL] userName] isPhone]) {
NSString *number = [[[call remoteURL] userName] phoneFormat];
phoneNumber = [[number readableNumber] copy];
[iPhoneField setText:phoneNumber];
NSString *name = [[SIPUser contacts] nameForNumber:number];
if (name==nil || [name isEqual:phoneNumber]) {
connectionManager = [MGMURLConnectionManager new];
MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:number delegate:self];
[connectionManager addHandler:handler];
[iNameField setText:@"Loading..."];
} else {
fullName = [name copy];
[iNameField setText:fullName];
}
} else {
phoneNumber = [[[call remoteURL] SIPAddress] copy];
[iPhoneField setText:phoneNumber];
if ([[call remoteURL] fullName]!=nil && ![[[call remoteURL] fullName] isEqual:@""]) {
fullName = [[[call remoteURL] fullName] copy];
[iNameField setText:fullName];
} else {
[iNameField setText:@"Unknown"];
}
}
[backgroundView addSubview:incomingView];
[call sendRingingNotification];
NSString *ringtonePath = [[[[SIPUser accountController] controller] themeManager] currentSoundPath:MGMTSSIPRingtone];
if (ringtonePath!=nil && ![ringtonePath isEqual:MGMTNoSound]) {
ringtone = [[MGMSound alloc] initWithContentsOfFile:ringtonePath];
[ringtone setLoops:YES];
[ringtone play];
}
} else {
if ([[[call remoteURL] userName] isPhone]) {
NSString *number = [[[call remoteURL] userName] phoneFormat];
phoneNumber = [[number readableNumber] copy];
NSString *name = [[SIPUser contacts] nameForNumber:number];
if (name==nil || [name isEqual:phoneNumber]) {
connectionManager = [MGMURLConnectionManager new];
MGMWhitePagesHandler *handler = [MGMWhitePagesHandler reverseLookup:number delegate:self];
[connectionManager addHandler:handler];
} else {
fullName = [name copy];
}
} else {
phoneNumber = [[[call remoteURL] SIPAddress] copy];
if ([[call remoteURL] fullName]!=nil && ![[[call remoteURL] fullName] isEqual:@""])
fullName = [[[call remoteURL] fullName] copy];
}
[self fillCallView];
if (phoneCalling!=nil)
[call answer];
[backgroundView addSubview:callView];
}
if ([call state]==MGMSIPCallDisconnectedState) {
[ringtone stop];
[ringtone release];
ringtone = nil;
}
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self selector:@selector(soundChanged:) name:MGMTSoundChangedNotification object:nil];
[notificationCenter addObserver:self selector:@selector(volumeChanged:) name:MGMSIPVolumeChangedNotification object:nil];
[notificationCenter addObserver:self selector:@selector(micVolumeChanged:) name:MGMSIPMicVolumeChangedNotification object:nil];
}
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[[NSNotificationCenter defaultCenter] removeObserver:self];
[call setDelegate:nil];
[call release];
[connectionManager cancelAll];
[connectionManager release];
[fullName release];
[phoneNumber release];
[ringtone stop];
[ringtone release];
[durationUpdater invalidate];
[durationUpdater release];
[startTime release];
[backgroundView release];
[iImageView release];
[incomingView release];
[iPhoneField release];
[iNameField release];
[callView release];
[scrollView release];
[phoneField release];
[nameField release];
[durationField release];
[statusField release];
[optionsView release];
[keypadView release];
[volumeSlider release];
[micVolumeSlider release];
[sound1Button release];
[sound2Button release];
[sound3Button release];
[sound4Button release];
[sound5Button release];
[holdButton release];
[super dealloc];
}
- (MGMSIPUser *)SIPUser {
return SIPUser;
}
- (MGMSIPCall *)call {
return call;
}
- (BOOL)didAnswer {
return answered;
}
- (UIView *)view {
return backgroundView;
}
- (void)disconnected:(MGMSIPCall *)theCall {
[ringtone stop];
[ringtone release];
ringtone = nil;
if ([callView superview]!=nil) {
[durationUpdater invalidate];
[durationUpdater release];
durationUpdater = nil;
[startTime release];
startTime = nil;
[statusField performSelectorOnMainThread:@selector(setText:) withObject:@"Disconnected" waitUntilDone:NO];
[[[[SIPUser accountController] controller] themeManager] playSound:MGMTSSIPDisconnected];
} else {
[ringtone stop];
[ringtone release];
ringtone = nil;
[SIPUser callDone:self];
}
}
- (void)confirmed:(MGMSIPCall *)theCall {
[statusField performSelectorOnMainThread:@selector(setText:) withObject:@"Connected" waitUntilDone:NO];
[[[[SIPUser accountController] controller] themeManager] playSound:MGMTSSIPConnected];
[self performSelectorOnMainThread:@selector(startDurationTimer) withObject:nil waitUntilDone:NO];
}
- (void)startDurationTimer {
startTime = [NSDate new];
durationUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateDuration) userInfo:nil repeats:YES] retain];
}
- (void)soundChanged:(NSNotification *)theNotification {
if ([[theNotification object] isEqual:MGMTSSIPSound1])
[sound1Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound1] forState:UIControlStateNormal];
if ([[theNotification object] isEqual:MGMTSSIPSound2])
[sound2Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound2] forState:UIControlStateNormal];
if ([[theNotification object] isEqual:MGMTSSIPSound3])
[sound3Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound3] forState:UIControlStateNormal];
if ([[theNotification object] isEqual:MGMTSSIPSound4])
[sound4Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound4] forState:UIControlStateNormal];
if ([[theNotification object] isEqual:MGMTSSIPSound5])
[sound5Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound5] forState:UIControlStateNormal];
}
- (void)fillCallView {
if (fullName!=nil)
[nameField setText:fullName];
else
[nameField setText:@"Unkown"];
[phoneField setText:phoneNumber];
[durationField setText:[NSString stringWithSeconds:0]];
[volumeSlider setValue:[[MGMSIP sharedSIP] volume]];
[micVolumeSlider setValue:[[MGMSIP sharedSIP] micVolume]];
if ([call state]!=MGMSIPCallConfirmedState)
[statusField setText:@"Connecting..."];
else
[self confirmed:call];
[sound1Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound1] forState:UIControlStateNormal];
[sound2Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound2] forState:UIControlStateNormal];
[sound3Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound3] forState:UIControlStateNormal];
[sound4Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound4] forState:UIControlStateNormal];
[sound5Button setTitle:[[[[SIPUser accountController] controller] themeManager] nameOfSound:MGMTSSIPSound5] forState:UIControlStateNormal];
}
- (IBAction)answer:(id)sender {
[ringtone stop];
[ringtone release];
ringtone = nil;
[call answer];
[self fillCallView];
[incomingView removeFromSuperview];
[backgroundView addSubview:callView];
answered = YES;
}
- (IBAction)ignore:(id)sender {
[ringtone stop];
[ringtone release];
ringtone = nil;
[SIPUser callDone:self];
}
- (void)updateDuration {
int time = [[NSDate date] timeIntervalSinceDate:startTime];
[durationField setText:[NSString stringWithSeconds:time]];
}
- (void)volumeChanged:(NSNotification *)theNotification {
[volumeSlider setValue:[[theNotification object] floatValue]];
}
- (IBAction)volume:(id)sender {
[[MGMSIP sharedSIP] setVolume:[volumeSlider value]];
}
- (void)micVolumeChanged:(NSNotification *)theNotification {
[micVolumeSlider setValue:[[theNotification object] floatValue]];
}
- (IBAction)micVolume:(id)sender {
[[MGMSIP sharedSIP] setMicVolume:[micVolumeSlider value]];
}
- (IBAction)hold:(id)sender {
[call hold];
[holdButton setTitle:([call isLocalOnHold] ? @"Unhold" : @"Hold") forState:UIControlStateNormal];
}
- (IBAction)hangUp:(id)sender {
[durationUpdater invalidate];
[durationUpdater release];
durationUpdater = nil;
[startTime release];
startTime = nil;
[call hangUp];
[SIPUser callDone:self];
}
- (void)middleViewDidCancel:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
if (theIndex==1) {
if ([call isRecording])
[theMiddleView setHighlighted:YES forButtonAtIndex:1];
} else if (theIndex==2) {
if ([call isOnSpeaker])
[theMiddleView setHighlighted:YES forButtonAtIndex:2];
} else if (theIndex==3) {
if ([call isMicMuted])
[theMiddleView setHighlighted:YES forButtonAtIndex:3];
} else if (theIndex==4) {
if ([call isMuted])
[theMiddleView setHighlighted:YES forButtonAtIndex:4];
}
}
- (void)showKeypad:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
CGSize scrollViewSize = [scrollView frame].size;
[scrollView scrollRectToVisible:CGRectMake(scrollViewSize.width*2, 0, scrollViewSize.width, scrollViewSize.height) animated:YES];
}
- (void)startRecording:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
if ([call isRecording]) {
[call stopRecording];
} else {
NSFileManager *manager = [NSFileManager defaultManager];
NSString *baseName = [[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@ - ", phoneNumber]];
if (![manager fileExistsAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder]])
[manager createDirectoryAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder] withIntermediateDirectories:YES attributes:nil error:nil];
NSString *name = nil;
for (int i=1; i<50; i++) { // Not like someone will have 50 recordings with one person on their desktop...
name = [[baseName stringByAppendingFormat:@"%02d", i] stringByAppendingPathExtension:MGMWavExt];
if (![manager fileExistsAtPath:name])
break;
}
[call startRecording:name];
}
if ([call isRecording])
[theMiddleView setHighlighted:YES forButtonAtIndex:1];
}
- (void)playThroughSpeakers:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
[call speaker];
if ([call isOnSpeaker])
[theMiddleView setHighlighted:YES forButtonAtIndex:2];
}
- (void)muteMicrophone:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
[call muteMic];
if ([call isMicMuted])
[theMiddleView setHighlighted:YES forButtonAtIndex:3];
}
- (void)muteSpeakers:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
[call mute];
if ([call isMuted])
[theMiddleView setHighlighted:YES forButtonAtIndex:4];
}
- (void)showSoundEffects:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
CGSize scrollViewSize = [scrollView frame].size;
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollViewSize.width, scrollViewSize.height) animated:YES];
}
- (IBAction)sound:(id)sender {
NSString *soundName = nil;
if (sender==sound1Button)
soundName = MGMTSSIPSound1;
else if (sender==sound2Button)
soundName = MGMTSSIPSound2;
else if (sender==sound3Button)
soundName = MGMTSSIPSound3;
else if (sender==sound4Button)
soundName = MGMTSSIPSound4;
else if (sender==sound5Button)
soundName = MGMTSSIPSound5;
NSString *soundFile = [[[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMTCallSoundsFolder] stringByAppendingPathComponent:soundName] stringByAppendingPathExtension:MGMWavExt];
[call playSound:soundFile];
[[[[SIPUser accountController] controller] themeManager] performSelector:@selector(playSound:) withObject:soundName afterDelay:0.2]; // The phone has a delay, so why not delay this so you hear it at the same time?
}
- (void)dial:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex {
if (theIndex==0)
[call sendDTMFDigits:@"1"];
else if (theIndex==1)
[call sendDTMFDigits:@"2"];
else if (theIndex==2)
[call sendDTMFDigits:@"3"];
else if (theIndex==3)
[call sendDTMFDigits:@"4"];
else if (theIndex==4)
[call sendDTMFDigits:@"5"];
else if (theIndex==5)
[call sendDTMFDigits:@"6"];
else if (theIndex==6)
[call sendDTMFDigits:@"7"];
else if (theIndex==7)
[call sendDTMFDigits:@"8"];
else if (theIndex==8)
[call sendDTMFDigits:@"9"];
else if (theIndex==9)
[call sendDTMFDigits:@"*"];
else if (theIndex==10)
[call sendDTMFDigits:@"0"];
else if (theIndex==11)
[call sendDTMFDigits:@"#"];
}
- (void)reverseLookupDidFindInfo:(MGMWhitePagesHandler *)theHandler forRequest:(NSDictionary *)theRequest {
if ([theHandler name]!=nil)
fullName = [[theHandler name] copy];
else if ([theHandler location]!=nil)
fullName = [[theHandler location] copy];
if (fullName!=nil && [callView superview]!=nil)
[nameField setText:fullName];
else if (fullName!=nil && [incomingView superview]!=nil)
[iNameField setText:fullName];
}
@end
#endif

View File

@ -0,0 +1,28 @@
//
// MGMSIPContacts.h
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import <UIKit/UIKit.h>
#import "MGMContactsController.h"
@class MGMSIPUser;
@interface MGMSIPContacts : MGMContactsController {
MGMSIPUser *SIPUser;
IBOutlet UIView *view;
}
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser;
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser;
- (MGMSIPUser *)SIPUser;
- (UIView *)view;
- (void)releaseView;
@end
#endif

View File

@ -0,0 +1,66 @@
//
// MGMSIPContacts.m
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import "MGMSIPContacts.h"
#import "MGMSIPUser.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMVMAddons.h"
#import <VoiceBase/VoiceBase.h>
@implementation MGMSIPContacts
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser {
return [[[self alloc] initWithSIPUser:theSIPUser] autorelease];
}
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser {
if ((self = [super initWithAccountController:[theSIPUser accountController]])) {
SIPUser = theSIPUser;
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[super dealloc];
}
- (MGMSIPUser *)SIPUser {
return SIPUser;
}
- (MGMContacts *)contacts {
return [SIPUser contacts];
}
- (UIView *)view {
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPContacts"] owner:self options:nil]) {
NSLog(@"Unable to load SIP Contacts");
} else {
[super awakeFromNib];
}
}
return view;
}
- (void)releaseView {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[view release];
view = nil;
[super releaseView];
}
- (void)selectedContact:(NSDictionary *)theContact {
[SIPUser showOptionsForNumber:[theContact objectForKey:MGMCNumber]];
[contactsTable deselectRowAtIndexPath:[contactsTable indexPathForSelectedRow] animated:YES];
}
@end
#endif

View File

@ -0,0 +1,50 @@
//
// MGMSIPHistory.h
// VoiceMob
//
// Created by Mr. Gecko on 10/14/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@class MGMSIPUser, MGMLiteConnection;
@interface MGMSIPInbox : NSObject {
MGMSIPUser *SIPUser;
MGMLiteConnection *inboxConnection;
NSDate *lastUpdate;
int currentView;
NSArray *inboxItems;
IBOutlet UITableView *inboxesTable;
IBOutlet UITableView *inboxTable;
int currentInbox;
int maxResults;
unsigned int start;
int resultsCount;
NSMutableArray *currentData;
}
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser;
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser;
- (void)registerSettings;
- (MGMSIPUser *)SIPUser;
- (UIView *)view;
- (void)releaseView;
- (void)addPhoneNumber:(NSString *)thePhoneNumber type:(int)theType;
- (NSArray *)dataForType:(int)theType start:(unsigned int)theStart;
- (void)loadInbox;
- (void)addData:(NSArray *)theData;
- (int)currentInbox;
@end

View File

@ -0,0 +1,323 @@
//
// MGMSIPHistory.m
// VoiceMob
//
// Created by Mr. Gecko on 10/14/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMSIPInbox.h"
#import "MGMSIPUser.h"
#import "MGMAccountController.h"
#import "MGMInboxMessageView.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
static NSMutableArray *MGMSIPInboxItems;
NSString * const MGMHInboxDB = @"inbox.db";
NSString * const MGMHInboxPlist = @"inbox.plist";
NSString * const MGMHInbox = @"MGMHInbox";
NSString * const MGMHStart = @"MGMHStart";
NSString * const MGMHResultsCount = @"MGMHResultsCount";
NSString * const MGMHLastUpdate = @"MGMHLastUpdate";
NSString * const MGMHName = @"name";
NSString * const MGMHID = @"id";
NSString * const MGMSIPInboxesCellIdentifier = @"MGMSIPInboxesCellIdentifier";
NSString * const MGMSIPInboxMessageCellIdentifier = @"MGMSIPInboxMessageCellIdentifier";
NSString * const MGMSIPInboxMessageLoadCellIdentifier = @"MGMSIPInboxMessageLoadCellIdentifier";
@implementation MGMSIPInbox
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser {
return [[[self alloc] initWithSIPUser:theSIPUser] autorelease];
}
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser {
if ((self = [super init])) {
if (MGMSIPInboxItems==nil) {
MGMSIPInboxItems = [NSMutableArray new];
[MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Inbox", MGMHName, [NSNumber numberWithInt:0], MGMHID, nil]];
[MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Placed", MGMHName, [NSNumber numberWithInt:1], MGMHID, nil]];
[MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Received", MGMHName, [NSNumber numberWithInt:2], MGMHID, nil]];
[MGMSIPInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Missed", MGMHName, [NSNumber numberWithInt:3], MGMHID, nil]];
}
SIPUser = theSIPUser;
BOOL buildDB = ![[NSFileManager defaultManager] fileExistsAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxDB]];
inboxConnection = [[MGMLiteConnection connectionWithPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxDB]] retain];
//[inboxConnection setLogQuery:YES];
if (buildDB)
[inboxConnection query:@"CREATE TABLE inbox (id INTEGER PRIMARY KEY AUTOINCREMENT, type INTEGER, isRead INTEGER, time INTEGER, phoneNumber TEXT)"];
[self registerSettings];
lastUpdate = [[[SIPUser user] settingForKey:MGMHLastUpdate] retain];
currentView = 1;
currentInbox = [[[SIPUser user] settingForKey:MGMHInbox] intValue];
maxResults = 10;
start = [[[SIPUser user] settingForKey:MGMHStart] intValue];
resultsCount = [[[SIPUser user] settingForKey:MGMHResultsCount] intValue];
inboxItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inboxes" style:UIBarButtonItemStyleBordered target:self action:@selector(showInboxes:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[SIPUser accountController] action:@selector(showSettings:)] autorelease], nil] retain];
currentData = [NSMutableArray new];
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[inboxConnection release];
[lastUpdate release];
[inboxItems release];
[currentData release];
[super dealloc];
}
- (void)registerSettings {
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
[settings setObject:[NSNumber numberWithInt:0] forKey:MGMHInbox];
[settings setObject:[NSNumber numberWithInt:0] forKey:MGMHResultsCount];
[settings setObject:[NSNumber numberWithInt:0] forKey:MGMHStart];
[[SIPUser user] registerSettings:settings];
}
- (MGMSIPUser *)SIPUser {
return SIPUser;
}
- (UIView *)view {
if (inboxesTable==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPInbox"] owner:self options:nil]) {
NSLog(@"Unable to load SIP Inbox");
} else {
if (start==0 || lastUpdate==nil || [lastUpdate earlierDate:[NSDate dateWithTimeIntervalSinceNow:-300]]==lastUpdate) {
start = 0;
resultsCount = 0;
[self loadInbox];
} else if ([currentData count]<=0 && [[NSFileManager defaultManager] fileExistsAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxPlist]]) {
[currentData addObjectsFromArray:[NSArray arrayWithContentsOfFile:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxPlist]]];
}
if (currentView==1)
[[SIPUser accountController] setItems:inboxItems animated:YES];
else
[[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES];
}
}
if (currentView==1)
return inboxTable;
return inboxesTable;
}
- (void)releaseView {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[inboxesTable release];
inboxesTable = nil;
[inboxTable release];
inboxTable = nil;
if (start!=0) {
[currentData writeToFile:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMHInboxPlist] atomically:YES];
[currentData removeAllObjects];
}
}
- (void)addPhoneNumber:(NSString *)thePhoneNumber type:(int)theType {
[inboxConnection query:@"INSERT INTO inbox (type, isRead, time, phoneNumber) VALUES (%d, %d, %qu, %@)", theType, (theType==MGMIMissedType ? 0 : 1), (unsigned long long)[[NSDate date] timeIntervalSince1970], thePhoneNumber];
}
- (IBAction)showInboxes:(id)sender {
CGRect outViewFrame = [inboxTable frame];
CGRect inViewFrame = [inboxesTable frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[inboxesTable setFrame:inViewFrame];
[[SIPUser tabView] addSubview:inboxesTable];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(inboxesAnimationDidStop:finished:context:)];
[inboxesTable setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[inboxTable setFrame:outViewFrame];
[UIView commitAnimations];
[[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES];
currentView = 0;
}
- (void)inboxesAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[inboxTable removeFromSuperview];
currentInbox = -1;
start = 0;
resultsCount = 0;
[currentData removeAllObjects];
[inboxTable reloadData];
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section {
if (theTableView==inboxesTable)
return [MGMSIPInboxItems count];
else if (theTableView==inboxTable)
return (resultsCount==maxResults ? [currentData count]+1 : [currentData count]);
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (theTableView==inboxesTable) {
UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMSIPInboxesCellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMSIPInboxesCellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
if ([cell respondsToSelector:@selector(textLabel)])
[[cell textLabel] setText:[[MGMSIPInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMHName]];
else
[cell setText:[[MGMSIPInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMHName]];
return cell;
} else if (theTableView==inboxTable) {
if ([currentData count]<=[indexPath indexAtPosition:1]) {
UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMSIPInboxMessageLoadCellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMSIPInboxMessageLoadCellIdentifier] autorelease];
NSString *text = @"Load More...";
if ([cell respondsToSelector:@selector(textLabel)]) {
[[cell textLabel] setText:text];
[[cell textLabel] setTextColor:[UIColor blueColor]];
[[cell textLabel] setTextAlignment:UITextAlignmentCenter];
} else {
[cell setText:text];
[cell setTextColor:[UIColor blueColor]];
[cell setTextAlignment:UITextAlignmentCenter];
}
}
return cell;
} else {
MGMInboxMessageView *cell = (MGMInboxMessageView *)[inboxTable dequeueReusableCellWithIdentifier:MGMSIPInboxMessageCellIdentifier];
if (cell==nil) {
cell = [[[MGMInboxMessageView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMSIPInboxMessageCellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
[cell setInstance:(MGMInstance *)SIPUser];
}
[cell setMessageData:[currentData objectAtIndex:[indexPath indexAtPosition:1]]];
return cell;
}
}
return nil;
}
- (BOOL)tableView:(UITableView *)theTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (theTableView==inboxesTable)
return NO;
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)theTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
return @"Delete";
}
- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *data = [currentData objectAtIndex:[indexPath indexAtPosition:1]];
[inboxConnection query:@"DELETE FROM inbox WHERE id=%@", [data objectForKey:MGMHID]];
[currentData removeObjectAtIndex:[indexPath indexAtPosition:1]];
[inboxTable reloadData];
}
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (theTableView==inboxesTable) {
currentInbox = [[[MGMSIPInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMHID] intValue];
[[SIPUser user] setSetting:[NSNumber numberWithInt:currentInbox] forKey:MGMHInbox];
[[inboxItems objectAtIndex:0] setEnabled:NO];
[[SIPUser accountController] setItems:inboxItems animated:YES];
CGRect outViewFrame = [inboxesTable frame];
CGRect inViewFrame = [inboxTable frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[inboxTable setFrame:inViewFrame];
[[SIPUser tabView] addSubview:inboxTable];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(inboxAnimationDidStop:finished:context:)];
[inboxTable setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[inboxesTable setFrame:outViewFrame];
[UIView commitAnimations];
currentView = 1;
[self loadInbox];
} else if (theTableView==inboxTable) {
if ([indexPath indexAtPosition:1]>=[currentData count]) {
start += maxResults;
[self loadInbox];
} else {
NSMutableDictionary *data = [[[currentData objectAtIndex:[indexPath indexAtPosition:1]] mutableCopy] autorelease];
if (![[data objectForKey:MGMIRead] boolValue]) {
[inboxConnection query:@"UPDATE inbox SET isRead=1 WHERE id=%@", [data objectForKey:MGMHID]];
[data setObject:[NSNumber numberWithBool:![[data objectForKey:MGMIRead] boolValue]] forKey:MGMIRead];
[currentData replaceObjectAtIndex:[indexPath indexAtPosition:1] withObject:data];
[inboxTable reloadData];
}
[SIPUser showOptionsForNumber:[data objectForKey:MGMIPhoneNumber]];
[inboxTable deselectRowAtIndexPath:[inboxTable indexPathForSelectedRow] animated:YES];
}
}
}
- (void)inboxAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[inboxesTable removeFromSuperview];
[inboxesTable deselectRowAtIndexPath:[inboxesTable indexPathForSelectedRow] animated:NO];
[[inboxItems objectAtIndex:0] setEnabled:YES];
}
- (NSArray *)dataForType:(int)theType start:(unsigned int)theStart {
MGMLiteResult *result = nil;
if (theType==-1)
result = [inboxConnection query:@"SELECT * FROM inbox ORDER BY id DESC LIMIT %u, %d", theStart, maxResults];
else
result = [inboxConnection query:@"SELECT * FROM inbox WHERE type = %d ORDER BY id DESC LIMIT %u, %d", theType, theStart, maxResults];
NSMutableArray *data = [NSMutableArray array];
NSDictionary *thisData = nil;
while ((thisData=[result nextRow])!=nil) {
NSMutableDictionary *dataDic = [NSMutableDictionary dictionaryWithDictionary:thisData];
[dataDic setObject:[NSDate dateWithTimeIntervalSince1970:[[thisData objectForKey:MGMITime] unsignedLongLongValue]] forKey:MGMITime];
[data addObject:dataDic];
}
return data;
}
- (void)loadInbox {
[lastUpdate release];
lastUpdate = [NSDate new];
[[SIPUser user] setSetting:lastUpdate forKey:MGMHLastUpdate];
[[SIPUser user] setSetting:[NSNumber numberWithInt:start] forKey:MGMHStart];
NSArray *data = nil;
switch (currentInbox) {
case 0:
data = [self dataForType:-1 start:start];
break;
case 1:
data = [self dataForType:MGMIPlacedType start:start];
break;
case 2:
data = [self dataForType:MGMIReceivedType start:start];
break;
case 3:
data = [self dataForType:MGMIMissedType start:start];
break;
}
[self addData:data];
}
- (void)addData:(NSArray *)theData {
resultsCount = [theData count];
[[SIPUser user] setSetting:[NSNumber numberWithInt:resultsCount] forKey:MGMHResultsCount];
[currentData addObjectsFromArray:theData];
[inboxTable reloadData];
}
- (int)currentInbox {
return currentInbox;
}
@end

View File

@ -0,0 +1,56 @@
//
// MGMSIPPad.h
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import <UIKit/UIKit.h>
@class MGMSIPUser, MGMNumberView;
@interface MGMSIPPad : NSObject <UIActionSheetDelegate, UITextFieldDelegate> {
MGMSIPUser *SIPUser;
IBOutlet UIView *view;
UITextField *keyboard;
BOOL keyboardInput;
IBOutlet UIButton *closeKeyboardButon;
NSString *numberString;
IBOutlet MGMNumberView *numberView;
IBOutlet MGMNumberView *number1View;
IBOutlet MGMNumberView *number2View;
IBOutlet MGMNumberView *number3View;
IBOutlet MGMNumberView *number4View;
IBOutlet MGMNumberView *number5View;
IBOutlet MGMNumberView *number6View;
IBOutlet MGMNumberView *number7View;
IBOutlet MGMNumberView *number8View;
IBOutlet MGMNumberView *number9View;
IBOutlet MGMNumberView *numberStarView;
IBOutlet MGMNumberView *number0View;
IBOutlet MGMNumberView *numberPondView;
IBOutlet MGMNumberView *numberKeyboardView;
IBOutlet MGMNumberView *numberCallView;
IBOutlet MGMNumberView *numberDeleteView;
}
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser;
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser;
- (MGMSIPUser *)SIPUser;
- (UIView *)view;
- (void)releaseView;
- (IBAction)numberDecide:(id)sender;
- (IBAction)dial:(id)sender;
- (IBAction)delete:(id)sender;
- (IBAction)call:(id)sender;
- (IBAction)showKeyboard:(id)sender;
- (IBAction)hideKeyboard:(id)sender;
@end
#endif

View File

@ -0,0 +1,247 @@
//
// MGMSIPPad.m
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import "MGMSIPPad.h"
#import "MGMSIPUser.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMNumberView.h"
#import "MGMVMAddons.h"
#import <VoiceBase/VoiceBase.h>
@implementation MGMSIPPad
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser {
return [[[self alloc] initWithSIPUser:theSIPUser] autorelease];
}
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser {
if ((self = [super init])) {
SIPUser = theSIPUser;
keyboardInput = NO;
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[numberString release];
[super dealloc];
}
- (MGMSIPUser *)SIPUser {
return SIPUser;
}
- (UIView *)view {
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPPad"] owner:self options:nil]) {
NSLog(@"Unable to load SIP Pad");
} else {
keyboard = [[UITextField alloc] initWithFrame:CGRectMake(-22, -22, 22, 22)];
[keyboard setDelegate:self];
[keyboard setReturnKeyType:UIReturnKeyDone];
[keyboard setAutocapitalizationType:UITextAutocapitalizationTypeNone];
[keyboard setText:@" "];
[view addSubview:keyboard];
[closeKeyboardButon setHidden:YES];
if (numberString!=nil)
[numberView setNumber:numberString];
else
[numberView setNumber:@""];
[numberView setStartColor:[UIColor colorWithRed:0.19 green:0.22 blue:0.37 alpha:1.0]];
[numberView setEndColor:[UIColor colorWithRed:0.04 green:0.16 blue:0.33 alpha:1.0]];
[numberView setGlass:YES];
[number1View setNumber:@"1"];
[number1View setAlphabet:@""];
[number2View setNumber:@"2"];
[number2View setAlphabet:@"ABC"];
[number3View setNumber:@"3"];
[number3View setAlphabet:@"DEF"];
[number4View setNumber:@"4"];
[number4View setAlphabet:@"GHI"];
[number5View setNumber:@"5"];
[number5View setAlphabet:@"JKL"];
[number6View setNumber:@"6"];
[number6View setAlphabet:@"MNO"];
[number7View setNumber:@"7"];
[number7View setAlphabet:@"PQRS"];
[number8View setNumber:@"8"];
[number8View setAlphabet:@"TUV"];
[number9View setNumber:@"9"];
[number9View setAlphabet:@"WXYZ"];
[numberStarView setNumber:@"✱"];
[numberStarView setAlphabet:@""];
[number0View setNumber:@"0"];
[number0View setAlphabet:@"+"];
[numberPondView setNumber:@"#"];
[numberPondView setAlphabet:@""];
[numberKeyboardView setNumber:@"ABC"];
UIColor *darkColor = [UIColor colorWithRed:0.02 green:0.09 blue:0.19 alpha:1.0];
[numberKeyboardView setStartColor:darkColor];
[numberKeyboardView setEndColor:darkColor];
[numberKeyboardView setGlass:YES];
[numberCallView setNumber:@"Call"];
[numberCallView setStartColor:[UIColor colorWithRed:0.13 green:0.81 blue:0.1 alpha:1.0]];
[numberCallView setEndColor:[UIColor colorWithRed:0.11 green:0.69 blue:0.09 alpha:1.0]];
[numberCallView setGlass:YES];
[numberDeleteView setImage:[[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DeleteKey" ofType:@"png"]] autorelease]];
[numberDeleteView setStartColor:darkColor];
[numberDeleteView setEndColor:darkColor];
[numberDeleteView setGlass:YES];
}
}
return view;
}
- (void)releaseView {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[view release];
view = nil;
[keyboard release];
keyboard = nil;
[closeKeyboardButon release];
closeKeyboardButon = nil;
[numberView release];
numberView = nil;
[number1View release];
number1View = nil;
[number2View release];
number2View = nil;
[number3View release];
number3View = nil;
[number4View release];
number4View = nil;
[number5View release];
number5View = nil;
[number6View release];
number6View = nil;
[number7View release];
number7View = nil;
[number8View release];
number8View = nil;
[number9View release];
number9View = nil;
[numberStarView release];
numberStarView = nil;
[number0View release];
number0View = nil;
[numberPondView release];
numberPondView = nil;
[numberKeyboardView release];
numberKeyboardView = nil;
[numberCallView release];
numberCallView = nil;
[numberDeleteView release];
numberDeleteView = nil;
}
- (IBAction)numberDecide:(id)sender {
UIActionSheet *theAction = [[UIActionSheet new] autorelease];
[theAction addButtonWithTitle:@"Copy"];
BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil);
if (pasteEnabled)
[theAction addButtonWithTitle:@"Paste"];
[theAction addButtonWithTitle:@"Reverse Lookup"];
[theAction addButtonWithTitle:@"Cancel"];
[theAction setCancelButtonIndex:(pasteEnabled ? 3 : 2)];
[theAction setDelegate:self];
[theAction showInView:[SIPUser view]];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil);
if (buttonIndex==0) {
[[UIPasteboard generalPasteboard] setString:numberString];
} else if (pasteEnabled && buttonIndex==1) {
[numberString release];
keyboardInput = ![[[UIPasteboard generalPasteboard] string] isPhoneComplete];
numberString = [(keyboardInput ? [[UIPasteboard generalPasteboard] string] : [[[UIPasteboard generalPasteboard] string] readableNumber]) copy];
[numberView setNumber:numberString];
} else if ((pasteEnabled && buttonIndex==2) || (!pasteEnabled && buttonIndex==1)) {
[[[SIPUser accountController] controller] showReverseLookupWithNumber:[numberString phoneFormatWithAreaCode:[SIPUser areaCode]]];
}
}
- (IBAction)dial:(id)sender {
NSString *number = [numberView number];
if ([number length]==0 && [sender tag]==0) {
[numberView setNumber:@"+"];
} else {
NSString *numberAdd = nil;
switch ([sender tag]) {
case 10:
case 11:
break;
default:
numberAdd = [[NSNumber numberWithInt:[sender tag]] stringValue];
break;
}
if (numberAdd!=nil)
number = [number stringByAppendingString:numberAdd];
[numberString release];
numberString = [(keyboardInput ? number : [number readableNumber]) copy];
[numberView setNumber:numberString];
}
}
- (IBAction)delete:(id)sender {
if ([numberString isEqual:@""])
keyboardInput = NO;
NSString *number = [numberView number];
if ([number length]!=0) {
number = [number substringToIndex:[number length]-1];
[numberString release];
numberString = [(keyboardInput ? number : [number readableNumber]) copy];
[numberView setNumber:numberString];
if ([numberString isEqual:@""])
keyboardInput = NO;
}
}
- (IBAction)call:(id)sender {
if ([numberString isPhoneComplete]) {
[SIPUser call:[numberString phoneFormatWithAreaCode:[SIPUser areaCode]]];
} else if (keyboardInput) {
[SIPUser call:numberString];
} else {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Incorrect Number"];
[alert setMessage:@"The phone number you have entered is incorrect."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
}
- (IBAction)showKeyboard:(id)sender {
[closeKeyboardButon setHidden:NO];
[keyboard becomeFirstResponder];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if ([string isEqual:@""])
[self delete:keyboard];
keyboardInput = YES;
NSString *number = [numberView number];
number = [number stringByAppendingString:string];
[numberString release];
numberString = [(keyboardInput ? number : [number readableNumber]) copy];
[numberView setNumber:numberString];
[keyboard setText:@" "];
return NO;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
[closeKeyboardButon setHidden:YES];
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[keyboard resignFirstResponder];
return NO;
}
- (IBAction)hideKeyboard:(id)sender {
[keyboard resignFirstResponder];
}
@end
#endif

View File

@ -0,0 +1,41 @@
//
// MGMSIPRecordings.h
// VoiceMob
//
// Created by Mr. Gecko on 10/14/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
extern NSString * const MGMRecordingsFolder;
extern NSString * const MGMRName;
extern NSString * const MGMRDate;
@class MGMSIPUser;
@interface MGMSIPRecordings : NSObject <UIWebViewDelegate, AVAudioPlayerDelegate> {
MGMSIPUser *SIPUser;
NSMutableArray *recordings;
NSArray *recordingItems;
IBOutlet UITableView *recordingsTable;
IBOutlet UIWebView *recordingView;
int currentRecording;
AVAudioPlayer *recordingPlayer;
NSTimer *recordingUpdater;
}
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser;
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser;
- (MGMSIPUser *)SIPUser;
- (UIView *)view;
- (void)releaseView;
- (void)setRecording:(int)theRecording;
@end

View File

@ -0,0 +1,254 @@
//
// MGMSIPRecordings.m
// VoiceMob
//
// Created by Mr. Gecko on 10/14/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMSIPRecordings.h"
#import "MGMSIPUser.h"
#import "MGMRecordingView.h"
#import "MGMAccountController.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
NSString * const MGMRecordingsFolder = @"recordings";
NSString * const MGMRName = @"name";
NSString * const MGMRDate = @"date";
NSString * const MGMRFile = @"file";
NSString * const MGMRecordingCellIdentifier = @"MGMRecordingCellIdentifier";
@implementation MGMSIPRecordings
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser {
return [[[self alloc] initWithSIPUser:theSIPUser] autorelease];
}
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser {
if ((self = [super init])) {
SIPUser = theSIPUser;
recordingItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Recordings" style:UIBarButtonItemStyleBordered target:self action:@selector(showRecordings:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[SIPUser accountController] action:@selector(showSettings:)] autorelease], nil] retain];
currentRecording = -1;
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[recordingItems release];
[recordingPlayer release];
[super dealloc];
}
- (MGMSIPUser *)SIPUser {
return SIPUser;
}
- (UIView *)view {
if (recordingsTable==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPRecordings"] owner:self options:nil]) {
NSLog(@"Unable to load SIP Recordings");
} else {
recordings = [NSMutableArray new];
NSDirectoryEnumerator *recordingFolder = [[NSFileManager defaultManager] enumeratorAtPath:[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder]];
NSString *recordingName = nil;
while ((recordingName = [recordingFolder nextObject])) {
NSMutableDictionary *recording = [NSMutableDictionary dictionary];
[recording setObject:[recordingName stringByDeletingPathExtension] forKey:MGMRName];
[recording setObject:[[recordingFolder fileAttributes] objectForKey:NSFileCreationDate] forKey:MGMRDate];
[recording setObject:[[[[SIPUser user] supportPath] stringByAppendingPathComponent:MGMRecordingsFolder] stringByAppendingPathComponent:recordingName] forKey:MGMRFile];
[recordings addObject:recording];
}
[recordingsTable reloadData];
[recordingView setDelegate:self];
[recordingView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"recording" ofType:@"html"]]]];
if (currentRecording!=-1)
[[SIPUser accountController] setItems:recordingItems animated:YES];
else
[[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES];
}
}
if (currentRecording!=-1)
return recordingView;
return recordingsTable;
}
- (void)releaseView {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[recordingsTable release];
recordingsTable = nil;
[recordings release];
recordings = nil;
[recordingView release];
recordingView = nil;
[recordingUpdater invalidate];
[recordingUpdater release];
recordingUpdater = nil;
[recordingPlayer pause];
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section {
return [recordings count];
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MGMRecordingView *cell = (MGMRecordingView *)[recordingsTable dequeueReusableCellWithIdentifier:MGMRecordingCellIdentifier];
if (cell==nil) {
cell = [[[MGMRecordingView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMRecordingCellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
[cell setRecording:[recordings objectAtIndex:[indexPath indexAtPosition:1]]];
return cell;
}
- (BOOL)tableView:(UITableView *)theTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)theTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
return @"Delete";
}
- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *recording = [recordings objectAtIndex:[indexPath indexAtPosition:1]];
[[NSFileManager defaultManager] removeItemAtPath:[recording objectForKey:MGMRFile] error:nil];
[recordings removeObject:recording];
[recordingsTable reloadData];
}
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self setRecording:[indexPath indexAtPosition:1]];
}
- (void)setRecording:(int)theRecording {
currentRecording = theRecording;
if (currentRecording==-1)
return;
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerLoading()"];
[[recordingItems objectAtIndex:0] setEnabled:NO];
[[SIPUser accountController] setItems:recordingItems animated:YES];
recordingPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:[[recordings objectAtIndex:currentRecording] objectForKey:MGMRFile]] error:nil];
[recordingPlayer setDelegate:self];
if (recordingView!=nil) {
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]];
[recordingView stringByEvaluatingJavaScriptFromString:@"setCurrent(0)"];
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"];
[recordingPlayer play];
recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain];
}
CGRect outViewFrame = [recordingsTable frame];
CGRect inViewFrame = [recordingView frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[recordingView setFrame:inViewFrame];
[[SIPUser tabView] addSubview:recordingView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(recordingAnimationDidStop:finished:context:)];
[recordingView setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[recordingsTable setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)recordingAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[recordingsTable removeFromSuperview];
[recordingsTable deselectRowAtIndexPath:[recordingsTable indexPathForSelectedRow] animated:NO];
[[recordingItems objectAtIndex:0] setEnabled:YES];
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPaused()"];
}
- (void)updateRecording {
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSString *scheme = [[url scheme] lowercaseString];
NSString *data = [url resourceSpecifier];
NSString *queryData = [url query];
NSDictionary *query;
if (queryData) {
NSMutableArray *dataArr = [NSMutableArray arrayWithArray:[data componentsSeparatedByString:@"?"]];
[dataArr removeLastObject];
data = [dataArr componentsJoinedByString:@"?"];
NSMutableDictionary *dataDic = [NSMutableDictionary dictionary];
NSArray *parameters = [queryData componentsSeparatedByString:@"&"];
for (int i=0; i<[parameters count]; i++) {
NSArray *info = [[parameters objectAtIndex:i] componentsSeparatedByString:@"="];
[dataDic setObject:[[[info subarrayWithRange:NSMakeRange(1, [info count]-1)] componentsJoinedByString:@"="] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[info objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
query = [NSDictionary dictionaryWithDictionary:dataDic];
}
if ([data hasPrefix:@"//"])
data = [data substringFromIndex:2];
if ([scheme isEqual:@"voicemob"]) {
if ([data isEqual:@"pause"])
[recordingPlayer pause];
else if ([data isEqual:@"play"])
[recordingPlayer play];
else if ([data isEqual:@"start"])
[recordingPlayer setCurrentTime:[[query objectForKey:@"time"] intValue]];
} else if ([scheme isEqual:@"tel"]) {
[SIPUser call:[data phoneFormatWithAreaCode:[SIPUser areaCode]]];
} else if ([scheme isEqual:@"file"]) {
return YES;
} else {
[[UIApplication sharedApplication] openURL:url];
}
return NO;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if (currentRecording!=-1) {
if (recordingPlayer!=nil) {
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]];
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]];
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"];
[recordingPlayer play];
recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain];
}
}
}
- (IBAction)showRecordings:(id)sender {
[[SIPUser accountController] setItems:[[SIPUser accountController] accountItems] animated:YES];
[recordingPlayer release];
recordingPlayer = nil;
[recordingUpdater invalidate];
[recordingUpdater release];
recordingUpdater = nil;
CGRect outViewFrame = [recordingView frame];
CGRect inViewFrame = [recordingsTable frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[recordingsTable setFrame:inViewFrame];
[[SIPUser tabView] addSubview:recordingsTable];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(showRecordingsAnimationDidStop:finished:context:)];
[recordingsTable setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[recordingView setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)showRecordingsAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[recordingView removeFromSuperview];
currentRecording = -1;
}
@end

View File

@ -3,27 +3,83 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import <UIKit/UIKit.h>
@class MGMSIPUser, MGMAccountController, MGMUser, MGMSIPAccount, MGMContacts, MGMProgressView, MGMSIPCall, MGMSIPCallView;
extern const int MGMSIPKeypadTabIndex;
extern const int MGMSIPContactsTabIndex;
extern const int MGMSIPInboxTabIndex;
extern const int MGMSIPRecordingsTabIndex;
extern NSString * const MGMSIPUserAreaCode;
@class MGMAccountController, MGMUser;
@protocol MGMSIPUserTabProtocol <NSObject>
+ (id)tabWithSIPUser:(MGMSIPUser *)theSIPUser;
- (id)initWithSIPUser:(MGMSIPUser *)theSIPUser;
@interface MGMSIPUser : NSObject {
MGMAccountController *accountController;
MGMUser *user;
IBOutlet UIView *view;
}
+ (id)SIPUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (MGMAccountController *)accountController;
- (MGMUser *)user;
- (MGMSIPUser *)SIPUser;
- (UIView *)view;
- (void)releaseView;
@end
@interface MGMSIPUser : NSObject <UIActionSheetDelegate> {
MGMAccountController *accountController;
MGMUser *user;
MGMSIPAccount *account;
NSMutableArray *calls;
MGMContacts *contacts;
int currentTab;
NSMutableArray *tabObjects;
BOOL loggingIn;
BOOL acountRegistered;
NSTimer *SIPRegistrationTimeout;
MGMProgressView *progressView;
IBOutlet UIView *view;
IBOutlet UIView *tabView;
IBOutlet UITabBar *tabBar;
NSString *optionsNumber;
MGMSIPCall *callToAwnswer;
}
+ (id)SIPUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (void)registerSettings;
- (MGMAccountController *)accountController;
- (MGMUser *)user;
- (MGMContacts *)contacts;
- (NSArray *)calls;
- (NSString *)title;
- (NSString *)areaCode;
- (void)loginErrored;
- (UIView *)view;
- (NSArray *)tabObjects;
- (UIView *)tabView;
- (UITabBar *)tabBar;
- (void)releaseView;
- (void)call:(NSString *)theNumber;
- (NSString *)phoneCalling;
- (void)gotNewCall:(MGMSIPCall *)theCall;
- (void)answerCall;
- (void)clearCall;
- (void)callDone:(MGMSIPCallView *)theCall;
- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item;
- (void)showOptionsForNumber:(NSString *)theNumber;
@end
#endif

View File

@ -3,62 +3,353 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#if MGMSIPENABLED
#import "MGMSIPUser.h"
#import "MGMSIPCallView.h"
#import "MGMSIPPad.h"
#import "MGMSIPContacts.h"
#import "MGMSIPInbox.h"
#import "MGMSIPRecordings.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMVoiceUser.h"
#import "MGMProgressView.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
const int MGMSIPKeypadTabIndex = 0;
const int MGMSIPContactsTabIndex = 1;
const int MGMSIPInboxTabIndex = 2;
const int MGMSIPRecordingsTabIndex = 3;
NSString * const MGMSIPUserAreaCode = @"MGMVSIPUserAreaCode";
NSString * const MGMSIPCurrentTab = @"MGMSIPCurrentTab";
@implementation MGMSIPUser
+ (id)SIPUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController {
return [[[self alloc] initWithUser:theUser accountController:theAccountController] autorelease];
}
- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController {
if (self = [super init]) {
if ((self = [super init])) {
accountController = theAccountController;
user = [theUser retain];
[self registerSettings];
if ([user isStarted]) {
account = [[MGMSIPAccount alloc] initWithSettings:[user settings]];
[account setDelegate:self];
calls = [NSMutableArray new];
loggingIn = NO;
acountRegistered = NO;
contacts = [[MGMContacts contactsWithClass:NSClassFromString([user settingForKey:MGMSContactsSourceKey]) delegate:self] retain];
[contacts updateContacts];
currentTab = [[user settingForKey:MGMSIPCurrentTab] intValue];
tabObjects = [NSMutableArray new];
[tabObjects addObject:[MGMSIPPad tabWithSIPUser:self]];
[tabObjects addObject:[MGMSIPContacts tabWithSIPUser:self]];
[tabObjects addObject:[MGMSIPInbox tabWithSIPUser:self]];
[tabObjects addObject:[MGMSIPRecordings tabWithSIPUser:self]];
loggingIn = YES;
[NSThread detachNewThreadSelector:@selector(login) toTarget:account withObject:nil];
}
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
if (user!=nil)
[user release];
[tabObjects removeAllObjects];
[tabObjects release];
[SIPRegistrationTimeout invalidate];
[SIPRegistrationTimeout release];
[calls removeAllObjects];
[calls release];
[account setDelegate:nil];
[account logout];
[account release];
[contacts stop];
[contacts setDelegate:nil];
[contacts release];
[user release];
[callToAwnswer release];
[optionsNumber release];
[callToAwnswer release];
[super dealloc];
}
- (void)registerSettings {
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
[settings setObject:NSStringFromClass([MGMAddressBook class]) forKey:MGMSContactsSourceKey];
[settings setObject:[NSNumber numberWithInt:MGMSIPKeypadTabIndex] forKey:MGMSIPCurrentTab];
[user registerSettings:settings];
}
- (MGMAccountController *)accountController {
return accountController;
}
- (MGMUser *)user {
return user;
}
- (MGMContacts *)contacts {
return contacts;
}
- (NSArray *)calls {
return calls;
}
- (NSString *)title {
if ([user settingForKey:MGMSIPAccountFullName]!=nil && ![[user settingForKey:MGMSIPAccountFullName] isEqual:@""])
return [user settingForKey:MGMSIPAccountFullName];
return [user settingForKey:MGMUserName];
NSString *userName = [user settingForKey:MGMUserName];
if ([userName isPhoneComplete])
userName = [userName readableNumber];
return userName;
}
- (NSString *)areaCode {
return [user settingForKey:MGMSIPUserAreaCode];
}
- (NSString *)password {
return [user password];
}
- (void)registrationChanged {
[SIPRegistrationTimeout invalidate];
[SIPRegistrationTimeout release];
SIPRegistrationTimeout = nil;
if (!acountRegistered) {
if (![account isRegistered]) {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Unable to Register with Server. Please check your credentials."];
[alert setMessage:[account lastError]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
acountRegistered = YES;
[self performSelectorOnMainThread:@selector(removeLoginProgress) withObject:nil waitUntilDone:NO];
}
}
- (void)loggedIn {
loggingIn = NO;
[self performSelectorOnMainThread:@selector(startRegistrationTimeoutTimer) withObject:nil waitUntilDone:NO];
}
- (void)startRegistrationTimeoutTimer {
if (!acountRegistered)
SIPRegistrationTimeout = [[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(SIPTimeout) userInfo:nil repeats:NO] retain];
}
- (void)SIPTimeout {
[SIPRegistrationTimeout invalidate];
[SIPRegistrationTimeout release];
SIPRegistrationTimeout = nil;
[account setLastError:@"Registration Timeout."];
[self loginErrored];
}
- (void)removeLoginProgress {
if (progressView!=nil) {
[progressView stopProgess];
[progressView setNeedsDisplay];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(progressFadeAnimationDidStop:finished:context:)];
[progressView setAlpha:0.0];
[UIView commitAnimations];
}
}
- (void)progressFadeAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[progressView removeFromSuperview];
[progressView release];
progressView = nil;
}
- (void)loginErrored {
loggingIn = NO;
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error logging in"];
[alert setMessage:[account lastError]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
[progressView stopProgess];
[progressView removeFromSuperview];
[progressView release];
progressView = nil;
[self performSelectorOnMainThread:@selector(removeLoginProgress) withObject:nil waitUntilDone:NO];
}
- (void)logoutErrored {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error logging out"];
[alert setMessage:[account lastError]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (UIView *)view {
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"SIPUser"] owner:self options:nil]) {
NSLog(@"Unable to load SIP User");
[self release];
self = nil;
} else {
[tabView addSubview:[[tabObjects objectAtIndex:currentTab] view]];
[tabBar setSelectedItem:[[tabBar items] objectAtIndex:currentTab]];
if (![account isRegistered]) {
CGSize contentSize = [view frame].size;
progressView = [[MGMProgressView alloc] initWithFrame:CGRectMake(0, 0, contentSize.width, contentSize.height)];
[progressView setProgressTitle:@"Logging In"];
[view addSubview:progressView];
[progressView startProgess];
[progressView becomeFirstResponder];
}
}
}
return view;
}
- (NSArray *)tabObjects {
return tabObjects;
}
- (UIView *)tabView {
return tabView;
}
- (UITabBar *)tabBar {
return tabBar;
}
- (void)releaseView {
if (view!=nil) {
[view release];
view = nil;
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[[tabObjects objectAtIndex:currentTab] releaseView];
[view release];
view = nil;
[tabView release];
tabView = nil;
[tabBar release];
tabBar = nil;
[progressView stopProgess];
[progressView release];
progressView = nil;
}
- (void)updatedContacts {
[[tabObjects objectAtIndex:MGMSIPContactsTabIndex] updatedContacts];
}
- (void)call:(NSString *)theNumber {
[[tabObjects objectAtIndex:MGMSIPInboxTabIndex] addPhoneNumber:theNumber type:MGMIPlacedType];
[account makeCallToNumber:theNumber];
}
- (NSString *)phoneCalling {
for (int i=0; i<[[accountController contactsControllers] count]; i++) {
if ([[[accountController contactsControllers] objectAtIndex:i] isKindOfClass:[MGMVoiceUser class]] && [[[accountController contactsControllers] objectAtIndex:i] isPlacingCall]) {
MGMVoiceUser *voiceUser = [[accountController contactsControllers] objectAtIndex:i];
[voiceUser donePlacingCall];
return [voiceUser currentPhoneNumber];
}
}
return nil;
}
- (void)gotNewCall:(MGMSIPCall *)theCall {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
if ([[accountController controller] isInBackground]) {
[self performSelectorOnMainThread:@selector(showNotificationForCall:) withObject:theCall waitUntilDone:YES];
} else {
#endif
[self performSelectorOnMainThread:@selector(mainGotNewCall:) withObject:theCall waitUntilDone:NO];
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
}
#endif
}
- (void)answerCall {
if (callToAwnswer!=nil) {
if ([callToAwnswer state]!=MGMSIPCallDisconnectedState) {
[callToAwnswer answer];
[self performSelectorOnMainThread:@selector(mainGotNewCall:) withObject:callToAwnswer waitUntilDone:NO];
}
[callToAwnswer release];
callToAwnswer = nil;
}
}
- (void)clearCall {
[callToAwnswer release];
callToAwnswer = nil;
}
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
- (void)showNotificationForCall:(MGMSIPCall *)theCall {
UILocalNotification *alert = [[[UILocalNotification alloc] init] autorelease];
if (alert!=nil) {
[callToAwnswer release];
callToAwnswer = [theCall retain];
[alert setRepeatInterval:0];
NSString *name = [[theCall remoteURL] userName];
if ([name isPhone])
name = [contacts nameForNumber:[name phoneFormatWithAreaCode:[self areaCode]]];
[alert setAlertBody:[NSString stringWithFormat:@"Call from %@", name]];
[alert setAlertAction:@"Answer"];
[[UIApplication sharedApplication] presentLocalNotificationNow:alert];
//[theCall sendRingingNotification];
}
}
#endif
- (void)mainGotNewCall:(MGMSIPCall *)theCall {
MGMSIPCallView *callView = [MGMSIPCallView viewWithCall:theCall SIPUser:self];
[calls addObject:callView];
[[accountController controller] showCallView:callView];
}
- (void)callDone:(MGMSIPCallView *)theCall {
if ([[theCall call] isIncoming])
[[tabObjects objectAtIndex:MGMSIPInboxTabIndex] addPhoneNumber:[[[theCall call] remoteURL] userName] type:([theCall didAnswer] ? MGMIReceivedType : MGMIMissedType)];
[[accountController controller] performSelectorOnMainThread:@selector(dismissCallView:) withObject:theCall waitUntilDone:NO];
[calls removeObject:theCall];
}
- (BOOL)isUserDone:(MGMUser *)theUser {
return !loggingIn;
}
- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item {
int tabIndex = [[tabBar items] indexOfObject:item];
if (tabIndex==currentTab)
return;
if (tabIndex!=MGMSIPRecordingsTabIndex)
[accountController setItems:[accountController accountItems] animated:YES];
id tab = [tabObjects objectAtIndex:currentTab];
currentTab = tabIndex;
[user setSetting:[NSNumber numberWithInt:currentTab] forKey:MGMSIPCurrentTab];
id newTab = [tabObjects objectAtIndex:currentTab];
CGRect tabFrame = [[newTab view] frame];
tabFrame.size = [tabView frame].size;
[[newTab view] setFrame:tabFrame];
[tabView addSubview:[newTab view]];
[[tab view] removeFromSuperview];
[tab releaseView];
}
- (void)showOptionsForNumber:(NSString *)theNumber {
optionsNumber = [theNumber copy];
UIActionSheet *theAction = [[UIActionSheet new] autorelease];
[theAction addButtonWithTitle:@"Call"];
[theAction addButtonWithTitle:@"Reverse Lookup"];
[theAction addButtonWithTitle:@"Cancel"];
[theAction setCancelButtonIndex:2];
[theAction setDelegate:self];
[theAction showInView:view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==0)
[self call:optionsNumber];
else if (buttonIndex==1)
[[accountController controller] showReverseLookupWithNumber:optionsNumber];
[optionsNumber release];
optionsNumber = nil;
}
@end
#endif

View File

@ -0,0 +1,39 @@
//
// MGMThemeDownloader.h
// VoiceMob
//
// Created by Mr. Gecko on 11/6/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
#import <MGMUsers/MGMUsers.h>
@class MGMURLConnectionManager;
@interface MGMDownloader : MGMSettingView <UIWebViewDelegate> {
MGMURLConnectionManager *connectionManager;
IBOutlet UIWebView *webView;
IBOutlet UIView *downloadView;
IBOutlet UIProgressView *progressView;
IBOutlet UILabel *nameField;
IBOutlet UILabel *sizeField;
IBOutlet UILabel *speedField;
IBOutlet UILabel *estimentField;
NSString *URLScheme;
NSString *tmpFile;
NSFileHandle *fileHandle;
int startTime;
int bytesReceivedSec;
int bytesReceived;
NSTimer *secCheckTimer;
NSString *receivedSec;
int receivedContentLength;
int expectedContentLength;
}
- (void)downloadURL:(NSURL *)theURL;
- (void)secCheck;
- (IBAction)close:(id)sender;
@end

View File

@ -0,0 +1,197 @@
//
// MGMThemeDownloader.m
// VoiceMob
//
// Created by Mr. Gecko on 11/6/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMDownloader.h"
#import "ZipArchive.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
NSString * const MGMTMPPath = @"~/tmp/";
NSString * const MGMZIPEXT = @"zip";
NSString * const MGMVMTURL = @"vmtheme";
NSString * const MGMVMSURL = @"vmsound";
@implementation MGMDownloader
- (id)initWithSetting:(MGMSetting *)theSetting {
if ((self = [super initWithSetting:theSetting])) {
connectionManager = [MGMURLConnectionManager new];
}
return self;
}
- (id)init {
if ((self = [super init])) {
connectionManager = [MGMURLConnectionManager new];
}
return self;
}
- (void)dealloc {
[self releaseView];
[URLScheme release];
[tmpFile release];
[fileHandle release];
[secCheckTimer invalidate];
[secCheckTimer release];
[receivedSec release];
[super dealloc];
}
- (UIView *)view {
if (webView==nil) {
if (![[NSBundle mainBundle] loadNibNamed:@"Downloader" owner:self options:nil]) {
NSLog(@"Unable to load Downloader");
[self release];
self = nil;
} else {
[webView setDelegate:self];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[[setting extra] objectForKey:MGMSExtraKey]]]];
}
}
return webView;
}
- (void)releaseView {
[webView release];
webView = nil;
[downloadView release];
downloadView = nil;
[progressView release];
progressView = nil;
[nameField release];
nameField = nil;
[sizeField release];
sizeField = nil;
[speedField release];
speedField = nil;
[estimentField release];
estimentField = nil;
}
- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ([[[[request URL] scheme] lowercaseString] isEqual:MGMVMTURL]) {
[self downloadURL:[request URL]];
return NO;
} else if ([[[[request URL] scheme] lowercaseString] isEqual:MGMVMSURL]) {
[self downloadURL:[request URL]];
return NO;
}
return YES;
}
- (void)downloadURL:(NSURL *)theURL {
[URLScheme release];
URLScheme = [[[theURL scheme] lowercaseString] copy];
theURL = [NSURL URLWithString:[@"http:" stringByAppendingString:[theURL resourceSpecifier]]];
UIView *view = [[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:0];
CGRect inViewFrame = [downloadView frame];
inViewFrame.size = [view frame].size;
inViewFrame.origin.y = +inViewFrame.size.height;
[downloadView setFrame:inViewFrame];
[view addSubview:downloadView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [downloadView frame];
outViewFrame.origin.y -= outViewFrame.size.height;
[downloadView setFrame:outViewFrame];
[UIView commitAnimations];
bytesReceivedSec = 1;
receivedContentLength = 0;
expectedContentLength = 0;
[self secCheck];
[progressView setProgress:0.0];
[nameField setText:@""];
srandomdev();
[tmpFile release];
tmpFile = [[[[[NSNumber numberWithLong:random()] stringValue] MD5] stringByAppendingPathExtension:MGMZIPEXT] retain];
if (secCheckTimer==nil)
secCheckTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(secCheck) userInfo:nil repeats:YES] retain];
MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:[NSURLRequest requestWithURL:theURL] delegate:self];
[handler setFile:[[MGMTMPPath stringByExpandingTildeInPath] stringByAppendingPathComponent:tmpFile]];
[connectionManager addHandler:handler];
}
- (IBAction)close:(id)sender {
[connectionManager cancelAll];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(closeAnimationDidStop:finished:context:)];
CGRect outViewFrame = [downloadView frame];
outViewFrame.origin.y = +outViewFrame.size.height;
[downloadView setFrame:outViewFrame];
[UIView commitAnimations];
[secCheckTimer release];
secCheckTimer = nil;
[fileHandle closeFile];
[fileHandle release];
fileHandle = nil;
[tmpFile release];
tmpFile = nil;
}
- (void)closeAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[downloadView removeFromSuperview];
}
- (NSString *)bytesToString:(double)bytes {
NSString *type = @"Bytes";
if (bytes>1024.00) {
type = @"KB";
bytes = bytes/1024.00;
if (bytes>1024.00) {
type = @"MB";
bytes = bytes/1024.00;
if (bytes>1024.00) {
type = @"GB";
bytes = bytes/1024.00;
}
}
}
return [NSString stringWithFormat:@"%.2f %@", bytes, type];
}
- (void)secCheck {
[receivedSec release];
receivedSec = [[self bytesToString:(double)bytesReceived] retain];
bytesReceivedSec = (bytesReceived==0 ? 1 : bytesReceived);
bytesReceived = 0;
int secs = (expectedContentLength-receivedContentLength)/bytesReceivedSec;
[sizeField setText:[NSString stringWithFormat:@"%@ of %@", [self bytesToString:(double)receivedContentLength], [self bytesToString:(double)expectedContentLength]]];
[speedField setText:[NSString stringWithFormat:@"%@/sec", receivedSec]];
[estimentField setText:[NSString stringWithSeconds:secs]];
}
- (void)handler:(MGMURLBasicHandler *)theHandler didReceiveResponse:(NSHTTPURLResponse *)theResponse {
[nameField setText:[theResponse suggestedFilename]];
}
- (void)handler:(MGMURLBasicHandler *)theHandler receivedBytes:(unsigned long)theBytes totalBytes:(unsigned long)theTotalBytes expectedBytes:(unsigned long)theExpectedBytes {
expectedContentLength = theExpectedBytes;
receivedContentLength = theTotalBytes;
bytesReceived += theBytes;
[progressView setProgress:(double)theTotalBytes/(double)theExpectedBytes];
}
- (void)handler:(MGMURLBasicHandler *)theHandler didFailWithError:(NSError *)theError {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error downloading"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
[self close:self];
}
- (void)handlerDidFinish:(MGMURLBasicHandler *)theHandler {
ZipArchive *zip = [ZipArchive new];
[zip UnzipOpenFile:[[MGMTMPPath stringByExpandingTildeInPath] stringByAppendingPathComponent:tmpFile]];
[zip UnzipFileTo:([URLScheme isEqual:MGMVMTURL] ? [[[MGMThemeManager new] autorelease] themesFolderPath] : [[[MGMThemeManager new] autorelease] soundsFolderPath]) overWrite:YES];
[zip UnzipCloseFile];
[zip release];
[[NSFileManager defaultManager] removeItemAtPath:[[MGMTMPPath stringByExpandingTildeInPath] stringByAppendingPathComponent:tmpFile] error:nil];
[self performSelector:@selector(close:) withObject:nil afterDelay:0.5];
}
@end

View File

@ -0,0 +1,24 @@
//
// MGMPhotoSelector.h
// VoiceMob
//
// Created by James on 3/25/11.
// Copyright 2011 Mr. Gecko's Media. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <MGMUsers/MGMUsers.h>
extern NSString * const MGMSIPBackground;
extern NSString * const MGMSIPBCustom;
extern NSString * const MGMSIPBDefault;
extern NSString * const MGMPSBackground;
@interface MGMPhotoSelector : MGMSettingView <UINavigationControllerDelegate,UIImagePickerControllerDelegate> {
IBOutlet UIView *view;
IBOutlet UIImageView *imageView;
UIImagePickerController *imagePickerController;
}
- (IBAction)selectPhoto:(id)sender;
- (void)dismiss;
@end

View File

@ -0,0 +1,159 @@
//
// MGMPhotoSelector.m
// VoiceMob
//
// Created by James on 3/25/11.
// Copyright 2011 Mr. Gecko's Media. All rights reserved.
//
#import "MGMPhotoSelector.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
NSString * const MGMSIPBackground = @"MGMSIPBackground";
NSString * const MGMSIPBCustom = @"custom";
NSString * const MGMSIPBDefault = @"default";
NSString * const MGMPSBackground = @"background.png";
@implementation MGMPhotoSelector
- (id)initWithSetting:(MGMSetting *)theSetting {
if ((self = [super initWithSetting:theSetting])) {
}
return self;
}
- (void)dealloc {
[self releaseView];
[super dealloc];
}
- (UIView *)view {
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:@"PhotoSelector" owner:self options:nil]) {
NSLog(@"Unable to load Photo Selector.");
} else {
if ([[[NSUserDefaults standardUserDefaults] objectForKey:MGMSIPBackground] isEqual:MGMSIPBCustom])
[imageView setImage:[UIImage imageWithContentsOfFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground]]];
else
[self selectPhoto:self];
}
}
return view;
}
- (void)releaseView {
[view release];
view = nil;
[imagePickerController release];
imagePickerController = nil;
[imageView release];
imageView = nil;
}
- (IBAction)selectPhoto:(id)sender {
imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setDelegate:self];
[imagePickerController setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
UIView *viewController = [[[[[UIApplication sharedApplication] windows] objectAtIndex:0] subviews] objectAtIndex:0];
CGRect inViewFrame = [[imagePickerController view] frame];
inViewFrame.size = [viewController frame].size;
inViewFrame.origin.y = +inViewFrame.size.height;
[[imagePickerController view] setFrame:inViewFrame];
[viewController addSubview:[imagePickerController view]];
[imagePickerController viewWillAppear:YES];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [[imagePickerController view] frame];
outViewFrame.origin.y -= outViewFrame.size.height;
[[imagePickerController view] setFrame:outViewFrame];
[UIView commitAnimations];
[imagePickerController viewDidAppear:YES];
}
- (UIImage *)cropImage:(UIImage *)theImage toSize:(CGSize)theSize {
if (theImage!=nil) {
CGSize size = [theImage size];
float scaleFactor = 0.0;
float scaledWidth = theSize.width;
float scaledHeight = theSize.height;
if (!CGSizeEqualToSize(size, theSize)) {
float widthFactor = theSize.width / size.width;
float heightFactor = theSize.height / size.height;
if (widthFactor > heightFactor)
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
scaledWidth = size.width * scaleFactor;
scaledHeight = size.height * scaleFactor;
}
CGSize newSize = CGSizeMake(scaledWidth, scaledHeight);
if (!CGSizeEqualToSize(newSize, CGSizeZero)) {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
UIGraphicsBeginImageContext(theSize);
[theImage drawInRect:CGRectMake((theSize.width-scaledWidth)/2, (theSize.height-scaledHeight)/2, scaledWidth, scaledHeight)];
UIImage *newImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
[pool drain];
return [newImage autorelease];
}
}
return theImage;
}
- (void)imagePickerController:(UIImagePickerController *)thePicker didFinishPickingMediaWithInfo:(NSDictionary *)theInfo {
CGSize size;
if ([[UIScreen mainScreen] isRetina])
size = CGSizeMake(640, 920);
else
size = CGSizeMake(320, 460);
UIImage *image = [self cropImage:[theInfo objectForKey:UIImagePickerControllerOriginalImage] toSize:size];
NSData *data = UIImagePNGRepresentation(image);
if (data!=nil) {
[imageView setImage:image];
[data writeToFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground] atomically:YES];
[[NSUserDefaults standardUserDefaults] setObject:MGMSIPBCustom forKey:MGMSIPBackground];
}
[self dismiss];
}
- (void)imagePickerController:(UIImagePickerController *)thePicker didFinishPickingImage:(UIImage *)theImage editingInfo:(NSDictionary *)theInfo {
CGSize size;
if ([[UIScreen mainScreen] isRetina])
size = CGSizeMake(640, 920);
else
size = CGSizeMake(320, 460);
UIImage *image = [self cropImage:theImage toSize:size];
NSData *data = UIImagePNGRepresentation(image);
if (data!=nil) {
[imageView setImage:image];
[data writeToFile:[[MGMUser applicationSupportPath] stringByAppendingPathComponent:MGMPSBackground] atomically:YES];
[[NSUserDefaults standardUserDefaults] setObject:MGMSIPBCustom forKey:MGMSIPBackground];
}
[self dismiss];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)thePicker {
[self dismiss];
}
- (void)dismiss {
[imagePickerController viewWillDisappear:YES];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:context:)];
CGRect outViewFrame = [[imagePickerController view] frame];
outViewFrame.origin.y = +outViewFrame.size.height;
[[imagePickerController view] setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(id)theContext {
[imagePickerController viewDidDisappear:YES];
[[imagePickerController view] removeFromSuperview];
[imagePickerController release];
imagePickerController = nil;
}
@end

View File

@ -0,0 +1,21 @@
//
// MGMThemePreviewer.h
// VoiceMob
//
// Created by Mr. Gecko on 11/6/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
#import <MGMUsers/MGMUsers.h>
@class MGMThemeManager;
@interface MGMThemePreviewer : MGMSettingView <UIWebViewDelegate> {
MGMThemeManager *themeManager;
UIWebView *SMSView;
NSMutableArray *testMessages;
NSMutableDictionary *testMessageInfo;
}
@end

View File

@ -0,0 +1,86 @@
//
// MGMThemePreviewer.m
// VoiceMob
//
// Created by Mr. Gecko on 11/6/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMThemePreviewer.h"
#import <VoiceBase/VoiceBase.h>
NSString * const MGMTestTYPhoto = @"yPhoto";
NSString * const MGMTestTTPhoto = @"tPhoto";
@implementation MGMThemePreviewer
- (id)initWithSetting:(MGMSetting *)theSetting {
if ((self = [super initWithSetting:theSetting])) {
themeManager = [MGMThemeManager new];
testMessages = [NSMutableArray new];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Hey, you got the message?", MGMIText, @"5:56 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"No, can you resend it?", MGMIText, @"5:57 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"No, all local copies were destroyed, because we don't want this to get out.", MGMIText, @"5:58 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Oh, yea, right, that thing.", MGMIText, @"5:59 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"I can't send you on SMS because your cell phone company spy's on you.", MGMIText, @"6:00 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"True. We can meet in the secret spot.", MGMIText, @"6:00 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"No thanks, I think we should meet at my house.", MGMIText, @"6:01 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Would you like to come for dinner?", MGMIText, @"6:01 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"I'd love, but my girl needs me more.", MGMIText, @"6:02 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Well why not make it a double date? I bring my wife and you bring yours.", MGMIText, @"6:03 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Sure I pick Mucha Pizza. What time should we meet?", MGMIText, @"6:05 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"7PM?", MGMIText, @"6:05 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"That sounds good.", MGMIText, @"6:06 PM", MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil]];
[testMessages addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Great, meet you then.", MGMIText, @"6:07 PM", MGMITime, [NSNumber numberWithBool:NO], MGMIYou, nil]];
testMessageInfo = [NSMutableDictionary new];
[testMessageInfo setObject:[NSDate dateWithTimeIntervalSince1970:1598915245] forKey:MGMITime];
[testMessageInfo setObject:@"Noah Jonson" forKey:MGMTInName];
[testMessageInfo setObject:@"+15555555555" forKey:MGMIPhoneNumber];
[testMessageInfo setObject:@"+17204325686" forKey:MGMTUserNumber];
[testMessageInfo setObject:@"673bd22599231d1a9ba78760f2df085a7237b4b3" forKey:MGMIID];
[testMessageInfo setObject:[[themeManager outgoingIconPath] filePath] forKey:MGMTestTYPhoto];
[testMessageInfo setObject:[[themeManager incomingIconPath] filePath] forKey:MGMTestTTPhoto];
}
return self;
}
- (void)dealloc {
[self releaseView];
[themeManager release];
[testMessages release];
[testMessageInfo release];
[super dealloc];
}
- (UIView *)view {
if (SMSView==nil) {
SMSView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 418)];
[SMSView setDelegate:self];
NSMutableArray *messageArray = [NSMutableArray array];
for (unsigned int i=0; i<[testMessages count]; i++) {
NSMutableDictionary *message = [NSMutableDictionary dictionaryWithDictionary:[testMessages objectAtIndex:i]];
[message setObject:[[NSNumber numberWithInt:i] stringValue] forKey:MGMIID];
if ([[message objectForKey:MGMIYou] boolValue]) {
[message setObject:[testMessageInfo objectForKey:MGMTestTYPhoto] forKey:MGMTPhoto];
[message setObject:NSFullUserName() forKey:MGMTName];
[message setObject:[testMessageInfo objectForKey:MGMTUserNumber] forKey:MGMIPhoneNumber];
} else {
[message setObject:[testMessageInfo objectForKey:MGMTestTTPhoto] forKey:MGMTPhoto];
[message setObject:[testMessageInfo objectForKey:MGMTInName] forKey:MGMTName];
[message setObject:[testMessageInfo objectForKey:MGMIPhoneNumber] forKey:MGMIPhoneNumber];
}
[messageArray addObject:message];
}
NSString *html = [themeManager buildHTMLWithMessages:messageArray messageInfo:testMessageInfo];
[SMSView loadHTMLString:html baseURL:[NSURL fileURLWithPath:[themeManager currentThemeVariantPath]]];
}
return SMSView;
}
- (void)releaseView {
[SMSView release];
SMSView = nil;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[SMSView stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"];
}
@end

View File

@ -0,0 +1,17 @@
//
// MGMInboxItem.h
// VoiceMob
//
// Created by James on 11/21/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@interface MGMBadgeView : UITableViewCell {
NSString *badge;
UILabel *nameField;
}
- (void)setName:(NSString *)theName;
- (void)setBadge:(NSString *)theBadge;
@end

View File

@ -0,0 +1,62 @@
//
// MGMInboxItem.m
// VoiceMob
//
// Created by James on 11/21/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMBadgeView.h"
#import <MGMUsers/MGMUsers.h>
@implementation MGMBadgeView
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
nameField = [[UILabel alloc] initWithFrame:CGRectZero];
[nameField setBackgroundColor:[UIColor clearColor]];
[nameField setFont:[UIFont boldSystemFontOfSize:20.0]];
[[self contentView] addSubview:nameField];
}
return self;
}
- (void)dealloc {
[badge release];
[nameField release];
[super dealloc];
}
- (void)setName:(NSString *)theName {
[nameField setText:theName];
}
- (void)setBadge:(NSString *)theBadge {
[badge release];
badge = [theBadge copy];
[self setNeedsDisplay];
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect frameRect = [[self contentView] bounds];
if (badge!=nil && ![badge isEqual:@""]) {
UIFont *badgeFont = [UIFont systemFontOfSize:18];
CGSize badgeSize = [badge sizeWithFont:badgeFont];
[nameField setFrame:CGRectMake(5, (frameRect.size.height/2)-12, (frameRect.size.width-badgeSize.width)-20, 24)];
} else {
[nameField setFrame:CGRectMake(5, (frameRect.size.height/2)-12, frameRect.size.width-10, 24)];
}
}
- (void)drawRect:(CGRect)rect {
if (badge!=nil && ![badge isEqual:@""]) {
CGRect frameRect = [[self contentView] bounds];
UIFont *badgeFont = [UIFont systemFontOfSize:18];
CGSize badgeSize = [badge sizeWithFont:badgeFont];
CGRect borderRect = CGRectMake((frameRect.size.width-(badgeSize.width+13))-5, (frameRect.size.height/2)-(badgeSize.height/2), badgeSize.width+13, badgeSize.height);
MGMPath *path = [MGMPath pathWithRoundedRect:borderRect cornerRadius:borderRect.size.height/2];
[[UIColor colorWithRed:0.5019 green:0.5843 blue:0.7412 alpha:1.0] setFill];
[path fill];
[[UIColor whiteColor] setFill];
[badge drawInRect:CGRectMake(borderRect.origin.x+((borderRect.size.width-badgeSize.width)/2), borderRect.origin.y-((borderRect.size.height-badgeSize.height)/2), badgeSize.width, badgeSize.height) withFont:badgeFont];
}
[super drawRect:rect];
}
@end

View File

@ -3,20 +3,28 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class MGMThemeManager;
@class MGMThemeManager, MGMContacts;
@interface MGMContactView : UITableViewCell {
MGMThemeManager *themeManager;
MGMContacts *contacts;
UIImageView *photoView;
UILabel *nameField;
UILabel *phoneField;
NSDictionary *contact;
NSString *number;
NSLock *photoLock;
int photoWaiting;
}
- (void)setThemeManager:(MGMThemeManager *)theThemeManager;
- (void)setContacts:(MGMContacts *)theContacts;
- (void)setContact:(NSDictionary *)theContact;
- (void)getPhotoForNumber:(NSString *)theNumber;
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMContactView.h"
@ -11,7 +11,7 @@
@implementation MGMContactView
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
photoView = [[UIImageView alloc] initWithFrame:CGRectZero];
[[self contentView] addSubview:photoView];
nameField = [[UILabel alloc] initWithFrame:CGRectZero];
@ -22,24 +22,31 @@
[phoneField setBackgroundColor:[UIColor clearColor]];
[phoneField setFont:[UIFont systemFontOfSize:15.0]];
[[self contentView] addSubview:phoneField];
photoLock = [NSLock new];
}
return self;
}
- (void)dealloc {
if (photoView!=nil)
[photoView release];
if (nameField!=nil)
[nameField release];
if (phoneField!=nil)
[phoneField release];
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[photoView release];
[nameField release];
[phoneField release];
[contact release];
[photoLock release];
[number release];
[super dealloc];
}
- (void)setThemeManager:(MGMThemeManager *)theThemeManager {
themeManager = theThemeManager;
}
- (void)setContacts:(MGMContacts *)theContacts {
contacts = theContacts;
}
- (void)setContact:(NSDictionary *)theContact {
if (contact!=nil) [contact release];
[contact release];
contact = [theContact retain];
}
@ -49,10 +56,12 @@
CGRect frameRect = [[self contentView] bounds];
if (contact!=nil) {
if ([contact objectForKey:MGMCPhoto]==nil || [[contact objectForKey:MGMCPhoto] isKindOfClass:[NSNull class]])
[photoView setImage:[[[UIImage alloc] initWithContentsOfFile:[themeManager incomingIconPath]] autorelease]];
else
[photoView setImage:[[[UIImage alloc] initWithData:[contact objectForKey:MGMCPhoto]] autorelease]];
if (![number isEqual:[contact objectForKey:MGMCNumber]]) {
[number release];
number = [[contact objectForKey:MGMCNumber] retain];
[photoView setImage:nil];
[NSThread detachNewThreadSelector:@selector(getPhotoForNumber:) toTarget:self withObject:number];
}
if ([[contact objectForKey:MGMCName] isEqual:@""])
[nameField setText:[contact objectForKey:MGMCCompany]];
else
@ -67,4 +76,27 @@
[nameField setFrame:CGRectMake(frameRect.size.height+8, 10, frameRect.size.width-(frameRect.size.height+12), 20)];
[phoneField setFrame:CGRectMake(frameRect.size.height+8, frameRect.size.height-27, frameRect.size.width-(frameRect.size.height+12), 20)];
}
- (void)getPhotoForNumber:(NSString *)theNumber {
photoWaiting++;
[photoLock lock];
photoWaiting--;
if (photoWaiting>=1) {
[photoLock unlock];
return;
}
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSData *photo = [contacts photoDataForNumber:number];
if (photoWaiting>=1) {
[pool release];
[photoLock unlock];
return;
}
if (photo==nil || [photo isKindOfClass:[NSNull class]])
[photoView setImage:[[[UIImage alloc] initWithContentsOfFile:[themeManager incomingIconPath]] autorelease]];
else
[photoView setImage:[[[UIImage alloc] initWithData:photo] autorelease]];
[pool release];
[photoLock unlock];
}
@end

View File

@ -0,0 +1,18 @@
//
// MGMGlassButton.h
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@interface MGMGlassButton : UIButton {
UIColor *buttonColor;
UIColor *buttonTouchColor;
UIColor *buttonDisabledColor;
BOOL touching;
}
@end

View File

@ -0,0 +1,108 @@
//
// MGMGlassButton.m
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMGlassButton.h"
#import <MGMUsers/MGMUsers.h>
#import "MGMVMAddons.h"
@implementation MGMGlassButton
- (void)awakeFromNib {
buttonColor = [[self backgroundColor] retain];
buttonTouchColor = [[buttonColor colorWithDifference:-0.1] retain];
buttonDisabledColor = [[buttonColor colorWithDifference:0.1] retain];
[self setBackgroundColor:[UIColor clearColor]];
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[buttonColor release];
[buttonTouchColor release];
[buttonDisabledColor release];
[super dealloc];
}
- (void)setTouching:(BOOL)isTouching {
touching = isTouching;
[self setNeedsDisplay];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[self setTouching:YES];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self setTouching:NO];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];
[self setTouching:NO];
}
- (void)setEnabled:(BOOL)isEnabled {
[super setEnabled:isEnabled];
[self setNeedsDisplay];
}
- (UIEdgeInsets)titleEdgeInsets {
return UIEdgeInsetsMake(-2.0, 0.0, 0.0, 0.0);
}
- (void)drawRect:(CGRect)frameRect {
UIColor *color = nil;
if (![self isEnabled])
color = buttonDisabledColor;
else if (touching)
color = buttonTouchColor;
else
color = buttonColor;
CGRect pathBounds = [self bounds];
pathBounds.size.width -= 1.0;
pathBounds.origin.x += 0.5;
pathBounds.size.height -= 1.0;
pathBounds.origin.y += 0.5;
MGMPath *path = [MGMPath pathWithRoundedRect:pathBounds cornerRadius:12];
[path setLineWidth:1.0];
[color setFill];
[[color colorWithDifference:-0.1] setStroke];
[path fill];
[path stroke];
CGRect gradientRect = pathBounds;
gradientRect.size.width -= 1.0;
gradientRect.origin.x += 0.5;
gradientRect.size.height -= 0.5;
gradientRect.origin.y += 0.5;
CGFloat gradientRadius = 12.0;
MGMPath *gradientPath = [MGMPath path];
float maxRadiusX = gradientRect.size.width / 2.0;
float maxRadiusY = gradientRect.size.height / 2.0;
gradientRadius = (gradientRadius<maxRadiusX ? gradientRadius : maxRadiusX);
gradientRadius = (gradientRadius<maxRadiusY ? gradientRadius : maxRadiusY);
float ellipse = 0.55228474983079;
float controlX = gradientRadius * ellipse;
float controlY = gradientRadius * ellipse;
CGRect edges = CGRectInset(gradientRect, gradientRadius, gradientRadius);
[gradientPath moveToPoint:CGPointMake(edges.origin.x, gradientRect.origin.y)];
// top right corner
[gradientPath addLineToPoint:CGPointMake(CGRectGetMaxX(edges), gradientRect.origin.y)];
[gradientPath addCurveToPoint:CGPointMake(CGRectGetMaxX(gradientRect), edges.origin.y) controlPoint1:CGPointMake(CGRectGetMaxX(edges) + controlX, gradientRect.origin.y) controlPoint2:CGPointMake(CGRectGetMaxX(gradientRect), edges.origin.y - controlY)];
[gradientPath addLineToPoint:CGPointMake(CGRectGetMaxX(gradientRect), CGRectGetMidY(gradientRect))];
[gradientPath addLineToPoint:CGPointMake(CGRectGetMinX(gradientRect), CGRectGetMidY(gradientRect))];
// top left corner
[gradientPath addLineToPoint:CGPointMake(gradientRect.origin.x, edges.origin.y)];
[gradientPath addCurveToPoint:CGPointMake(edges.origin.x, gradientRect.origin.y) controlPoint1:CGPointMake(gradientRect.origin.x, edges.origin.y - controlY) controlPoint2:CGPointMake(edges.origin.x - controlX, gradientRect.origin.y)];
[gradientPath closePath];
[gradientPath fillGradientFrom:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.6] to:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.2]];
[super drawRect:frameRect];
}
@end

View File

@ -0,0 +1,15 @@
//
// MGMGlassView.h
// VoiceMob
//
// Created by Mr. Gecko on 10/9/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@interface MGMGlassView : UIView {
}
@end

View File

@ -0,0 +1,43 @@
//
// MGMGlassView.m
// VoiceMob
//
// Created by Mr. Gecko on 10/9/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMGlassView.h"
#import <MGMUsers/MGMUsers.h>
@implementation MGMGlassView
- (void)drawRect:(CGRect)frameRect {
CGRect bounds = [self bounds];
MGMPath *path = [MGMPath pathWithRect:bounds];
[[UIColor colorWithWhite:0.0 alpha:0.6] setFill];
[path fill];
CGRect glassBounds = bounds;
glassBounds.size.height = glassBounds.size.height/2;
MGMPath *glassPath = [MGMPath pathWithRect:glassBounds];
[glassPath fillGradientFrom:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.5] to:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.1]];
[[UIColor colorWithWhite:0.0 alpha:0.6] setFill];
CGRect line1Bounds = bounds;
line1Bounds.size.height = 1;
MGMPath *line1Path = [MGMPath pathWithRect:line1Bounds];
[line1Path fill];
CGRect line3Bounds = line1Bounds;
line3Bounds.origin.y += bounds.size.height-1;
MGMPath *line3Path = [MGMPath pathWithRect:line3Bounds];
[line3Path fill];
[[UIColor colorWithWhite:1.0 alpha:0.1] setFill];
CGRect line2Bounds = line1Bounds;
line2Bounds.origin.y += 1;
MGMPath *line2Path = [MGMPath pathWithRect:line2Bounds];
[line2Path fill];
CGRect line4Bounds = line3Bounds;
line4Bounds.origin.y -= 1;
MGMPath *line4Path = [MGMPath pathWithRect:line4Bounds];
[line4Path fill];
}
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>

View File

@ -3,11 +3,11 @@
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMGradientButton.h"
#import "MGMPath.h"
#import <MGMUsers/MGMUsers.h>
#import "MGMVMAddons.h"
@implementation MGMGradientButton
@ -18,12 +18,12 @@
[self setBackgroundColor:[UIColor clearColor]];
}
- (void)dealloc {
if (buttonColor!=nil)
[buttonColor release];
if (buttonTouchColor!=nil)
[buttonTouchColor release];
if (buttonDisabledColor!=nil)
[buttonDisabledColor release];
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[buttonColor release];
[buttonTouchColor release];
[buttonDisabledColor release];
[super dealloc];
}
@ -63,8 +63,8 @@
CGRect pathBounds = whitePathBounds;
whitePathBounds.size.width -= 2.0;
whitePathBounds.origin.x += 1.0;
whitePathBounds.size.height -= 2.0;
whitePathBounds.origin.y += 0.7;
whitePathBounds.size.height -= 2.3;
whitePathBounds.origin.y += 1.0;
MGMPath *whitePath = [MGMPath pathWithRoundedRect:whitePathBounds cornerRadius:12];
[[UIColor colorWithWhite:1.0 alpha:1.0] setStroke];
[whitePath setLineWidth:2.0];
@ -103,7 +103,7 @@
[gradientPath addCurveToPoint:CGPointMake(CGRectGetMaxX(gradientRect), edges.origin.y) controlPoint1:CGPointMake(CGRectGetMaxX(edges) + controlX, gradientRect.origin.y) controlPoint2:CGPointMake(CGRectGetMaxX(gradientRect), edges.origin.y - controlY)];
[gradientPath addLineToPoint:CGPointMake(CGRectGetMaxX(gradientRect), CGRectGetMidY(gradientRect))];
[gradientPath addLineToPoint:CGPointMake(CGRectGetMidX(gradientRect), CGRectGetMidY(gradientRect))];
[gradientPath addLineToPoint:CGPointMake(CGRectGetMinX(gradientRect), CGRectGetMidY(gradientRect))];
// top left corner
[gradientPath addLineToPoint:CGPointMake(gradientRect.origin.x, edges.origin.y)];

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/30/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>

View File

@ -3,15 +3,16 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/30/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMInboxMessageView.h"
#import <VoiceBase/VoiceBase.h>
#import <MGMUsers/MGMUsers.h>
@implementation MGMInboxMessageView
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
nameField = [[UILabel alloc] initWithFrame:CGRectZero];
[nameField setBackgroundColor:[UIColor clearColor]];
[nameField setFont:[UIFont boldSystemFontOfSize:18.0]];
@ -33,12 +34,13 @@
return self;
}
- (void)dealloc {
if (nameField!=nil)
[nameField release];
if (dateField!=nil)
[dateField release];
if (messageField!=nil)
[messageField release];
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[nameField release];
[dateField release];
[messageField release];
[messageData release];
[super dealloc];
}
@ -46,7 +48,7 @@
instance = theInstance;
}
- (void)setMessageData:(NSDictionary *)theMessageData {
if (messageData!=nil) [messageData release];
[messageData release];
messageData = [theMessageData retain];
}
@ -55,16 +57,15 @@
CGRect frameRect = [[self contentView] bounds];
if (messageField!=nil) {
if (messageData!=nil) {
[nameField setText:[[instance contacts] nameForNumber:[messageData objectForKey:MGMIPhoneNumber]]];
int type = [[messageData objectForKey:MGMIType] intValue];
if (type==MGMIVoicemailType) {
if (type==MGMIVoicemailType)
[messageField setText:[messageData objectForKey:MGMIText]];
} else if (type==MGMISMSIn || type==MGMISMSOut) {
else if (type==MGMISMSInType || type==MGMISMSOutType)
[messageField setText:[[[[messageData objectForKey:MGMIMessages] lastObject] objectForKey:MGMIText] flattenHTML]];
} else {
else
[messageField setText:[[[messageData objectForKey:MGMIPhoneNumber] areaCode] areaCodeLocation]];
}
NSDate *today = [NSDate dateWithTimeIntervalSinceNow:-86400];
if ([[messageData objectForKey:MGMITime] earlierDate:today]==today) {
NSDateFormatter *formatter = [[NSDateFormatter new] autorelease];
@ -77,8 +78,19 @@
}
}
[nameField setFrame:CGRectMake(8, 3, frameRect.size.width-74, 20)];
[nameField setFrame:CGRectMake(20, 3, frameRect.size.width-86, 20)];
[dateField setFrame:CGRectMake(frameRect.size.width-64, 3, 60, 20)];
[messageField setFrame:CGRectMake(8, frameRect.size.height-35, frameRect.size.width-12, 32)];
[messageField setFrame:CGRectMake(20, frameRect.size.height-41, frameRect.size.width-18, 32)];
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect {
if (messageData!=nil) {
if (![[messageData objectForKey:MGMIRead] boolValue]) {
CGRect frameRect = [[self contentView] bounds];
MGMPath *path = [MGMPath pathWithRoundedRect:CGRectMake(4, (frameRect.size.height/2)-6.5, 13, 13) cornerRadius:6.5];
[path fillGradientFrom:[UIColor colorWithRed:0.5215 green:0.6901 blue:0.9607 alpha:1.0] to:[UIColor colorWithRed:0.1255 green:0.3138 blue:0.6589 alpha:1.0]];
}
}
[super drawRect:rect];
}
@end

View File

@ -0,0 +1,65 @@
//
// MGMMiddleView.h
// VoiceMob
//
// Created by Mr. Gecko on 10/11/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
extern NSString * const MGMMTitle;
extern NSString * const MGMMImage;
extern NSString * const MGMMTarget;
extern NSString * const MGMMAction;
extern NSString * const MGMMHighlighted;
extern NSString * const MGMMRect;
@class MGMMiddleView;
@interface MGMMiddleViewButton : NSObject {
NSString *title;
NSString *image;
id target;
SEL action;
BOOL highlighted;
CGRect rect;
}
+ (id)buttonWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction;
- (id)initWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction;
- (void)setTitle:(NSString *)theTitle;
- (NSString *)title;
- (void)setImage:(NSString *)theImage;
- (NSString *)image;
- (void)setTarget:(id)theTarget;
- (id)target;
- (void)setAction:(SEL)theAction;
- (SEL)action;
- (void)setHighlighted:(BOOL)isHighlighted;
- (BOOL)highlighted;
- (void)setRect:(CGRect)theRect;
- (CGRect)rect;
@end
@protocol MGMMiddleViewDelegate <NSObject>
- (void)middleViewDidCancel:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex;
- (void)middleViewDidSelect:(MGMMiddleView *)theMiddleView atIndex:(int)theIndex;
@end
@interface MGMMiddleView : UIView {
IBOutlet id<MGMMiddleViewDelegate> delegate;
NSMutableArray *buttons;
CGPoint touchStartPoint;
int touchStartIndex;
}
- (void)setDelegate:(id)theDelegate;
- (id<MGMMiddleViewDelegate>)delegate;
- (void)addButtonWithTitle:(NSString *)theTitle imageName:(NSString *)theImage target:(id)theTarget action:(SEL)theAction;
- (void)setButtons:(NSArray *)theButtons;
- (NSArray *)buttons;
- (void)updateButtonRects;
- (void)setHighlighted:(BOOL)isHighlighted forButtonAtIndex:(int)theIndex;
@end

View File

@ -0,0 +1,291 @@
//
// MGMMiddleView.m
// VoiceMob
//
// Created by Mr. Gecko on 10/11/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMMiddleView.h"
#import <MGMUsers/MGMUsers.h>
NSString * const MGMMFontName = @"Helvetica";
@implementation MGMMiddleViewButton
+ (id)buttonWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction {
return [[[self alloc] initWithTitle:theTitle image:theImage target:theTarget action:theAction] autorelease];
}
- (id)initWithTitle:(NSString *)theTitle image:(NSString *)theImage target:(id)theTarget action:(SEL)theAction {
if ((self = [super init])) {
title = [theTitle copy];
image = [theImage copy];
target = theTarget;
action = theAction;
}
return self;
}
- (void)dealloc {
[title release];
[image release];
[super dealloc];
}
- (void)setTitle:(NSString *)theTitle {
[title release];
title = [theTitle copy];
}
- (NSString *)title {
return title;
}
- (void)setImage:(NSString *)theImage {
[image release];
image = [theImage copy];
}
- (NSString *)image {
return image;
}
- (void)setTarget:(id)theTarget {
target = theTarget;
}
- (id)target {
return target;
}
- (void)setAction:(SEL)theAction {
action = theAction;
}
- (SEL)action {
return action;
}
- (void)setHighlighted:(BOOL)isHighlighted {
highlighted = isHighlighted;
}
- (BOOL)highlighted {
return highlighted;
}
- (void)setRect:(CGRect)theRect {
rect = theRect;
}
- (CGRect)rect {
return rect;
}
@end
@implementation MGMMiddleView
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[buttons release];
[super dealloc];
}
- (void)setDelegate:(id)theDelegate {
delegate = theDelegate;
}
- (id<MGMMiddleViewDelegate>)delegate {
return delegate;
}
- (void)addButtonWithTitle:(NSString *)theTitle imageName:(NSString *)theImage target:(id)theTarget action:(SEL)theAction {
if (buttons==nil) buttons = [NSMutableArray new];
[buttons addObject:[MGMMiddleViewButton buttonWithTitle:theTitle image:theImage target:theTarget action:theAction]];
[self updateButtonRects];
[self setNeedsDisplay];
}
- (void)setButtons:(NSArray *)theButtons {
[buttons release];
buttons = [theButtons mutableCopy];
[self updateButtonRects];
}
- (NSArray *)buttons {
return buttons;
}
- (void)updateButtonRects {
CGRect bounds = [self bounds];
int count = [buttons count];
int row = 3;
int numRow = count/row;
if (numRow<=1) {
row = 2;
numRow = count/row;
}
int width = bounds.size.width/row;
int height = bounds.size.height/numRow;
int index = 0;
for (int r=0; r<numRow; r++) {
int y = (r*height) + bounds.origin.y;
for (int i=0; i<row; i++) {
int x = (i*width) + bounds.origin.x;
CGRect buttonRect = CGRectMake(x, y, width, height);
[[buttons objectAtIndex:index] setRect:buttonRect];
index++;
}
}
}
- (void)setHighlighted:(BOOL)isHighlighted forButtonAtIndex:(int)theIndex {
[[buttons objectAtIndex:theIndex] setHighlighted:isHighlighted];
[self setNeedsDisplay];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
touchStartPoint = [touch locationInView:self];
for (int i=0; i<[buttons count]; i++) {
if (CGRectContainsPoint([[buttons objectAtIndex:i] rect], touchStartPoint)) {
touchStartIndex = i;
[self setHighlighted:YES forButtonAtIndex:i];
break;
}
}
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[self setHighlighted:NO forButtonAtIndex:touchStartIndex];
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
BOOL cancel = YES;
for (int i=0; i<[buttons count]; i++) {
if (CGRectContainsPoint([[buttons objectAtIndex:i] rect], point)) {
if (touchStartIndex==i) {
cancel = NO;
MGMMiddleViewButton *button = [buttons objectAtIndex:i];
NSMethodSignature *signature = [[button target] methodSignatureForSelector:[button action]];
if (signature!=nil) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:[button action]];
[invocation setArgument:&self atIndex:2];
[invocation setArgument:&i atIndex:3];
[invocation invokeWithTarget:[button target]];
}
if (delegate!=nil && [delegate respondsToSelector:@selector(middleViewDidSelect:atIndex:)]) [delegate middleViewDidSelect:self atIndex:touchStartIndex];
}
break;
}
}
if (cancel && delegate!=nil && [delegate respondsToSelector:@selector(middleViewDidCancel:atIndex:)]) [delegate middleViewDidCancel:self atIndex:touchStartIndex];
[super touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
if (delegate!=nil && [delegate respondsToSelector:@selector(middleViewDidCancel:atIndex:)]) [delegate middleViewDidCancel:self atIndex:touchStartIndex];
[self setHighlighted:NO forButtonAtIndex:touchStartIndex];
[super touchesCancelled:touches withEvent:event];
}
- (void)drawRect:(CGRect)frameRect {
UIColor *blackColor = [UIColor colorWithWhite:0.0 alpha:0.6];
UIColor *whiteColor = [UIColor colorWithWhite:1.0 alpha:0.1];
UIColor *highlightStartColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.6];
UIColor *highlightEndColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.5 alpha:0.6];
CGFloat radius = 20.0;
CGRect bounds = [self bounds];
MGMPath *path = [MGMPath pathWithRoundedRect:bounds cornerRadius:radius];
[path fillGradientFrom:[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:0.6] to:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.6]];
CGRect innerBounds = bounds;
innerBounds.size.width -= 1;
innerBounds.origin.x += 0.5;
innerBounds.size.height -= 1;
innerBounds.origin.y += 0.5;
MGMPath *innerPath = [MGMPath pathWithRoundedRect:innerBounds cornerRadius:radius];
[blackColor setStroke];
[innerPath stroke];
CGRect innerWhiteBounds = innerBounds;
innerWhiteBounds.size.width -= 2;
innerWhiteBounds.origin.x += 1;
innerWhiteBounds.size.height -= 2;
innerWhiteBounds.origin.y += 1;
MGMPath *innerWhitePath = [MGMPath pathWithRoundedRect:innerWhiteBounds cornerRadius:radius];
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
[innerWhitePath addClip];
int count = [buttons count];
int row = 3;
int numRow = count/row;
if (numRow<=1) {
row = 2;
numRow = count/row;
}
int width = bounds.size.width/row;
int height = bounds.size.height/numRow;
int index = 0;
for (int r=0; r<numRow; r++) {
int y = (r*height) + bounds.origin.y;
for (int i=0; i<row; i++) {
int x = (i*width) + bounds.origin.x;
MGMMiddleViewButton *button = [buttons objectAtIndex:index];
if ([button highlighted]) {
CGRect highlightRect = CGRectMake(x, y, width, height);
MGMPath *highlightPath = [MGMPath pathWithRect:highlightRect];
[highlightPath fillGradientFrom:highlightStartColor to:highlightEndColor];
}
if ([button image]!=nil) {
CGRect imageRect = CGRectMake(x+5, y+10, width-10, height-30);
UIImage *image = [UIImage imageNamed:[button image]];
CGSize size = [image size];
float scaleFactor = 0.0;
float scaledWidth = imageRect.size.width;
float scaledHeight = imageRect.size.height;
if (!CGSizeEqualToSize(size, imageRect.size)) {
float widthFactor = imageRect.size.width / size.width;
float heightFactor = imageRect.size.height / size.height;
if (widthFactor < heightFactor)
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
scaledWidth = size.width * scaleFactor;
scaledHeight = size.height * scaleFactor;
}
[image drawInRect:CGRectMake(imageRect.origin.x+((imageRect.size.width-scaledWidth)/2), imageRect.origin.y+((imageRect.size.height-scaledHeight)/2), scaledWidth, scaledHeight)];
}
if ([button title]!=nil) {
[[UIColor whiteColor] set];
UIFont *font = [UIFont fontWithName:MGMMFontName size:12.0];
CGFloat actualSize;
CGSize titleSize = [[button title] sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:width-15 lineBreakMode:UILineBreakModeClip];
font = [UIFont fontWithName:MGMMFontName size:actualSize];
titleSize = [[button title] sizeWithFont:font forWidth:width-15 lineBreakMode:UILineBreakModeClip];
CGPoint titlePoint = CGPointMake(x+((width-titleSize.width)/2), (y+height)-20);
[[button title] drawAtPoint:titlePoint withFont:font];
}
if (x!=bounds.origin.x) {
CGRect lineRect = CGRectMake(x, bounds.origin.y, 1, bounds.size.height);
MGMPath *linePath = [MGMPath pathWithRect:lineRect];
[blackColor setFill];
[linePath fill];
CGRect lineWhiteRect = CGRectMake(x+1, bounds.origin.y, 1, bounds.size.height);
MGMPath *lineWhitePath = [MGMPath pathWithRect:lineWhiteRect];
[whiteColor setFill];
[lineWhitePath fill];
}
index++;
}
if (y!=bounds.origin.y) {
CGRect lineRect = CGRectMake(bounds.origin.x, y, bounds.size.width, 1);
MGMPath *linePath = [MGMPath pathWithRect:lineRect];
[blackColor setFill];
[linePath fill];
CGRect lineWhiteRect = CGRectMake(bounds.origin.x, y-1, bounds.size.width, 1);
MGMPath *lineWhitePath = [MGMPath pathWithRect:lineWhiteRect];
[whiteColor setFill];
[lineWhitePath fill];
}
}
CGContextRestoreGState(currentContext);
[whiteColor setStroke];
[innerWhitePath stroke];
}
@end

View File

@ -3,17 +3,45 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/28/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@interface MGMNumberView : UIControl {
NSString *number;
NSString *info;
NSString *credit;
UIImage *image;
NSString *alphabet;
BOOL touching;
UIColor *startColor;
UIColor *endColor;
UIColor *touchingStartColor;
UIColor *touchingEndColor;
BOOL glass;
}
- (NSString *)number;
- (void)setStartColor:(UIColor *)theColor;
- (UIColor *)startColor;
- (void)setEndColor:(UIColor *)theColor;
- (UIColor *)endColor;
- (void)setTouchingStartColor:(UIColor *)theColor;
- (UIColor *)touchingStartColor;
- (void)setTouchingEndColor:(UIColor *)theColor;
- (UIColor *)touchingEndColor;
- (void)setImage:(UIImage *)theImage;
- (UIImage *)image;
- (void)setNumber:(NSString *)theNumber;
- (NSString *)number;
- (void)setInfo:(NSString *)theInfo;
- (NSString *)info;
- (void)setCredit:(NSString *)theCredit;
- (NSString *)credit;
- (void)setAlphabet:(NSString *)theAlphabet;
- (NSString *)alphabet;
- (void)setGlass:(BOOL)isGlass;
- (BOOL)glass;
@end

View File

@ -3,92 +3,111 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/28/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMNumberView.h"
#import "MGMPath.h"
NSString * const MGMFontName = @"Helvetica";
#import <MGMUsers/MGMUsers.h>
@implementation MGMNumberView
- (void)dealloc {
if (number!=nil)
[number release];
if (alphabet!=nil)
[alphabet release];
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[number release];
[info release];
[credit release];
[image release];
[alphabet release];
[startColor release];
[endColor release];
[touchingStartColor release];
[touchingEndColor release];
[super dealloc];
}
- (NSString *)number {
if (number==nil) {
switch ([self tag]) {
case -1:
break;
case 10:
number = [@"✱" retain];
break;
case 11:
number = [@"#" retain];
break;
case 12:
number = [@"SMS" retain];
break;
case 13:
number = [@"Call" retain];
break;
case 14:
number = [@"↵" retain];
break;
default:
number = [[[NSNumber numberWithInt:[self tag]] stringValue] copy];
break;
}
}
return number;
- (void)setFrame:(CGRect)frameRect {
[super setFrame:frameRect];
[self setNeedsDisplay];
}
- (void)setStartColor:(UIColor *)theColor {
[startColor release];
startColor = [theColor retain];
}
- (UIColor *)startColor {
return startColor;
}
- (void)setEndColor:(UIColor *)theColor {
[endColor release];
endColor = [theColor retain];
}
- (UIColor *)endColor {
return endColor;
}
- (void)setTouchingStartColor:(UIColor *)theColor {
[touchingStartColor release];
touchingStartColor = [theColor retain];
}
- (UIColor *)touchingStartColor {
return touchingStartColor;
}
- (void)setTouchingEndColor:(UIColor *)theColor {
[touchingEndColor release];
touchingEndColor = [theColor retain];
}
- (UIColor *)touchingEndColor {
return touchingEndColor;
}
- (void)setImage:(UIImage *)theImage {
[image release];
image = [theImage retain];
[self setNeedsDisplay];
}
- (UIImage *)image {
return image;
}
- (void)setInfo:(NSString *)theInfo {
[info release];
info = [theInfo retain];
[self setNeedsDisplay];
}
- (NSString *)info {
return info;
}
- (void)setCredit:(NSString *)theCredit {
[credit release];
credit = [theCredit retain];
[self setNeedsDisplay];
}
- (NSString *)credit {
return credit;
}
- (void)setNumber:(NSString *)theNumber {
if (number!=nil) [number release];
[number release];
number = [theNumber copy];
[self setNeedsDisplay];
}
- (NSString *)number {
return number;
}
- (void)setAlphabet:(NSString *)theAlphabet {
[alphabet release];
alphabet = [theAlphabet copy];
[self setNeedsDisplay];
}
- (NSString *)alphabet {
if (alphabet==nil) {
switch ([self tag]) {
case 0:
alphabet = [@"+" retain];
break;
case 2:
alphabet = [@"ABC" retain];
break;
case 3:
alphabet = [@"DEF" retain];
break;
case 4:
alphabet = [@"GHI" retain];
break;
case 5:
alphabet = [@"JKL" retain];
break;
case 6:
alphabet = [@"MNO" retain];
break;
case 7:
alphabet = [@"PQRS" retain];
break;
case 8:
alphabet = [@"TUV" retain];
break;
case 9:
alphabet = [@"WXYZ" retain];
break;
default:
break;
}
}
return alphabet;
}
- (void)setGlass:(BOOL)isGlass {
glass = isGlass;
}
- (BOOL)glass {
return glass;
}
- (void)setTouching:(BOOL)isTouching {
touching = isTouching;
[self setNeedsDisplay];
@ -107,64 +126,113 @@ NSString * const MGMFontName = @"Helvetica";
}
- (void)drawRect:(CGRect)frameRect {
UIColor *startColor = nil;
UIColor *endColor = nil;
if (touching) {
startColor = [UIColor colorWithRed:0.5 green:0.5 blue:1.0 alpha:1.0];
endColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.5 alpha:1.0];
} else {
if ([self tag]==13) {
startColor = [UIColor colorWithRed:0.5 green:1.0 blue:0.5 alpha:1.0];
endColor = [UIColor colorWithRed:0.1 green:0.5 blue:0.1 alpha:1.0];
} else if ([self tag]==14) {
startColor = [UIColor colorWithRed:1.0 green:0.5 blue:0.5 alpha:1.0];
endColor = [UIColor colorWithRed:0.5 green:0.1 blue:0.1 alpha:1.0];
} else {
startColor = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];
endColor = [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1.0];
}
if (startColor==nil) {
startColor = [[UIColor colorWithRed:0.11 green:0.14 blue:0.18 alpha:1.0] retain];
endColor = [[UIColor colorWithRed:0.04 green:0.06 blue:0.1 alpha:1.0] retain];
}
if (touchingStartColor==nil) {
UIColor *touchColor = [UIColor colorWithRed:0.12 green:0.42 blue:0.91 alpha:1.0];
touchingStartColor = [touchColor retain];
touchingEndColor = [touchColor retain];
}
CGRect bounds = [self bounds];
MGMPath *path = [MGMPath pathWithRect:bounds];
[path setLineWidth:2.0];
[[UIColor colorWithWhite:1.0 alpha:1.0] setStroke];
[path fillGradientFrom:startColor to:endColor];
[path stroke];
[path fillGradientFrom:(touching ? touchingStartColor : startColor) to:(touching ? touchingEndColor : endColor)];
if (glass) {
CGRect glassBounds = bounds;
glassBounds.size.height = glassBounds.size.height/2;
MGMPath *glassPath = [MGMPath pathWithRect:glassBounds];
[glassPath fillGradientFrom:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.3] to:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.1]];
}
CGRect line = bounds;
line.size.width += 1.5;
line.size.height += 1.5;
line.origin.x -= 0.2;
line.origin.y -= 0.2;
MGMPath *linePath = [MGMPath pathWithRect:line];
[[UIColor colorWithRed:0.3 green:0.32 blue:0.36 alpha:1.0] setStroke];
[linePath setLineWidth:2];
[linePath stroke];
[[UIColor whiteColor] set];
if ([self number]!=nil) {
if ([self tag]>=0 && [self tag]<=11) {
UIFont *font = [UIFont fontWithName:MGMFontName size:bounds.size.height-20.0];
CGFloat actualSize;
CGSize numberSize = [[self number] sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
font = [UIFont fontWithName:MGMFontName size:actualSize];
numberSize = [[self number] sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)/2, 1);
[[self number] drawAtPoint:numberPoint withFont:font];
} else {
UIFont *font = nil;
if ([self tag]<=13)
font = [UIFont fontWithName:MGMFontName size:bounds.size.height-10.0];
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGContextSaveGState(currentContext);
CGContextSetShadowWithColor(currentContext, CGSizeMake(0, 1), 3.0, [[UIColor colorWithWhite:0.0 alpha:1.0] CGColor]);
[[UIColor whiteColor] setFill];
if (image!=nil) {
CGRect imageRect;
int y = 1;
if (alphabet!=nil)
imageRect = CGRectMake(0, 0, bounds.size.width, bounds.size.height-20.0);
else
imageRect = CGRectMake(0, 0, bounds.size.width, bounds.size.height-12.0);
CGSize size = [image size];
float scaleFactor = 0.0;
float scaledWidth = imageRect.size.width;
float scaledHeight = imageRect.size.height;
if (!CGSizeEqualToSize(size, imageRect.size)) {
float widthFactor = imageRect.size.width / size.width;
float heightFactor = imageRect.size.height / size.height;
if (widthFactor < heightFactor)
scaleFactor = widthFactor;
else
font = [UIFont fontWithName:MGMFontName size:bounds.size.height-6.0];
CGFloat actualSize;
CGSize numberSize = [[self number] sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
font = [UIFont fontWithName:MGMFontName size:actualSize];
numberSize = [[self number] sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)/2, (bounds.size.height-numberSize.height)/2);
[[self number] drawAtPoint:numberPoint withFont:font];
}
}
scaleFactor = heightFactor;
if ([self alphabet]!=nil) {
UIFont *font = [UIFont fontWithName:MGMFontName size:14.0];
CGFloat actualSize;
CGSize alphabetSize = [[self alphabet] sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
font = [UIFont fontWithName:MGMFontName size:actualSize];
alphabetSize = [[self alphabet] sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
CGPoint alphabetPoint = CGPointMake((bounds.size.width-alphabetSize.width)/2, bounds.size.height-20);
[[self alphabet] drawAtPoint:alphabetPoint withFont:font];
scaledWidth = size.width * scaleFactor;
scaledHeight = size.height * scaleFactor;
}
if (alphabet==nil)
y = (bounds.size.height-scaledHeight)/2;
[image drawInRect:CGRectMake((bounds.size.width-scaledWidth)/2, y, scaledWidth, scaledHeight)];
}
if (number!=nil) {
UIFont *font = nil;
int y = 1;
if (alphabet!=nil)
font = [UIFont boldSystemFontOfSize:bounds.size.height-20.0];
else
font = [UIFont boldSystemFontOfSize:bounds.size.height-10.0];
CGFloat actualSize;
CGSize numberSize = [number sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width-4 lineBreakMode:UILineBreakModeClip];
font = [UIFont boldSystemFontOfSize:actualSize];
numberSize = [number sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
if (alphabet==nil)
y = (bounds.size.height-numberSize.height)/2;
CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)/2, y);
[number drawAtPoint:numberPoint withFont:font];
}
if (!touching)
[[UIColor colorWithRed:0.44 green:0.45 blue:0.46 alpha:1.0] setFill];
if (info!=nil) {
UIFont *font = [UIFont boldSystemFontOfSize:10.0];
CGFloat actualSize;
CGSize numberSize = [info sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width-4 lineBreakMode:UILineBreakModeClip];
font = [UIFont boldSystemFontOfSize:actualSize];
numberSize = [info sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
CGPoint numberPoint = CGPointMake(4, bounds.size.height-numberSize.height);
[info drawAtPoint:numberPoint withFont:font];
}
if (credit!=nil) {
UIFont *font = [UIFont boldSystemFontOfSize:10.0];
CGFloat actualSize;
CGSize numberSize = [credit sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width-4 lineBreakMode:UILineBreakModeClip];
font = [UIFont boldSystemFontOfSize:actualSize];
numberSize = [credit sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
CGPoint numberPoint = CGPointMake((bounds.size.width-numberSize.width)-4, bounds.size.height-numberSize.height);
[credit drawAtPoint:numberPoint withFont:font];
}
if (alphabet!=nil) {
UIFont *font = [UIFont boldSystemFontOfSize:14.0];
CGFloat actualSize;
CGSize alphabetSize = [alphabet sizeWithFont:font minFontSize:0.5 actualFontSize:&actualSize forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
font = [UIFont boldSystemFontOfSize:actualSize];
alphabetSize = [alphabet sizeWithFont:font forWidth:bounds.size.width lineBreakMode:UILineBreakModeClip];
CGPoint alphabetPoint = CGPointMake((bounds.size.width-alphabetSize.width)/2, bounds.size.height-20);
[alphabet drawAtPoint:alphabetPoint withFont:font];
}
CGContextRestoreGState(currentContext);
}
@end

View File

@ -1,9 +1,9 @@
//
// MGMLoginProcessView.h
// MGMProgressView.h
// VoiceMac
//
// Created by Mr. Gecko on 8/19/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>

View File

@ -1,16 +1,16 @@
//
// MGMLoginProcessView.m
// MGMProgressView.m
// VoiceMac
//
// Created by Mr. Gecko on 8/19/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMProgressView.h"
@implementation MGMProgressView
- (id)initWithFrame:(CGRect)frameRect {
if (self = [super initWithFrame:frameRect]) {
if ((self = [super initWithFrame:frameRect])) {
[self setBackgroundColor:[UIColor clearColor]];
progress = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[progress setFrame:CGRectMake((frameRect.size.width-37)/2, (frameRect.size.height-37)/2, 37, 37)];
@ -31,12 +31,12 @@
return self;
}
- (void)dealloc {
if (progress)
[progress release];
if (pleaseWaitField!=nil)
[pleaseWaitField release];
if (progressField!=nil)
[progressField release];
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[progress release];
[pleaseWaitField release];
[progressField release];
[super dealloc];
}
- (void)layoutSubviews {

View File

@ -0,0 +1,18 @@
//
// MGMRecordingView.h
// VoiceMob
//
// Created by Mr. Gecko on 10/14/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@interface MGMRecordingView : UITableViewCell {
UILabel *nameField;
UILabel *dateField;
NSDictionary *recording;
}
- (void)setRecording:(NSDictionary *)theRecording;
@end

View File

@ -0,0 +1,65 @@
//
// MGMRecordingView.m
// VoiceMob
//
// Created by Mr. Gecko on 10/14/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMRecordingView.h"
#import "MGMSIPRecordings.h"
@implementation MGMRecordingView
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
nameField = [[UILabel alloc] initWithFrame:CGRectZero];
[nameField setBackgroundColor:[UIColor clearColor]];
[nameField setFont:[UIFont boldSystemFontOfSize:18.0]];
[[self contentView] addSubview:nameField];
dateField = [[UILabel alloc] initWithFrame:CGRectZero];
[dateField setBackgroundColor:[UIColor clearColor]];
[dateField setFont:[UIFont systemFontOfSize:12.0]];
[dateField setTextAlignment:UITextAlignmentRight];
[dateField setTextColor:[UIColor blueColor]];
[[self contentView] addSubview:dateField];
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[nameField release];
[dateField release];
[recording release];
[super dealloc];
}
- (void)setRecording:(NSDictionary *)theRecording {
[recording release];
recording = [theRecording retain];
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect frameRect = [[self contentView] bounds];
if (recording!=nil) {
[nameField setText:[recording objectForKey:MGMRName]];
NSDate *today = [NSDate dateWithTimeIntervalSinceNow:-86400];
if ([[recording objectForKey:MGMRDate] earlierDate:today]==today) {
NSDateFormatter *formatter = [[NSDateFormatter new] autorelease];
[formatter setDateFormat:@"h:mm a"];
[dateField setText:[formatter stringFromDate:[recording objectForKey:MGMRDate]]];
} else {
NSDateFormatter *formatter = [[NSDateFormatter new] autorelease];
[formatter setDateFormat:@"M/d/yy"];
[dateField setText:[formatter stringFromDate:[recording objectForKey:MGMRDate]]];
}
}
[nameField setFrame:CGRectMake(8, (frameRect.size.height-20)/2, frameRect.size.width-74, 20)];
[dateField setFrame:CGRectMake(frameRect.size.width-64, (frameRect.size.height-20)/2, 60, 20)];
}
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>

View File

@ -3,11 +3,11 @@
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMSMSBottomView.h"
#import "MGMPath.h"
#import <MGMUsers/MGMUsers.h>
@implementation MGMSMSBottomView
- (void)drawRect:(CGRect)frameRect {

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>

View File

@ -3,11 +3,11 @@
// VoiceMob
//
// Created by Mr. Gecko on 10/1/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMSMSTextView.h"
#import "MGMPath.h"
#import <MGMUsers/MGMUsers.h>
@implementation MGMSMSTextView
- (void)awakeFromNib {

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@ -11,11 +11,10 @@
@class MGMVoiceUser;
@interface MGMVoiceContacts : MGMContactsController <UIActionSheetDelegate> {
@interface MGMVoiceContacts : MGMContactsController {
MGMVoiceUser *voiceUser;
IBOutlet UIView *view;
NSDictionary *selectedContact;
}
+ (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser;
- (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser;

View File

@ -3,11 +3,13 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMVoiceContacts.h"
#import "MGMVoiceUser.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMVoiceSMS.h"
#import "MGMVMAddons.h"
#import <VoiceBase/VoiceBase.h>
@ -17,11 +19,18 @@
return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease];
}
- (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser {
if (self = [super initWithAccountController:[theVoiceUser accountController]]) {
if ((self = [super initWithAccountController:[theVoiceUser accountController]])) {
voiceUser = theVoiceUser;
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[super dealloc];
}
- (MGMVoiceUser *)voiceUser {
return voiceUser;
@ -34,8 +43,6 @@
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceContacts"] owner:self options:nil]) {
NSLog(@"Unable to load Voice Contacts");
[self release];
self = nil;
} else {
[super awakeFromNib];
}
@ -43,32 +50,16 @@
return view;
}
- (void)releaseView {
if (view!=nil) {
[view release];
view = nil;
}
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[view release];
view = nil;
[super releaseView];
}
- (void)selectedContact:(NSDictionary *)theContact {
selectedContact = theContact;
UIActionSheet *theAction = [[UIActionSheet new] autorelease];
[theAction addButtonWithTitle:@"Call"];
[theAction addButtonWithTitle:@"SMS"];
[theAction addButtonWithTitle:@"Reverse Lookup"];
[theAction addButtonWithTitle:@"Cancel"];
[theAction setCancelButtonIndex:3];
[theAction setDelegate:self];
[theAction showInView:[voiceUser view]];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==0) {
[voiceUser call:[selectedContact objectForKey:MGMCNumber]];
} else if (buttonIndex==1) {
[[[voiceUser tabObjects] objectAtIndex:MGMSMSTabIndex] messageWithNumber:[selectedContact objectForKey:MGMCNumber] instance:[voiceUser instance]];
}
selectedContact = nil;
[voiceUser showOptionsForNumber:[theContact objectForKey:MGMCNumber]];
[contactsTable deselectRowAtIndexPath:[contactsTable indexPathForSelectedRow] animated:YES];
}
@end

View File

@ -3,23 +3,27 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/30/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@class MGMVoiceUser, MGMProgressView, MGMInstance;
@class MGMVoiceUser, MGMProgressView, MGMInstance, MGMURLConnectionManager, AVAudioPlayer;
@interface MGMVoiceInbox : NSObject {
@interface MGMVoiceInbox : NSObject <UIWebViewDelegate, AVAudioPlayerDelegate> {
MGMVoiceUser *voiceUser;
IBOutlet UITableView *inboxesTable;
IBOutlet UITableView *messagesTable;
MGMProgressView *progressView;
NSDate *lastUpdate;
int currentView;
NSArray *inboxItems;
NSArray *recordingItems;
NSArray *messagesItems;
IBOutlet UITableView *inboxesTable;
IBOutlet UITableView *inboxTable;
IBOutlet UIWebView *recordingView;
MGMProgressView *progressView;
int progressStartCount;
int currentInbox;
@ -27,23 +31,32 @@
unsigned int start;
int resultsCount;
float rightMax;
float leftMax;
NSMutableArray *currentData;
NSDate *lastDate;
int currentRecording;
MGMURLConnectionManager *recordingConnection;
AVAudioPlayer *recordingPlayer;
NSTimer *recordingUpdater;
}
+ (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser;
- (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser;
- (void)registerSettings;
- (MGMVoiceUser *)voiceUser;
- (void)checkVoicemail;
- (UIView *)view;
- (void)releaseView;
- (void)startProgress;
- (void)startProgress:(NSString *)theTitle;
- (void)stopProgress;
- (void)loadInbox;
- (void)addData:(NSArray *)theData;
- (int)currentInbox;
- (void)setRecording:(int)theRecording;
@end

View File

@ -3,20 +3,29 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/30/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMVoiceInbox.h"
#import "MGMVoiceUser.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMVoiceSMS.h"
#import "MGMBadgeView.h"
#import "MGMInboxMessageView.h"
#import "MGMProgressView.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
static NSMutableArray *MGMInboxItems;
NSString * const MGMSInboxPlist = @"inbox.plist";
NSString * const MGMSInbox = @"MGMSInbox";
NSString * const MGMSLastUpdate = @"MGMSLastUpdate";
NSString * const MGMSResultsCount = @"MGMSResultsCount";
NSString * const MGMSStart = @"MGMSStart";
NSString * const MGMSName = @"name";
NSString * const MGMSID = @"id";
@ -24,12 +33,15 @@ NSString * const MGMInboxesCellIdentifier = @"MGMInboxesCellIdentifier";
NSString * const MGMInboxMessageCellIdentifier = @"MGMInboxMessageCellIdentifier";
NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellIdentifier";
NSString * const MGMITLoading = @"Loading...";
NSString * const MGMITDeleting = @"Deleting...";
@implementation MGMVoiceInbox
+ (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser {
return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease];
}
- (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser {
if (self = [super init]) {
if ((self = [super init])) {
if (MGMInboxItems==nil) {
MGMInboxItems = [NSMutableArray new];
[MGMInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Inbox", MGMSName, [NSNumber numberWithInt:0], MGMSID, nil]];
@ -44,68 +56,141 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId
[MGMInboxItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:@"Missed", MGMSName, [NSNumber numberWithInt:9], MGMSID, nil]];
}
voiceUser = theVoiceUser;
currentView = -1;
currentInbox = 0;
[self registerSettings];
lastUpdate = [[[voiceUser user] settingForKey:MGMSLastUpdate] retain];
currentView = 1;
currentInbox = [[[voiceUser user] settingForKey:MGMSInbox] intValue];
maxResults = 10;
start = 0;
resultsCount = 0;
messagesItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inboxes" style:UIBarButtonItemStyleBordered target:self action:@selector(showInboxes:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain];
start = [[[voiceUser user] settingForKey:MGMSStart] intValue];
resultsCount = [[[voiceUser user] settingForKey:MGMSResultsCount] intValue];
inboxItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inboxes" style:UIBarButtonItemStyleBordered target:self action:@selector(showInboxes:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain];
recordingItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Inbox" style:UIBarButtonItemStyleBordered target:self action:@selector(showInbox:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain];
currentData = [NSMutableArray new];
currentRecording = -1;
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[lastUpdate release];
[inboxItems release];
[recordingItems release];
[currentData release];
[lastDate release];
[recordingConnection cancelAll];
[recordingConnection release];
[recordingPlayer release];
[super dealloc];
}
- (void)registerSettings {
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
[settings setObject:[NSNumber numberWithInt:0] forKey:MGMSInbox];
[settings setObject:[NSNumber numberWithInt:0] forKey:MGMSResultsCount];
[settings setObject:[NSNumber numberWithInt:0] forKey:MGMSStart];
[[voiceUser user] registerSettings:settings];
}
- (MGMVoiceUser *)voiceUser {
return voiceUser;
}
- (NSString *)title {
if (currentRecording!=-1)
return [[[currentData objectAtIndex:currentRecording] objectForKey:MGMIPhoneNumber] readableNumber];
return [voiceUser title];
}
- (void)checkVoicemail {
[[[voiceUser instance] inbox] getVoicemailForPage:1 delegate:self didFailWithError:@selector(voicemail:didFailWithError:instance:) didReceiveInfo:@selector(voicemailGotInfo:instance:)];
}
- (void)voicemail:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
NSLog(@"Voicemail Error: %@ for instance: %@", theError, theInstance);
}
- (void)voicemailGotInfo:(NSArray *)theMessages instance:(MGMInstance *)theInstance {
NSDate *newestDate = [NSDate distantPast];
BOOL newMessage = NO;
for (unsigned int i=0; i<[theMessages count]; i++) {
if (![[[theMessages objectAtIndex:i] objectForKey:MGMIRead] boolValue] && (lastDate==nil || (![lastDate isEqual:[[theMessages objectAtIndex:i] objectForKey:MGMITime]] && [lastDate earlierDate:[[theMessages objectAtIndex:i] objectForKey:MGMITime]]==lastDate))) {
newMessage = YES;
if ([newestDate earlierDate:[[theMessages objectAtIndex:i] objectForKey:MGMITime]]==newestDate)
newestDate = [[theMessages objectAtIndex:i] objectForKey:MGMITime];
}
}
if (newMessage) {
[lastDate release];
lastDate = [newestDate copy];
[[[[voiceUser accountController] controller] themeManager] playSound:MGMTSVoicemail];
}
}
- (UIView *)view {
if (currentView==-1) {
currentView = 1;
[self loadInbox];
}
if (inboxesTable==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceInbox"] owner:self options:nil]) {
NSLog(@"Unable to load Voice Inbox");
[self release];
self = nil;
} else {
if (lastUpdate==nil || [lastUpdate earlierDate:[NSDate dateWithTimeIntervalSinceNow:-300]]==lastUpdate) {
start = 0;
resultsCount = 0;
[self loadInbox];
} else if ([currentData count]<=0 && [[NSFileManager defaultManager] fileExistsAtPath:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSInboxPlist]]) {
[currentData addObjectsFromArray:[NSArray arrayWithContentsOfFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSInboxPlist]]];
}
CGSize contentSize = [[voiceUser tabView] frame].size;
progressView = [[MGMProgressView alloc] initWithFrame:CGRectMake(0, 0, contentSize.width, contentSize.height)];
[progressView setProgressTitle:@"Loading..."];
[progressView setHidden:(progressStartCount<=0)];
if (progressStartCount>0) {
[progressView startProgess];
[progressView setProgressTitle:MGMITLoading];
[[voiceUser tabView] performSelector:@selector(addSubview:) withObject:progressView afterDelay:0.1];
}
[recordingView setDelegate:self];
[recordingView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"recording" ofType:@"html"]]]];
if (currentView==1)
[[voiceUser accountController] setItems:messagesItems animated:YES];
[[voiceUser accountController] setItems:inboxItems animated:YES];
else if (currentView==2)
[[voiceUser accountController] setItems:recordingItems animated:YES];
else
[[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES];
[[voiceUser accountController] setTitle:[self title]];
}
}
if (currentView==1)
return messagesTable;
return inboxTable;
if (currentView==2)
return recordingView;
return inboxesTable;
}
- (void)releaseView {
if (inboxesTable!=nil) {
[inboxesTable release];
inboxesTable = nil;
}
if (messagesTable!=nil) {
[messagesTable release];
messagesTable = nil;
}
if (progressView!=nil) {
[progressView release];
progressView = nil;
}
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[inboxesTable release];
inboxesTable = nil;
[inboxTable release];
inboxTable = nil;
[progressView release];
progressView = nil;
[recordingView release];
recordingView = nil;
[recordingUpdater invalidate];
[recordingUpdater release];
recordingUpdater = nil;
[recordingPlayer pause];
[currentData writeToFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSInboxPlist] atomically:YES];
[currentData removeAllObjects];
}
- (void)startProgress {
- (void)startProgress:(NSString *)theTitle {
if (progressView!=nil) {
[progressView setProgressTitle:theTitle];
CGRect viewFrame = [progressView frame];
viewFrame.size = [[voiceUser tabView] frame].size;
[progressView setFrame:viewFrame];
if ([progressView superview]==nil)
[[voiceUser tabView] addSubview:progressView];
[progressView startProgess];
@ -114,17 +199,17 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId
progressStartCount++;
}
- (void)stopProgress {
if (progressView!=nil) {
if (progressStartCount==1) {
[progressView stopProgess];
[progressView removeFromSuperview];
}
if (progressStartCount==1) {
[progressView stopProgess];
[progressView removeFromSuperview];
}
progressStartCount--;
}
- (IBAction)showInboxes:(id)sender {
CGRect outViewFrame = [inboxTable frame];
CGRect inViewFrame = [inboxesTable frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[inboxesTable setFrame:inViewFrame];
[[voiceUser tabView] addSubview:inboxesTable];
@ -133,56 +218,84 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(inboxesAnimationDidStop:finished:context:)];
[inboxesTable setFrame:[messagesTable frame]];
CGRect outViewFrame = [messagesTable frame];
[inboxesTable setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[messagesTable setFrame:outViewFrame];
[inboxTable setFrame:outViewFrame];
[UIView commitAnimations];
[[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES];
currentView = 0;
}
- (void)inboxesAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[messagesTable removeFromSuperview];
[inboxTable removeFromSuperview];
currentInbox = -1;
start = 0;
resultsCount = 0;
[currentData removeAllObjects];
[messagesTable reloadData];
[inboxTable reloadData];
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section {
if (theTableView==inboxesTable)
return [MGMInboxItems count];
else if (theTableView==messagesTable)
else if (theTableView==inboxTable)
return (resultsCount==maxResults ? [currentData count]+1 : [currentData count]);
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (theTableView==inboxesTable) {
UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMInboxesCellIdentifier];
MGMBadgeView *cell = (MGMBadgeView *)[inboxesTable dequeueReusableCellWithIdentifier:MGMInboxesCellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxesCellIdentifier] autorelease];
cell = [[[MGMBadgeView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxesCellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
[cell setText:[[MGMInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMSName]];
NSDictionary *info = [MGMInboxItems objectAtIndex:[indexPath indexAtPosition:1]];
[cell setName:[info objectForKey:MGMSName]];
NSString *countName = @"";
int sid = [[info objectForKey:MGMSID] intValue];
if (sid==0)
countName = MGMUCInbox;
else if (sid==1)
countName = MGMUCStarred;
else if (sid==2)
countName = MGMUCSpam;
else if (sid==3)
countName = MGMUCTrash;
else if (sid==4)
countName = MGMUCVoicemail;
else if (sid==5)
countName = MGMUCSMS;
else if (sid==6)
countName = MGMUCRecorded;
else if (sid==7)
countName = MGMUCPlaced;
else if (sid==8)
countName = MGMUCReceived;
else if (sid==9)
countName = MGMUCMissed;
if ([[[[voiceUser instance] unreadCounts] objectForKey:countName] intValue]!=0)
[cell setBadge:[[[[voiceUser instance] unreadCounts] objectForKey:countName] stringValue]];
else
[cell setBadge:nil];
return cell;
} else if (theTableView==messagesTable) {
} else if (theTableView==inboxTable) {
if ([currentData count]<=[indexPath indexAtPosition:1]) {
UITableViewCell *cell = [inboxesTable dequeueReusableCellWithIdentifier:MGMInboxMessageLoadCellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxMessageLoadCellIdentifier] autorelease];
[cell setText:@"Load More..."];
NSString *text = @"Load More...";
if ([cell respondsToSelector:@selector(textLabel)]) {
[[cell textLabel] setText:text];
[[cell textLabel] setTextColor:[UIColor blueColor]];
[[cell textLabel] setTextAlignment:UITextAlignmentCenter];
} else {
[cell setText:text];
[cell setTextColor:[UIColor blueColor]];
[cell setTextAlignment:UITextAlignmentCenter];
}
}
return cell;
} else {
MGMInboxMessageView *cell = (MGMInboxMessageView *)[messagesTable dequeueReusableCellWithIdentifier:MGMInboxMessageCellIdentifier];
MGMInboxMessageView *cell = (MGMInboxMessageView *)[inboxTable dequeueReusableCellWithIdentifier:MGMInboxMessageCellIdentifier];
if (cell==nil) {
cell = [[[MGMInboxMessageView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMInboxMessageCellIdentifier] autorelease];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
@ -203,64 +316,94 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId
return UITableViewCellEditingStyleDelete;
}
- (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
return @"Delete";
return (currentInbox==3 ? @"Delete Forever" : @"Delete");
}
- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *data = [currentData objectAtIndex:[indexPath indexAtPosition:1]];
[self startProgress:MGMITDeleting];
if (currentInbox==3)
[[[voiceUser instance] inbox] deleteEntriesForever:[NSArray arrayWithObject:[data objectForKey:MGMIID]] delegate:self];
else
[[[voiceUser instance] inbox] deleteEntries:[NSArray arrayWithObject:[data objectForKey:MGMIID]] delegate:self];
}
- (void)delete:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
NSLog(@"Delete Error: %@ for instance: %@", theError, theInstance);
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error deleting"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
[self stopProgress];
}
- (void)deleteDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance {
int dataCount = [currentData count]-1;
for (int i=0; i<resultsCount; i++) {
[currentData removeObjectAtIndex:dataCount-i];
}
[self loadInbox];
[self stopProgress];
}
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (theTableView==inboxesTable) {
currentInbox = [[[MGMInboxItems objectAtIndex:[indexPath indexAtPosition:1]] objectForKey:MGMSID] intValue];
[[messagesItems objectAtIndex:0] setEnabled:NO];
[[voiceUser accountController] setItems:messagesItems animated:YES];
[[voiceUser user] setSetting:[NSNumber numberWithInt:currentInbox] forKey:MGMSInbox];
[[inboxItems objectAtIndex:0] setEnabled:NO];
[[voiceUser accountController] setItems:inboxItems animated:YES];
CGRect inViewFrame = [messagesTable frame];
CGRect outViewFrame = [inboxesTable frame];
CGRect inViewFrame = [inboxTable frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[messagesTable setFrame:inViewFrame];
[[voiceUser tabView] addSubview:messagesTable];
[inboxTable setFrame:inViewFrame];
[[voiceUser tabView] addSubview:inboxTable];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(messagesAnimationDidStop:finished:context:)];
[messagesTable setFrame:[inboxesTable frame]];
CGRect outViewFrame = [inboxesTable frame];
[UIView setAnimationDidStopSelector:@selector(inboxAnimationDidStop:finished:context:)];
[inboxTable setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[inboxesTable setFrame:outViewFrame];
[UIView commitAnimations];
currentView = 1;
[self loadInbox];
} else if (theTableView==messagesTable) {
} else if (theTableView==inboxTable) {
if ([indexPath indexAtPosition:1]>=[currentData count]) {
start += maxResults;
[self loadInbox];
} else {
NSDictionary *data = [currentData objectAtIndex:[indexPath indexAtPosition:1]];
int type = [[data objectForKey:MGMIType] intValue];
if (type==MGMIVoicemailType) {
} else if (type==MGMIRecordedType) {
} else if (type==MGMISMSIn || type==MGMISMSOut) {
[[[voiceUser tabObjects] objectAtIndex:MGMSMSTabIndex] messageWithData:data instance:[voiceUser instance]];
} else {
}
NSMutableDictionary *data = [[[currentData objectAtIndex:[indexPath indexAtPosition:1]] mutableCopy] autorelease];
if (![[data objectForKey:MGMIRead] boolValue]) {
[[[voiceUser instance] inbox] markEntries:[NSArray arrayWithObject:[data objectForKey:MGMIID]] read:![[data objectForKey:MGMIRead] boolValue] delegate:self];
[data setObject:[NSNumber numberWithBool:![[data objectForKey:MGMIRead] boolValue]] forKey:MGMIRead];
[currentData replaceObjectAtIndex:[indexPath indexAtPosition:1] withObject:data];
[inboxTable reloadData];
}
int type = [[data objectForKey:MGMIType] intValue];
if (type==MGMIVoicemailType || type==MGMIRecordedType) {
[self setRecording:[indexPath indexAtPosition:1]];
} else if (type==MGMISMSInType || type==MGMISMSOutType) {
[[[voiceUser tabObjects] objectAtIndex:MGMVUSMSTabIndex] messageWithData:data instance:[voiceUser instance]];
} else {
[voiceUser showOptionsForNumber:[data objectForKey:MGMIPhoneNumber]];
[inboxTable deselectRowAtIndexPath:[inboxTable indexPathForSelectedRow] animated:YES];
}
}
}
}
- (void)messagesAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
- (void)inboxAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[inboxesTable removeFromSuperview];
[inboxesTable deselectRowAtIndexPath:[inboxesTable indexPathForSelectedRow] animated:NO];
[[messagesItems objectAtIndex:0] setEnabled:YES];
[[inboxItems objectAtIndex:0] setEnabled:YES];
}
- (void)loadInbox {
[lastUpdate release];
lastUpdate = [NSDate new];
[[voiceUser user] setSetting:lastUpdate forKey:MGMSLastUpdate];
[[voiceUser user] setSetting:[NSNumber numberWithInt:start] forKey:MGMSStart];
int page = (start/maxResults)+1;
[self startProgress];
[self startProgress:MGMITLoading];
switch (currentInbox) {
case 0:
[[[voiceUser instance] inbox] getInboxForPage:page delegate:self didFailWithError:@selector(inbox:didFailWithError:instance:) didReceiveInfo:@selector(inboxGotInfo:instance:)];
@ -294,13 +437,13 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId
break;
}
}
- (void)inbox:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
- (void)inbox:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
NSLog(@"Inbox Error: %@ for instance: %@", theError, theInstance);
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Error loading inbox"];
[theAlert setMessage:[theError localizedDescription]];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error loading inbox"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
[self stopProgress];
}
- (void)inboxGotInfo:(NSArray *)theInfo instance:(MGMInstance *)theInstance {
@ -312,10 +455,173 @@ NSString * const MGMInboxMessageLoadCellIdentifier = @"MGMInboxMessageLoadCellId
}
- (void)addData:(NSArray *)theData {
resultsCount = [theData count];
[[voiceUser user] setSetting:[NSNumber numberWithInt:resultsCount] forKey:MGMSResultsCount];
[currentData addObjectsFromArray:theData];
[messagesTable reloadData];
[inboxTable reloadData];
}
- (int)currentInbox {
return currentInbox;
}
- (void)setRecording:(int)theRecording {
currentRecording = theRecording;
if (currentRecording==-1)
return;
NSMutableDictionary *data = [currentData objectAtIndex:currentRecording];
int type = [[data objectForKey:MGMIType] intValue];
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerLoading()"];
NSString *transcript = @"";
if (type==MGMIVoicemailType)
transcript = [data objectForKey:MGMIText];
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setTranscription('%@')", [transcript javascriptEscape]]];
[[recordingItems objectAtIndex:0] setEnabled:NO];
[[voiceUser accountController] setItems:recordingItems animated:YES];
if (recordingConnection==nil)
recordingConnection = [[MGMURLConnectionManager managerWithCookieStorage:[[voiceUser instance] cookieStorage]] retain];
MGMURLBasicHandler *handler = [MGMURLBasicHandler handlerWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:MGMIVoiceMailDownloadURL, [[data objectForKey:MGMIID] addPercentEscapes]]]] delegate:self];
[recordingConnection addHandler:handler];
CGRect outViewFrame = [inboxTable frame];
CGRect inViewFrame = [recordingView frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[recordingView setFrame:inViewFrame];
[[voiceUser tabView] addSubview:recordingView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(recordingAnimationDidStop:finished:context:)];
[recordingView setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[inboxTable setFrame:outViewFrame];
[UIView commitAnimations];
currentView = 2;
[[voiceUser accountController] setTitle:[self title]];
}
- (void)recordingAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[inboxTable removeFromSuperview];
[inboxTable deselectRowAtIndexPath:[inboxTable indexPathForSelectedRow] animated:NO];
[[recordingItems objectAtIndex:0] setEnabled:YES];
}
- (void)request:(MGMURLBasicHandler *)theHandler didFailWithError:(NSError *)theError {
NSLog(@"Starting Audio Error: %@", theError);
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error loading audio"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (void)requestDidFinish:(MGMURLBasicHandler *)theHandler {
recordingPlayer = [[AVAudioPlayer alloc] initWithData:[theHandler data] error:nil];
[recordingPlayer setDelegate:self];
if (recordingView!=nil) {
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]];
[recordingView stringByEvaluatingJavaScriptFromString:@"setCurrent(0)"];
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"];
[recordingPlayer play];
recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain];
}
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPaused()"];
}
- (void)updateRecording {
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSString *scheme = [[url scheme] lowercaseString];
NSString *data = [url resourceSpecifier];
NSString *queryData = [url query];
NSDictionary *query;
if (queryData) {
NSMutableArray *dataArr = [NSMutableArray arrayWithArray:[data componentsSeparatedByString:@"?"]];
[dataArr removeLastObject];
data = [dataArr componentsJoinedByString:@"?"];
NSMutableDictionary *dataDic = [NSMutableDictionary dictionary];
NSArray *parameters = [queryData componentsSeparatedByString:@"&"];
for (int i=0; i<[parameters count]; i++) {
NSArray *info = [[parameters objectAtIndex:i] componentsSeparatedByString:@"="];
[dataDic setObject:[[[info subarrayWithRange:NSMakeRange(1, [info count]-1)] componentsJoinedByString:@"="] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[info objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
query = [NSDictionary dictionaryWithDictionary:dataDic];
}
if ([data hasPrefix:@"//"])
data = [data substringFromIndex:2];
if ([scheme isEqual:@"voicemob"]) {
if ([data isEqual:@"pause"])
[recordingPlayer pause];
else if ([data isEqual:@"play"])
[recordingPlayer play];
else if ([data isEqual:@"start"])
[recordingPlayer setCurrentTime:[[query objectForKey:@"time"] intValue]];
} else if ([scheme isEqual:@"tel"]) {
[voiceUser call:[data phoneFormatWithAreaCode:[voiceUser areaCode]]];
} else if ([scheme isEqual:@"file"]) {
return YES;
} else {
[[UIApplication sharedApplication] openURL:url];
}
return NO;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if (currentRecording!=-1) {
if (recordingPlayer!=nil) {
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setDurration(%d)", (int)[recordingPlayer duration]]];
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setCurrent(%d)", (int)[recordingPlayer currentTime]]];
[recordingView stringByEvaluatingJavaScriptFromString:@"setPlayerPlaying()"];
[recordingPlayer play];
recordingUpdater = [[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateRecording) userInfo:nil repeats:YES] retain];
}
NSMutableDictionary *data = [currentData objectAtIndex:currentRecording];
int type = [[data objectForKey:MGMIType] intValue];
NSString *transcript = @"";
if (type==MGMIVoicemailType)
transcript = [data objectForKey:MGMIText];
[recordingView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"setTranscription('%@')", [transcript javascriptEscape]]];
}
}
- (IBAction)showInbox:(id)sender {
[[inboxItems objectAtIndex:0] setEnabled:NO];
[[voiceUser accountController] setItems:inboxItems animated:YES];
[recordingPlayer release];
recordingPlayer = nil;
[recordingUpdater invalidate];
[recordingUpdater release];
recordingUpdater = nil;
[recordingConnection cancelAll];
[recordingConnection release];
recordingConnection = nil;
CGRect outViewFrame = [recordingView frame];
CGRect inViewFrame = [inboxTable frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[inboxTable setFrame:inViewFrame];
[[voiceUser tabView] addSubview:inboxTable];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(showInboxAnimationDidStop:finished:context:)];
[inboxTable setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[recordingView setFrame:outViewFrame];
[UIView commitAnimations];
currentView = 1;
}
- (void)showInboxAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
[recordingView removeFromSuperview];
[[inboxItems objectAtIndex:0] setEnabled:YES];
currentRecording = -1;
[[voiceUser accountController] setTitle:[self title]];
}
@end

View File

@ -0,0 +1,86 @@
//
// MGMVoiceMultiSMS.h
// VoiceMob
//
// Created by James on 12/2/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <Foundation/Foundation.h>
#import "MGMContactsController.h"
@class MGMInstance, MGMController, MGMNumberView;
@interface MGMVoiceMultiSMS : MGMContactsController <UIActionSheetDelegate> {
MGMInstance *instance;
MGMController *controller;
IBOutlet UIView *view;
IBOutlet UIBarButtonItem *sendButton;
IBOutlet UIBarButtonItem *cancelButton;
IBOutlet UITextView *SMSTextView;
IBOutlet UILabel *SMSTextCountField;
NSArray *groups;
IBOutlet UIButton *groupButton;
IBOutlet UIView *groupView;
IBOutlet UIPickerView *groupPicker;
NSMutableArray *additional;
IBOutlet UIButton *additionalButton;
IBOutlet UIView *additionalView;
int currentTab;
IBOutlet UIView *tabView;
IBOutlet UITabBar *tabBar;
IBOutlet UIView *keypadView;
IBOutlet UIView *contactsView;
IBOutlet UITableView *selectedView;
IBOutlet MGMNumberView *numberView;
IBOutlet MGMNumberView *number1View;
IBOutlet MGMNumberView *number2View;
IBOutlet MGMNumberView *number3View;
IBOutlet MGMNumberView *number4View;
IBOutlet MGMNumberView *number5View;
IBOutlet MGMNumberView *number6View;
IBOutlet MGMNumberView *number7View;
IBOutlet MGMNumberView *number8View;
IBOutlet MGMNumberView *number9View;
IBOutlet MGMNumberView *numberStarView;
IBOutlet MGMNumberView *number0View;
IBOutlet MGMNumberView *numberPondView;
IBOutlet MGMNumberView *numberRemoveView;
IBOutlet MGMNumberView *numberAddView;
IBOutlet MGMNumberView *numberDeleteView;
IBOutlet UITableView *numbersTable;
}
- (id)initWithInstance:(MGMInstance *)theInstance controller:(MGMController *)theController;
- (MGMInstance *)instance;
- (MGMController *)controller;
- (UIView *)view;
- (IBAction)chooseGroup:(id)sender;
- (IBAction)closeGroups:(id)sender;
- (IBAction)chooseAdditional:(id)sender;
- (IBAction)numberDecide:(id)sender;
- (IBAction)dial:(id)sender;
- (IBAction)delete:(id)sender;
- (IBAction)add:(id)sender;
- (IBAction)remove:(id)sender;
- (IBAction)closeAdditional:(id)sender;
- (IBAction)close:(id)sender;
- (IBAction)send:(id)sender;
@end
@interface MGMMultiSMSTextView : UITextView {
}
@end

View File

@ -0,0 +1,457 @@
//
// MGMVoiceMultiSMS.m
// VoiceMob
//
// Created by James on 12/2/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMVoiceMultiSMS.h"
#import "MGMController.h"
#import "MGMNumberView.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
NSString * const MGMAdditionalCellIdentifier = @"MGMAdditionalCellIdentifier";
NSString * const MGMKeyboardBoundsM = @"UIKeyboardBoundsUserInfoKey";
@implementation MGMVoiceMultiSMS
- (id)initWithInstance:(MGMInstance *)theInstance controller:(MGMController *)theController {
if ((self = [super init])) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceMultiSMS"] owner:self options:nil]) {
NSLog(@"Unable to load Multi SMS");
[self release];
self = nil;
} else {
instance = theInstance;
controller = theController;
accountController = [controller accountController];
groups = [[[instance contacts] groups] retain];
additional = [NSMutableArray new];
[tabView addSubview:keypadView];
[tabBar setSelectedItem:[[tabBar items] objectAtIndex:0]];
[numberView setNumber:@""];
[numberView setStartColor:[UIColor colorWithRed:0.19 green:0.22 blue:0.37 alpha:1.0]];
[numberView setEndColor:[UIColor colorWithRed:0.04 green:0.16 blue:0.33 alpha:1.0]];
[numberView setGlass:YES];
[number1View setNumber:@"1"];
[number1View setAlphabet:@""];
[number2View setNumber:@"2"];
[number2View setAlphabet:@"ABC"];
[number3View setNumber:@"3"];
[number3View setAlphabet:@"DEF"];
[number4View setNumber:@"4"];
[number4View setAlphabet:@"GHI"];
[number5View setNumber:@"5"];
[number5View setAlphabet:@"JKL"];
[number6View setNumber:@"6"];
[number6View setAlphabet:@"MNO"];
[number7View setNumber:@"7"];
[number7View setAlphabet:@"PQRS"];
[number8View setNumber:@"8"];
[number8View setAlphabet:@"TUV"];
[number9View setNumber:@"9"];
[number9View setAlphabet:@"WXYZ"];
[numberStarView setNumber:@"✱"];
[numberStarView setAlphabet:@""];
[number0View setNumber:@"0"];
[number0View setAlphabet:@"+"];
[numberPondView setNumber:@"#"];
[numberPondView setAlphabet:@""];
[numberRemoveView setNumber:@""];
[numberRemoveView setStartColor:[UIColor colorWithRed:0.79 green:0.18 blue:0.07 alpha:1.0]];
[numberRemoveView setEndColor:[UIColor colorWithRed:0.76 green:0.19 blue:0.13 alpha:1.0]];
[numberRemoveView setGlass:YES];
[numberAddView setNumber:@"+"];
[numberAddView setStartColor:[UIColor colorWithRed:0.13 green:0.81 blue:0.1 alpha:1.0]];
[numberAddView setEndColor:[UIColor colorWithRed:0.11 green:0.69 blue:0.09 alpha:1.0]];
[numberAddView setGlass:YES];
[numberDeleteView setImage:[[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DeleteKey" ofType:@"png"]] autorelease]];
UIColor *darkColor = [UIColor colorWithRed:0.02 green:0.09 blue:0.19 alpha:1.0];
[numberDeleteView setStartColor:darkColor];
[numberDeleteView setEndColor:darkColor];
[numberDeleteView setGlass:YES];
NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter];
[notifications addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[notifications addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[groups release];
[view release];
[sendButton release];
[cancelButton release];
[SMSTextView release];
[SMSTextCountField release];
[groupButton release];
[groupView release];
[groupPicker release];
[tabView release];
[tabBar release];
[keypadView release];
[contactsView release];
[selectedView release];
[additional release];
[additionalButton release];
[additionalView release];
[numberView release];
[number1View release];
[number2View release];
[number3View release];
[number4View release];
[number5View release];
[number6View release];
[number7View release];
[number8View release];
[number9View release];
[numberStarView release];
[number0View release];
[numberPondView release];
[numberRemoveView release];
[numberAddView release];
[numberDeleteView release];
[numbersTable release];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (MGMInstance *)instance {
return instance;
}
- (MGMController *)controller {
return controller;
}
- (UIView *)view {
return view;
}
- (IBAction)chooseGroup:(id)sender {
[SMSTextView resignFirstResponder];
CGRect inViewFrame = [groupView frame];
inViewFrame.origin.y = +[[self view] frame].size.height;
[groupView setFrame:inViewFrame];
[[self view] addSubview:groupView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [groupView frame];
outViewFrame.origin.y -= outViewFrame.size.height;
[groupView setFrame:outViewFrame];
[UIView commitAnimations];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)theComponent {
return [groups count]+1;
}
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)theRow forComponent:(NSInteger)theComponent {
if (theRow!=0) {
NSDictionary *group = [groups objectAtIndex:theRow-1];
return [NSString stringWithFormat:@"%@ (%@)", [group objectForKey:MGMCName], [[instance contacts] membersCountOfGroup:group]];
}
return @"None";
}
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)theRow inComponent:(NSInteger)theComponent {
NSString *title = [self pickerView:thePickerView titleForRow:theRow forComponent:theComponent];
[groupButton setTitle:title forState:UIControlStateNormal];
}
- (IBAction)closeGroups:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:groups:)];
CGRect outViewFrame = [groupView frame];
outViewFrame.origin.y = +[[self view] frame].size.height;
[groupView setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished groups:(id)context {
[groupView removeFromSuperview];
}
- (IBAction)chooseAdditional:(id)sender {
[SMSTextView resignFirstResponder];
CGRect inViewFrame = [additionalView frame];
inViewFrame.origin.y = +[[self view] frame].size.height;
[additionalView setFrame:inViewFrame];
[[self view] addSubview:additionalView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [additionalView frame];
outViewFrame.origin.y -= outViewFrame.size.height;
[additionalView setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)theItem {
int tabIndex = [[tabBar items] indexOfObject:theItem];
if (tabIndex==currentTab)
return;
UIView *newTabView = nil;
if (tabIndex==0)
newTabView = keypadView;
else if (tabIndex==1) {
[super awakeFromNib];
newTabView = contactsView;
} else if (tabIndex==2) {
[selectedView reloadData];
newTabView = selectedView;
}
CGRect tabFrame = [newTabView frame];
tabFrame.size = [tabView frame].size;
[newTabView setFrame:tabFrame];
[tabView addSubview:newTabView];
if (currentTab==0)
[keypadView removeFromSuperview];
else if (currentTab==1) {
[super cleanup];
[contactsView removeFromSuperview];
} else if (currentTab==2)
[selectedView removeFromSuperview];
currentTab = tabIndex;
}
- (IBAction)numberDecide:(id)sender {
UIActionSheet *theAction = [[UIActionSheet new] autorelease];
[theAction addButtonWithTitle:@"Copy"];
BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil);
if (pasteEnabled)
[theAction addButtonWithTitle:@"Paste"];
[theAction addButtonWithTitle:@"Reverse Lookup"];
[theAction addButtonWithTitle:@"Cancel"];
[theAction setCancelButtonIndex:(pasteEnabled ? 3 : 2)];
[theAction setDelegate:self];
[theAction showInView:additionalView];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil);
if (buttonIndex==0) {
[[UIPasteboard generalPasteboard] setString:[numberView number]];
} else if (pasteEnabled && buttonIndex==1) {
[numberView setNumber:[[[UIPasteboard generalPasteboard] string] readableNumber]];
} else if ((pasteEnabled && buttonIndex==2) || (!pasteEnabled && buttonIndex==1)) {
[controller showReverseLookupWithNumber:[[numberView number] phoneFormatWithAreaCode:[instance userAreaCode]]];
}
}
- (IBAction)dial:(id)sender {
NSString *number = [numberView number];
if ([number length]==0 && [sender tag]==0) {
[numberView setNumber:@"+"];
} else {
NSString *numberAdd = nil;
switch ([sender tag]) {
case 10:
case 11:
break;
default:
numberAdd = [[NSNumber numberWithInt:[sender tag]] stringValue];
break;
}
if (numberAdd!=nil)
number = [number stringByAppendingString:numberAdd];
[numberView setNumber:[number readableNumber]];
}
}
- (IBAction)delete:(id)sender {
NSString *number = [numberView number];
if ([number length]!=0) {
number = [number substringToIndex:[number length]-1];
[numberView setNumber:[number readableNumber]];
}
}
- (IBAction)add:(id)sender {
NSString *number = [[numberView number] phoneFormatWithAreaCode:[instance userAreaCode]];
if (![additional containsObject:number])
[additional addObject:number];
[numberView setNumber:@""];
}
- (IBAction)remove:(id)sender {
NSString *number = [[numberView number] phoneFormatWithAreaCode:[instance userAreaCode]];
[additional removeObject:number];
}
- (MGMContacts *)contacts {
return [instance contacts];
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)theSection {
if (theTableView!=numbersTable)
return [super tableView:theTableView numberOfRowsInSection:theSection];
return [additional count];
}
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)theIndexPath {
if (theTableView!=numbersTable)
return [super tableView:theTableView cellForRowAtIndexPath:theIndexPath];
UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:MGMAdditionalCellIdentifier];
if (cell==nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MGMAdditionalCellIdentifier] autorelease];
}
NSString *number = [[additional objectAtIndex:[theIndexPath indexAtPosition:1]] readableNumber];
NSString *name = [[instance contacts] nameForNumber:[additional objectAtIndex:[theIndexPath indexAtPosition:1]]];
if (name!=nil && ![name isEqual:number])
number = [NSString stringWithFormat:@"%@ (%@)", number, name];
if ([cell respondsToSelector:@selector(textLabel)])
[[cell textLabel] setText:number];
else
[cell setText:number];
return cell;
}
- (BOOL)tableView:(UITableView *)theTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (theTableView==selectedView)
return YES;
return NO;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)theTableView editingStyleForRowAtIndexPath:(NSIndexPath *)theIndexPath {
return UITableViewCellEditingStyleDelete;
}
- (NSString *)tableView:(UITableView *)theTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)theIndexPath {
return @"Remove";
}
- (void)tableView:(UITableView *)theTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)theIndexPath {
[additional removeObjectAtIndex:[theIndexPath indexAtPosition:1]];
[selectedView reloadData];
}
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)theIndexPath {
if (theTableView!=numbersTable)
[super tableView:theTableView didSelectRowAtIndexPath:theIndexPath];
}
- (void)selectedContact:(NSDictionary *)theContact {
NSString *number = [theContact objectForKey:MGMCNumber];
if (![additional containsObject:number])
[additional addObject:number];
[contactsTable deselectRowAtIndexPath:[contactsTable indexPathForSelectedRow] animated:YES];
}
- (IBAction)closeAdditional:(id)sender {
NSString *numbers = @"None";
if ([additional count]==1) {
numbers = [[additional objectAtIndex:0] readableNumber];
} else if ([additional count]>1) {
numbers = [NSString stringWithFormat:@"%@, …", [[additional objectAtIndex:0] readableNumber]];
}
[additionalButton setTitle:numbers forState:UIControlStateNormal];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:additional:)];
CGRect outViewFrame = [additionalView frame];
outViewFrame.origin.y = +[[self view] frame].size.height;
[additionalView setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished additional:(id)context {
[additionalView removeFromSuperview];
}
- (void)keyboardWillShow:(NSNotification *)theNotification {
CGSize keyboardSize = CGSizeZero;
if ([[theNotification userInfo] objectForKey:MGMKeyboardBoundsM]!=nil)
keyboardSize = [[[theNotification userInfo] objectForKey:MGMKeyboardBoundsM] CGRectValue].size;
else
keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect frame = [SMSTextView frame];
frame.size.height -= keyboardSize.height;
[SMSTextView setFrame:frame];
}
- (void)textViewDidChange:(UITextView *)textView {
[SMSTextCountField setText:[[NSNumber numberWithInt:160-[[SMSTextView text] length]] stringValue]];
}
- (void)keyboardWillHide:(NSNotification *)theNotification {
CGSize keyboardSize = CGSizeZero;
if ([[theNotification userInfo] objectForKey:MGMKeyboardBoundsM]!=nil)
keyboardSize = [[[theNotification userInfo] objectForKey:MGMKeyboardBoundsM] CGRectValue].size;
else
keyboardSize = [[[theNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect frame = [SMSTextView frame];
frame.size.height += keyboardSize.height;
[SMSTextView setFrame:frame];
}
- (IBAction)close:(id)sender {
[SMSTextView resignFirstResponder];
[controller dismissMultiSMS:self];
}
- (IBAction)send:(id)sender {
NSMutableArray *SMSNumbers = [NSMutableArray arrayWithArray:additional];
if ([groupPicker selectedRowInComponent:0]!=0) {
NSArray *members = [[instance contacts] membersOfGroupID:[[groups objectAtIndex:[groupPicker selectedRowInComponent:0]-1] objectForKey:MGMCDocID]];
for (unsigned int i=0; i<[members count]; i++) {
[SMSNumbers addObject:[[members objectAtIndex:i] objectForKey:MGMCNumber]];
}
}
if ([SMSNumbers count]<=0) {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error sending a SMS Message"];
[alert setMessage:@"You need to at least have 1 contact to send to."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
} else if ([[SMSTextView text] isEqual:@""]) {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error sending a SMS Message"];
[alert setMessage:@"Message is blank."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
} else {
[SMSTextView resignFirstResponder];
[SMSTextView setEditable:NO];
[sendButton setTitle:@"Sending..."];
[sendButton setEnabled:NO];
[cancelButton setEnabled:NO];
[[instance inbox] sendMessage:[SMSTextView text] phoneNumbers:SMSNumbers smsID:@"" delegate:self];
}
}
- (void)message:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
[SMSTextView setEditable:YES];
[sendButton setTitle:@"Send"];
[sendButton setEnabled:YES];
[cancelButton setEnabled:YES];
[SMSTextView becomeFirstResponder];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error sending a SMS Message"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (void)messageDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance {
[controller dismissMultiSMS:self];
}
@end
@implementation MGMMultiSMSTextView
- (void)awakeFromNib {
[self setContentInset:UIEdgeInsetsMake(0.0, 0.0, 5.0, 0.0)];
}
- (void)setContentOffset:(CGPoint)theOffset {
if ([self isTracking] || [self isDecelerating]) {
[self setContentInset:UIEdgeInsetsMake(0.0, 0.0, 5.0, 0.0)];
[super setContentOffset:theOffset];
} else {
[super setContentOffset:theOffset];
[self setContentInset:UIEdgeInsetsMake(0.0, 0.0, 5.0, 0.0)];
}
}
@end

View File

@ -3,20 +3,40 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@class MGMVoiceUser, MGMNumberView;
@interface MGMVoicePad : NSObject {
@interface MGMVoicePad : NSObject <UIActionSheetDelegate> {
MGMVoiceUser *voiceUser;
IBOutlet UIView *view;
NSString *info;
NSString *credit;
NSString *numberString;
IBOutlet MGMNumberView *numberView;
IBOutlet MGMNumberView *number1View;
IBOutlet MGMNumberView *number2View;
IBOutlet MGMNumberView *number3View;
IBOutlet MGMNumberView *number4View;
IBOutlet MGMNumberView *number5View;
IBOutlet MGMNumberView *number6View;
IBOutlet MGMNumberView *number7View;
IBOutlet MGMNumberView *number8View;
IBOutlet MGMNumberView *number9View;
IBOutlet MGMNumberView *numberStarView;
IBOutlet MGMNumberView *number0View;
IBOutlet MGMNumberView *numberPondView;
IBOutlet MGMNumberView *numberSMSView;
IBOutlet MGMNumberView *numberCallView;
IBOutlet MGMNumberView *numberDeleteView;
IBOutlet UIView *phonesView;
IBOutlet UIPickerView *phonesPicker;
}
+ (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser;
- (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser;
@ -26,7 +46,15 @@
- (UIView *)view;
- (void)releaseView;
- (void)updateInfo;
- (void)setCredit:(NSString *)theCredit;
- (IBAction)numberDecide:(id)sender;
- (IBAction)closePhones:(id)sender;
- (IBAction)dial:(id)sender;
- (IBAction)delete:(id)sender;
- (IBAction)call:(id)sender;
- (IBAction)sms:(id)sender;
@end

View File

@ -3,29 +3,37 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/29/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMVoicePad.h"
#import "MGMVoiceUser.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMVoiceSMS.h"
#import "MGMNumberView.h"
#import "MGMVMAddons.h"
#import <VoiceBase/VoiceBase.h>
#import <MGMUsers/MGMUsers.h>
@implementation MGMVoicePad
+ (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser {
return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease];
}
- (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser {
if (self = [super init]) {
if ((self = [super init])) {
voiceUser = theVoiceUser;
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
if (numberString!=nil)
[numberString release];
[info release];
[credit release];
[numberString release];
[super dealloc];
}
@ -37,22 +45,187 @@
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoicePad"] owner:self options:nil]) {
NSLog(@"Unable to load Voice Pad");
[self release];
self = nil;
} else {
if (numberString!=nil)
[numberView setNumber:numberString];
else
[numberView setNumber:@""];
[numberView setInfo:info];
[numberView setCredit:credit];
[numberView setStartColor:[UIColor colorWithRed:0.19 green:0.22 blue:0.37 alpha:1.0]];
[numberView setEndColor:[UIColor colorWithRed:0.04 green:0.16 blue:0.33 alpha:1.0]];
[numberView setGlass:YES];
[number1View setNumber:@"1"];
[number1View setAlphabet:@""];
[number2View setNumber:@"2"];
[number2View setAlphabet:@"ABC"];
[number3View setNumber:@"3"];
[number3View setAlphabet:@"DEF"];
[number4View setNumber:@"4"];
[number4View setAlphabet:@"GHI"];
[number5View setNumber:@"5"];
[number5View setAlphabet:@"JKL"];
[number6View setNumber:@"6"];
[number6View setAlphabet:@"MNO"];
[number7View setNumber:@"7"];
[number7View setAlphabet:@"PQRS"];
[number8View setNumber:@"8"];
[number8View setAlphabet:@"TUV"];
[number9View setNumber:@"9"];
[number9View setAlphabet:@"WXYZ"];
[numberStarView setNumber:@"✱"];
[numberStarView setAlphabet:@""];
[number0View setNumber:@"0"];
[number0View setAlphabet:@"+"];
[numberPondView setNumber:@"#"];
[numberPondView setAlphabet:@""];
[numberSMSView setNumber:@"SMS"];
UIColor *darkColor = [UIColor colorWithRed:0.02 green:0.09 blue:0.19 alpha:1.0];
[numberSMSView setStartColor:darkColor];
[numberSMSView setEndColor:darkColor];
[numberSMSView setGlass:YES];
[numberCallView setNumber:@"Call"];
[numberCallView setStartColor:[UIColor colorWithRed:0.13 green:0.81 blue:0.1 alpha:1.0]];
[numberCallView setEndColor:[UIColor colorWithRed:0.11 green:0.69 blue:0.09 alpha:1.0]];
[numberCallView setGlass:YES];
[numberDeleteView setImage:[[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"DeleteKey" ofType:@"png"]] autorelease]];
[numberDeleteView setStartColor:darkColor];
[numberDeleteView setEndColor:darkColor];
[numberDeleteView setGlass:YES];
}
}
return view;
}
- (void)releaseView {
if (view!=nil) {
[view release];
view = nil;
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[view release];
view = nil;
[numberView release];
numberView = nil;
[number1View release];
number1View = nil;
[number2View release];
number2View = nil;
[number3View release];
number3View = nil;
[number4View release];
number4View = nil;
[number5View release];
number5View = nil;
[number6View release];
number6View = nil;
[number7View release];
number7View = nil;
[number8View release];
number8View = nil;
[number9View release];
number9View = nil;
[numberStarView release];
numberStarView = nil;
[number0View release];
number0View = nil;
[numberPondView release];
numberPondView = nil;
[numberSMSView release];
numberSMSView = nil;
[numberCallView release];
numberCallView = nil;
[numberDeleteView release];
numberDeleteView = nil;
[phonesView release];
phonesView = nil;
[phonesPicker release];
phonesPicker = nil;
}
- (void)updateInfo {
[info release];
info = nil;
if ([[[voiceUser instance] userPhoneNumbers] count]>=1) {
if ([[[voiceUser instance] userPhoneNumbers] count]<([[[voiceUser user] settingForKey:MGMLastUserPhoneKey] intValue]+1))
[[voiceUser user] setSetting:[NSNumber numberWithInt:0] forKey:MGMLastUserPhoneKey];
NSDictionary *phone = [[[voiceUser instance] userPhoneNumbers] objectAtIndex:[[[voiceUser user] settingForKey:MGMLastUserPhoneKey] intValue]];
info = [[NSString stringWithFormat:@"%@ [%@]", [[phone objectForKey:MGMPhoneNumber] readableNumber], [phone objectForKey:MGMName]] retain];
}
[numberView setInfo:info];
}
- (void)setCredit:(NSString *)theCredit {
[credit release];
credit = [theCredit retain];
[numberView setCredit:credit];
}
- (IBAction)numberDecide:(id)sender {
UIActionSheet *theAction = [[UIActionSheet new] autorelease];
[theAction addButtonWithTitle:@"Copy"];
BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil);
if (pasteEnabled)
[theAction addButtonWithTitle:@"Paste"];
[theAction addButtonWithTitle:@"Reverse Lookup"];
[theAction addButtonWithTitle:@"Change Ring Phone"];
[theAction addButtonWithTitle:@"Cancel"];
[theAction setCancelButtonIndex:(pasteEnabled ? 4 : 3)];
[theAction setDelegate:self];
[theAction showInView:[voiceUser view]];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
BOOL pasteEnabled = ([[UIPasteboard generalPasteboard] string]!=nil);
if (buttonIndex==0) {
[[UIPasteboard generalPasteboard] setString:numberString];
} else if (pasteEnabled && buttonIndex==1) {
[numberString release];
numberString = [[[[UIPasteboard generalPasteboard] string] readableNumber] copy];
[numberView setNumber:numberString];
} else if ((pasteEnabled && buttonIndex==2) || (!pasteEnabled && buttonIndex==1)) {
[[[voiceUser accountController] controller] showReverseLookupWithNumber:[numberString phoneFormatWithAreaCode:[voiceUser areaCode]]];
} else if ((pasteEnabled && buttonIndex==3) || (!pasteEnabled && buttonIndex==2)) {
[phonesPicker reloadAllComponents];
[phonesPicker selectRow:[[[voiceUser user] settingForKey:MGMLastUserPhoneKey] intValue] inComponent:0 animated:NO];
CGRect inViewFrame = [phonesView frame];
inViewFrame.origin.y = +([[self view] frame].size.height+[[voiceUser tabBar] frame].size.height);
[phonesView setFrame:inViewFrame];
[[self view] addSubview:phonesView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
CGRect outViewFrame = [phonesView frame];
outViewFrame.origin.y -= outViewFrame.size.height+[[voiceUser tabBar] frame].size.height;
[phonesView setFrame:outViewFrame];
[UIView commitAnimations];
}
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)theComponent {
return [[[voiceUser instance] userPhoneNumbers] count];
}
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)theRow forComponent:(NSInteger)theComponent {
NSDictionary *phone = [[[voiceUser instance] userPhoneNumbers] objectAtIndex:theRow];
return [NSString stringWithFormat:@"%@ [%@]", [[phone objectForKey:MGMPhoneNumber] readableNumber], [phone objectForKey:MGMName]];
}
- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)theRow inComponent:(NSInteger)theComponent {
[[voiceUser user] setSetting:[NSNumber numberWithInt:theRow] forKey:MGMLastUserPhoneKey];
[self updateInfo];
}
- (IBAction)closePhones:(id)sender {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(dismissAnimationDidStop:finished:groups:)];
CGRect outViewFrame = [phonesView frame];
outViewFrame.origin.y = +([[self view] frame].size.height+[[voiceUser tabBar] frame].size.height);
[phonesView setFrame:outViewFrame];
[UIView commitAnimations];
}
- (void)dismissAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished groups:(id)context {
[phonesView removeFromSuperview];
}
- (IBAction)dial:(id)sender {
@ -71,7 +244,7 @@
}
if (numberAdd!=nil)
number = [number stringByAppendingString:numberAdd];
if (numberString!=nil) [numberString release];
[numberString release];
numberString = [[number readableNumber] copy];
[numberView setNumber:numberString];
}
@ -80,7 +253,7 @@
NSString *number = [numberView number];
if ([number length]!=0) {
number = [number substringToIndex:[number length]-1];
if (numberString!=nil) [numberString release];
[numberString release];
numberString = [[number readableNumber] copy];
[numberView setNumber:numberString];
}
@ -89,11 +262,22 @@
if ([numberString isPhoneComplete]) {
[voiceUser call:[numberString phoneFormatWithAreaCode:[voiceUser areaCode]]];
} else {
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Incorrect Number"];
[theAlert setMessage:@"The phone number you have entered is incorrect."];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Incorrect Number"];
[alert setMessage:@"The phone number you have entered is incorrect."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
}
- (IBAction)sms:(id)sender {
if ([numberString isPhoneComplete]) {
[[[voiceUser tabObjects] objectAtIndex:MGMVUSMSTabIndex] messageWithNumber:[numberString phoneFormatWithAreaCode:[voiceUser areaCode]] instance:[voiceUser instance]];
} else {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Incorrect Number"];
[alert setMessage:@"The phone number you have entered is incorrect."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
}
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/30/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>
@ -14,6 +14,7 @@
MGMVoiceUser *voiceUser;
NSArray *messageItems;
NSArray *messagesItems;
NSMutableArray *SMSMessages;
int currentSMSMessage;

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/30/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMVoiceSMS.h"
@ -14,6 +14,9 @@
#import "MGMInboxMessageView.h"
#import "MGMVMAddons.h"
#import <VoiceBase/VoiceBase.h>
#import <MGMUsers/MGMUsers.h>
NSString * const MGMSMSDB = @"sms.db";
NSString * const MGMMessageViewText = @"MGMMessageViewText";
NSString * const MGMKeyboardBounds = @"UIKeyboardBoundsUserInfoKey";
@ -27,11 +30,13 @@ const float updateTimeInterval = 300.0;
return [[[self alloc] initWithVoiceUser:theVoiceUser] autorelease];
}
- (id)initWithVoiceUser:(MGMVoiceUser *)theVoiceUser {
if (self = [super init]) {
if ((self = [super init])) {
voiceUser = theVoiceUser;
messageItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Messages" style:UIBarButtonItemStyleBordered target:self action:@selector(showMessages:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showSettings:)] autorelease], nil] retain];
messagesItems = [[NSArray arrayWithObjects:[[[UIBarButtonItem alloc] initWithTitle:@"Accounts" style:UIBarButtonItemStyleBordered target:[voiceUser accountController] action:@selector(showAccounts:)] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL] autorelease], [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showMulti:)] autorelease], nil] retain];
SMSMessages = [NSMutableArray new];
currentSMSMessage = -1;
updateTimer = [[NSTimer scheduledTimerWithTimeInterval:updateTimeInterval target:self selector:@selector(update) userInfo:nil repeats:YES] retain];
@ -39,7 +44,16 @@ const float updateTimeInterval = 300.0;
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[self releaseView];
[messageItems release];
[messagesItems release];
[SMSMessages release];
[lastDate release];
[updateTimer invalidate];
[updateTimer release];
[super dealloc];
}
@ -49,14 +63,20 @@ const float updateTimeInterval = 300.0;
- (MGMThemeManager *)themeManager {
return [[[voiceUser accountController] controller] themeManager];
}
- (NSString *)title {
if (currentSMSMessage!=-1)
return [[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMIPhoneNumber] readableNumber];
return [voiceUser title];
}
- (UIView *)view {
if (messageView==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceSMS"] owner:self options:nil]) {
NSLog(@"Unable to load Voice SMS");
[self release];
self = nil;
} else {
if ([SMSMessages count]<=0 && [[NSFileManager defaultManager] fileExistsAtPath:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSMSDB]])
[SMSMessages addObjectsFromArray:[NSArray arrayWithContentsOfFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSMSDB]]];
[SMSTextCountField setHidden:YES];
[SMSView setDelegate:self];
if (currentSMSMessage!=-1) {
@ -65,10 +85,12 @@ const float updateTimeInterval = 300.0;
[self buildHTML];
[[voiceUser accountController] setItems:messageItems animated:YES];
} else {
[[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES];
[[voiceUser accountController] setItems:messagesItems animated:YES];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
NSNotificationCenter *notifications = [NSNotificationCenter defaultCenter];
[notifications addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[notifications addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[[voiceUser accountController] setTitle:[self title]];
}
}
if (currentSMSMessage!=-1)
@ -76,25 +98,33 @@ const float updateTimeInterval = 300.0;
return messagesTable;
}
- (void)releaseView {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (messagesTable!=nil) {
[messagesTable release];
messagesTable = nil;
}
[messagesTable release];
messagesTable = nil;
if (messageView!=nil) {
if (currentSMSMessage!=-1) {
NSMutableDictionary *messageInfo = [[SMSMessages objectAtIndex:currentSMSMessage] mutableCopy];
NSMutableDictionary *messageInfo = [NSMutableDictionary dictionaryWithDictionary:[SMSMessages objectAtIndex:currentSMSMessage]];
[messageInfo setObject:[SMSTextView text] forKey:MGMMessageViewText];
[SMSMessages replaceObjectAtIndex:currentSMSMessage withObject:messageInfo];
[messageInfo release];
}
[messageView release];
messageView = nil;
SMSView = nil;
SMSBottomView = nil;
SMSTextView = nil;
SMSTextCountField = nil;
}
[SMSView release];
SMSView = nil;
[SMSBottomView release];
SMSBottomView = nil;
[SMSTextView release];
SMSTextView = nil;
[SMSTextCountField release];
SMSTextCountField = nil;
[SMSSendButton release];
SMSSendButton = nil;
[SMSMessages writeToFile:[[[voiceUser user] supportPath] stringByAppendingPathComponent:MGMSMSDB] atomically:YES];
[SMSMessages removeAllObjects];
}
@ -106,15 +136,13 @@ const float updateTimeInterval = 300.0;
- (void)checkSMSMessages {
[[[voiceUser instance] inbox] getSMSForPage:1 delegate:self];
}
- (void)inbox:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
- (void)inbox:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
NSLog(@"SMS Error: %@ for instance: %@", theError, theInstance);
}
- (void)inboxGotInfo:(NSArray *)theMessages instance:(MGMInstance *)theInstance {
if (updateTimer!=nil) {
[updateTimer invalidate];
[updateTimer release];
updateTimer = [[NSTimer scheduledTimerWithTimeInterval:updateTimeInterval target:self selector:@selector(update) userInfo:nil repeats:YES] retain];
}
[updateTimer invalidate];
[updateTimer release];
updateTimer = [[NSTimer scheduledTimerWithTimeInterval:updateTimeInterval target:self selector:@selector(update) userInfo:nil repeats:YES] retain];
NSDate *newestDate = [NSDate distantPast];
BOOL newMessage = NO;
BOOL newTab = NO;
@ -144,7 +172,7 @@ const float updateTimeInterval = 300.0;
}
}
if (newMessage) {
if (lastDate!=nil) [lastDate release];
[lastDate release];
lastDate = [newestDate copy];
[[self themeManager] playSound:MGMTSSMSMessage];
if (currentSMSMessage==-1 && messagesTable!=nil)
@ -165,7 +193,7 @@ const float updateTimeInterval = 300.0;
[self view];
NSMutableDictionary *messageInfo = [NSMutableDictionary dictionary];
[messageInfo setObject:[NSArray array] forKey:MGMIMessages];
[messageInfo setObject:[NSNumber numberWithInt:MGMISMSOut] forKey:MGMIType];
[messageInfo setObject:[NSNumber numberWithInt:MGMISMSOutType] forKey:MGMIType];
[messageInfo setObject:[NSDate date] forKey:MGMITime];
[messageInfo setObject:[[theInstance contacts] nameForNumber:theNumber] forKey:MGMTInName];
[messageInfo setObject:theNumber forKey:MGMIPhoneNumber];
@ -180,11 +208,15 @@ const float updateTimeInterval = 300.0;
if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil)
[SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]];
[self buildHTML];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex];
[[voiceUser tabBar] setSelectedItem:thisTab];
[voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab];
CGRect viewFrame = [messageView frame];
viewFrame.size = [[voiceUser tabView] frame].size;
[messageView setFrame:viewFrame];
[[voiceUser tabView] addSubview:messageView];
[messagesTable removeFromSuperview];
[[voiceUser accountController] setTitle:[self title]];
break;
}
}
@ -195,11 +227,15 @@ const float updateTimeInterval = 300.0;
if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil)
[SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]];
[self buildHTML];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex];
[[voiceUser tabBar] setSelectedItem:thisTab];
[voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab];
CGRect viewFrame = [messageView frame];
viewFrame.size = [[voiceUser tabView] frame].size;
[messageView setFrame:viewFrame];
[[voiceUser tabView] addSubview:messageView];
[messagesTable removeFromSuperview];
[[voiceUser accountController] setTitle:[self title]];
}
[[voiceUser accountController] setItems:messageItems animated:YES];
}
@ -215,7 +251,7 @@ const float updateTimeInterval = 300.0;
[SMSView loadHTMLString:@"" baseURL:nil];
}
[self view];
NSMutableDictionary *messageInfo = [NSMutableDictionary dictionaryWithDictionary:theData];
NSMutableDictionary *messageInfo = [[theData mutableCopy] autorelease];
[messageInfo setObject:[[theInstance contacts] nameForNumber:[messageInfo objectForKey:MGMIPhoneNumber]] forKey:MGMTInName];
[messageInfo setObject:[theInstance userNumber] forKey:MGMTUserNumber];
BOOL window = NO;
@ -227,11 +263,15 @@ const float updateTimeInterval = 300.0;
if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil)
[SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]];
[self buildHTML];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex];
[[voiceUser tabBar] setSelectedItem:thisTab];
[voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab];
CGRect viewFrame = [messageView frame];
viewFrame.size = [[voiceUser tabView] frame].size;
[messageView setFrame:viewFrame];
[[voiceUser tabView] addSubview:messageView];
[messagesTable removeFromSuperview];
[[voiceUser accountController] setTitle:[self title]];
break;
}
}
@ -242,22 +282,30 @@ const float updateTimeInterval = 300.0;
if ([[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]!=nil)
[SMSTextView setText:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMMessageViewText]];
[self buildHTML];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMSMSTabIndex];
UITabBarItem *thisTab = [[[voiceUser tabBar] items] objectAtIndex:MGMVUSMSTabIndex];
[[voiceUser tabBar] setSelectedItem:thisTab];
[voiceUser tabBar:[voiceUser tabBar] didSelectItem:thisTab];
CGRect viewFrame = [messageView frame];
viewFrame.size = [[voiceUser tabView] frame].size;
[messageView setFrame:viewFrame];
[[voiceUser tabView] addSubview:messageView];
[messagesTable removeFromSuperview];
[[voiceUser accountController] setTitle:[self title]];
}
[[voiceUser accountController] setItems:messageItems animated:YES];
}
- (IBAction)showMulti:(id)sender {
[[[voiceUser accountController] controller] showMultiSMSWithInstance:[voiceUser instance]];
}
- (IBAction)showMessages:(id)sender {
if (sendingMessage) {
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Sending a SMS Message"];
[theAlert setMessage:@"Your SMS Message is currently being sent, please wait for it to be sent."];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Sending a SMS Message"];
[alert setMessage:@"Your SMS Message is currently being sent, please wait for it to be sent."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
} else if (marking) {
} else if (![[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMIRead] boolValue]) {
@ -265,7 +313,9 @@ const float updateTimeInterval = 300.0;
[[[voiceUser instance] inbox] markEntries:[NSArray arrayWithObject:[[SMSMessages objectAtIndex:currentSMSMessage] objectForKey:MGMIID]] read:YES delegate:self];
} else {
[messagesTable reloadData];
CGRect outViewFrame = [messageView frame];
CGRect inViewFrame = [messagesTable frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = -inViewFrame.size.width;
[messagesTable setFrame:inViewFrame];
[[voiceUser tabView] addSubview:messagesTable];
@ -274,23 +324,22 @@ const float updateTimeInterval = 300.0;
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(messagesAnimationDidStop:finished:context:)];
[messagesTable setFrame:[messageView frame]];
CGRect outViewFrame = [messageView frame];
[messagesTable setFrame:outViewFrame];
outViewFrame.origin.x = +outViewFrame.size.width;
[messageView setFrame:outViewFrame];
[UIView commitAnimations];
[[voiceUser accountController] setItems:[[voiceUser accountController] accountItems] animated:YES];
[[voiceUser accountController] setItems:messagesItems animated:YES];
}
}
- (void)mark:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
- (void)mark:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
marking = NO;
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Error marking as read"];
[theAlert setMessage:[theError localizedDescription]];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error marking as read"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (void)markDidFinish:(NSDictionary *)theInfo instance:(MGMInstance *)theInstance {
- (void)markDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance {
marking = NO;
[self setMessage:currentSMSMessage read:YES];
[self showMessages:self];
@ -305,6 +354,7 @@ const float updateTimeInterval = 300.0;
[self textViewDidChange:SMSTextView];
currentSMSMessage = -1;
[SMSView loadHTMLString:@"" baseURL:nil];
[[voiceUser accountController] setTitle:[self title]];
}
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section {
@ -341,7 +391,9 @@ const float updateTimeInterval = 300.0;
[[messageItems objectAtIndex:0] setEnabled:NO];
[[voiceUser accountController] setItems:messageItems animated:YES];
CGRect outViewFrame = [messagesTable frame];
CGRect inViewFrame = [messageView frame];
inViewFrame.size = outViewFrame.size;
inViewFrame.origin.x = +inViewFrame.size.width;
[messageView setFrame:inViewFrame];
[[voiceUser tabView] addSubview:messageView];
@ -350,8 +402,7 @@ const float updateTimeInterval = 300.0;
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(messageAnimationDidStop:finished:context:)];
[messageView setFrame:[messagesTable frame]];
CGRect outViewFrame = [messagesTable frame];
[messageView setFrame:outViewFrame];
outViewFrame.origin.x = -outViewFrame.size.width;
[messagesTable setFrame:outViewFrame];
[UIView commitAnimations];
@ -360,6 +411,7 @@ const float updateTimeInterval = 300.0;
[messagesTable removeFromSuperview];
[messagesTable deselectRowAtIndexPath:[messagesTable indexPathForSelectedRow] animated:NO];
[[messageItems objectAtIndex:0] setEnabled:YES];
[[voiceUser accountController] setTitle:[self title]];
}
- (void)setMessage:(int)theMessage read:(BOOL)isRead {
@ -460,9 +512,8 @@ const float updateTimeInterval = 300.0;
UIScrollView *SMSScrollView = [[SMSView subviews] objectAtIndex:0];
[SMSScrollView setContentInset:UIEdgeInsetsZero];
[SMSScrollView setScrollIndicatorInsets:UIEdgeInsetsZero];
if (heightDifference<0) {
if (heightDifference<0)
[SMSScrollView scrollRectToVisible:CGRectMake(0, [SMSScrollView contentSize].height-44, 320, 44) animated:NO];
}
}
if (![SMSTextCountField isHidden])
[SMSTextCountField setText:[[NSNumber numberWithInt:160-[[SMSTextView text] length]] stringValue]];
@ -486,7 +537,7 @@ const float updateTimeInterval = 300.0;
[SMSView setFrame:SMSViewFrame];
UIScrollView *SMSScrollView = [[SMSView subviews] objectAtIndex:0];
UIEdgeInsets SMSScrollContentInset = [SMSScrollView contentInset];
SMSScrollContentInset.bottom += (keyboardSize.height-SMSBottomFrame.size.height)-SMSViewHeightDifference;
//SMSScrollContentInset.bottom -= (keyboardSize.height-SMSBottomFrame.size.height)-SMSViewHeightDifference;
[SMSScrollView setContentInset:SMSScrollContentInset];
UIEdgeInsets SMSScrollInset = [SMSScrollView scrollIndicatorInsets];
SMSScrollInset.bottom += (keyboardSize.height-SMSBottomFrame.size.height)-SMSViewHeightDifference;
@ -518,14 +569,15 @@ const float updateTimeInterval = 300.0;
[message setObject:[messageInfo objectForKey:MGMIPhoneNumber] forKey:MGMIPhoneNumber];
}
[messageArray addObject:message];
}NSString *html = [[self themeManager] buildHTMLWithMessages:messageArray messageInfo:messageInfo];
}
NSString *html = [[self themeManager] buildHTMLWithMessages:messageArray messageInfo:messageInfo];
[SMSView loadHTMLString:html baseURL:[NSURL fileURLWithPath:[[self themeManager] currentThemeVariantPath]]];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[SMSView stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"];
}
- (void)addMessage:(NSDictionary *)theMessage withInfo:(NSMutableDictionary *)theMessageInfo {
NSArray *messages = [theMessageInfo objectForKey:MGMIMessage];
NSArray *messages = [theMessageInfo objectForKey:MGMIMessages];
NSString *yPhotoPath = [[[voiceUser instance] contacts] cachedPhotoForNumber:[theMessageInfo objectForKey:MGMTUserNumber]];
if (yPhotoPath==nil)
yPhotoPath = [[[self themeManager] outgoingIconPath] filePath];
@ -534,21 +586,31 @@ const float updateTimeInterval = 300.0;
tPhotoPath = [[[self themeManager] incomingIconPath] filePath];
NSMutableDictionary *message = [NSMutableDictionary dictionaryWithDictionary:theMessage];
[message setObject:[[NSNumber numberWithInt:[messages count]-1] stringValue] forKey:MGMIID];
NSMutableArray *classes = [NSMutableArray array];
int type = 1;
if ([[message objectForKey:MGMIYou] boolValue]) {
[classes addObject:MGMTCOutgoing];
type = (([[message objectForKey:MGMIID] intValue]==0 || ![[[messages objectAtIndex:[[message objectForKey:MGMIID] intValue]-1] objectForKey:MGMIYou] boolValue]) ? 1 : 2);
if (type==2)
[classes addObject:MGMTCNext];
[message setObject:yPhotoPath forKey:MGMTPhoto];
[message setObject:NSFullUserName() forKey:MGMTName];
[message setObject:[theMessageInfo objectForKey:MGMTUserNumber] forKey:MGMIPhoneNumber];
} else {
[classes addObject:MGMTCIncoming];
type = (([[message objectForKey:MGMIID] intValue]==0 || [[[messages objectAtIndex:[[message objectForKey:MGMIID] intValue]-1] objectForKey:MGMIYou] boolValue]) ? 3 : 4);
if (type==4)
[classes addObject:MGMTCNext];
[message setObject:tPhotoPath forKey:MGMTPhoto];
[message setObject:[theMessageInfo objectForKey:MGMTInName] forKey:MGMTName];
[message setObject:[theMessageInfo objectForKey:MGMIPhoneNumber] forKey:MGMIPhoneNumber];
}
[classes addObject:MGMTCMessage];
if (![[NSUserDefaults standardUserDefaults] boolForKey:MGMTShowIcons])
[classes addObject:MGMTCHideIcons];
NSDateFormatter *formatter = [[NSDateFormatter new] autorelease];
[formatter setDateFormat:[[[self themeManager] variant] objectForKey:MGMTDate]];
[SMSView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"newMessage('%@', '%@', '%@', %@, '%@', '%@', '%@', %d);", [[message objectForKey:MGMIText] escapeSMS], [[message objectForKey:MGMTPhoto] escapeSMS], [[message objectForKey:MGMITime] escapeSMS], [message objectForKey:MGMIID], [[message objectForKey:MGMTName] escapeSMS], [[[message objectForKey:MGMIPhoneNumber] readableNumber] escapeSMS], [formatter stringFromDate:[theMessageInfo objectForKey:MGMITime]], type]];
[SMSView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"newMessage('%@', '%@', '%@', %@, '%@', '%@', '%@', %d, '%@');", [[[self themeManager] htmlTextFromMessage:message] javascriptEscape], [[message objectForKey:MGMTPhoto] javascriptEscape], [[message objectForKey:MGMITime] javascriptEscape], [message objectForKey:MGMIID], [[message objectForKey:MGMTName] javascriptEscape], [[[message objectForKey:MGMIPhoneNumber] readableNumber] javascriptEscape], [formatter stringFromDate:[theMessageInfo objectForKey:MGMITime]], type, [classes componentsJoinedByString:@" "]]];
[SMSView stringByEvaluatingJavaScriptFromString:@"scrollToBottom();"];
}
@ -561,25 +623,25 @@ const float updateTimeInterval = 300.0;
[SMSTextView setText:@""];
[self textViewDidChange:SMSTextView];
}
- (void)message:(NSDictionary *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
- (void)message:(MGMDelegateInfo *)theInfo didFailWithError:(NSError *)theError instance:(MGMInstance *)theInstance {
sendingMessage = NO;
[SMSSendButton setEnabled:YES];
[SMSTextView setText:[[theInfo objectForKey:MGMIMessage] stringByAppendingFormat:@" %@", [SMSTextView text]]];
[SMSTextView setText:[[theInfo message] stringByAppendingFormat:@" %@", [SMSTextView text]]];
[self textViewDidChange:SMSTextView];
[SMSTextView becomeFirstResponder];
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Error sending a SMS Message"];
[theAlert setMessage:[theError localizedDescription]];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error sending a SMS Message"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (void)messageDidFinish:(NSDictionary *)theInfo instance:(MGMInstance *)theInstance {
- (void)messageDidFinish:(MGMDelegateInfo *)theInfo instance:(MGMInstance *)theInstance {
sendingMessage = NO;
NSDateFormatter *formatter = [[NSDateFormatter new] autorelease];
[formatter setDateFormat:@"h:mm a"];
NSMutableDictionary *messageInfo = [[SMSMessages objectAtIndex:currentSMSMessage] mutableCopy];
NSMutableArray *messages = [[messageInfo objectForKey:MGMIMessages] mutableCopy];
NSDictionary *message = [NSDictionary dictionaryWithObjectsAndKeys:[theInfo objectForKey:MGMIMessage], MGMIText, [formatter stringFromDate:[NSDate date]], MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil];
NSDictionary *message = [NSDictionary dictionaryWithObjectsAndKeys:[theInfo message], MGMIText, [formatter stringFromDate:[NSDate date]], MGMITime, [NSNumber numberWithBool:YES], MGMIYou, nil];
[messages addObject:message];
[messageInfo setObject:messages forKey:MGMIMessages];
[messageInfo setObject:[NSDate date] forKey:MGMITime];

View File

@ -3,17 +3,19 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/28/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class MGMVoiceUser, MGMAccountController, MGMUser, MGMInstance, MGMProgressView;
extern const int MGMKeypadTabIndex;
extern const int MGMContactsTabIndex;
extern const int MGMSMSTabIndex;
extern const int MGMInboxTabIndex;
extern const int MGMVUKeypadTabIndex;
extern const int MGMVUContactsTabIndex;
extern const int MGMVUSMSTabIndex;
extern const int MGMVUInboxTabIndex;
extern NSString * const MGMLastUserPhoneKey;
@protocol MGMVoiceUserTabProtocol <NSObject>
+ (id)tabWithVoiceUser:(MGMVoiceUser *)theVoiceUser;
@ -25,7 +27,7 @@ extern const int MGMInboxTabIndex;
- (void)releaseView;
@end
@interface MGMVoiceUser : NSObject {
@interface MGMVoiceUser : NSObject <UIActionSheetDelegate> {
MGMAccountController *accountController;
MGMUser *user;
MGMInstance *instance;
@ -34,6 +36,8 @@ extern const int MGMInboxTabIndex;
NSMutableArray *tabObjects;
MGMProgressView *progressView;
UIAlertView *verificationView;
UITextField *verificationField;
IBOutlet UIView *view;
IBOutlet UIView *tabView;
IBOutlet UITabBar *tabBar;
@ -41,10 +45,18 @@ extern const int MGMInboxTabIndex;
BOOL placingCall;
NSTimer *callTimer;
UIAlertView *callCancelView;
NSString *currentPhoneNumber;
NSString *optionsNumber;
int unreadCount;
}
+ (id)voiceUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController;
- (void)registerSettings;
- (MGMAccountController *)accountController;
- (MGMUser *)user;
- (MGMInstance *)instance;
@ -61,7 +73,11 @@ extern const int MGMInboxTabIndex;
- (void)setInstanceInfo;
- (BOOL)isPlacingCall;
- (void)donePlacingCall;
- (NSString *)currentPhoneNumber;
- (void)call:(NSString *)theNumber;
- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item;
- (void)showOptionsForNumber:(NSString *)theNumber;
@end

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/28/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import "MGMVoiceUser.h"
@ -13,43 +13,69 @@
#import "MGMVoiceInbox.h"
#import "MGMProgressView.h"
#import "MGMAccountController.h"
#import "MGMController.h"
#import "MGMVMAddons.h"
#import <MGMUsers/MGMUsers.h>
#import <VoiceBase/VoiceBase.h>
const int MGMKeypadTabIndex = 0;
const int MGMContactsTabIndex = 1;
const int MGMSMSTabIndex = 2;
const int MGMInboxTabIndex = 3;
const int MGMVUKeypadTabIndex = 0;
const int MGMVUContactsTabIndex = 1;
const int MGMVUSMSTabIndex = 2;
const int MGMVUInboxTabIndex = 3;
NSString * const MGMVUCurrentTab = @"MGMVUCurrentTab";
NSString * const MGMLastUserPhoneKey = @"MGMLastUserPhone";
@implementation MGMVoiceUser
+ (id)voiceUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController {
return [[[self alloc] initWithUser:theUser accountController:theAccountController] autorelease];
}
- (id)initWithUser:(MGMUser *)theUser accountController:(MGMAccountController *)theAccountController {
if (self = [super init]) {
if ((self = [super init])) {
accountController = theAccountController;
user = [theUser retain];
[self registerSettings];
currentTab = 0;
tabObjects = [NSMutableArray new];
[tabObjects addObject:[MGMVoicePad tabWithVoiceUser:self]];
[tabObjects addObject:[MGMVoiceContacts tabWithVoiceUser:self]];
[tabObjects addObject:[MGMVoiceSMS tabWithVoiceUser:self]];
[tabObjects addObject:[MGMVoiceInbox tabWithVoiceUser:self]];
if ([user isStarted]) {
currentTab = [[user settingForKey:MGMVUCurrentTab] intValue];
tabObjects = [NSMutableArray new];
[tabObjects addObject:[MGMVoicePad tabWithVoiceUser:self]];
[tabObjects addObject:[MGMVoiceContacts tabWithVoiceUser:self]];
[tabObjects addObject:[MGMVoiceSMS tabWithVoiceUser:self]];
[tabObjects addObject:[MGMVoiceInbox tabWithVoiceUser:self]];
if ([user isStarted])
instance = [[MGMInstance instanceWithUser:user delegate:self] retain];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(becameActive) name:UIApplicationDidBecomeActiveNotification object:nil];
}
return self;
}
- (void)dealloc {
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self releaseView];
if (user!=nil)
[user release];
[tabObjects release];
[callTimer invalidate];
[callTimer release];
[callCancelView release];
[optionsNumber release];
[instance stop];
[instance release];
[user release];
[currentPhoneNumber release];
[optionsNumber release];
[super dealloc];
}
- (void)registerSettings {
NSMutableDictionary *settings = [NSMutableDictionary dictionary];
[settings setObject:[NSNumber numberWithInt:0] forKey:MGMLastUserPhoneKey];
[settings setObject:[NSNumber numberWithInt:MGMVUKeypadTabIndex] forKey:MGMVUCurrentTab];
[user registerSettings:settings];
}
- (MGMAccountController *)accountController {
return accountController;
}
@ -74,8 +100,6 @@ const int MGMInboxTabIndex = 3;
if (view==nil) {
if (![[NSBundle mainBundle] loadNibNamed:[[UIDevice currentDevice] appendDeviceSuffixToString:@"VoiceUser"] owner:self options:nil]) {
NSLog(@"Unable to load Voice User");
[self release];
self = nil;
} else {
[tabView addSubview:[[tabObjects objectAtIndex:currentTab] view]];
[tabBar setSelectedItem:[[tabBar items] objectAtIndex:currentTab]];
@ -88,6 +112,10 @@ const int MGMInboxTabIndex = 3;
[progressView becomeFirstResponder];
} else {
[self setInstanceInfo];
if (unreadCount!=0)
[[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:[[NSNumber numberWithInt:unreadCount] stringValue]];
else
[[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:nil];
}
}
}
@ -103,37 +131,67 @@ const int MGMInboxTabIndex = 3;
return tabBar;
}
- (void)releaseView {
if (view!=nil) {
[view release];
view = nil;
[[tabObjects objectAtIndex:currentTab] releaseView];
}
#if releaseDebug
NSLog(@"%s Releasing", __PRETTY_FUNCTION__);
#endif
[[tabObjects objectAtIndex:currentTab] releaseView];
[view release];
view = nil;
[tabView release];
tabView = nil;
[tabBar release];
tabBar = nil;
[progressView stopProgess];
[progressView release];
progressView = nil;
}
- (void)loginError:(NSError *)theError {
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Error logging in"];
[theAlert setMessage:[theError localizedDescription]];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Error logging in"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
if (progressView!=nil) {
[progressView stopProgess];
[progressView removeFromSuperview];
[progressView release];
progressView = nil;
}
[verificationView release];
verificationView = nil;
[verificationField release];
verificationField = nil;
[progressView stopProgess];
[progressView removeFromSuperview];
[progressView release];
progressView = nil;
}
- (void)loginVerificationRequested {
[verificationView release];
verificationView = [UIAlertView new];
[verificationView setTitle:@"Account Verification"];
[verificationView setMessage:@" "];
[verificationView addButtonWithTitle:@"Cancel"];
[verificationView addButtonWithTitle:@"Verify"];
[verificationView setCancelButtonIndex:1];
[verificationView setDelegate:self];
[verificationField release];
verificationField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)];
[verificationField setBorderStyle:UITextBorderStyleLine];
[verificationField setBackgroundColor:[UIColor whiteColor]];
[verificationField setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
[verificationView addSubview:verificationField];
[verificationView show];
[verificationField becomeFirstResponder];
}
- (void)loginSuccessful {
if (progressView!=nil) {
[progressView stopProgess];
[progressView setNeedsDisplay];
}
[verificationView release];
verificationView = nil;
[verificationField release];
verificationField = nil;
[progressView stopProgess];
[progressView setNeedsDisplay];
[self setInstanceInfo];
if ([accountController isCurrent:self])
[accountController setTitle:[[instance userNumber] readableNumber]];
[accountController setTitle:[self title]];
if (progressView!=nil) {
[UIView beginAnimations:nil context:nil];
@ -146,92 +204,163 @@ const int MGMInboxTabIndex = 3;
}
}
- (void)setInstanceInfo {
[[tabObjects objectAtIndex:MGMVUKeypadTabIndex] updateInfo];
}
- (void)progressFadeAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
if (progressView!=nil) {
[progressView removeFromSuperview];
[progressView release];
progressView = nil;
}
[progressView removeFromSuperview];
[progressView release];
progressView = nil;
}
- (void)becameActive {
[instance checkPhones];
}
- (void)updatedUserPhones {
[[tabObjects objectAtIndex:MGMVUKeypadTabIndex] updateInfo];
}
- (void)updatedContacts {
[[tabObjects objectAtIndex:MGMContactsTabIndex] updatedContacts];
[[tabObjects objectAtIndex:MGMVUContactsTabIndex] updatedContacts];
}
- (void)updateUnreadCount:(int)theCount {
unreadCount = theCount;
[accountController setBadge:unreadCount forInstance:instance];
if (unreadCount!=0)
[[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:[[NSNumber numberWithInt:unreadCount] stringValue]];
else
[[[tabBar items] objectAtIndex:MGMVUInboxTabIndex] setBadgeValue:nil];
}
- (void)updateSMS {
[[tabObjects objectAtIndex:MGMSMSTabIndex] checkSMSMessages];
[[tabObjects objectAtIndex:MGMVUSMSTabIndex] checkSMSMessages];
}
- (void)updateVoicemail {
[[tabObjects objectAtIndex:MGMVUInboxTabIndex] checkVoicemail];
}
- (void)updateCredit:(NSString *)theCredit {
[[tabObjects objectAtIndex:MGMVUKeypadTabIndex] setCredit:theCredit];
}
- (BOOL)isPlacingCall {
return (callTimer!=nil);
}
- (void)donePlacingCall {
[callTimer fire];
}
- (NSString *)currentPhoneNumber {
return currentPhoneNumber;
}
- (void)call:(NSString *)theNumber {
if ([[instance userPhoneNumbers] count]<=0) {
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Call Failed"];
[alert setMessage:@"You need to have a phone number setup with your Google Voice account. To add one, visit voice.google.com and in the settings add a phone number. Once you got a phone number setup with Google Voice, reopen VoiceMob."];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
return;
}
[currentPhoneNumber release];
currentPhoneNumber = [theNumber copy];
placingCall = YES;
callTimer = [[NSTimer scheduledTimerWithTimeInterval:20.0 target:self selector:@selector(callTimer) userInfo:nil repeats:NO] retain];
[instance placeCall:theNumber usingPhone:0 delegate:self];
[instance placeCall:theNumber usingPhone:[[user settingForKey:MGMLastUserPhoneKey] intValue] delegate:self];
callCancelView = [UIAlertView new];
[callCancelView setTitle:@"Placing Call"];
[callCancelView addButtonWithTitle:@"Cancel Call"];
[callCancelView setDelegate:self];
[callCancelView show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView==callCancelView) {
if (callTimer!=nil) {
[callTimer invalidate];
[callTimer release];
callTimer = nil;
}
- (void)alertView:(UIAlertView *)theAlertView clickedButtonAtIndex:(NSInteger)theIndex {
if (theAlertView==callCancelView) {
[currentPhoneNumber release];
currentPhoneNumber = nil;
placingCall = NO;
[callTimer invalidate];
[callTimer release];
callTimer = nil;
[callCancelView release];
callCancelView = nil;
[instance cancelCallWithDelegate:self];
} else if (theAlertView==verificationView) {
if (theIndex==1)
[instance verifyWithCode:[verificationField text]];
else
[instance cancelVerification];
}
}
- (void)call:(NSDictionary *)theInfo didFailWithError:(NSError *)theError {
[currentPhoneNumber release];
currentPhoneNumber = nil;
placingCall = NO;
if (callTimer!=nil)
[callTimer fire];
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Call Failed"];
[theAlert setMessage:[theError localizedDescription]];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
[callTimer fire];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Call Failed"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (void)callDidFinish:(NSDictionary *)theInfo {
[currentPhoneNumber release];
currentPhoneNumber = nil;
placingCall = NO;
NSLog(@"YEA! We Made The Call!");
}
- (void)callCancel:(NSDictionary *)theInfo didFailWithError:(NSError *)theError {
UIAlertView *theAlert = [[UIAlertView new] autorelease];
[theAlert setTitle:@"Call Cancel Failed"];
[theAlert setMessage:[theError localizedDescription]];
[theAlert addButtonWithTitle:MGMOkButtonTitle];
[theAlert show];
UIAlertView *alert = [[UIAlertView new] autorelease];
[alert setTitle:@"Call Cancel Failed"];
[alert setMessage:[theError localizedDescription]];
[alert addButtonWithTitle:MGMOkButtonTitle];
[alert show];
}
- (void)callTimer {
if (callTimer!=nil) {
[callTimer invalidate];
[callTimer release];
callTimer = nil;
}
[callTimer invalidate];
[callTimer release];
callTimer = nil;
[callCancelView dismissWithClickedButtonIndex:0 animated:YES];
[callCancelView release];
callCancelView = nil;
}
- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)item {
int tabIndex = [[tabBar items] indexOfObject:item];
- (void)tabBar:(UITabBar *)theTabBar didSelectItem:(UITabBarItem *)theItem {
int tabIndex = [[tabBar items] indexOfObject:theItem];
if (tabIndex==currentTab)
return;
if (tabIndex!=MGMSMSTabIndex && tabIndex!=MGMInboxTabIndex)
if (tabIndex!=MGMVUSMSTabIndex && tabIndex!=MGMVUInboxTabIndex) {
[accountController setTitle:[self title]];
[accountController setItems:[accountController accountItems] animated:YES];
}
id tab = [tabObjects objectAtIndex:currentTab];
currentTab = tabIndex;
[user setSetting:[NSNumber numberWithInt:currentTab] forKey:MGMVUCurrentTab];
id newTab = [tabObjects objectAtIndex:currentTab];
CGRect tabFrame = [[newTab view] frame];
tabFrame.size = [tabView frame].size;
[[newTab view] setFrame:tabFrame];
[tabView addSubview:[newTab view]];
[[tab view] removeFromSuperview];
[tab releaseView];
}
- (void)showOptionsForNumber:(NSString *)theNumber {
optionsNumber = [theNumber copy];
UIActionSheet *theAction = [[UIActionSheet new] autorelease];
[theAction addButtonWithTitle:@"Call"];
[theAction addButtonWithTitle:@"SMS"];
[theAction addButtonWithTitle:@"Reverse Lookup"];
[theAction addButtonWithTitle:@"Cancel"];
[theAction setCancelButtonIndex:3];
[theAction setDelegate:self];
[theAction showInView:view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==0)
[self call:optionsNumber];
else if (buttonIndex==1)
[[tabObjects objectAtIndex:MGMVUSMSTabIndex] messageWithNumber:optionsNumber instance:instance];
else if (buttonIndex==2)
[[accountController controller] showReverseLookupWithNumber:optionsNumber];
[optionsNumber release];
optionsNumber = nil;
}
@end

View File

@ -0,0 +1,48 @@
//
// ZipArchive.h
//
//
// Created by aish on 08-9-11.
// acsolu@gmail.com
// Copyright 2008 Inc. All rights reserved.
//
// History:
// 09-11-2008 version 1.0 release
// 10-18-2009 version 1.1 support password protected zip files
// 10-21-2009 version 1.2 fix date bug
#import <UIKit/UIKit.h>
#include "minizip/zip.h"
#include "minizip/unzip.h"
@protocol ZipArchiveDelegate <NSObject>
@optional
-(void) ErrorMessage:(NSString*) msg;
-(BOOL) OverWriteOperation:(NSString*) file;
@end
@interface ZipArchive : NSObject {
@private
zipFile _zipFile;
unzFile _unzFile;
NSString* _password;
id _delegate;
}
@property (nonatomic, retain) id delegate;
-(BOOL) CreateZipFile2:(NSString*) zipFile;
-(BOOL) CreateZipFile2:(NSString*) zipFile Password:(NSString*) password;
-(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname;
-(BOOL) CloseZipFile2;
-(BOOL) UnzipOpenFile:(NSString*) zipFile;
-(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password;
-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite;
-(BOOL) UnzipCloseFile;
@end

View File

@ -0,0 +1,336 @@
//
// ZipArchive.mm
//
//
// Created by aish on 08-9-11.
// acsolu@gmail.com
// Copyright 2008 Inc. All rights reserved.
//
#import "ZipArchive.h"
#import "zlib.h"
#import "zconf.h"
@interface ZipArchive (Private)
-(void) OutputErrorMessage:(NSString*) msg;
-(BOOL) OverWrite:(NSString*) file;
-(NSDate*) Date1980;
@end
@implementation ZipArchive
@synthesize delegate = _delegate;
-(id) init
{
if ((self=[super init])) {
_zipFile = NULL ;
}
return self;
}
-(void) dealloc
{
[self CloseZipFile2];
[super dealloc];
}
-(BOOL) CreateZipFile2:(NSString*) zipFile
{
_zipFile = zipOpen( (const char*)[zipFile UTF8String], 0 );
if( !_zipFile )
return NO;
return YES;
}
-(BOOL) CreateZipFile2:(NSString*) zipFile Password:(NSString*) password
{
_password = password;
return [self CreateZipFile2:zipFile];
}
-(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname;
{
if( !_zipFile )
return NO;
// tm_zip filetime;
time_t current;
time( &current );
zip_fileinfo zipInfo = {0};
// zipInfo.dosDate = (unsigned long) current;
NSDictionary* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:nil];
if( attr )
{
NSDate* fileDate = (NSDate*)[attr objectForKey:NSFileModificationDate];
if( fileDate )
{
// some application does use dosDate, but tmz_date instead
// zipInfo.dosDate = [fileDate timeIntervalSinceDate:[self Date1980] ];
NSCalendar* currCalendar = [NSCalendar currentCalendar];
uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit |
NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ;
NSDateComponents* dc = [currCalendar components:flags fromDate:fileDate];
zipInfo.tmz_date.tm_sec = [dc second];
zipInfo.tmz_date.tm_min = [dc minute];
zipInfo.tmz_date.tm_hour = [dc hour];
zipInfo.tmz_date.tm_mday = [dc day];
zipInfo.tmz_date.tm_mon = [dc month] - 1;
zipInfo.tmz_date.tm_year = [dc year];
}
}
int ret ;
NSData* data = nil;
if( [_password length] == 0 )
{
ret = zipOpenNewFileInZip( _zipFile,
(const char*) [newname UTF8String],
&zipInfo,
NULL,0,
NULL,0,
NULL,//comment
Z_DEFLATED,
Z_DEFAULT_COMPRESSION );
}
else
{
data = [ NSData dataWithContentsOfFile:file];
uLong crcValue = crc32( 0L,NULL, 0L );
crcValue = crc32( crcValue, (const Bytef*)[data bytes], [data length] );
ret = zipOpenNewFileInZip3( _zipFile,
(const char*) [newname UTF8String],
&zipInfo,
NULL,0,
NULL,0,
NULL,//comment
Z_DEFLATED,
Z_DEFAULT_COMPRESSION,
0,
15,
8,
Z_DEFAULT_STRATEGY,
[_password cStringUsingEncoding:NSASCIIStringEncoding],
crcValue );
}
if( ret!=Z_OK )
{
return NO;
}
if( data==nil )
{
data = [ NSData dataWithContentsOfFile:file];
}
unsigned int dataLen = [data length];
ret = zipWriteInFileInZip( _zipFile, (const void*)[data bytes], dataLen);
if( ret!=Z_OK )
{
return NO;
}
ret = zipCloseFileInZip( _zipFile );
if( ret!=Z_OK )
return NO;
return YES;
}
-(BOOL) CloseZipFile2
{
_password = nil;
if( _zipFile==NULL )
return NO;
BOOL ret = zipClose( _zipFile,NULL )==Z_OK?YES:NO;
_zipFile = NULL;
return ret;
}
-(BOOL) UnzipOpenFile:(NSString*) zipFile
{
_unzFile = unzOpen( (const char*)[zipFile UTF8String] );
if( _unzFile )
{
unz_global_info globalInfo = {0};
if( unzGetGlobalInfo(_unzFile, &globalInfo )==UNZ_OK )
{
NSLog(@"%ld entries in the zip file",globalInfo.number_entry );
}
}
return _unzFile!=NULL;
}
-(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password
{
_password = password;
return [self UnzipOpenFile:zipFile];
}
-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite
{
BOOL success = YES;
int ret = unzGoToFirstFile( _unzFile );
unsigned char buffer[4096] = {0};
NSFileManager* fman = [NSFileManager defaultManager];
if( ret!=UNZ_OK )
{
[self OutputErrorMessage:@"Failed"];
}
do{
if( [_password length]==0 )
ret = unzOpenCurrentFile( _unzFile );
else
ret = unzOpenCurrentFilePassword( _unzFile, [_password cStringUsingEncoding:NSASCIIStringEncoding] );
if( ret!=UNZ_OK )
{
[self OutputErrorMessage:@"Error occurs"];
success = NO;
break;
}
// reading data and write to file
int read ;
unz_file_info fileInfo ={0};
ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
if( ret!=UNZ_OK )
{
[self OutputErrorMessage:@"Error occurs while getting file info"];
success = NO;
unzCloseCurrentFile( _unzFile );
break;
}
char* filename = (char*) malloc( fileInfo.size_filename +1 );
unzGetCurrentFileInfo(_unzFile, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
filename[fileInfo.size_filename] = '\0';
// check if it contains directory
NSString * strPath = [NSString stringWithUTF8String:filename];
BOOL isDirectory = NO;
if( filename[fileInfo.size_filename-1]=='/' || filename[fileInfo.size_filename-1]=='\\')
isDirectory = YES;
free( filename );
if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound )
{// contains a path
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}
NSString* fullPath = [path stringByAppendingPathComponent:strPath];
if( isDirectory )
[fman createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil];
else
[fman createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
if( [fman fileExistsAtPath:fullPath] && !isDirectory && !overwrite )
{
if( ![self OverWrite:fullPath] )
{
unzCloseCurrentFile( _unzFile );
ret = unzGoToNextFile( _unzFile );
continue;
}
}
FILE* fp = fopen( (const char*)[fullPath UTF8String], "wb");
while( fp )
{
read=unzReadCurrentFile(_unzFile, buffer, 4096);
if( read > 0 )
{
fwrite(buffer, read, 1, fp );
}
else if( read<0 )
{
[self OutputErrorMessage:@"Failed to reading zip file"];
break;
}
else
break;
}
if( fp )
{
fclose( fp );
// set the orignal datetime property
NSDate* orgDate = nil;
//{{ thanks to brad.eaton for the solution
NSDateComponents *dc = [[NSDateComponents alloc] init];
dc.second = fileInfo.tmu_date.tm_sec;
dc.minute = fileInfo.tmu_date.tm_min;
dc.hour = fileInfo.tmu_date.tm_hour;
dc.day = fileInfo.tmu_date.tm_mday;
dc.month = fileInfo.tmu_date.tm_mon+1;
dc.year = fileInfo.tmu_date.tm_year;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
orgDate = [gregorian dateFromComponents:dc] ;
[dc release];
[gregorian release];
//}}
NSDictionary* attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; //[[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:YES];
if( attr )
{
// [attr setValue:orgDate forKey:NSFileCreationDate];
if( ![[NSFileManager defaultManager] setAttributes:attr ofItemAtPath:fullPath error:nil] )
{
// cann't set attributes
NSLog(@"Failed to set attributes");
}
}
}
unzCloseCurrentFile( _unzFile );
ret = unzGoToNextFile( _unzFile );
}while( ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE );
return success;
}
-(BOOL) UnzipCloseFile
{
_password = nil;
if( _unzFile )
return unzClose( _unzFile )==UNZ_OK;
return YES;
}
#pragma mark wrapper for delegate
-(void) OutputErrorMessage:(NSString*) msg
{
if( _delegate && [_delegate respondsToSelector:@selector(ErrorMessage)] )
[_delegate ErrorMessage:msg];
}
-(BOOL) OverWrite:(NSString*) file
{
if( _delegate && [_delegate respondsToSelector:@selector(OverWriteOperation)] )
return [_delegate OverWriteOperation:file];
return YES;
}
#pragma mark get NSDate object for 1980-01-01
-(NSDate*) Date1980
{
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:1];
[comps setMonth:1];
[comps setYear:1980];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
[gregorian release];
return date;
}
@end

View File

@ -0,0 +1,132 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution
The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported.
*/
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/***********************************************************************
* Return the next byte in the pseudo-random sequence
*/
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
/***********************************************************************
* Update the encryption keys with the next byte of plain text
*/
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{
(*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{
register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
}
return c;
}
/***********************************************************************
* Initialize the encryption keys and the random header according to
* the given password.
*/
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
{
*(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L;
while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++;
}
}
#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif
static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
const char *passwd; /* password string */
unsigned char *buf; /* where to write header */
int bufSize;
unsigned long* pkeys;
const unsigned long* pcrc_32_tab;
unsigned long crcForCrypting;
{
int n; /* index in random header */
int t; /* temporary */
int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN)
return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is
* often poorly implemented.
*/
if (++calls == 1)
{
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
}
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
}
/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++)
{
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
}
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n;
}
#endif

View File

@ -0,0 +1,177 @@
/* ioapi.c -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
#include "ioapi.h"
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
#ifndef SEEK_CUR
#define SEEK_CUR 1
#endif
#ifndef SEEK_END
#define SEEK_END 2
#endif
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
voidpf ZCALLBACK fopen_file_func OF((
voidpf opaque,
const char* filename,
int mode));
uLong ZCALLBACK fread_file_func OF((
voidpf opaque,
voidpf stream,
void* buf,
uLong size));
uLong ZCALLBACK fwrite_file_func OF((
voidpf opaque,
voidpf stream,
const void* buf,
uLong size));
long ZCALLBACK ftell_file_func OF((
voidpf opaque,
voidpf stream));
long ZCALLBACK fseek_file_func OF((
voidpf opaque,
voidpf stream,
uLong offset,
int origin));
int ZCALLBACK fclose_file_func OF((
voidpf opaque,
voidpf stream));
int ZCALLBACK ferror_file_func OF((
voidpf opaque,
voidpf stream));
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
voidpf opaque;
const char* filename;
int mode;
{
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb";
else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b";
else
if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen);
return file;
}
uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
voidpf opaque;
voidpf stream;
void* buf;
uLong size;
{
uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
voidpf opaque;
voidpf stream;
const void* buf;
uLong size;
{
uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
}
long ZCALLBACK ftell_file_func (opaque, stream)
voidpf opaque;
voidpf stream;
{
long ret;
ret = ftell((FILE *)stream);
return ret;
}
long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
voidpf opaque;
voidpf stream;
uLong offset;
int origin;
{
int fseek_origin=0;
long ret;
switch (origin)
{
case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR;
break;
case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END;
break;
case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET;
break;
default: return -1;
}
ret = 0;
fseek((FILE *)stream, offset, fseek_origin);
return ret;
}
int ZCALLBACK fclose_file_func (opaque, stream)
voidpf opaque;
voidpf stream;
{
int ret;
ret = fclose((FILE *)stream);
return ret;
}
int ZCALLBACK ferror_file_func (opaque, stream)
voidpf opaque;
voidpf stream;
{
int ret;
ret = ferror((FILE *)stream);
return ret;
}
void fill_fopen_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def;
{
pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL;
}

View File

@ -0,0 +1,75 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
*/
#ifndef _ZLIBIOAPI_H
#define _ZLIBIOAPI_H
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK
#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK
#else
#define ZCALLBACK
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
voidpf opaque;
} zlib_filefunc_def;
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,281 @@
/*
Additional tools for Minizip
Code: Xavier Roche '2004
License: Same as ZLIB (www.gzip.org)
*/
/* Code */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
#include "unzip.h"
#define READ_8(adr) ((unsigned char)*(adr))
#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
#define WRITE_8(buff, n) do { \
*((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
} while(0)
#define WRITE_16(buff, n) do { \
WRITE_8((unsigned char*)(buff), n); \
WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
} while(0)
#define WRITE_32(buff, n) do { \
WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
} while(0)
extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
const char* file;
const char* fileOut;
const char* fileOutTmp;
uLong* nRecovered;
uLong* bytesRecovered;
{
int err = Z_OK;
FILE* fpZip = fopen(file, "rb");
FILE* fpOut = fopen(fileOut, "wb");
FILE* fpOutCD = fopen(fileOutTmp, "wb");
if (fpZip != NULL && fpOut != NULL) {
int entries = 0;
uLong totalBytes = 0;
char header[30];
char filename[256];
char extra[1024];
int offset = 0;
int offsetCD = 0;
while ( fread(header, 1, 30, fpZip) == 30 ) {
int currentOffset = offset;
/* File entry */
if (READ_32(header) == 0x04034b50) {
unsigned int version = READ_16(header + 4);
unsigned int gpflag = READ_16(header + 6);
unsigned int method = READ_16(header + 8);
unsigned int filetime = READ_16(header + 10);
unsigned int filedate = READ_16(header + 12);
unsigned int crc = READ_32(header + 14); /* crc */
unsigned int cpsize = READ_32(header + 18); /* compressed size */
unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
unsigned int fnsize = READ_16(header + 26); /* file name length */
unsigned int extsize = READ_16(header + 28); /* extra field length */
filename[0] = extra[0] = '\0';
/* Header */
if (fwrite(header, 1, 30, fpOut) == 30) {
offset += 30;
} else {
err = Z_ERRNO;
break;
}
/* Filename */
if (fnsize > 0) {
if (fread(filename, 1, fnsize, fpZip) == fnsize) {
if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
offset += fnsize;
} else {
err = Z_ERRNO;
break;
}
} else {
err = Z_ERRNO;
break;
}
} else {
err = Z_STREAM_ERROR;
break;
}
/* Extra field */
if (extsize > 0) {
if (fread(extra, 1, extsize, fpZip) == extsize) {
if (fwrite(extra, 1, extsize, fpOut) == extsize) {
offset += extsize;
} else {
err = Z_ERRNO;
break;
}
} else {
err = Z_ERRNO;
break;
}
}
/* Data */
{
int dataSize = cpsize;
if (dataSize == 0) {
dataSize = uncpsize;
}
if (dataSize > 0) {
char* data = malloc(dataSize);
if (data != NULL) {
if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
offset += dataSize;
totalBytes += dataSize;
} else {
err = Z_ERRNO;
}
} else {
err = Z_ERRNO;
}
free(data);
if (err != Z_OK) {
break;
}
} else {
err = Z_MEM_ERROR;
break;
}
}
}
/* Central directory entry */
{
char header[46];
char* comment = "";
int comsize = (int) strlen(comment);
WRITE_32(header, 0x02014b50);
WRITE_16(header + 4, version);
WRITE_16(header + 6, version);
WRITE_16(header + 8, gpflag);
WRITE_16(header + 10, method);
WRITE_16(header + 12, filetime);
WRITE_16(header + 14, filedate);
WRITE_32(header + 16, crc);
WRITE_32(header + 20, cpsize);
WRITE_32(header + 24, uncpsize);
WRITE_16(header + 28, fnsize);
WRITE_16(header + 30, extsize);
WRITE_16(header + 32, comsize);
WRITE_16(header + 34, 0); /* disk # */
WRITE_16(header + 36, 0); /* int attrb */
WRITE_32(header + 38, 0); /* ext attrb */
WRITE_32(header + 42, currentOffset);
/* Header */
if (fwrite(header, 1, 46, fpOutCD) == 46) {
offsetCD += 46;
/* Filename */
if (fnsize > 0) {
if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
offsetCD += fnsize;
} else {
err = Z_ERRNO;
break;
}
} else {
err = Z_STREAM_ERROR;
break;
}
/* Extra field */
if (extsize > 0) {
if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
offsetCD += extsize;
} else {
err = Z_ERRNO;
break;
}
}
/* Comment field */
if (comsize > 0) {
if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
offsetCD += comsize;
} else {
err = Z_ERRNO;
break;
}
}
} else {
err = Z_ERRNO;
break;
}
}
/* Success */
entries++;
} else {
break;
}
}
/* Final central directory */
{
int entriesZip = entries;
char header[22];
char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
int comsize = (int) strlen(comment);
if (entriesZip > 0xffff) {
entriesZip = 0xffff;
}
WRITE_32(header, 0x06054b50);
WRITE_16(header + 4, 0); /* disk # */
WRITE_16(header + 6, 0); /* disk # */
WRITE_16(header + 8, entriesZip); /* hack */
WRITE_16(header + 10, entriesZip); /* hack */
WRITE_32(header + 12, offsetCD); /* size of CD */
WRITE_32(header + 16, offset); /* offset to CD */
WRITE_16(header + 20, comsize); /* comment */
/* Header */
if (fwrite(header, 1, 22, fpOutCD) == 22) {
/* Comment field */
if (comsize > 0) {
if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
err = Z_ERRNO;
}
}
} else {
err = Z_ERRNO;
}
}
/* Final merge (file + central directory) */
fclose(fpOutCD);
if (err == Z_OK) {
fpOutCD = fopen(fileOutTmp, "rb");
if (fpOutCD != NULL) {
int nRead;
char buffer[8192];
while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
err = Z_ERRNO;
break;
}
}
fclose(fpOutCD);
}
}
/* Close */
fclose(fpZip);
fclose(fpOut);
/* Wipe temporary file */
(void)remove(fileOutTmp);
/* Number of recovered entries */
if (err == Z_OK) {
if (nRecovered != NULL) {
*nRecovered = entries;
}
if (bytesRecovered != NULL) {
*bytesRecovered = totalBytes;
}
}
} else {
err = Z_STREAM_ERROR;
}
return err;
}

View File

@ -0,0 +1,31 @@
/*
Additional tools for Minizip
Code: Xavier Roche '2004
License: Same as ZLIB (www.gzip.org)
*/
#ifndef _zip_tools_H
#define _zip_tools_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#include "unzip.h"
/* Repair a ZIP file (missing central directory)
file: file to recover
fileOut: output file after recovery
fileOutTmp: temporary file name used for recovery
*/
extern int ZEXPORT unzRepair(const char* file,
const char* fileOut,
const char* fileOutTmp,
uLong* nRecovered,
uLong* bytesRecovered);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,354 @@
/* unzip.h -- IO for uncompress .zip files using zlib
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible.
Multi volume ZipFile (span) are not supported.
Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
http://www.info-zip.org/pub/infozip/doc/
PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip
*/
#ifndef _unz_H
#define _unz_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagunzFile__ { int unused; } unzFile__;
typedef unzFile__ *unzFile;
#else
typedef voidp unzFile;
#endif
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
These data comes from the end of central dir */
typedef struct unz_global_info_s
{
uLong number_entry; /* total number of entries in
the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info_s
{
uLong version; /* version made by 2 bytes */
uLong version_needed; /* version needed to extract 2 bytes */
uLong flag; /* general purpose bit flag 2 bytes */
uLong compression_method; /* compression method 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong crc; /* crc-32 4 bytes */
uLong compressed_size; /* compressed size 4 bytes */
uLong uncompressed_size; /* uncompressed size 4 bytes */
uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong size_file_comment; /* file comment length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
tm_unz tmu_date;
} unz_file_info;
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
const char* fileName2,
int iCaseSensitivity));
/*
Compare two filename (fileName1,fileName2).
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
or strcasecmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile ZEXPORT unzOpen OF((const char *path));
/*
Open a Zip file. path contain the full pathname (by example,
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
"zlib/zlib113.zip".
If the zipfile cannot be opened (file don't exist or in not valid), the
return value is NULL.
Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
*/
extern unzFile ZEXPORT unzOpen2 OF((const char *path,
zlib_filefunc_def* pzlib_filefunc_def));
/*
Open a Zip file, like unzOpen, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
*/
extern int ZEXPORT unzClose OF((unzFile file));
/*
Close a ZipFile opened with unzipOpen.
If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
unz_global_info *pglobal_info));
/*
Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
uLong uSizeBuf));
/*
Get the global comment string of the ZipFile, in the szComment buffer.
uSizeBuf is the size of the szComment buffer.
return the number of byte copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
/*
Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
*/
extern int ZEXPORT unzGoToNextFile OF((unzFile file));
/*
Set the current file of the zipfile to the next file.
return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
*/
extern int ZEXPORT unzLocateFile OF((unzFile file,
const char *szFileName,
int iCaseSensitivity));
/*
Try locate the file szFileName in the zipfile.
For the iCaseSensitivity signification, see unzStringFileNameCompare
return value :
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
/* ****************************************** */
/* Ryan supplied functions */
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_pos_s
{
uLong pos_in_zip_directory; /* offset in zip file directory */
uLong num_of_file; /* # of file */
} unz_file_pos;
extern int ZEXPORT unzGetFilePos(
unzFile file,
unz_file_pos* file_pos);
extern int ZEXPORT unzGoToFilePos(
unzFile file,
unz_file_pos* file_pos);
/* ****************************************** */
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
unz_file_info *pfile_info,
char *szFileName,
uLong fileNameBufferSize,
void *extraField,
uLong extraFieldBufferSize,
char *szComment,
uLong commentBufferSize));
/*
Get Info about the current file
if pfile_info!=NULL, the *pfile_info structure will contain somes info about
the current file
if szFileName!=NULL, the filemane string will be copied in szFileName
(fileNameBufferSize is the size of the buffer)
if extraField!=NULL, the extra field information will be copied in extraField
(extraFieldBufferSize is the size of the buffer).
This is the Central-header version of the extra field
if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
*/
/***************************************************************************/
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
*/
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
/*
Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
const char* password));
/*
Open for reading data the current file in the zipfile.
password is a crypting password
If there is no error, the return value is UNZ_OK.
*/
extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
int* method,
int* level,
int raw));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
*method will receive method of compression, *level will receive level of
compression
note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
int* method,
int* level,
int raw,
const char* password));
/*
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
if raw==1
*method will receive method of compression, *level will receive level of
compression
note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
*/
extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
voidp buf,
unsigned len));
/*
Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
len the size of buf.
return the number of byte copied if somes bytes are copied
return 0 if the end of file was reached
return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
*/
extern z_off_t ZEXPORT unztell OF((unzFile file));
/*
Give the current position in uncompressed data
*/
extern int ZEXPORT unzeof OF((unzFile file));
/*
return 1 if the end of file was reached, 0 elsewhere
*/
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
voidp buf,
unsigned len));
/*
Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
more info in the local-header version than in the central-header)
if buf==NULL, it return the size of the local extra field
if buf!=NULL, len is the size of the buffer, the extra header is copied in
buf.
the return value is the number of bytes copied in buf, or (if <0)
the error code
*/
/***************************************************************************/
/* Get the current file offset */
extern uLong ZEXPORT unzGetOffset (unzFile file);
/* Set the current file offset */
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
#ifdef __cplusplus
}
#endif
#endif /* _unz_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,235 @@
/* zip.h -- IO for compress .zip files using zlib
Version 1.01e, February 12th, 2005
Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible.
Multi volume ZipFile (span) are not supported.
Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported
For uncompress .zip file, look at unzip.h
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
http://www.info-zip.org/pub/infozip/doc/
PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip
*/
#ifndef _zip_H
#define _zip_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#endif
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagzipFile__ { int unused; } zipFile__;
typedef zipFile__ *zipFile;
#else
typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0)
#define ZIP_ERRNO (Z_ERRNO)
#define ZIP_PARAMERROR (-102)
#define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mday; /* day of the month - [1,31] */
uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{
tm_zip tmz_date; /* date in understandable format */
uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
/*
Create a zipfile.
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
an Unix computer "zlib/zlib113.zip".
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
will be created at the end of the file.
(useful if the file contain a self extractor code)
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
add files in existing zip (be sure you don't add file that doesn't exist)
If the zipfile cannot be opened, the return value is NULL.
Else, the return value is a zipFile Handle, usable with other function
of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another
Of couse, you can use RAW reading and writing to copy the file you did not want delte
*/
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
int append,
zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def));
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level));
/*
Open a file in the ZIP for writing.
filename : the filename in zip (if NULL, '-' without quote will be used
*zipfi contain supplemental information
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
contains the extrafield data the the local header
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
contains the extrafield data the the local header
if comment != NULL, comment contain the comment string
method contain the compression method (0 for store, Z_DEFLATED for deflate)
level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
*/
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw));
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
const void* extrafield_local,
uInt size_extrafield_local,
const void* extrafield_global,
uInt size_extrafield_global,
const char* comment,
int method,
int level,
int raw,
int windowBits,
int memLevel,
int strategy,
const char* password,
uLong crcForCtypting));
/*
Same than zipOpenNewFileInZip2, except
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
password : crypting password (NULL for no crypting)
crcForCtypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
const void* buf,
unsigned len));
/*
Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/*
Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong uncompressed_size,
uLong crc32));
/*
Close the current file in the zipfile, for fiel opened with
parameter raw=1 in zipOpenNewFileInZip2
uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose OF((zipFile file,
const char* global_comment));
/*
Close the zipfile
*/
#ifdef __cplusplus
}
#endif
#endif /* _zip_H */

View File

@ -3,7 +3,7 @@
// VoiceMob
//
// Created by Mr. Gecko on 9/24/10.
// Copyright (c) 2010 Mr. Gecko's Media (James Coleman). All rights reserved. http://mrgeckosmedia.com/
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
#import <UIKit/UIKit.h>

View File

@ -6,4 +6,5 @@
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#define MGMOkButtonTitle @"Ok"
#define releaseDebug 0
#endif

View File

@ -1,25 +1,27 @@
#!/bin/bash
#PPCFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch ppc"
PPCFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch ppc"
PPCCC="/usr/bin/gcc-4.0"
PPCHOST="ppc-apple-darwin8"
PPCFLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch ppc -ggdb"
PPCCC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2"
PPCCXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2"
PPCAR="/Applications/Xcode.app/Contents/Developer/usr/bin/ar rv"
PPCRANLIB="/Applications/Xcode.app/Contents/Developer/usr/bin/ranlib"
PPCHOST="ppc-apple-darwin10"
PPCPATH="${PWD}/opt-ppc"
PPCLDFLAGS="${PPCFLAGS}"
PPCLDFLAGS="-arch ppc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk"
#I386FLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch i386"
I386FLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch i386"
I386CC="/usr/bin/gcc-4.0"
I386HOST="i386-apple-darwin8"
I386FLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.4 -arch i386 -ggdb"
I386CC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2"
I386CXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2"
I386HOST="i386-apple-darwin10"
I386PATH="${PWD}/opt-i386"
I386LDFLAGS="${I386FLAGS}"
I386LDFLAGS="-arch i386"
#X86_64FLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.5 -arch x86_64"
X86_64FLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 -arch x86_64"
X86_64CC="/usr/bin/gcc-4.0"
X86_64HOST="x86_64-apple-darwin9"
X86_64FLAGS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 -arch x86_64 -ggdb"
X86_64CC="/Applications/Xcode.app/Contents/Developer/usr/bin/gcc-4.2"
X86_64CXX="/Applications/Xcode.app/Contents/Developer/usr/bin/g++-4.2"
X86_64HOST="x86_64-apple-darwin10"
X86_64PATH="${PWD}/opt-x86_64"
X86_64LDFLAGS="${X86_64FLAGS}"
X86_64LDFLAGS="-arch x86_64"
STANDARD="--disable-bzlib --enable-pthreads --disable-network --enable-small --disable-ffprobe --disable-ffplay --disable-ffserver --disable-decoder=atrac3 --disable-shared --enable-static \
--disable-decoders \
@ -240,11 +242,11 @@ if [ "$1" = "" ]; then
echo "Configuring FFmpeg"
cd ${FFMPEGNAME}-ppc
LDFLAGS="${PPCLDFLAGS} -L${PPCPATH}/lib" CFLAGS="${PPCFLAGS} -I${PPCPATH}/include -mdynamic-no-pic" CC="${PPCCC}" ./configure --prefix="${PPCPATH}" --arch=ppc ${STANDARD}
LDFLAGS="${PPCLDFLAGS} -L${PPCPATH}/lib" CFLAGS="${PPCFLAGS} -I${PPCPATH}/include -mdynamic-no-pic" ./configure --enable-cross-compile --prefix="${PPCPATH}" --enable-memalign-hack --target-os=darwin --cc="${PPCCC}" --arch=ppc ${STANDARD}
cd ../${FFMPEGNAME}-i386
LDFLAGS="${I386LDFLAGS} -L${I386PATH}/lib" CFLAGS="${I386FLAGS} -I${I386PATH}/include -mdynamic-no-pic" CC="${I386CC}" ./configure --prefix="${I386PATH}" --arch=i386 ${STANDARD}
LDFLAGS="${I386LDFLAGS} -L${I386PATH}/lib" CFLAGS="${I386FLAGS} -I${I386PATH}/include -mdynamic-no-pic" ./configure --enable-cross-compile --prefix="${I386PATH}" --enable-memalign-hack --target-os=darwin --cc="${I386CC}" --arch=i386 ${STANDARD}
cd ../${FFMPEGNAME}-x86_64
LDFLAGS="${X86_64LDFLAGS} -L${X86_64PATH}/lib" CFLAGS="${X86_64FLAGS} -I${X86_64PATH}/include -mdynamic-no-pic" CC="${X86_64CC}" ./configure --prefix="${X86_64PATH}" --enable-cross-compile --target-os=darwin --arch=x86_64 ${STANDARD}
LDFLAGS="${X86_64LDFLAGS} -L${X86_64PATH}/lib" CFLAGS="${X86_64FLAGS} -I${X86_64PATH}/include -mdynamic-no-pic" ./configure --prefix="${X86_64PATH}" --target-os=darwin --cc="${X86_64CC}" --arch=x86_64 ${STANDARD}
echo "Compiling FFmpeg"
cd ../${FFMPEGNAME}-ppc

View File

@ -1,6 +1,5 @@
#include "GrowlDefines.h"
#include <Growl/GrowlDefines.h>
#ifdef __OBJC__
# include "GrowlApplicationBridge.h"
# include <Growl/GrowlApplicationBridge.h>
#endif
#include "GrowlApplicationBridge-Carbon.h"

View File

@ -1,780 +0,0 @@
//
// GrowlApplicationBridge-Carbon.h
// Growl
//
// Created by Mac-arena the Bored Zo on Wed Jun 18 2004.
// Based on GrowlApplicationBridge.h by Evan Schoenberg.
// This source code is in the public domain. You may freely link it into any
// program.
//
#ifndef _GROWLAPPLICATIONBRIDGE_CARBON_H_
#define _GROWLAPPLICATIONBRIDGE_CARBON_H_
#include <sys/cdefs.h>
#include <Carbon/Carbon.h>
#ifndef GROWL_EXPORT
#define GROWL_EXPORT __attribute__((visibility("default")))
#endif
/*! @header GrowlApplicationBridge-Carbon.h
* @abstract Declares an API that Carbon applications can use to interact with Growl.
* @discussion GrowlApplicationBridge uses a delegate to provide information //XXX
* to Growl (such as your application's name and what notifications it may
* post) and to provide information to your application (such as that Growl
* is listening for notifications or that a notification has been clicked).
*
* You can set the Growldelegate with Growl_SetDelegate and find out the
* current delegate with Growl_GetDelegate. See struct Growl_Delegate for more
* information about the delegate.
*/
__BEGIN_DECLS
/*! @struct Growl_Delegate
* @abstract Delegate to supply GrowlApplicationBridge with information and respond to events.
* @discussion The Growl delegate provides your interface to
* GrowlApplicationBridge. When GrowlApplicationBridge needs information about
* your application, it looks for it in the delegate; when Growl or the user
* does something that you might be interested in, GrowlApplicationBridge
* looks for a callback in the delegate and calls it if present
* (meaning, if it is not <code>NULL</code>).
* XXX on all of that
* @field size The size of the delegate structure.
* @field applicationName The name of your application.
* @field registrationDictionary A dictionary describing your application and the notifications it can send out.
* @field applicationIconData Your application's icon.
* @field growlInstallationWindowTitle The title of the installation window.
* @field growlInstallationInformation Text to display in the installation window.
* @field growlUpdateWindowTitle The title of the update window.
* @field growlUpdateInformation Text to display in the update window.
* @field referenceCount A count of owners of the delegate.
* @field retain Called when GrowlApplicationBridge receives this delegate.
* @field release Called when GrowlApplicationBridge no longer needs this delegate.
* @field growlIsReady Called when GrowlHelperApp is listening for notifications.
* @field growlNotificationWasClicked Called when a Growl notification is clicked.
* @field growlNotificationTimedOut Called when a Growl notification timed out.
*/
struct Growl_Delegate {
/* @discussion This should be sizeof(struct Growl_Delegate).
*/
size_t size;
/*All of these attributes are optional.
*Optional attributes can be NULL; required attributes that
* are NULL cause setting the Growl delegate to fail.
*XXX - move optional/required status into the discussion for each field
*/
/* This name is used both internally and in the Growl preferences.
*
* This should remain stable between different versions and incarnations of
* your application.
* For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and
* "SurfWriter Lite" are not.
*
* This can be <code>NULL</code> if it is provided elsewhere, namely in an
* auto-discoverable plist file in your app bundle
* (XXX refer to more information on that) or in registrationDictionary.
*/
CFStringRef applicationName;
/*
* Must contain at least these keys:
* GROWL_NOTIFICATIONS_ALL (CFArray):
* Contains the names of all notifications your application may post.
*
* Can also contain these keys:
* GROWL_NOTIFICATIONS_DEFAULT (CFArray):
* Names of notifications that should be enabled by default.
* If omitted, GROWL_NOTIFICATIONS_ALL will be used.
* GROWL_APP_NAME (CFString):
* Same as the applicationName member of this structure.
* If both are present, the applicationName member shall prevail.
* If this key is present, you may omit applicationName (set it to <code>NULL</code>).
* GROWL_APP_ICON (CFData):
* Same as the iconData member of this structure.
* If both are present, the iconData member shall prevail.
* If this key is present, you may omit iconData (set it to <code>NULL</code>).
*
* If you change the contents of this dictionary after setting the delegate,
* be sure to call Growl_Reregister.
*
* This can be <code>NULL</code> if you have an auto-discoverable plist file in your app
* bundle. (XXX refer to more information on that)
*/
CFDictionaryRef registrationDictionary;
/* The data can be in any format supported by NSImage. As of
* Mac OS X 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and
* PICT formats.
*
* If this is not supplied, Growl will look up your application's icon by
* its application name.
*/
CFDataRef applicationIconData;
/* Installer display attributes
*
* These four attributes are used by the Growl installer, if this framework
* supports it.
* For any of these being <code>NULL</code>, a localised default will be
* supplied.
*/
/* If this is <code>NULL</code>, Growl will use a default,
* localized title.
*
* Only used if you're using Growl-WithInstaller.framework. Otherwise,
* this member is ignored.
*/
CFStringRef growlInstallationWindowTitle;
/* This information may be as long or short as desired (the
* window will be sized to fit it). If Growl is not installed, it will
* be displayed to the user as an explanation of what Growl is and what
* it can do in your application.
* It should probably note that no download is required to install.
*
* If this is <code>NULL</code>, Growl will use a default, localized
* explanation.
*
* Only used if you're using Growl-WithInstaller.framework. Otherwise,
* this member is ignored.
*/
CFStringRef growlInstallationInformation;
/* If this is <code>NULL</code>, Growl will use a default,
* localized title.
*
* Only used if you're using Growl-WithInstaller.framework. Otherwise,
* this member is ignored.
*/
CFStringRef growlUpdateWindowTitle;
/* This information may be as long or short as desired (the
* window will be sized to fit it). If an older version of Growl is
* installed, it will be displayed to the user as an explanation that an
* updated version of Growl is included in your application and
* no download is required.
*
* If this is <code>NULL</code>, Growl will use a default, localized
* explanation.
*
* Only used if you're using Growl-WithInstaller.framework. Otherwise,
* this member is ignored.
*/
CFStringRef growlUpdateInformation;
/* This member is provided for use by your retain and release
* callbacks (see below).
*
* GrowlApplicationBridge never directly uses this member. Instead, it
* calls your retain callback (if non-<code>NULL</code>) and your release
* callback (if non-<code>NULL</code>).
*/
unsigned referenceCount;
//Functions. Currently all of these are optional (any of them can be NULL).
/* When you call Growl_SetDelegate(newDelegate), it will call
* oldDelegate->release(oldDelegate), and then it will call
* newDelegate->retain(newDelegate), and the return value from retain
* is what will be set as the delegate.
* (This means that this member works like CFRetain and -[NSObject retain].)
* This member is optional (it can be <code>NULL</code>).
* For a delegate allocated with malloc, this member would be
* <code>NULL</code>.
* @result A delegate to which GrowlApplicationBridge holds a reference.
*/
void *(*retain)(void *);
/* When you call Growl_SetDelegate(newDelegate), it will call
* oldDelegate->release(oldDelegate), and then it will call
* newDelegate->retain(newDelegate), and the return value from retain
* is what will be set as the delegate.
* (This means that this member works like CFRelease and
* -[NSObject release].)
* This member is optional (it can be NULL).
* For a delegate allocated with malloc, this member might be
* <code>free</code>(3).
*/
void (*release)(void *);
/* Informs the delegate that Growl (specifically, the GrowlHelperApp) was
* launched successfully (or was already running). The application can
* take actions with the knowledge that Growl is installed and functional.
*/
void (*growlIsReady)(void);
/* Informs the delegate that a Growl notification was clicked. It is only
* sent for notifications sent with a non-<code>NULL</code> clickContext,
* so if you want to receive a message when a notification is clicked,
* clickContext must not be <code>NULL</code> when calling
* Growl_PostNotification or
* Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext.
*/
void (*growlNotificationWasClicked)(CFPropertyListRef clickContext);
/* Informs the delegate that a Growl notification timed out. It is only
* sent for notifications sent with a non-<code>NULL</code> clickContext,
* so if you want to receive a message when a notification is clicked,
* clickContext must not be <code>NULL</code> when calling
* Growl_PostNotification or
* Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext.
*/
void (*growlNotificationTimedOut)(CFPropertyListRef clickContext);
};
/*! @struct Growl_Notification
* @abstract Structure describing a Growl notification.
* @discussion XXX
* @field size The size of the notification structure.
* @field name Identifies the notification.
* @field title Short synopsis of the notification.
* @field description Additional text.
* @field iconData An icon for the notification.
* @field priority An indicator of the notification's importance.
* @field reserved Bits reserved for future usage.
* @field isSticky Requests that a notification stay on-screen until dismissed explicitly.
* @field clickContext An identifier to be passed to your click callback when a notification is clicked.
* @field clickCallback A callback to call when the notification is clicked.
*/
struct Growl_Notification {
/* This should be sizeof(struct Growl_Notification).
*/
size_t size;
/* The notification name distinguishes one type of
* notification from another. The name should be human-readable, as it
* will be displayed in the Growl preference pane.
*
* The name is used in the GROWL_NOTIFICATIONS_ALL and
* GROWL_NOTIFICATIONS_DEFAULT arrays in the registration dictionary, and
* in this member of the Growl_Notification structure.
*/
CFStringRef name;
/* A notification's title describes the notification briefly.
* It should be easy to read quickly by the user.
*/
CFStringRef title;
/* The description supplements the title with more
* information. It is usually longer and sometimes involves a list of
* subjects. For example, for a 'Download complete' notification, the
* description might have one filename per line. GrowlMail in Growl 0.6
* uses a description of '%d new mail(s)' (formatted with the number of
* messages).
*/
CFStringRef description;
/* The notification icon usually indicates either what
* happened (it may have the same icon as e.g. a toolbar item that
* started the process that led to the notification), or what it happened
* to (e.g. a document icon).
*
* The icon data is optional, so it can be <code>NULL</code>. In that
* case, the application icon is used alone. Not all displays support
* icons.
*
* The data can be in any format supported by NSImage. As of Mac OS X
* 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and PICT form
* ats.
*/
CFDataRef iconData;
/* Priority is new in Growl 0.6, and is represented as a
* signed integer from -2 to +2. 0 is Normal priority, -2 is Very Low
* priority, and +2 is Very High priority.
*
* Not all displays support priority. If you do not wish to assign a
* priority to your notification, assign 0.
*/
signed int priority;
/* These bits are not used in Growl 0.6. Set them to 0.
*/
unsigned reserved: 31;
/* When the sticky bit is clear, in most displays,
* notifications disappear after a certain amount of time. Sticky
* notifications, however, remain on-screen until the user dismisses them
* explicitly, usually by clicking them.
*
* Sticky notifications were introduced in Growl 0.6. Most notifications
* should not be sticky. Not all displays support sticky notifications,
* and the user may choose in Growl's preference pane to force the
* notification to be sticky or non-sticky, in which case the sticky bit
* in the notification will be ignored.
*/
unsigned isSticky: 1;
/* If this is not <code>NULL</code>, and your click callback
* is not <code>NULL</code> either, this will be passed to the callback
* when your notification is clicked by the user.
*
* Click feedback was introduced in Growl 0.6, and it is optional. Not
* all displays support click feedback.
*/
CFPropertyListRef clickContext;
/* If this is not <code>NULL</code>, it will be called instead
* of the Growl delegate's click callback when clickContext is
* non-<code>NULL</code> and the notification is clicked on by the user.
*
* Click feedback was introduced in Growl 0.6, and it is optional. Not
* all displays support click feedback.
*
* The per-notification click callback is not yet supported as of Growl
* 0.7.
*/
void (*clickCallback)(CFPropertyListRef clickContext);
CFStringRef identifier;
};
#pragma mark -
#pragma mark Easy initialisers
/*! @defined InitGrowlDelegate
* @abstract Callable macro. Initializes a Growl delegate structure to defaults.
* @discussion Call with a pointer to a struct Growl_Delegate. All of the
* members of the structure will be set to 0 or <code>NULL</code>, except for
* size (which will be set to <code>sizeof(struct Growl_Delegate)</code>) and
* referenceCount (which will be set to 1).
*/
#define InitGrowlDelegate(delegate) \
do { \
if (delegate) { \
(delegate)->size = sizeof(struct Growl_Delegate); \
(delegate)->applicationName = NULL; \
(delegate)->registrationDictionary = NULL; \
(delegate)->applicationIconData = NULL; \
(delegate)->growlInstallationWindowTitle = NULL; \
(delegate)->growlInstallationInformation = NULL; \
(delegate)->growlUpdateWindowTitle = NULL; \
(delegate)->growlUpdateInformation = NULL; \
(delegate)->referenceCount = 1U; \
(delegate)->retain = NULL; \
(delegate)->release = NULL; \
(delegate)->growlIsReady = NULL; \
(delegate)->growlNotificationWasClicked = NULL; \
(delegate)->growlNotificationTimedOut = NULL; \
} \
} while(0)
/*! @defined InitGrowlNotification
* @abstract Callable macro. Initializes a Growl notification structure to defaults.
* @discussion Call with a pointer to a struct Growl_Notification. All of
* the members of the structure will be set to 0 or <code>NULL</code>, except
* for size (which will be set to
* <code>sizeof(struct Growl_Notification)</code>).
*/
#define InitGrowlNotification(notification) \
do { \
if (notification) { \
(notification)->size = sizeof(struct Growl_Notification); \
(notification)->name = NULL; \
(notification)->title = NULL; \
(notification)->description = NULL; \
(notification)->iconData = NULL; \
(notification)->priority = 0; \
(notification)->reserved = 0U; \
(notification)->isSticky = false; \
(notification)->clickContext = NULL; \
(notification)->clickCallback = NULL; \
(notification)->identifier = NULL; \
} \
} while(0)
#pragma mark -
#pragma mark Public API
// @functiongroup Managing the Growl delegate
/*! @function Growl_SetDelegate
* @abstract Replaces the current Growl delegate with a new one, or removes
* the Growl delegate.
* @param newDelegate
* @result Returns false and does nothing else if a pointer that was passed in
* is unsatisfactory (because it is non-<code>NULL</code>, but at least one
* required member of it is <code>NULL</code>). Otherwise, sets or unsets the
* delegate and returns true.
* @discussion When <code>newDelegate</code> is non-<code>NULL</code>, sets
* the delegate to <code>newDelegate</code>. When it is <code>NULL</code>,
* the current delegate will be unset, and no delegate will be in place.
*
* It is legal for <code>newDelegate</code> to be the current delegate;
* nothing will happen, and Growl_SetDelegate will return true. It is also
* legal for it to be <code>NULL</code>, as described above; again, it will
* return true.
*
* If there was a delegate in place before the call, Growl_SetDelegate will
* call the old delegate's release member if it was non-<code>NULL</code>. If
* <code>newDelegate</code> is non-<code>NULL</code>, Growl_SetDelegate will
* call <code>newDelegate->retain</code>, and set the delegate to its return
* value.
*
* If you are using Growl-WithInstaller.framework, and an older version of
* Growl is installed on the user's system, the user will automatically be
* prompted to update.
*
* GrowlApplicationBridge currently does not copy this structure, nor does it
* retain any of the CF objects in the structure (it regards the structure as
* a container that retains the objects when they are added and releases them
* when they are removed or the structure is destroyed). Also,
* GrowlApplicationBridge currently does not modify any member of the
* structure, except possibly the referenceCount by calling the retain and
* release members.
*/
GROWL_EXPORT Boolean Growl_SetDelegate(struct Growl_Delegate *newDelegate);
/*! @function Growl_GetDelegate
* @abstract Returns the current Growl delegate, if any.
* @result The current Growl delegate.
* @discussion Returns the last pointer passed into Growl_SetDelegate, or
* <code>NULL</code> if no such call has been made.
*
* This function follows standard Core Foundation reference-counting rules.
* Because it is a Get function, not a Copy function, it will not retain the
* delegate on your behalf. You are responsible for retaining and releasing
* the delegate as needed.
*/
GROWL_EXPORT struct Growl_Delegate *Growl_GetDelegate(void);
#pragma mark -
// @functiongroup Posting Growl notifications
/*! @function Growl_PostNotification
* @abstract Posts a Growl notification.
* @param notification The notification to post.
* @discussion This is the preferred means for sending a Growl notification.
* The notification name and at least one of the title and description are
* required (all three are preferred). All other parameters may be
* <code>NULL</code> (or 0 or false as appropriate) to accept default values.
*
* If using the Growl-WithInstaller framework, if Growl is not installed the
* user will be prompted to install Growl.
* If the user cancels, this function will have no effect until the next
* application session, at which time when it is called the user will be
* prompted again. The user is also given the option to not be prompted again.
* If the user does choose to install Growl, the requested notification will
* be displayed once Growl is installed and running.
*/
GROWL_EXPORT void Growl_PostNotification(const struct Growl_Notification *notification);
/*! @function Growl_PostNotificationWithDictionary
* @abstract Notifies using a userInfo dictionary suitable for passing to
* CFDistributedNotificationCenter.
* @param userInfo The dictionary to notify with.
* @discussion Before Growl 0.6, your application would have posted
* notifications using CFDistributedNotificationCenter by creating a userInfo
* dictionary with the notification data. This had the advantage of allowing
* you to add other data to the dictionary for programs besides Growl that
* might be listening.
*
* This function allows you to use such dictionaries without being restricted
* to using CFDistributedNotificationCenter. The keys for this dictionary
* can be found in GrowlDefines.h.
*/
GROWL_EXPORT void Growl_PostNotificationWithDictionary(CFDictionaryRef userInfo);
/*! @function Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext
* @abstract Posts a Growl notification using parameter values.
* @param title The title of the notification.
* @param description The description of the notification.
* @param notificationName The name of the notification as listed in the
* registration dictionary.
* @param iconData Data representing a notification icon. Can be <code>NULL</code>.
* @param priority The priority of the notification (-2 to +2, with -2
* being Very Low and +2 being Very High).
* @param isSticky If true, requests that this notification wait for a
* response from the user.
* @param clickContext An object to pass to the clickCallback, if any. Can
* be <code>NULL</code>, in which case the clickCallback is not called.
* @discussion Creates a temporary Growl_Notification, fills it out with the
* supplied information, and calls Growl_PostNotification on it.
* See struct Growl_Notification and Growl_PostNotification for more
* information.
*
* The icon data can be in any format supported by NSImage. As of Mac OS X
* 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and PICT formats.
*/
GROWL_EXPORT void Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext(
/*inhale*/
CFStringRef title,
CFStringRef description,
CFStringRef notificationName,
CFDataRef iconData,
signed int priority,
Boolean isSticky,
CFPropertyListRef clickContext);
#pragma mark -
// @functiongroup Registering
/*! @function Growl_RegisterWithDictionary
* @abstract Register your application with Growl without setting a delegate.
* @discussion When you call this function with a dictionary,
* GrowlApplicationBridge registers your application using that dictionary.
* If you pass <code>NULL</code>, GrowlApplicationBridge will ask the delegate
* (if there is one) for a dictionary, and if that doesn't work, it will look
* in your application's bundle for an auto-discoverable plist.
* (XXX refer to more information on that)
*
* If you pass a dictionary to this function, it must include the
* <code>GROWL_APP_NAME</code> key, unless a delegate is set.
*
* This function is mainly an alternative to the delegate system introduced
* with Growl 0.6. Without a delegate, you cannot receive callbacks such as
* <code>growlIsReady</code> (since they are sent to the delegate). You can,
* however, set a delegate after registering without one.
*
* This function was introduced in Growl.framework 0.7.
* @result <code>false</code> if registration failed (e.g. if Growl isn't installed).
*/
GROWL_EXPORT Boolean Growl_RegisterWithDictionary(CFDictionaryRef regDict);
/*! @function Growl_Reregister
* @abstract Updates your registration with Growl.
* @discussion If your application changes the contents of the
* GROWL_NOTIFICATIONS_ALL key in the registrationDictionary member of the
* Growl delegate, or if it changes the value of that member, or if it
* changes the contents of its auto-discoverable plist, call this function
* to have Growl update its registration information for your application.
*
* Otherwise, this function does not normally need to be called. If you're
* using a delegate, your application will be registered when you set the
* delegate if both the delegate and its registrationDictionary member are
* non-<code>NULL</code>.
*
* This function is now implemented using
* <code>Growl_RegisterWithDictionary</code>.
*/
GROWL_EXPORT void Growl_Reregister(void);
#pragma mark -
/*! @function Growl_SetWillRegisterWhenGrowlIsReady
* @abstract Tells GrowlApplicationBridge to register with Growl when Growl
* launches (or not).
* @discussion When Growl has started listening for notifications, it posts a
* <code>GROWL_IS_READY</code> notification on the Distributed Notification
* Center. GrowlApplicationBridge listens for this notification, using it to
* perform various tasks (such as calling your delegate's
* <code>growlIsReady</code> callback, if it has one). If this function is
* called with <code>true</code>, one of those tasks will be to reregister
* with Growl (in the manner of <code>Growl_Reregister</code>).
*
* This attribute is automatically set back to <code>false</code>
* (the default) after every <code>GROWL_IS_READY</code> notification.
* @param flag <code>true</code> if you want GrowlApplicationBridge to register with
* Growl when next it is ready; <code>false</code> if not.
*/
GROWL_EXPORT void Growl_SetWillRegisterWhenGrowlIsReady(Boolean flag);
/*! @function Growl_WillRegisterWhenGrowlIsReady
* @abstract Reports whether GrowlApplicationBridge will register with Growl
* when Growl next launches.
* @result <code>true</code> if GrowlApplicationBridge will register with
* Growl when next it posts GROWL_IS_READY; <code>false</code> if not.
*/
GROWL_EXPORT Boolean Growl_WillRegisterWhenGrowlIsReady(void);
#pragma mark -
// @functiongroup Obtaining registration dictionaries
/*! @function Growl_CopyRegistrationDictionaryFromDelegate
* @abstract Asks the delegate for a registration dictionary.
* @discussion If no delegate is set, or if the delegate's
* <code>registrationDictionary</code> member is <code>NULL</code>, this
* function returns <code>NULL</code>.
*
* This function does not attempt to clean up the dictionary in any way - for
* example, if it is missing the <code>GROWL_APP_NAME</code> key, the result
* will be missing it too. Use
* <code>Growl_CreateRegistrationDictionaryByFillingInDictionary</code> or
* <code>Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys</code>
* to try to fill in missing keys.
*
* This function was introduced in Growl.framework 0.7.
* @result A registration dictionary.
*/
GROWL_EXPORT CFDictionaryRef Growl_CopyRegistrationDictionaryFromDelegate(void);
/*! @function Growl_CopyRegistrationDictionaryFromBundle
* @abstract Looks in a bundle for a registration dictionary.
* @discussion This function looks in a bundle for an auto-discoverable
* registration dictionary file using <code>CFBundleCopyResourceURL</code>.
* If it finds one, it loads the file using <code>CFPropertyList</code> and
* returns the result.
*
* If you pass <code>NULL</code> as the bundle, the main bundle is examined.
*
* This function does not attempt to clean up the dictionary in any way - for
* example, if it is missing the <code>GROWL_APP_NAME</code> key, the result
* will be missing it too. Use
* <code>Growl_CreateRegistrationDictionaryByFillingInDictionary:</code> or
* <code>Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys</code>
* to try to fill in missing keys.
*
* This function was introduced in Growl.framework 0.7.
* @result A registration dictionary.
*/
GROWL_EXPORT CFDictionaryRef Growl_CopyRegistrationDictionaryFromBundle(CFBundleRef bundle);
/*! @function Growl_CreateBestRegistrationDictionary
* @abstract Obtains a registration dictionary, filled out to the best of
* GrowlApplicationBridge's knowledge.
* @discussion This function creates a registration dictionary as best
* GrowlApplicationBridge knows how.
*
* First, GrowlApplicationBridge examines the Growl delegate (if there is
* one) and gets the registration dictionary from that. If no such dictionary
* was obtained, GrowlApplicationBridge looks in your application's main
* bundle for an auto-discoverable registration dictionary file. If that
* doesn't exist either, this function returns <code>NULL</code>.
*
* Second, GrowlApplicationBridge calls
* <code>Growl_CreateRegistrationDictionaryByFillingInDictionary</code> with
* whatever dictionary was obtained. The result of that function is the
* result of this function.
*
* GrowlApplicationBridge uses this function when you call
* <code>Growl_SetDelegate</code>, or when you call
* <code>Growl_RegisterWithDictionary</code> with <code>NULL</code>.
*
* This function was introduced in Growl.framework 0.7.
* @result A registration dictionary.
*/
GROWL_EXPORT CFDictionaryRef Growl_CreateBestRegistrationDictionary(void);
#pragma mark -
// @functiongroup Filling in registration dictionaries
/*! @function Growl_CreateRegistrationDictionaryByFillingInDictionary
* @abstract Tries to fill in missing keys in a registration dictionary.
* @param regDict The dictionary to fill in.
* @result The dictionary with the keys filled in.
* @discussion This function examines the passed-in dictionary for missing keys,
* and tries to work out correct values for them. As of 0.7, it uses:
*
* Key Value
* --- -----
* <code>GROWL_APP_NAME</code> <code>CFBundleExecutableName</code>
* <code>GROWL_APP_ICON</code> The icon of the application.
* <code>GROWL_APP_LOCATION</code> The location of the application.
* <code>GROWL_NOTIFICATIONS_DEFAULT</code> <code>GROWL_NOTIFICATIONS_ALL</code>
*
* Keys are only filled in if missing; if a key is present in the dictionary,
* its value will not be changed.
*
* This function was introduced in Growl.framework 0.7.
*/
GROWL_EXPORT CFDictionaryRef Growl_CreateRegistrationDictionaryByFillingInDictionary(CFDictionaryRef regDict);
/*! @function Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys
* @abstract Tries to fill in missing keys in a registration dictionary.
* @param regDict The dictionary to fill in.
* @param keys The keys to fill in. If <code>NULL</code>, any missing keys are filled in.
* @result The dictionary with the keys filled in.
* @discussion This function examines the passed-in dictionary for missing keys,
* and tries to work out correct values for them. As of 0.7, it uses:
*
* Key Value
* --- -----
* <code>GROWL_APP_NAME</code> <code>CFBundleExecutableName</code>
* <code>GROWL_APP_ICON</code> The icon of the application.
* <code>GROWL_APP_LOCATION</code> The location of the application.
* <code>GROWL_NOTIFICATIONS_DEFAULT</code> <code>GROWL_NOTIFICATIONS_ALL</code>
*
* Only those keys that are listed in <code>keys</code> will be filled in.
* Other missing keys are ignored. Also, keys are only filled in if missing;
* if a key is present in the dictionary, its value will not be changed.
*
* This function was introduced in Growl.framework 0.7.
*/
GROWL_EXPORT CFDictionaryRef Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys(CFDictionaryRef regDict, CFSetRef keys);
/*! @brief Tries to fill in missing keys in a notification dictionary.
* @param notifDict The dictionary to fill in.
* @return The dictionary with the keys filled in. This will be a separate instance from \a notifDict.
* @discussion This function examines the \a notifDict for missing keys, and
* tries to get them from the last known registration dictionary. As of 1.1,
* the keys that it will look for are:
*
* \li <code>GROWL_APP_NAME</code>
* \li <code>GROWL_APP_ICON</code>
*
* @since Growl.framework 1.1
*/
GROWL_EXPORT CFDictionaryRef Growl_CreateNotificationDictionaryByFillingInDictionary(CFDictionaryRef notifDict);
#pragma mark -
// @functiongroup Querying Growl's status
/*! @function Growl_IsInstalled
* @abstract Determines whether the Growl prefpane and its helper app are
* installed.
* @result Returns true if Growl is installed, false otherwise.
*/
GROWL_EXPORT Boolean Growl_IsInstalled(void);
/*! @function Growl_IsRunning
* @abstract Cycles through the process list to find whether GrowlHelperApp
* is running.
* @result Returns true if Growl is running, false otherwise.
*/
GROWL_EXPORT Boolean Growl_IsRunning(void);
#pragma mark -
// @functiongroup Launching Growl
/*! @typedef GrowlLaunchCallback
* @abstract Callback to notify you that Growl is running.
* @param context The context pointer passed to Growl_LaunchIfInstalled.
* @discussion Growl_LaunchIfInstalled calls this callback function if Growl
* was already running or if it launched Growl successfully.
*/
typedef void (*GrowlLaunchCallback)(void *context);
/*! @function Growl_LaunchIfInstalled
* @abstract Launches GrowlHelperApp if it is not already running.
* @param callback A callback function which will be called if Growl was successfully
* launched or was already running. Can be <code>NULL</code>.
* @param context The context pointer to pass to the callback. Can be <code>NULL</code>.
* @result Returns true if Growl was successfully launched or was already
* running; returns false and does not call the callback otherwise.
* @discussion Returns true and calls the callback (if the callback is not
* <code>NULL</code>) if the Growl helper app began launching or was already
* running. Returns false and performs no other action if Growl could not be
* launched (e.g. because the Growl preference pane is not properly installed).
*
* If <code>Growl_CreateBestRegistrationDictionary</code> returns
* non-<code>NULL</code>, this function will register with Growl atomically.
*
* The callback should take a single argument; this is to allow applications
* to have context-relevant information passed back. It is perfectly
* acceptable for context to be <code>NULL</code>. The callback itself can be
* <code>NULL</code> if you don't want one.
*/
GROWL_EXPORT Boolean Growl_LaunchIfInstalled(GrowlLaunchCallback callback, void *context);
#pragma mark -
#pragma mark Constants
/*! @defined GROWL_PREFPANE_BUNDLE_IDENTIFIER
* @abstract The CFBundleIdentifier of the Growl preference pane bundle.
* @discussion GrowlApplicationBridge uses this to determine whether Growl is
* currently installed, by searching for the Growl preference pane. Your
* application probably does not need to use this macro itself.
*/
#ifndef GROWL_PREFPANE_BUNDLE_IDENTIFIER
#define GROWL_PREFPANE_BUNDLE_IDENTIFIER CFSTR("com.growl.prefpanel")
#endif
__END_DECLS
#endif /* _GROWLAPPLICATIONBRIDGE_CARBON_H_ */

Some files were not shown because too many files have changed in this diff Show More