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 */; }; 765052B3182BF839008313E1 /* HelveticaNeueLTStd-Th.otf in Resources */ = {isa = PBXBuildFile; fileRef = 765052B1182BF839008313E1 /* HelveticaNeueLTStd-Th.otf */; };
768A1A2B17FC9CD300E00ED8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 768A1A2A17FC9CD300E00ED8 /* libz.dylib */; }; 768A1A2B17FC9CD300E00ED8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 768A1A2A17FC9CD300E00ED8 /* libz.dylib */; };
76919BF71805D190008C664A /* ContactManagerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 76919BF61805D190008C664A /* ContactManagerTest.m */; }; 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 */; }; 76B818A1182C39460088060E /* PreferenceListViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 76B8189D182C39460088060E /* PreferenceListViewController.xib */; };
76C87F13181EE11C00C4ACAB /* InboxFeedFooterCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76C87F12181EE11C00C4ACAB /* InboxFeedFooterCell.m */; }; 76C87F13181EE11C00C4ACAB /* InboxFeedFooterCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 76C87F12181EE11C00C4ACAB /* InboxFeedFooterCell.m */; };
76C87F14181EE11C00C4ACAB /* 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 */; }; A1C32D5017A06538000A904E /* AddressBookUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4F17A06537000A904E /* AddressBookUI.framework */; };
A1C32D5117A06544000A904E /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4D17A0652C000A904E /* AddressBook.framework */; }; A1C32D5117A06544000A904E /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C32D4D17A0652C000A904E /* AddressBook.framework */; };
AA0C8E498E2046B0B81EEE6E /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8313AE91B4954215858A5662 /* libPods.a */; }; 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 */; }; B67EBF5D19194AC60084CCFD /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B67EBF5C19194AC60084CCFD /* Settings.bundle */; };
B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; }; B69CD25119773E79005CE69A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B69CD25019773E79005CE69A /* XCTest.framework */; };
B6B1013C196D213F007E3930 /* SGNKeychainUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B6B1013B196D213F007E3930 /* SGNKeychainUtil.m */; }; 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>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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; }; 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; }; 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; }; 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>"; }; 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; }; 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; }; 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 */, 76EB041B18170B33006006FC /* Release.m */,
B6B1013A196D213F007E3930 /* SGNKeychainUtil.h */, B6B1013A196D213F007E3930 /* SGNKeychainUtil.h */,
B6B1013B196D213F007E3930 /* SGNKeychainUtil.m */, B6B1013B196D213F007E3930 /* SGNKeychainUtil.m */,
B60C16631988999D00E97A6C /* VersionMigrations.h */,
B60C16641988999D00E97A6C /* VersionMigrations.m */,
); );
path = environment; path = environment;
sourceTree = "<group>"; sourceTree = "<group>";
@ -2123,8 +2124,6 @@
76EB050E18170B33006006FC /* LeftSideMenuViewController.m */, 76EB050E18170B33006006FC /* LeftSideMenuViewController.m */,
76EB050F18170B33006006FC /* NextResponderScrollView.h */, 76EB050F18170B33006006FC /* NextResponderScrollView.h */,
76EB051018170B33006006FC /* NextResponderScrollView.m */, 76EB051018170B33006006FC /* NextResponderScrollView.m */,
76B8189B182C39460088060E /* PreferenceListViewController.h */,
76B8189C182C39460088060E /* PreferenceListViewController.m */,
76EB051518170B33006006FC /* RegisterViewController.h */, 76EB051518170B33006006FC /* RegisterViewController.h */,
76EB051618170B33006006FC /* RegisterViewController.m */, 76EB051618170B33006006FC /* RegisterViewController.m */,
76EB051718170B33006006FC /* SettingsViewController.h */, 76EB051718170B33006006FC /* SettingsViewController.h */,
@ -3038,6 +3037,7 @@
76EB066218170B34006006FC /* SettingsViewController.m in Sources */, 76EB066218170B34006006FC /* SettingsViewController.m in Sources */,
76EB054818170B33006006FC /* CancelTokenSource.m in Sources */, 76EB054818170B33006006FC /* CancelTokenSource.m in Sources */,
76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */, 76EB05AC18170B33006006FC /* SrtpSocket.m in Sources */,
B60C16651988999D00E97A6C /* VersionMigrations.m in Sources */,
76EB062A18170B33006006FC /* BadState.m in Sources */, 76EB062A18170B33006006FC /* BadState.m in Sources */,
B97940271832BD2400BD66CB /* UIUtil.m in Sources */, B97940271832BD2400BD66CB /* UIUtil.m in Sources */,
76EB05BE18170B33006006FC /* ConfirmPacket.m in Sources */, 76EB05BE18170B33006006FC /* ConfirmPacket.m in Sources */,
@ -3098,7 +3098,6 @@
76EB058218170B33006006FC /* Environment.m in Sources */, 76EB058218170B33006006FC /* Environment.m in Sources */,
76EB064418170B33006006FC /* ThreadManager.m in Sources */, 76EB064418170B33006006FC /* ThreadManager.m in Sources */,
70B8011A190C55660042E3F0 /* UnknownFieldSet.m in Sources */, 70B8011A190C55660042E3F0 /* UnknownFieldSet.m in Sources */,
76B8189E182C39460088060E /* PreferenceListViewController.m in Sources */,
70B80114190C55660042E3F0 /* Field.m in Sources */, 70B80114190C55660042E3F0 /* Field.m in Sources */,
E197B61E18BBEC6D00F073E5 /* AudioRouter.m in Sources */, E197B61E18BBEC6D00F073E5 /* AudioRouter.m in Sources */,
E197B60D18BBEC1A00F073E5 /* AudioSocket.m in Sources */, E197B60D18BBEC1A00F073E5 /* AudioSocket.m in Sources */,
@ -3232,7 +3231,6 @@
76EB05BF18170B33006006FC /* ConfirmPacket.m in Sources */, 76EB05BF18170B33006006FC /* ConfirmPacket.m in Sources */,
76EB05E518170B33006006FC /* UdpSocket.m in Sources */, 76EB05E518170B33006006FC /* UdpSocket.m in Sources */,
76EB05BD18170B33006006FC /* ConfirmAckPacket.m in Sources */, 76EB05BD18170B33006006FC /* ConfirmAckPacket.m in Sources */,
76B8189F182C39460088060E /* PreferenceListViewController.m in Sources */,
76EB05DB18170B33006006FC /* LowLatencyConnector.m in Sources */, 76EB05DB18170B33006006FC /* LowLatencyConnector.m in Sources */,
76EB060F18170B33006006FC /* DecayingSampleEstimator.m in Sources */, 76EB060F18170B33006006FC /* DecayingSampleEstimator.m in Sources */,
76EB055318170B33006006FC /* TimeoutFailure.m in Sources */, 76EB055318170B33006006FC /* TimeoutFailure.m in Sources */,

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

@ -16,6 +16,7 @@
#import "Util.h" #import "Util.h"
#import <UICKeyChainStore/UICKeyChainStore.h> #import <UICKeyChainStore/UICKeyChainStore.h>
#import "Environment.h" #import "Environment.h"
#import "VersionMigrations.h"
#define kSignalVersionKey @"SignalUpdateVersionKey" #define kSignalVersionKey @"SignalUpdateVersionKey"
@ -47,18 +48,39 @@
[Environment setCurrent:[Release releaseEnvironmentWithLogging:nil]]; [Environment setCurrent:[Release releaseEnvironmentWithLogging:nil]];
[Environment resetAppData]; // We clean previous keychain entries in case their are some entries remaining. [Environment resetAppData]; // We clean previous keychain entries in case their are some entries remaining.
} else if ([currentVersion compare:previousVersion options:NSNumericSearch] == NSOrderedDescending){ } else if ([currentVersion compare:previousVersion options:NSNumericSearch] == NSOrderedDescending){
// The application was updated // Application was updated, let's see if we have a migration scheme for it.
DDLogWarn(@"Application was updated from %@ to %@", previousVersion, currentVersion);
if ([previousVersion isEqualToString:@"1.0.2"]) {
}
} }
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:kSignalVersionKey]; [[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:kSignalVersionKey];
[[NSUserDefaults standardUserDefaults] synchronize]; [[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"]]; NSString *userDefaultsString = [NSString stringWithFormat:@"%@/%@.plist", preferencesPath,[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"]];
NSURL *userDefaultsURL = [NSURL fileURLWithPath:userDefaultsString]; NSURL *userDefaultsURL = [NSURL fileURLWithPath:userDefaultsString];
@ -81,7 +103,7 @@
[DDLog addLogger:self.fileLogger]; [DDLog addLogger:self.fileLogger];
[self performUpdateCheck]; [self performUpdateCheck];
[self disableCallLogBackup]; [self protectPreferenceFiles];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.notificationTracker = [NotificationTracker notificationTracker]; self.notificationTracker = [NotificationTracker notificationTracker];

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

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

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

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

@ -20,15 +20,6 @@
#define CONTACT_IMAGES_ENABLED_KEY @"Contact Images Enabled Key" #define CONTACT_IMAGES_ENABLED_KEY @"Contact Images Enabled Key"
#define AUTOCORRECT_ENABLED_KEY @"Autocorrect Enabled Key" #define AUTOCORRECT_ENABLED_KEY @"Autocorrect Enabled Key"
#define HISTORY_LOG_ENABLED_KEY @"History Log 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) @implementation PropertyListPreferences (PropertyUtil)
@ -42,7 +33,6 @@
andExpirationDate:expiration]; andExpirationDate:expiration];
} }
-(void) setSavedPhoneNumberDirectory:(PhoneNumberDirectoryFilter*)phoneNumberDirectoryFilter { -(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_DATA_KEY toValue:nil];
[self setValueForKey:PHONE_DIRECTORY_BLOOM_FILTER_HASH_COUNT_KEY toValue:nil]; [self setValueForKey:PHONE_DIRECTORY_BLOOM_FILTER_HASH_COUNT_KEY toValue:nil];
[self setValueForKey:PHONE_DIRECTORY_EXPIRATION 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]]; [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 { -(BOOL) getFreshInstallTutorialsEnabled {
NSNumber *preference = [self tryGetValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY]; NSNumber *preference = [self tryGetValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY];
if (preference) { if (preference) {
@ -131,18 +93,6 @@
return YES; 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 { -(void) setFreshInstallTutorialsEnabled:(BOOL)enabled {
[self setValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY toValue:[NSNumber numberWithBool:enabled]]; [self setValueForKey:FRESH_INSTALL_TUTORIALS_ENABLED_KEY toValue:[NSNumber numberWithBool:enabled]];
@ -156,7 +106,5 @@
-(void) setHistoryLogEnabled:(BOOL)enabled { -(void) setHistoryLogEnabled:(BOOL)enabled {
[self setValueForKey:HISTORY_LOG_ENABLED_KEY toValue:[NSNumber numberWithBool: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 @end

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

@ -4,63 +4,25 @@
@implementation PropertyListPreferences @implementation PropertyListPreferences
+(PropertyListPreferences*) propertyListPreferencesWithName:(NSString*)name {
PropertyListPreferences* p = [PropertyListPreferences new];
p->plistName = name;
p->dictionary = [[PropertyListPreferences readPlist:name] mutableCopy];
return p;
}
-(void) clear { -(void) clear {
@synchronized(self) { @synchronized(self) {
dictionary = [NSMutableDictionary dictionary]; NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[PropertyListPreferences writePlist:dictionary withName:plistName]; [[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 { -(id) tryGetValueForKey:(NSString *)key {
require(key != nil); require(key != nil);
@synchronized(self) { @synchronized(self) {
return [dictionary objectForKey:key]; return [[NSUserDefaults standardUserDefaults] objectForKey:key];
} }
} }
-(void) setValueForKey:(NSString *)key toValue:(id)value { -(void) setValueForKey:(NSString *)key toValue:(id)value {
require(key != nil); require(key != nil);
@synchronized(self) { @synchronized(self) {
if (value == nil) { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[dictionary removeObjectForKey:key]; [userDefaults setObject:value forKey:key];
DDLogWarn(@"Removing object for key: %@ ", key); [userDefaults synchronize];
} else {
[dictionary setObject:value forKey:key];
}
[PropertyListPreferences writePlist:dictionary withName:plistName];
} }
} }
-(id) adjustAndTryGetNewValueForKey:(NSString *)key afterAdjuster:(id (^)(id))adjuster { -(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 { -(void) secureTrySetValueForKey:(NSString *)key toValue:(id)value {
require(key != nil); require(key != nil);
@ -125,7 +87,7 @@
@synchronized(self) { @synchronized(self) {
NSString *oldValue = [self secureTryGetStringForKey:key]; NSString *oldValue = [self secureTryGetStringForKey:key];
NSString *newValue = adjuster(oldValue); NSString *newValue = adjuster(oldValue);
[UICKeyChainStore setString:newValue forKey:key]; [UICKeyChainStore setString:newValue forKey:key];
return newValue; return newValue;
} }
} }

@ -49,8 +49,7 @@ static unsigned char DH3K_PRIME[]={
//ErrorHandlerBlock errorDiscarder = ^(id error, id relatedInfo, bool causedTermination) {}; //ErrorHandlerBlock errorDiscarder = ^(id error, id relatedInfo, bool causedTermination) {};
ErrorHandlerBlock errorNoter = ^(id error, id relatedInfo, bool causedTermination) { DDLogError(@"%@: %@, %d", error, relatedInfo, causedTermination); }; ErrorHandlerBlock errorNoter = ^(id error, id relatedInfo, bool causedTermination) { DDLogError(@"%@: %@, %d", error, relatedInfo, causedTermination); };
return [Environment environmentWithPreferences:[PropertyListPreferences propertyListPreferencesWithName:@"RedPhone-Data"] return [Environment environmentWithLogging:logging
andLogging:logging
andErrorNoter:errorNoter andErrorNoter:errorNoter
andServerPort:31337 andServerPort:31337
andMasterServerHostName:@"master.whispersystems.org" andMasterServerHostName:@"master.whispersystems.org"
@ -69,8 +68,7 @@ static unsigned char DH3K_PRIME[]={
} }
+(Environment*) unitTestEnvironment:(NSArray*)testingAndLegacyOptions { +(Environment*) unitTestEnvironment:(NSArray*)testingAndLegacyOptions {
return [Environment environmentWithPreferences:[PropertyListPreferences propertyListPreferencesWithName:@"RedPhone-Test-Data"] return [Environment environmentWithLogging:[DiscardingLog discardingLog]
andLogging:[DiscardingLog discardingLog]
andErrorNoter:^(id error, id relatedInfo, bool causedTermination) {} andErrorNoter:^(id error, id relatedInfo, bool causedTermination) {}
andServerPort:31337 andServerPort:31337
andMasterServerHostName:@"testing.whispersystems.org" 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) { @synchronized(self) {
phoneNumberDirectoryFilter = directory; phoneNumberDirectoryFilter = directory;
} }
[[Environment preferences] setSavedPhoneNumberDirectory:directory]; [[[Environment getCurrent]preferences] setSavedPhoneNumberDirectory:directory];
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_WAS_UPDATED object:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_WAS_UPDATED object:nil];
[self scheduleUpdate]; [self scheduleUpdate];
}]; }];

@ -12,20 +12,20 @@ static NSString *const DATE_FORMAT_HOUR_MINUTE = @"h:mm a ";
+ (NSDateFormatter *)dateFormatter { + (NSDateFormatter *)dateFormatter {
NSDateFormatter *formatter = [NSDateFormatter new]; NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:[[[Environment getCurrent] preferences] getDateFormat]]; [formatter setTimeStyle:NSDateFormatterShortStyle];
return formatter; return formatter;
} }
+ (NSDateFormatter *)weekdayFormatter { + (NSDateFormatter *)weekdayFormatter {
NSDateFormatter *formatter = [NSDateFormatter new]; NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:DATE_FORMAT_WEEKDAY]; [formatter setDateFormat:DATE_FORMAT_WEEKDAY];
return formatter; return formatter;
} }
+ (NSDateFormatter *)timeFormatter { + (NSDateFormatter *)timeFormatter {
NSDateFormatter *formatter = [NSDateFormatter new]; NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:DATE_FORMAT_HOUR_MINUTE]; [formatter setDateFormat:DATE_FORMAT_HOUR_MINUTE];
return formatter; return formatter;
} }
+ (BOOL)dateIsOlderThanOneDay:(NSDate *)date { + (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 UITableView *settingsTableView;
@property (nonatomic, strong) IBOutlet UILabel *phoneNumberLabel; @property (nonatomic, strong) IBOutlet UILabel *phoneNumberLabel;
@property (nonatomic, strong) IBOutlet UILabel *currentDateFormatLabel;
@property (nonatomic, strong) IBOutlet UILabel *titleLabel; @property (nonatomic, strong) IBOutlet UILabel *titleLabel;
@property (nonatomic, strong) IBOutlet SettingsTableHeaderView *privacyAndSecurityHeaderView; @property (nonatomic, strong) IBOutlet SettingsTableHeaderView *privacyAndSecurityHeaderView;
@ -31,14 +30,9 @@
@property (nonatomic, strong) IBOutlet UIButton *disableAutocorrectButton; @property (nonatomic, strong) IBOutlet UIButton *disableAutocorrectButton;
@property (nonatomic, strong) IBOutlet UIButton *disableHistoryButton; @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 SettingsTableHeaderView *callQualityHeaderView;
@property (nonatomic, strong) IBOutlet UITableViewCell *feedbackCell;
@property (nonatomic, strong) IBOutlet UITableViewCell *directoryUpdateCell; @property (nonatomic, strong) IBOutlet UITableViewCell *directoryUpdateCell;
@property (nonatomic, strong) IBOutlet UIButton *sendFeedbackButton;
@property (nonatomic, strong) IBOutlet UITableViewCell *sendDebugLog; @property (nonatomic, strong) IBOutlet UITableViewCell *sendDebugLog;
@property (nonatomic, assign) FutureSource *apnId; @property (nonatomic, assign) FutureSource *apnId;
@ -51,8 +45,6 @@
- (IBAction)disableAutocorrectButtonTapped; - (IBAction)disableAutocorrectButtonTapped;
- (IBAction)disableHistoryButtonTapped; - (IBAction)disableHistoryButtonTapped;
- (IBAction)sendFeedbackButtonTapped;
- (IBAction)menuButtonTapped; - (IBAction)menuButtonTapped;
@end @end

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

@ -8,21 +8,16 @@
<connections> <connections>
<outlet property="callQualityHeaderView" destination="j1j-ta-39S" id="l3w-bt-UWR"/> <outlet property="callQualityHeaderView" destination="j1j-ta-39S" id="l3w-bt-UWR"/>
<outlet property="clearHistoryLogCell" destination="d8g-sW-ZOU" id="gqj-U8-aKQ"/> <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="directoryUpdateCell" destination="spk-JC-Hnw" id="mbt-cO-iOG"/>
<outlet property="disableAutocorrectButton" destination="dLe-ku-opM" id="Edi-TS-ZcR"/> <outlet property="disableAutocorrectButton" destination="dLe-ku-opM" id="Edi-TS-ZcR"/>
<outlet property="disableAutocorrectCell" destination="nQL-pT-i5g" id="YZo-pL-RM7"/> <outlet property="disableAutocorrectCell" destination="nQL-pT-i5g" id="YZo-pL-RM7"/>
<outlet property="disableHistoryButton" destination="trw-DG-amf" id="97O-Y4-iu3"/> <outlet property="disableHistoryButton" destination="trw-DG-amf" id="97O-Y4-iu3"/>
<outlet property="disableHistoryCell" destination="5Wr-Th-YJI" id="fQY-Qd-xv0"/> <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="hideContactImagesButton" destination="kv5-cc-It9" id="Ftz-lp-Eqd"/>
<outlet property="hideContactImagesCell" destination="1Sy-9w-LqE" id="Rvh-96-REp"/> <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="phoneNumberLabel" destination="G77-lz-XM0" id="adE-bu-2Kn"/>
<outlet property="privacyAndSecurityHeaderView" destination="XIa-5u-rk1" id="kap-XQ-9AL"/> <outlet property="privacyAndSecurityHeaderView" destination="XIa-5u-rk1" id="kap-XQ-9AL"/>
<outlet property="sendDebugLog" destination="Yc0-ZL-RM6" id="wyq-HF-B9c"/> <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="settingsTableView" destination="ajL-B0-V0M" id="0zr-QP-yQl"/>
<outlet property="titleLabel" destination="X1p-jb-cMh" id="Duc-Ac-qHm"/> <outlet property="titleLabel" destination="X1p-jb-cMh" id="Duc-Ac-qHm"/>
<outlet property="view" destination="1" id="3"/> <outlet property="view" destination="1" id="3"/>
@ -298,45 +293,6 @@
<outlet property="columnStateImageView" destination="Xs2-Ls-WP3" id="gqY-mD-1n8"/> <outlet property="columnStateImageView" destination="Xs2-Ls-WP3" id="gqY-mD-1n8"/>
</connections> </connections>
</view> </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"> <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"/> <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
@ -411,58 +367,6 @@
</subviews> </subviews>
</tableViewCellContentView> </tableViewCellContentView>
</tableViewCell> </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"> <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"/> <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
@ -484,55 +388,6 @@
</subviews> </subviews>
</tableViewCellContentView> </tableViewCellContentView>
</tableViewCell> </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"> <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="spk-JC-Hnw">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/> <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>

@ -125,7 +125,7 @@
"SETTINGS_PRIVACY_AND_SECURITY" = "Privacy and Security"; "SETTINGS_PRIVACY_AND_SECURITY" = "Privacy and Security";
"SETTINGS_RINGTONE" = "Ringtone"; "SETTINGS_RINGTONE" = "Ringtone";
"SETTINGS_SENDLOG" = "Submit Debug Log"; "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_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_PASTE" = "Email";
"SETTINGS_SENDLOG_ALERT_EMAIL" = "GitHub Issue"; "SETTINGS_SENDLOG_ALERT_EMAIL" = "GitHub Issue";

Loading…
Cancel
Save