Transitioning off custom preference files

pull/1/head
Frederic Jacobs 11 years ago
parent 583373ba72
commit c73e6b65eb

@ -48,8 +48,6 @@
765052B3182BF839008313E1 /* HelveticaNeueLTStd-Th.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052B1182BF839008313E1 /* HelveticaNeueLTStd-Th.otf */; };
768A1A2B17FC9CD300E00ED8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 768A1A2A17FC9CD300E00ED8 /* libz.dylib */; };
76919BF71805D190008C664A /* ContactManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 76919BF61805D190008C664A /* ContactManagerTest.m */; };
76B8189E182C39460088060E /* PreferenceListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76B8189C182C39460088060E /* PreferenceListViewController.m */; };
76B8189F182C39460088060E /* PreferenceListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76B8189C182C39460088060E /* PreferenceListViewController.m */; };
76B818A1182C39460088060E /* PreferenceListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 76B8189D182C39460088060E /* PreferenceListViewController.xib */; };
76C87F13181EE11C00C4ACAB /* InboxFeedFooterCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76C87F12181EE11C00C4ACAB /* InboxFeedFooterCell.m */; };
76C87F14181EE11C00C4ACAB /* InboxFeedFooterCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76C87F12181EE11C00C4ACAB /* InboxFeedFooterCell.m */; };
@ -380,6 +378,7 @@
A1C32D5017A06538000A904E /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4F17A06537000A904E /* AddressBookUI.framework */; };
A1C32D5117A06544000A904E /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4D17A0652C000A904E /* AddressBook.framework */; };
AA0C8E498E2046B0B81EEE6E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313AE91B4954215858A5662 /* libPods.a */; };
B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */ = {isa = PBXBuildFile; fileRef = B60C16641988999D00E97A6C /* VersionMigrations.m */; };
B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B67EBF5C19194AC60084CCFD /* Settings.bundle */; };
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
B6B1013C196D213F007E3930 /* SGNKeychainUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B1013B196D213F007E3930 /* SGNKeychainUtil.m */; };
@ -719,8 +718,6 @@
765052B1182BF839008313E1 /* HelveticaNeueLTStd-Th.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "HelveticaNeueLTStd-Th.otf"; sourceTree = "<group>"; };
768A1A2A17FC9CD300E00ED8 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
76919BF61805D190008C664A /* ContactManagerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ContactManagerTest.m; path = contact/ContactManagerTest.m; sourceTree = "<group>"; };
76B8189B182C39460088060E /* PreferenceListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreferenceListViewController.h; sourceTree = "<group>"; };
76B8189C182C39460088060E /* PreferenceListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PreferenceListViewController.m; sourceTree = "<group>"; };
76B8189D182C39460088060E /* PreferenceListViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = PreferenceListViewController.xib; path = ../PreferenceListViewController.xib; sourceTree = "<group>"; };
76C87F11181EE11C00C4ACAB /* InboxFeedFooterCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InboxFeedFooterCell.h; sourceTree = "<group>"; };
76C87F12181EE11C00C4ACAB /* InboxFeedFooterCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InboxFeedFooterCell.m; sourceTree = "<group>"; };
@ -1102,6 +1099,8 @@
A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
A1C32D4F17A06537000A904E /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
A1FDCBEE16DAA6C300868894 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
B60C16631988999D00E97A6C /* VersionMigrations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VersionMigrations.h; sourceTree = "<group>"; };
B60C16641988999D00E97A6C /* VersionMigrations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VersionMigrations.m; sourceTree = "<group>"; };
B657DDC91911A40500F45B0C /* Signal.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = Signal.entitlements; sourceTree = "<group>"; };
B67EBF5C19194AC60084CCFD /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = Settings.bundle; path = SettingsBundle/Settings.bundle; sourceTree = SOURCE_ROOT; };
B69CD25019773E79005CE69A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
@ -1686,6 +1685,8 @@
76EB041B18170B33006006FC /* Release.m */,
B6B1013A196D213F007E3930 /* SGNKeychainUtil.h */,
B6B1013B196D213F007E3930 /* SGNKeychainUtil.m */,
B60C16631988999D00E97A6C /* VersionMigrations.h */,
B60C16641988999D00E97A6C /* VersionMigrations.m */,
);
path = environment;
sourceTree = "<group>";
@ -2123,8 +2124,6 @@
76EB050E18170B33006006FC /* LeftSideMenuViewController.m */,
76EB050F18170B33006006FC /* NextResponderScrollView.h */,
76EB051018170B33006006FC /* NextResponderScrollView.m */,
76B8189B182C39460088060E /* PreferenceListViewController.h */,
76B8189C182C39460088060E /* PreferenceListViewController.m */,
76EB051518170B33006006FC /* RegisterViewController.h */,
76EB051618170B33006006FC /* RegisterViewController.m */,
76EB051718170B33006006FC /* SettingsViewController.h */,
@ -3038,6 +3037,7 @@
76EB066218170B34006006FC /* SettingsViewController.m in Sources */,
76EB054818170B33006006FC /* CancelTokenSource.m in Sources */,
76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */,
B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */,
76EB062A18170B33006006FC /* BadState.m in Sources */,
B97940271832BD2400BD66CB /* UIUtil.m in Sources */,
76EB05BE18170B33006006FC /* ConfirmPacket.m in Sources */,
@ -3098,7 +3098,6 @@
76EB058218170B33006006FC /* Environment.m in Sources */,
76EB064418170B33006006FC /* ThreadManager.m in Sources */,
70B8011A190C55660042E3F0 /* UnknownFieldSet.m in Sources */,
76B8189E182C39460088060E /* PreferenceListViewController.m in Sources */,
70B80114190C55660042E3F0 /* Field.m in Sources */,
E197B61E18BBEC6D00F073E5 /* AudioRouter.m in Sources */,
E197B60D18BBEC1A00F073E5 /* AudioSocket.m in Sources */,
@ -3232,7 +3231,6 @@
76EB05BF18170B33006006FC /* ConfirmPacket.m in Sources */,
76EB05E518170B33006006FC /* UdpSocket.m in Sources */,
76EB05BD18170B33006006FC /* ConfirmAckPacket.m in Sources */,
76B8189F182C39460088060E /* PreferenceListViewController.m in Sources */,
76EB05DB18170B33006006FC /* LowLatencyConnector.m in Sources */,
76EB060F18170B33006006FC /* DecayingSampleEstimator.m in Sources */,
76EB055318170B33006006FC /* TimeoutFailure.m in Sources */,

@ -29,11 +29,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.2</string>
<string>1.0.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0.2</string>
<string>1.0.3</string>
<key>LSApplicationCategoryType</key>
<string></string>
<key>LSRequiresIPhoneOS</key>

@ -16,6 +16,7 @@
#import "Util.h"
#import <UICKeyChainStore/UICKeyChainStore.h>
#import "Environment.h"
#import "VersionMigrations.h"
#define kSignalVersionKey @"SignalUpdateVersionKey"
@ -47,18 +48,39 @@
[Environment setCurrent:[Release releaseEnvironmentWithLogging:nil]];
[Environment resetAppData]; // We clean previous keychain entries in case their are some entries remaining.
} else if ([currentVersion compare:previousVersion options:NSNumericSearch] == NSOrderedDescending){
// The application was updated
DDLogWarn(@"Application was updated from %@ to %@", previousVersion, currentVersion);
// Application was updated, let's see if we have a migration scheme for it.
if ([previousVersion isEqualToString:@"1.0.2"]) {
}
}
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:kSignalVersionKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#pragma mark Disable cloud/iTunes syncing of call log
- (void)disableCallLogBackup{
NSString *preferencesPath = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"/Preferences"];
/**
* Protects the preference and logs file with disk encryption and prevents them to leak to iCloud.
*/
- (void)protectPreferenceFiles{
// We have two kind of data to deal with for now, preference files (/Library/Preferences), logs (/Library/Caches) and pr
NSString *path = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSLog(@"PATH: %@", path);
NSString *path2 = [NSHomeDirectory() stringByAppendingString:@"/Documents"];
NSArray *directoryEnum = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path2 error:nil];
NSLog(@"%@",directoryEnum);
NSLog(@"%@ vs %@", NSHomeDirectory(), [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]);
NSString *preferencesPath = [NSHomeDirectory() stringByAppendingString:@"/Library/Preferences"];
NSString *userDefaultsString = [NSString stringWithFormat:@"%@/%@.plist", preferencesPath,[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]];
NSURL *userDefaultsURL = [NSURL fileURLWithPath:userDefaultsString];
@ -81,7 +103,7 @@
[DDLog addLogger:self.fileLogger];
[self performUpdateCheck];
[self disableCallLogBackup];
[self protectPreferenceFiles];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.notificationTracker = [NotificationTracker notificationTracker];

@ -17,7 +17,7 @@
NSTimeInterval audioDurationPerPacket = (NSTimeInterval)(AUDIO_FRAMES_PER_PACKET*[SpeexCodec frameSizeInSamples])
/ SAMPLE_RATE;
double initialDesiredBufferDepth = [[Environment preferences] getCachedOrDefaultDesiredBufferDepth];
double initialDesiredBufferDepth = [[[Environment getCurrent]preferences] getCachedOrDefaultDesiredBufferDepth];
DropoutTracker* dropoutTracker = [DropoutTracker dropoutTrackerWithAudioDurationPerPacket:audioDurationPerPacket];
@ -59,7 +59,7 @@
}
-(void) terminate {
[[Environment preferences] setCachedDesiredBufferDepth:[decayingDesiredBufferDepth currentEstimate]];
[[[Environment getCurrent]preferences] setCachedDesiredBufferDepth:[decayingDesiredBufferDepth currentEstimate]];
}
@end

@ -9,7 +9,7 @@
* Environment is a data and data accessor class.
* It handles application-level component wiring in order to support mocks for testing.
* It also handles network configuration for testing/deployment server configurations.
*
*
**/
#define SAMPLE_RATE 8000
@ -24,7 +24,6 @@
@class PhoneNumberDirectoryFilterManager;
@interface Environment : NSObject
@property (nonatomic, readonly) PropertyListPreferences* preferences;
@property (nonatomic, readonly) in_port_t serverPort;
@property (nonatomic, readonly) id<Logging> logging;
@property (nonatomic, readonly) SecureEndPoint* masterServerSecureEndPoint;
@ -46,27 +45,25 @@
+(SecureEndPoint*) getSecureEndPointToDefaultRelayServer;
+(SecureEndPoint*) getSecureEndPointToSignalingServerNamed:(NSString*)name;
+(Environment*) environmentWithPreferences:(PropertyListPreferences*)preferences
andLogging:(id<Logging>)logging
andErrorNoter:(ErrorHandlerBlock)errorNoter
andServerPort:(in_port_t)serverPort
andMasterServerHostName:(NSString*)masterServerHostName
andDefaultRelayName:(NSString*)defaultRelayName
andRelayServerHostNameSuffix:(NSString*)relayServerHostNameSuffix
andCertificate:(Certificate*)certificate
andCurrentRegionCodeForPhoneNumbers:(NSString*)currentRegionCodeForPhoneNumbers
andSupportedKeyAgreementProtocols:(NSArray*)keyAgreementProtocolsInDescendingPriority
andPhoneManager:(PhoneManager*)phoneManager
andRecentCallManager:(RecentCallManager *)recentCallManager
andTestingAndLegacyOptions:(NSArray*)testingAndLegacyOptions
andZrtpClientId:(NSData*)zrtpClientId
andZrtpVersionId:(NSData*)zrtpVersionId
andContactsManager:(ContactsManager *)contactsManager
andPhoneDirectoryManager:(PhoneNumberDirectoryFilterManager*)phoneDirectoryManager;
+(Environment*) environmentWithLogging:(id<Logging>)logging
andErrorNoter:(ErrorHandlerBlock)errorNoter
andServerPort:(in_port_t)serverPort
andMasterServerHostName:(NSString*)masterServerHostName
andDefaultRelayName:(NSString*)defaultRelayName
andRelayServerHostNameSuffix:(NSString*)relayServerHostNameSuffix
andCertificate:(Certificate*)certificate
andCurrentRegionCodeForPhoneNumbers:(NSString*)currentRegionCodeForPhoneNumbers
andSupportedKeyAgreementProtocols:(NSArray*)keyAgreementProtocolsInDescendingPriority
andPhoneManager:(PhoneManager*)phoneManager
andRecentCallManager:(RecentCallManager *)recentCallManager
andTestingAndLegacyOptions:(NSArray*)testingAndLegacyOptions
andZrtpClientId:(NSData*)zrtpClientId
andZrtpVersionId:(NSData*)zrtpVersionId
andContactsManager:(ContactsManager *)contactsManager
andPhoneDirectoryManager:(PhoneNumberDirectoryFilterManager*)phoneDirectoryManager;
+(Environment*) getCurrent;
+(void) setCurrent:(Environment*)curEnvironment;
+(PropertyListPreferences*) preferences;
+(id<Logging>) logging;
+(NSString*) relayServerNameToHostName:(NSString*)name;
+(ErrorHandlerBlock) errorNoter;
@ -74,6 +71,8 @@
+(bool) hasEnabledTestingOrLegacyOption:(NSString*)flag;
+(PhoneManager*) phoneManager;
-(PropertyListPreferences*)preferences;
+(BOOL)isRegistered;
+(void)setRegistered:(BOOL)status;
+(void)resetAppData;

@ -16,22 +16,21 @@ static Environment* environment = nil;
@implementation Environment
@synthesize testingAndLegacyOptions,
currentRegionCodeForPhoneNumbers,
errorNoter,
keyAgreementProtocolsInDescendingPriority,
logging,
masterServerSecureEndPoint,
preferences,
defaultRelayName,
relayServerHostNameSuffix,
certificate,
serverPort,
zrtpClientId,
zrtpVersionId,
phoneManager,
recentCallManager,
contactsManager,
phoneDirectoryManager;
currentRegionCodeForPhoneNumbers,
errorNoter,
keyAgreementProtocolsInDescendingPriority,
logging,
masterServerSecureEndPoint,
defaultRelayName,
relayServerHostNameSuffix,
certificate,
serverPort,
zrtpClientId,
zrtpVersionId,
phoneManager,
recentCallManager,
contactsManager,
phoneDirectoryManager;
+(NSString*) currentRegionCodeForPhoneNumbers {
return [[self getCurrent] currentRegionCodeForPhoneNumbers];
@ -71,8 +70,7 @@ static Environment* environment = nil;
return [SecureEndPoint secureEndPointForHost:location identifiedByCertificate:env.certificate];
}
+(Environment*) environmentWithPreferences:(PropertyListPreferences*)preferences
andLogging:(id<Logging>)logging
+(Environment*) environmentWithLogging:(id<Logging>)logging
andErrorNoter:(ErrorHandlerBlock)errorNoter
andServerPort:(in_port_t)serverPort
andMasterServerHostName:(NSString*)masterServerHostName
@ -88,8 +86,8 @@ static Environment* environment = nil;
andZrtpVersionId:(NSData*)zrtpVersionId
andContactsManager:(ContactsManager *)contactsManager
andPhoneDirectoryManager:(PhoneNumberDirectoryFilterManager*)phoneDirectoryManager {
require(errorNoter != nil);
require(preferences != nil);
require(zrtpClientId != nil);
require(zrtpVersionId != nil);
require(testingAndLegacyOptions != nil);
@ -98,14 +96,13 @@ static Environment* environment = nil;
require([keyAgreementProtocolsInDescendingPriority all:^int(id p) {
return [p conformsToProtocol:@protocol(KeyAgreementProtocol)];
}]);
// must support DH3k
require([keyAgreementProtocolsInDescendingPriority any:^int(id p) {
return [p isKindOfClass:[DH3KKeyAgreementProtocol class]];
}]);
Environment* e = [Environment new];
e->preferences = preferences;
e->errorNoter = errorNoter;
e->logging = logging;
e->testingAndLegacyOptions = testingAndLegacyOptions;
@ -124,7 +121,7 @@ static Environment* environment = nil;
e->zrtpClientId = zrtpClientId;
e->zrtpVersionId = zrtpVersionId;
e->contactsManager = contactsManager;
// @todo: better place for this?
if (recentCallManager != nil) {
[recentCallManager watchForCallsThrough:phoneManager
@ -132,13 +129,10 @@ static Environment* environment = nil;
[recentCallManager watchForContactUpdatesFrom:contactsManager
untillCancelled:nil];
}
return e;
}
+(PropertyListPreferences*) preferences {
return [[Environment getCurrent] preferences];
}
+(PhoneManager*) phoneManager {
return [[Environment getCurrent] phoneManager];
}
@ -165,6 +159,10 @@ static Environment* environment = nil;
[[NSUserDefaults standardUserDefaults] setObject:status?@YES:@NO forKey:isRegisteredUserDefaultString];
}
-(PropertyListPreferences*)preferences{
return [[PropertyListPreferences alloc]init];
}
+(void)resetAppData{
[SGNKeychainUtil wipeKeychain];
[NSUserDefaults resetStandardUserDefaults];

@ -12,24 +12,15 @@
-(void) setSavedPhoneNumberDirectory:(PhoneNumberDirectoryFilter*)phoneNumberDirectoryFilter;
-(NSTimeInterval) getCachedOrDefaultDesiredBufferDepth;
-(void) setCachedDesiredBufferDepth:(double)value;
-(void) setSettingsRowExpandedPrefs:(NSArray *)prefs;
-(NSArray *) getOrGenerateSettingsRowExpandedPrefs;
-(NSArray *) getAvailableDateFormats;
-(BOOL) getFreshInstallTutorialsEnabled;
-(BOOL) getContactImagesEnabled;
-(BOOL) getAutocorrectEnabled;
-(BOOL) getHistoryLogEnabled;
-(BOOL) getAnonymousFeedbackEnabled;
-(NSString *) getDateFormat;
-(void) setDateFormat:(NSString *)format;
-(void) setFreshInstallTutorialsEnabled:(BOOL)enabled;
-(void) setContactImagesEnabled:(BOOL)enabled;
-(void) setAutocorrectEnabled:(BOOL)enabled;
-(void) setHistoryLogEnabled:(BOOL)enabled;
-(void) setAnonymousFeedbackEnabled:(BOOL)enabled;
-(NSString *)getDateFormatKey;
@end

@ -20,15 +20,6 @@
#define CONTACT_IMAGES_ENABLED_KEY @"Contact Images Enabled Key"
#define AUTOCORRECT_ENABLED_KEY @"Autocorrect Enabled Key"
#define HISTORY_LOG_ENABLED_KEY @"History Log Enabled Key"
#define ANONYMOUS_FEEDBACK_ENABLED_KEY @"Anonymous Feedback Enabled Key"
#define DATE_FORMAT_KEY @"Date Format Key"
#define DATE_FORMAT_1 @"dd-MM-yyyy"
#define DATE_FORMAT_2 @"yyyy-MM-dd"
#define DATE_FORMAT_3 @"MM-dd-yyyy"
#define DATE_FORMAT_4 @"dd/MM/yyyy"
#define DATE_FORMAT_5 @"yyyy/MM/dd"
#define DATE_FORMAT_6 @"MM/dd/yyyy"
@implementation PropertyListPreferences (PropertyUtil)
@ -42,7 +33,6 @@
andExpirationDate:expiration];
}
-(void) setSavedPhoneNumberDirectory:(PhoneNumberDirectoryFilter*)phoneNumberDirectoryFilter {
// note: clearing before setting so that torn reads can be detected
[self setValueForKey:PHONE_DIRECTORY_BLOOM_FILTER_DATA_KEY toValue:nil];
[self setValueForKey:PHONE_DIRECTORY_BLOOM_FILTER_HASH_COUNT_KEY toValue:nil];
[self setValueForKey:PHONE_DIRECTORY_EXPIRATION toValue:nil];
@ -71,34 +61,6 @@
[self setValueForKey:CALL_STREAM_DES_BUFFER_LEVEL_KEY toValue:[NSNumber numberWithDouble:value]];
}
-(void) setSettingsRowExpandedPrefs:(NSArray *)prefs {
[self setValueForKey:SETTINGS_EXPANDED_ROW_PREF_DICT_KEY toValue:prefs];
}
-(NSArray *) getOrGenerateSettingsRowExpandedPrefs {
NSArray *prefs = [self tryGetValueForKey:SETTINGS_EXPANDED_ROW_PREF_DICT_KEY];
if (!prefs) {
prefs = @[[NSNumber numberWithBool:true], [NSNumber numberWithBool:true], [NSNumber numberWithBool:true], [NSNumber numberWithBool:true]];
}
return prefs;
}
-(NSArray *) getAvailableDateFormats {
return @[DATE_FORMAT_1, DATE_FORMAT_2, DATE_FORMAT_3, DATE_FORMAT_4, DATE_FORMAT_5, DATE_FORMAT_6];
}
- (NSString *)getDateFormat {
NSString *format = [self tryGetValueForKey:DATE_FORMAT_KEY];
if (format) {
return format;
} else {
return DATE_FORMAT_1;
}
}
- (NSString *)getDateFormatKey {
return DATE_FORMAT_KEY;
}
-(BOOL) getFreshInstallTutorialsEnabled {
NSNumber *preference = [self tryGetValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY];
if (preference) {
@ -131,18 +93,6 @@
return YES;
}
}
-(BOOL) getAnonymousFeedbackEnabled {
NSNumber *preference = [self tryGetValueForKey:ANONYMOUS_FEEDBACK_ENABLED_KEY];
if (preference) {
return [preference boolValue];
} else {
return NO;
}
}
-(void) setDateFormat:(NSString *)format {
[self setValueForKey:DATE_FORMAT_KEY toValue:format];
}
-(void) setFreshInstallTutorialsEnabled:(BOOL)enabled {
[self setValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY toValue:[NSNumber numberWithBool:enabled]];
@ -156,7 +106,5 @@
-(void) setHistoryLogEnabled:(BOOL)enabled {
[self setValueForKey:HISTORY_LOG_ENABLED_KEY toValue:[NSNumber numberWithBool:enabled]];
}
-(void) setAnonymousFeedbackEnabled:(BOOL)enabled {
[self setValueForKey:ANONYMOUS_FEEDBACK_ENABLED_KEY toValue:[NSNumber numberWithBool:enabled]];
}
@end

@ -1,11 +1,6 @@
#import <Foundation/Foundation.h>
@interface PropertyListPreferences : NSObject {
@private NSMutableDictionary* dictionary;
@private NSString* plistName;
}
+(PropertyListPreferences*) propertyListPreferencesWithName:(NSString*)name;
@interface PropertyListPreferences : NSObject
-(id) tryGetValueForKey:(NSString*)key;
-(void) setValueForKey:(NSString*)key toValue:(id)value;

@ -4,63 +4,25 @@
@implementation PropertyListPreferences
+(PropertyListPreferences*) propertyListPreferencesWithName:(NSString*)name {
PropertyListPreferences* p = [PropertyListPreferences new];
p->plistName = name;
p->dictionary = [[PropertyListPreferences readPlist:name] mutableCopy];
return p;
}
-(void) clear {
@synchronized(self) {
dictionary = [NSMutableDictionary dictionary];
[PropertyListPreferences writePlist:dictionary withName:plistName];
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
}
}
+(NSDictionary*) readPlist:(NSString*)name {require(name != nil);
NSString* documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"/Documents/"];
NSString *path = [NSString stringWithFormat:@"%@/%@.plist", documentsDirectory, name];
NSData *plistData = [NSData dataWithContentsOfFile:path];
// assume empty dictionary, if no data
if (plistData == nil) return @{};
NSString *error;
NSPropertyListFormat format;
id plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
checkOperationDescribe(plist != nil, ([NSString stringWithFormat:@"Error parsing plist data: %@", error]));
checkOperationDescribe([plist isKindOfClass:[NSDictionary class]], @"Plist file didn't contain a dictionary");
return plist;
}
+(void) writePlist:(NSDictionary*)plist withName:(NSString*)name {
NSString *errorDesc;
NSData* xmlData = [NSPropertyListSerialization dataFromPropertyList:plist format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
checkOperationDescribe(xmlData != nil, ([NSString stringWithFormat:@"Error serializing plist: %@", errorDesc]));
NSError* error;
NSString* documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"/Documents/"];
NSString *path = [NSString stringWithFormat:@"%@/%@.plist",documentsDirectory,name];
bool written = [xmlData writeToFile:path options:NSDataWritingAtomic error:&error];
checkOperationDescribe(written, ([NSString stringWithFormat:@"Error atomically writing plist to file: %@", error]));
}
-(id) tryGetValueForKey:(NSString *)key {
require(key != nil);
@synchronized(self) {
return [dictionary objectForKey:key];
return [[NSUserDefaults standardUserDefaults] objectForKey:key];
}
}
-(void) setValueForKey:(NSString *)key toValue:(id)value {
require(key != nil);
@synchronized(self) {
if (value == nil) {
[dictionary removeObjectForKey:key];
DDLogWarn(@"Removing object for key: %@ ", key);
} else {
[dictionary setObject:value forKey:key];
}
[PropertyListPreferences writePlist:dictionary withName:plistName];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:value forKey:key];
[userDefaults synchronize];
}
}
-(id) adjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id))adjuster {
@ -74,7 +36,7 @@
}
}
#pragma mark KeyChain store
#pragma mark KeyChain store
-(void) secureTrySetValueForKey:(NSString *)key toValue:(id)value {
require(key != nil);
@ -125,7 +87,7 @@
@synchronized(self) {
NSString *oldValue = [self secureTryGetStringForKey:key];
NSString *newValue = adjuster(oldValue);
[UICKeyChainStore setString:newValue forKey:key];
[UICKeyChainStore setString:newValue forKey:key];
return newValue;
}
}

@ -49,8 +49,7 @@ static unsigned char DH3K_PRIME[]={
//ErrorHandlerBlock errorDiscarder = ^(id error, id relatedInfo, bool causedTermination) {};
ErrorHandlerBlock errorNoter = ^(id error, id relatedInfo, bool causedTermination) { DDLogError(@"%@: %@, %d", error, relatedInfo, causedTermination); };
return [Environment environmentWithPreferences:[PropertyListPreferences propertyListPreferencesWithName:@"RedPhone-Data"]
andLogging:logging
return [Environment environmentWithLogging:logging
andErrorNoter:errorNoter
andServerPort:31337
andMasterServerHostName:@"master.whispersystems.org"
@ -69,8 +68,7 @@ static unsigned char DH3K_PRIME[]={
}
+(Environment*) unitTestEnvironment:(NSArray*)testingAndLegacyOptions {
return [Environment environmentWithPreferences:[PropertyListPreferences propertyListPreferencesWithName:@"RedPhone-Test-Data"]
andLogging:[DiscardingLog discardingLog]
return [Environment environmentWithLogging:[DiscardingLog discardingLog]
andErrorNoter:^(id error, id relatedInfo, bool causedTermination) {}
andServerPort:31337
andMasterServerHostName:@"testing.whispersystems.org"

@ -0,0 +1,15 @@
//
// VersionMigrations.h
// Signal
//
// Created by Frederic Jacobs on 29/07/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface VersionMigrations : NSObject
+ (void)migrationFrom1Dot0Dot2toLarger;
@end

@ -0,0 +1,39 @@
//
// VersionMigrations.m
// Signal
//
// Created by Frederic Jacobs on 29/07/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "VersionMigrations.h"
@implementation VersionMigrations
+ (void)migrationFrom1Dot0Dot2toLarger{
// Read everything in preference file, drop into NSUserDefaults
NSString* documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"/Documents/"];
NSString *path = [NSString stringWithFormat:@"%@/%@.plist", documentsDirectory, @"RedPhone-Data"];
NSData *plistData = [NSData dataWithContentsOfFile:path];
NSString *error;
NSPropertyListFormat format;
NSDictionary *dict = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
NSLog(@"%@", dict);
NSArray *entries = [dict allKeys];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
for (NSUInteger i = 0; i < [entries count]; i++) {
NSString *key = [entries objectAtIndex:i];
[defaults setObject:[dict objectForKey:key] forKey:key];
}
[defaults synchronize];
// delete
}
@end

@ -103,7 +103,7 @@
@synchronized(self) {
phoneNumberDirectoryFilter = directory;
}
[[Environment preferences] setSavedPhoneNumberDirectory:directory];
[[[Environment getCurrent]preferences] setSavedPhoneNumberDirectory:directory];
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_WAS_UPDATED object:nil];
[self scheduleUpdate];
}];

@ -12,20 +12,20 @@ static NSString *const DATE_FORMAT_HOUR_MINUTE = @"h:mm a ";
+ (NSDateFormatter *)dateFormatter {
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:[[[Environment getCurrent] preferences] getDateFormat]];
return formatter;
[formatter setTimeStyle:NSDateFormatterShortStyle];
return formatter;
}
+ (NSDateFormatter *)weekdayFormatter {
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:DATE_FORMAT_WEEKDAY];
return formatter;
return formatter;
}
+ (NSDateFormatter *)timeFormatter {
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:DATE_FORMAT_HOUR_MINUTE];
return formatter;
return formatter;
}
+ (BOOL)dateIsOlderThanOneDay:(NSDate *)date {

@ -1,26 +0,0 @@
#import <UIKit/UIKit.h>
/**
*
* PreferenceListViewController displays a list of options and highlights a selected one indicated by selectedValueBlock.
* When selected, the selected block is called and the value should be updated manually.
*
*/
typedef void (^SelectedBlock) (NSString *newValue);
typedef NSString* (^GetSelectedValueBlock) ();
@interface PreferenceListViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
@private SelectedBlock selectedBlock;
@private GetSelectedValueBlock getSelectedValueBlock;
@private NSString *settingsValue;
}
@property (nonatomic, strong) IBOutlet UITableView *optionTableView;
@property (nonatomic, strong) NSArray *options;
+ (PreferenceListViewController *)preferenceListViewControllerForSelectedValue:(GetSelectedValueBlock)selectedValueBlock
andOptions:(NSArray *)options
andSelectedBlock:(SelectedBlock)block;
@end

@ -1,67 +0,0 @@
#import "Environment.h"
#import "PreferencesUtil.h"
#import "PreferenceListTableViewCell.h"
#import "PreferenceListViewController.h"
#import "Util.h"
static NSString *const PREFERENCE_LIST_TABLE_VIEW_CELL = @"PreferenceListTableViewCell";
@implementation PreferenceListViewController
+ (PreferenceListViewController *)preferenceListViewControllerForSelectedValue:(GetSelectedValueBlock)selectedValueBlock
andOptions:(NSArray *)options
andSelectedBlock:(SelectedBlock)block {
require(selectedValueBlock != nil);
require(block != nil);
PreferenceListViewController *vc = [PreferenceListViewController new];
vc.options = options;
vc->selectedBlock = block;
vc->getSelectedValueBlock = selectedValueBlock;
return vc;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.barTintColor = [UIUtil darkBackgroundColor];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
self.navigationController.navigationBar.translucent = NO;
settingsValue = getSelectedValueBlock();
[_optionTableView reloadData];
}
#pragma mark - UITableViewDelegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return (NSInteger)[_options count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PreferenceListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PREFERENCE_LIST_TABLE_VIEW_CELL];
if (!cell) {
cell = [[PreferenceListTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:PREFERENCE_LIST_TABLE_VIEW_CELL];
}
if ([settingsValue isEqualToString:_options[(NSUInteger)indexPath.row]]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
NSString *date = _options[(NSUInteger)indexPath.row];
cell.preferenceTextLabel.text = [date lowercaseString];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
selectedBlock(_options[(NSUInteger)indexPath.row]);
settingsValue = getSelectedValueBlock();
[_optionTableView reloadData];
}
@end

@ -18,7 +18,6 @@
@property (nonatomic, strong) IBOutlet UITableView *settingsTableView;
@property (nonatomic, strong) IBOutlet UILabel *phoneNumberLabel;
@property (nonatomic, strong) IBOutlet UILabel *currentDateFormatLabel;
@property (nonatomic, strong) IBOutlet UILabel *titleLabel;
@property (nonatomic, strong) IBOutlet SettingsTableHeaderView *privacyAndSecurityHeaderView;
@ -31,14 +30,9 @@
@property (nonatomic, strong) IBOutlet UIButton *disableAutocorrectButton;
@property (nonatomic, strong) IBOutlet UIButton *disableHistoryButton;
@property (nonatomic, strong) IBOutlet SettingsTableHeaderView *locationOverridesHeaderView;
@property (nonatomic, strong) IBOutlet UITableViewCell *dateFormatCell;
@property (nonatomic, strong) IBOutlet SettingsTableHeaderView *callQualityHeaderView;
@property (nonatomic, strong) IBOutlet UITableViewCell *feedbackCell;
@property (nonatomic, strong) IBOutlet UITableViewCell *directoryUpdateCell;
@property (nonatomic, strong) IBOutlet UIButton *sendFeedbackButton;
@property (nonatomic, strong) IBOutlet UITableViewCell *sendDebugLog;
@property (nonatomic, assign) FutureSource *apnId;
@ -51,8 +45,6 @@
- (IBAction)disableAutocorrectButtonTapped;
- (IBAction)disableHistoryButtonTapped;
- (IBAction)sendFeedbackButtonTapped;
- (IBAction)menuButtonTapped;
@end

@ -4,7 +4,6 @@
#import "Operation.h"
#import "PreferencesUtil.h"
#import "PhoneNumber.h"
#import "PreferenceListViewController.h"
#import "RecentCallManager.h"
#import "RegisterViewController.h"
#import "SettingsViewController.h"
@ -15,8 +14,7 @@
#define SECTION_HEADER_VIEW_HEIGHT 27
#define PRIVACY_SECTION_INDEX 0
#define LOCALIZATION_SECTION_INDEX 1
#define CALL_QUALITY_SECTION_INDEX 2
#define CALL_QUALITY_SECTION_INDEX 1
static NSString *const CHECKBOX_CHECKMARK_IMAGE_NAME = @"checkbox_checkmark";
static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
@ -24,7 +22,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
@interface SettingsViewController () {
NSArray *_sectionHeaderViews;
NSArray *_privacyTableViewCells;
NSArray *_localizationTableViewCells;
NSArray *_callQualityTableViewCells;
NSString *gistURL;
@ -37,8 +34,7 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
- (void)viewDidLoad {
[super viewDidLoad];
_sectionHeaderViews = @[_privacyAndSecurityHeaderView,
_locationOverridesHeaderView];
_sectionHeaderViews = @[_privacyAndSecurityHeaderView];
_titleLabel.text = SETTINGS_NAV_BAR_TITLE;
}
@ -101,8 +97,7 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
- (void)configureCheckboxPreferences {
NSArray *buttons = @[_hideContactImagesButton,
_disableAutocorrectButton,
_disableHistoryButton,
_sendFeedbackButton];
_disableHistoryButton];
for (UIButton *button in buttons) {
[button setImage:[UIImage imageNamed:CHECKBOX_EMPTY_IMAGE_NAME]
@ -115,22 +110,11 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
_hideContactImagesButton.selected = ![prefs getContactImagesEnabled];
_disableAutocorrectButton.selected = ![prefs getAutocorrectEnabled];
_disableHistoryButton.selected = ![prefs getHistoryLogEnabled];
_sendFeedbackButton.selected = [prefs getAnonymousFeedbackEnabled];
}
- (void)configureAllCells {
PropertyListPreferences *prefs = [[Environment getCurrent] preferences];
NSArray *expandedSectionPrefs = [prefs getOrGenerateSettingsRowExpandedPrefs];
BOOL privacyExpanded = [expandedSectionPrefs[PRIVACY_SECTION_INDEX] boolValue];
_privacyTableViewCells = privacyExpanded ? [self privacyAndSecurityCells] : nil;
[_privacyAndSecurityHeaderView setColumnStateExpanded:privacyExpanded andIsAnimated:NO];
BOOL localizationExpanded = [expandedSectionPrefs[LOCALIZATION_SECTION_INDEX] boolValue];
_localizationTableViewCells = localizationExpanded ? [self localizationCells] : nil;
[_locationOverridesHeaderView setColumnStateExpanded:localizationExpanded andIsAnimated:NO];
_currentDateFormatLabel.text = [[prefs getDateFormat] lowercaseString];
_privacyTableViewCells = [self privacyAndSecurityCells];
[_privacyAndSecurityHeaderView setColumnStateExpanded:YES andIsAnimated:NO];
}
- (void)saveExpandedSectionPreferences {
@ -139,8 +123,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
NSNumber *numberBoolNo = [NSNumber numberWithBool:NO];
[expandedSectionPrefs addObject:(_privacyTableViewCells ? numberBoolYes : numberBoolNo)];
[expandedSectionPrefs addObject:(_localizationTableViewCells ? numberBoolYes : numberBoolNo)];
[[[Environment getCurrent] preferences] setSettingsRowExpandedPrefs:expandedSectionPrefs];
}
#pragma mark - Table View Helpers
@ -153,10 +135,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
_sendDebugLog];
}
- (NSArray *)localizationCells {
return @[_dateFormatCell];
}
- (NSArray *)indexPathsForCells:(NSArray *)cells forRow:(NSInteger)row {
NSMutableArray *indexPaths = [NSMutableArray array];
for (NSUInteger i = 0; i < [cells count]; i++) {
@ -169,8 +147,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
- (NSArray *)cellsForRow:(NSInteger)row {
if (row == PRIVACY_SECTION_INDEX) {
return [self privacyAndSecurityCells];
} else if(row == LOCALIZATION_SECTION_INDEX) {
return [self localizationCells];
} else {
return @[];
}
@ -189,12 +165,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
[_privacyAndSecurityHeaderView setColumnStateExpanded:columnExpanded andIsAnimated:YES];
}
- (void)localizationTapped {
[self toggleCells:&_localizationTableViewCells forRow:LOCALIZATION_SECTION_INDEX];
BOOL columnExpanded = _localizationTableViewCells != nil;
[_locationOverridesHeaderView setColumnStateExpanded:columnExpanded andIsAnimated:YES];
}
- (void)toggleCells:(NSArray *__strong*)cells forRow:(NSInteger)row {
[_settingsTableView beginUpdates];
if (*cells) {
@ -224,11 +194,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
[[[Environment getCurrent] preferences] setHistoryLogEnabled:!_disableHistoryButton.selected];
}
- (IBAction)sendFeedbackButtonTapped {
_sendFeedbackButton.selected = !_sendFeedbackButton.selected;
[[[Environment getCurrent] preferences] setAnonymousFeedbackEnabled:_sendFeedbackButton.selected];
}
- (void)clearHistory {
[[[Environment getCurrent] recentCallManager] clearRecentCalls];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:SETTINGS_LOG_CLEAR_TITLE
@ -239,18 +204,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
[alertView show];
}
- (void)showDateFormatPicker {
NSArray *dateFormats = [[[Environment getCurrent] preferences] getAvailableDateFormats];
PreferenceListViewController *prefPicker = [PreferenceListViewController preferenceListViewControllerForSelectedValue:^NSString *{
return [[Environment preferences] getDateFormat];
} andOptions:dateFormats andSelectedBlock:^(NSString *newValue) {
[[Environment preferences] setDateFormat:newValue];
}];
[self.navigationController pushViewController:prefPicker animated:YES];
}
#pragma mark - UITableViewDelegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
@ -269,8 +222,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
UIView *headerView = _sectionHeaderViews[(NSUInteger)section];
if (headerView == _privacyAndSecurityHeaderView) {
return (NSInteger)[_privacyTableViewCells count];
} else if (headerView == _locationOverridesHeaderView) {
return (NSInteger)[_localizationTableViewCells count];
} else {
return 0;
}
@ -281,10 +232,7 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
UITableViewCell *cell = nil;
if (headerView == _privacyAndSecurityHeaderView) {
cell = _privacyTableViewCells[(NSUInteger)indexPath.row];
} else if (headerView == _locationOverridesHeaderView) {
cell = _localizationTableViewCells[(NSUInteger)indexPath.row];
}
[self findAndLocalizeLabelsForView:cell];
return cell;
@ -297,9 +245,6 @@ static NSString *const CHECKBOX_EMPTY_IMAGE_NAME = @"checkbox_empty";
if (cell == _clearHistoryLogCell) {
[self clearHistory];
}
if (cell == _dateFormatCell) {
[self showDateFormatPicker];
}
if (cell == _sendDebugLog) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:SETTINGS_SENDLOG_WAITING

@ -8,21 +8,16 @@
<connections>
<outlet property="callQualityHeaderView" destination="j1j-ta-39S" id="l3w-bt-UWR"/>
<outlet property="clearHistoryLogCell" destination="d8g-sW-ZOU" id="gqj-U8-aKQ"/>
<outlet property="currentDateFormatLabel" destination="cGf-l6-5Ou" id="Mt9-kb-HbC"/>
<outlet property="dateFormatCell" destination="cdn-V5-RZJ" id="oPA-Xc-ZEF"/>
<outlet property="directoryUpdateCell" destination="spk-JC-Hnw" id="mbt-cO-iOG"/>
<outlet property="disableAutocorrectButton" destination="dLe-ku-opM" id="Edi-TS-ZcR"/>
<outlet property="disableAutocorrectCell" destination="nQL-pT-i5g" id="YZo-pL-RM7"/>
<outlet property="disableHistoryButton" destination="trw-DG-amf" id="97O-Y4-iu3"/>
<outlet property="disableHistoryCell" destination="5Wr-Th-YJI" id="fQY-Qd-xv0"/>
<outlet property="feedbackCell" destination="bY5-kP-UqY" id="Ka3-bC-LCj"/>
<outlet property="hideContactImagesButton" destination="kv5-cc-It9" id="Ftz-lp-Eqd"/>
<outlet property="hideContactImagesCell" destination="1Sy-9w-LqE" id="Rvh-96-REp"/>
<outlet property="locationOverridesHeaderView" destination="9Ou-py-Aq1" id="nC3-ta-AyD"/>
<outlet property="phoneNumberLabel" destination="G77-lz-XM0" id="adE-bu-2Kn"/>
<outlet property="privacyAndSecurityHeaderView" destination="XIa-5u-rk1" id="kap-XQ-9AL"/>
<outlet property="sendDebugLog" destination="Yc0-ZL-RM6" id="wyq-HF-B9c"/>
<outlet property="sendFeedbackButton" destination="cqe-Lt-yoW" id="yOB-Zk-xpw"/>
<outlet property="settingsTableView" destination="ajL-B0-V0M" id="0zr-QP-yQl"/>
<outlet property="titleLabel" destination="X1p-jb-cMh" id="Duc-Ac-qHm"/>
<outlet property="view" destination="1" id="3"/>
@ -298,45 +293,6 @@
<outlet property="columnStateImageView" destination="Xs2-Ls-WP3" id="gqY-mD-1n8"/>
</connections>
</view>
<view contentMode="scaleToFill" id="9Ou-py-Aq1" userLabel="Localization View" customClass="SettingsTableHeaderView">
<rect key="frame" x="0.0" y="0.0" width="320" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Localization Overrides" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JwO-Um-wHr" customClass="HelveticaNeueLTStdBoldLabel">
<rect key="frame" x="15" y="5" width="223" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" red="0.0" green="0.5450980392" blue="0.93725490199999995" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="localizationKey" value="SETTINGS_LOCALIZATION_OVERRIDES"/>
</userDefinedRuntimeAttributes>
</label>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gnO-X7-613">
<rect key="frame" x="0.0" y="0.0" width="320" height="27"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<state key="normal">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="localizationTapped" destination="-1" eventType="touchUpInside" id="UmR-Bq-qeI"/>
</connections>
</button>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="expanded_cell_icon.png" translatesAutoresizingMaskIntoConstraints="NO" id="cLT-Qy-Cbs">
<rect key="frame" x="155" y="9" width="7" height="7"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView>
<view contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2uB-Ie-fJa" userLabel="Seperator View">
<rect key="frame" x="15" y="25" width="290" height="2"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.7843137255" green="0.7843137255" blue="0.7843137255" alpha="1" colorSpace="calibratedRGB"/>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<connections>
<outlet property="columnStateImageView" destination="cLT-Qy-Cbs" id="C7z-uY-RxV"/>
</connections>
</view>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="SettingsTableViewCell" id="5Wr-Th-YJI">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
@ -411,58 +367,6 @@
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="SettingsTableViewCell" id="bY5-kP-UqY">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bY5-kP-UqY" id="FM0-Ax-NhR">
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Send Anonymous Feedback" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mc9-ef-Jff" customClass="HelveticaNeueLTStdMedLabel">
<rect key="frame" x="20" y="0.0" width="280" height="43"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="43" id="JRI-YE-Ayq"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="localizationKey" value="SETTINGS_ANONYMOUS_FEEDBACK"/>
</userDefinedRuntimeAttributes>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3DJ-aP-2s4" userLabel="Seperator View">
<rect key="frame" x="15" y="42" width="290" height="1"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.7843137255" green="0.7843137255" blue="0.7843137255" alpha="1" colorSpace="calibratedRGB"/>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cqe-Lt-yoW">
<rect key="frame" x="265" y="2" width="40" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="40" id="eaO-AG-QBH"/>
</constraints>
<state key="normal" image="checkbox_empty.png">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="sendFeedbackButtonTapped" destination="-1" eventType="touchUpInside" id="aEV-h6-00Z"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="3DJ-aP-2s4" firstAttribute="top" secondItem="cqe-Lt-yoW" secondAttribute="bottom" id="Cyo-df-6Io"/>
<constraint firstItem="mc9-ef-Jff" firstAttribute="top" secondItem="FM0-Ax-NhR" secondAttribute="top" id="Icc-a4-41Y"/>
<constraint firstItem="3DJ-aP-2s4" firstAttribute="top" secondItem="FM0-Ax-NhR" secondAttribute="top" constant="42" id="Iyo-ab-hps"/>
<constraint firstItem="3DJ-aP-2s4" firstAttribute="trailing" secondItem="cqe-Lt-yoW" secondAttribute="trailing" id="KKF-hX-zna"/>
<constraint firstItem="mc9-ef-Jff" firstAttribute="bottom" secondItem="3DJ-aP-2s4" secondAttribute="bottom" id="P8W-jv-GI0"/>
<constraint firstItem="mc9-ef-Jff" firstAttribute="leading" secondItem="FM0-Ax-NhR" secondAttribute="leading" constant="20" symbolic="YES" id="PKl-q6-a6O"/>
<constraint firstAttribute="trailing" secondItem="mc9-ef-Jff" secondAttribute="trailing" constant="20" symbolic="YES" id="cKS-7o-XWf"/>
<constraint firstItem="3DJ-aP-2s4" firstAttribute="leading" secondItem="FM0-Ax-NhR" secondAttribute="leading" constant="15" id="eHq-ye-ech"/>
<constraint firstItem="cqe-Lt-yoW" firstAttribute="top" secondItem="FM0-Ax-NhR" secondAttribute="top" constant="2" id="frh-5w-ewk"/>
<constraint firstItem="mc9-ef-Jff" firstAttribute="centerX" secondItem="3DJ-aP-2s4" secondAttribute="centerX" id="pc0-bS-vyX"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="SettingsTableViewCell" id="Ssg-87-RAe">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
@ -484,55 +388,6 @@
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="none" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="SettingsTableViewCell" id="cdn-V5-RZJ">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="cdn-V5-RZJ" id="ive-4o-xNn">
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Date Format" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yPf-W5-xpJ" customClass="HelveticaNeueLTStdMedLabel">
<rect key="frame" x="20" y="0.0" width="174" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="C8c-kv-nwJ"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="localizationKey" value="SETTINGS_DATE_FORMAT"/>
</userDefinedRuntimeAttributes>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Db2-IE-idC" userLabel="Seperator View">
<rect key="frame" x="15" y="42" width="290" height="1"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" red="0.7843137255" green="0.7843137255" blue="0.7843137255" alpha="1" colorSpace="calibratedRGB"/>
</view>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="yyyy/mm/dd" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cGf-l6-5Ou" customClass="HelveticaNeueLTStdMedLabel">
<rect key="frame" x="174" y="0.0" width="113" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="113" id="R2u-ge-9yf"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="Db2-IE-idC" firstAttribute="leading" secondItem="ive-4o-xNn" secondAttribute="leading" constant="15" id="5W9-Wj-gae"/>
<constraint firstItem="yPf-W5-xpJ" firstAttribute="leading" secondItem="ive-4o-xNn" secondAttribute="leading" constant="20" symbolic="YES" id="Hmn-CD-aSb"/>
<constraint firstItem="yPf-W5-xpJ" firstAttribute="top" secondItem="cGf-l6-5Ou" secondAttribute="top" id="JmN-ki-WH6"/>
<constraint firstItem="yPf-W5-xpJ" firstAttribute="baseline" secondItem="cGf-l6-5Ou" secondAttribute="baseline" id="NRC-z5-vPU"/>
<constraint firstItem="Db2-IE-idC" firstAttribute="top" secondItem="ive-4o-xNn" secondAttribute="top" constant="42" id="RLW-dl-KDT"/>
<constraint firstAttribute="trailing" secondItem="Db2-IE-idC" secondAttribute="trailing" constant="-18" id="a56-sm-kfU"/>
<constraint firstAttribute="bottom" secondItem="Db2-IE-idC" secondAttribute="bottom" id="boI-ec-kmX"/>
<constraint firstAttribute="trailing" secondItem="yPf-W5-xpJ" secondAttribute="trailing" constant="93" id="iq0-5z-b3G"/>
<constraint firstItem="yPf-W5-xpJ" firstAttribute="top" secondItem="ive-4o-xNn" secondAttribute="top" id="jdn-o6-kHd"/>
<constraint firstAttribute="trailing" secondItem="cGf-l6-5Ou" secondAttribute="trailing" id="x6K-Gp-L77"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="spk-JC-Hnw">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>

@ -125,7 +125,7 @@
"SETTINGS_PRIVACY_AND_SECURITY" = "Privacy and Security";
"SETTINGS_RINGTONE" = "Ringtone";
"SETTINGS_SENDLOG" = "Submit Debug Log";
"SETTINGS_SENDLOGS_WAITING" = "Sending anonymized log file\n Please wait...";
"SETTINGS_SENDLOGS_WAITING" = "Sending log file\n Please wait...";
"SETTINGS_SENDLOG_ALERT_BODY" = "Bugs can be reported by email or by copying the log in a GitHub Issue (advanced).";
"SETTINGS_SENDLOG_ALERT_PASTE" = "Email";
"SETTINGS_SENDLOG_ALERT_EMAIL" = "GitHub Issue";

Loading…
Cancel
Save