NewsBlur/clients/ios/Other Sources/InAppSettingsKit/Models/IASKSpecifier.m
David Sinclair c5e4e2a740 #1597 (account deletion)
- Added a Delete Account button to the bottom of Preferences.
- Enhanced Preferences to make the button red.
- Tapping it dismisses Prrefs and shows the delete account web page.
- I created a “dejaldeletetest” account, then deleted it, to confirm it works.
2022-03-09 21:06:09 -07:00

436 lines
15 KiB
Objective-C
Executable file

//
// IASKSpecifier.m
// http://www.inappsettingskit.com
//
// Copyright (c) 2009:
// Luc Vandal, Edovia Inc., http://www.edovia.com
// Ortwin Gentz, FutureTap GmbH, http://www.futuretap.com
// All rights reserved.
//
// It is appreciated but not required that you give credit to Luc Vandal and Ortwin Gentz,
// as the original authors of this code. You can give credit in a blog post, a tweet or on
// a info page of your app. Also, the original authors appreciate letting them know if you use this code.
//
// This code is licensed under the BSD license that is available at: http://www.opensource.org/licenses/bsd-license.php
//
#import "IASKSpecifier.h"
#import "IASKSettingsReader.h"
// DJS: Commented out this to avoid UIWebView. Not used by NewsBlur.
//#import "IASKAppSettingsWebViewController.h"
@interface IASKSpecifier ()
@property (nonatomic, retain) NSDictionary *multipleValuesDict;
@property (nonatomic, copy) NSString *radioGroupValue;
@end
@implementation IASKSpecifier
- (id)initWithSpecifier:(NSDictionary*)specifier {
if ((self = [super init])) {
[self setSpecifierDict:specifier];
if ([self isMultiValueSpecifierType]) {
[self updateMultiValuesDict];
}
}
return self;
}
- (BOOL)isMultiValueSpecifierType {
static NSArray *types = nil;
if (!types) {
types = @[kIASKPSMultiValueSpecifier, kIASKPSTitleValueSpecifier, kIASKPSRadioGroupSpecifier];
}
return [types containsObject:[self type]];
}
- (id)initWithSpecifier:(NSDictionary *)specifier
radioGroupValue:(NSString *)radioGroupValue {
self = [self initWithSpecifier:specifier];
if (self) {
self.radioGroupValue = radioGroupValue;
}
return self;
}
- (void)updateMultiValuesDict {
NSArray *values = [_specifierDict objectForKey:kIASKValues];
NSArray *titles = [_specifierDict objectForKey:kIASKTitles];
NSArray *shortTitles = [_specifierDict objectForKey:kIASKShortTitles];
NSMutableDictionary *multipleValuesDict = [NSMutableDictionary new];
if (values) {
[multipleValuesDict setObject:values forKey:kIASKValues];
}
if (titles) {
[multipleValuesDict setObject:titles forKey:kIASKTitles];
}
if (shortTitles.count) {
[multipleValuesDict setObject:shortTitles forKey:kIASKShortTitles];
}
[self setMultipleValuesDict:multipleValuesDict];
}
- (void)sortIfNeeded {
if (self.displaySortedByTitle) {
NSArray *values = [_specifierDict objectForKey:kIASKValues];
NSArray *titles = [_specifierDict objectForKey:kIASKTitles];
NSArray *shortTitles = [_specifierDict objectForKey:kIASKShortTitles];
NSAssert(values.count == titles.count, @"Malformed multi-value specifier found in settings bundle. Number of values and titles differ.");
NSAssert(shortTitles == nil || shortTitles.count == values.count, @"Malformed multi-value specifier found in settings bundle. Number of short titles and values differ.");
NSMutableDictionary *multipleValuesDict = [NSMutableDictionary new];
NSMutableArray *temporaryMappingsForSort = [NSMutableArray arrayWithCapacity:titles.count];
static NSString *const titleKey = @"title";
static NSString *const shortTitleKey = @"shortTitle";
static NSString *const localizedTitleKey = @"localizedTitle";
static NSString *const valueKey = @"value";
IASKSettingsReader *strongSettingsReader = self.settingsReader;
[titles enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *localizedTitle = [strongSettingsReader titleForId:obj];
[temporaryMappingsForSort addObject:@{titleKey : obj,
valueKey : values[idx],
localizedTitleKey : localizedTitle,
shortTitleKey : (shortTitles[idx] ?: [NSNull null]),
}];
}];
NSArray *sortedTemporaryMappings = [temporaryMappingsForSort sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString *localizedTitle1 = obj1[localizedTitleKey];
NSString *localizedTitle2 = obj2[localizedTitleKey];
if ([localizedTitle1 isKindOfClass:[NSString class]] && [localizedTitle2 isKindOfClass:[NSString class]]) {
return [localizedTitle1 localizedCompare:localizedTitle2];
} else {
return NSOrderedSame;
}
}];
NSMutableArray *sortedTitles = [NSMutableArray arrayWithCapacity:sortedTemporaryMappings.count];
NSMutableArray *sortedShortTitles = [NSMutableArray arrayWithCapacity:sortedTemporaryMappings.count];
NSMutableArray *sortedValues = [NSMutableArray arrayWithCapacity:sortedTemporaryMappings.count];
[sortedTemporaryMappings enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDictionary *mapping = obj;
sortedTitles[idx] = mapping[titleKey];
sortedValues[idx] = mapping[valueKey];
if (mapping[shortTitleKey] != [NSNull null]) {
sortedShortTitles[idx] = mapping[shortTitleKey];
}
}];
titles = [sortedTitles copy];
values = [sortedValues copy];
shortTitles = [sortedShortTitles copy];
if (values) {
[multipleValuesDict setObject:values forKey:kIASKValues];
}
if (titles) {
[multipleValuesDict setObject:titles forKey:kIASKTitles];
}
if (shortTitles.count) {
[multipleValuesDict setObject:shortTitles forKey:kIASKShortTitles];
}
[self setMultipleValuesDict:multipleValuesDict];
}
}
- (BOOL)displaySortedByTitle {
return [[_specifierDict objectForKey:kIASKDisplaySortedByTitle] boolValue];
}
- (NSString*)localizedObjectForKey:(NSString*)key {
IASKSettingsReader *settingsReader = self.settingsReader;
return [settingsReader titleForId:[_specifierDict objectForKey:key]];
}
- (NSString*)title {
return [self localizedObjectForKey:kIASKTitle];
}
- (NSString*)subtitle {
return [self localizedObjectForKey:kIASKSubtitle];
}
- (NSString *)placeholder {
return [self localizedObjectForKey:kIASKPlaceholder];
}
- (NSString*)footerText {
return [self localizedObjectForKey:kIASKFooterText];
}
- (BOOL)isCritical {
return [[_specifierDict objectForKey:kIASKIsCritical] boolValue];
}
- (Class)viewControllerClass {
// DJS: Commented out this to avoid UIWebView. Not used by NewsBlur.
// [IASKAppSettingsWebViewController class]; // make sure this is linked into the binary/library
NSString *classString = [_specifierDict objectForKey:kIASKViewControllerClass];
return classString ? ([self classFromString:classString] ?: [NSNull class]) : nil;
}
- (Class)classFromString:(NSString *)className {
Class class = NSClassFromString(className);
if (!class) {
// if the class doesn't exist as a pure Obj-C class then try to retrieve it as a Swift class.
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
NSString *classStringName = [NSString stringWithFormat:@"_TtC%lu%@%lu%@", (unsigned long)appName.length, appName, (unsigned long)className.length, className];
class = NSClassFromString(classStringName);
}
return class;
}
- (SEL)viewControllerSelector {
return NSSelectorFromString([_specifierDict objectForKey:kIASKViewControllerSelector]);
}
- (NSString*)viewControllerStoryBoardFile {
return [_specifierDict objectForKey:kIASKViewControllerStoryBoardFile];
}
- (NSString*)viewControllerStoryBoardID {
return [_specifierDict objectForKey:kIASKViewControllerStoryBoardId];
}
- (NSString*)segueIdentifier {
return [_specifierDict objectForKey:kIASKSegueIdentifier];
}
- (Class)buttonClass {
return NSClassFromString([_specifierDict objectForKey:kIASKButtonClass]);
}
- (SEL)buttonAction {
return NSSelectorFromString([_specifierDict objectForKey:kIASKButtonAction]);
}
- (NSString*)key {
return [_specifierDict objectForKey:kIASKKey];
}
- (NSString*)type {
return [_specifierDict objectForKey:kIASKType];
}
- (NSString*)titleForCurrentValue:(id)currentValue {
NSArray *values = [self multipleValues];
NSArray *titles = [self multipleShortTitles];
if (!titles) {
titles = [self multipleTitles];
}
if (values.count != titles.count) {
return nil;
}
NSInteger keyIndex = [values indexOfObject:currentValue];
if (keyIndex == NSNotFound) {
return nil;
}
@try {
IASKSettingsReader *strongSettingsReader = self.settingsReader;
return [strongSettingsReader titleForId:[titles objectAtIndex:keyIndex]];
}
@catch (NSException * e) {}
return nil;
}
- (NSInteger)multipleValuesCount {
return [[_multipleValuesDict objectForKey:kIASKValues] count];
}
- (NSArray*)multipleValues {
return [_multipleValuesDict objectForKey:kIASKValues];
}
- (NSArray*)multipleTitles {
return [_multipleValuesDict objectForKey:kIASKTitles];
}
- (NSArray*)multipleShortTitles {
return [_multipleValuesDict objectForKey:kIASKShortTitles];
}
- (NSString*)file {
return [_specifierDict objectForKey:kIASKFile];
}
- (id)defaultValue {
return [_specifierDict objectForKey:kIASKDefaultValue];
}
- (id)defaultStringValue {
return [[_specifierDict objectForKey:kIASKDefaultValue] description];
}
- (BOOL)defaultBoolValue {
id defaultValue = [self defaultValue];
if ([defaultValue isEqual:[self trueValue]]) {
return YES;
}
if ([defaultValue isEqual:[self falseValue]]) {
return NO;
}
return [defaultValue boolValue];
}
- (id)trueValue {
return [_specifierDict objectForKey:kIASKTrueValue];
}
- (id)falseValue {
return [_specifierDict objectForKey:kIASKFalseValue];
}
- (float)minimumValue {
return [[_specifierDict objectForKey:kIASKMinimumValue] floatValue];
}
- (float)maximumValue {
return [[_specifierDict objectForKey:kIASKMaximumValue] floatValue];
}
- (NSString*)minimumValueImage {
return [_specifierDict objectForKey:kIASKMinimumValueImage];
}
- (NSString*)maximumValueImage {
return [_specifierDict objectForKey:kIASKMaximumValueImage];
}
- (BOOL)isSecure {
return [[_specifierDict objectForKey:kIASKIsSecure] boolValue];
}
- (UIKeyboardType)keyboardType {
if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardAlphabet]) {
return UIKeyboardTypeDefault;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumbersAndPunctuation]) {
return UIKeyboardTypeNumbersAndPunctuation;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNumberPad]) {
return UIKeyboardTypeNumberPad;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardPhonePad]) {
return UIKeyboardTypePhonePad;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardNamePhonePad]) {
return UIKeyboardTypeNamePhonePad;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardASCIICapable]) {
return UIKeyboardTypeASCIICapable;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardDecimalPad]) {
return UIKeyboardTypeDecimalPad;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:KIASKKeyboardURL]) {
return UIKeyboardTypeURL;
}
else if ([[_specifierDict objectForKey:KIASKKeyboardType] isEqualToString:kIASKKeyboardEmailAddress]) {
return UIKeyboardTypeEmailAddress;
}
return UIKeyboardTypeDefault;
}
- (UITextAutocapitalizationType)autocapitalizationType {
if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapNone]) {
return UITextAutocapitalizationTypeNone;
}
else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapSentences]) {
return UITextAutocapitalizationTypeSentences;
}
else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapWords]) {
return UITextAutocapitalizationTypeWords;
}
else if ([[_specifierDict objectForKey:kIASKAutocapitalizationType] isEqualToString:kIASKAutoCapAllCharacters]) {
return UITextAutocapitalizationTypeAllCharacters;
}
return UITextAutocapitalizationTypeNone;
}
- (UITextAutocorrectionType)autoCorrectionType {
if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrDefault]) {
return UITextAutocorrectionTypeDefault;
}
else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrNo]) {
return UITextAutocorrectionTypeNo;
}
else if ([[_specifierDict objectForKey:kIASKAutoCorrectionType] isEqualToString:kIASKAutoCorrYes]) {
return UITextAutocorrectionTypeYes;
}
return UITextAutocorrectionTypeDefault;
}
- (UIImage *)cellImage
{
NSString *imageName = [_specifierDict objectForKey:kIASKCellImage];
if( imageName.length == 0 )
return nil;
return [UIImage imageNamed:imageName];
}
- (UIImage *)highlightedCellImage
{
NSString *imageName = [[_specifierDict objectForKey:kIASKCellImage ] stringByAppendingString:@"Highlighted"];
if( imageName.length == 0 )
return nil;
return [UIImage imageNamed:imageName];
}
- (BOOL)adjustsFontSizeToFitWidth {
NSNumber *boxedResult = [_specifierDict objectForKey:kIASKAdjustsFontSizeToFitWidth];
return !boxedResult || [boxedResult boolValue];
}
- (NSTextAlignment)textAlignment
{
if (self.subtitle.length || [[_specifierDict objectForKey:kIASKTextLabelAlignment] isEqualToString:kIASKTextLabelAlignmentLeft]) {
return NSTextAlignmentLeft;
} else if ([[_specifierDict objectForKey:kIASKTextLabelAlignment] isEqualToString:kIASKTextLabelAlignmentCenter]) {
return NSTextAlignmentCenter;
} else if ([[_specifierDict objectForKey:kIASKTextLabelAlignment] isEqualToString:kIASKTextLabelAlignmentRight]) {
return NSTextAlignmentRight;
}
if ([self.type isEqualToString:kIASKButtonSpecifier] && !self.cellImage) {
return NSTextAlignmentCenter;
} else if ([self.type isEqualToString:kIASKPSMultiValueSpecifier] || [self.type isEqualToString:kIASKPSTitleValueSpecifier] || [self.type isEqualToString:kIASKTextViewSpecifier]) {
return NSTextAlignmentRight;
}
return NSTextAlignmentLeft;
}
- (NSArray *)userInterfaceIdioms {
NSArray *idiomStrings = _specifierDict[kIASKSupportedUserInterfaceIdioms];
if (idiomStrings.count == 0) {
return @[@(UIUserInterfaceIdiomPhone), @(UIUserInterfaceIdiomPad)];
}
NSMutableArray *idioms = [NSMutableArray new];
for (NSString *idiomString in idiomStrings) {
if ([idiomString isEqualToString:@"Phone"]) {
[idioms addObject:@(UIUserInterfaceIdiomPhone)];
} else if ([idiomString isEqualToString:@"Pad"]) {
[idioms addObject:@(UIUserInterfaceIdiomPad)];
}
}
return idioms;
}
- (id)valueForKey:(NSString *)key {
return [_specifierDict objectForKey:key];
}
@end