mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00

- 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.
436 lines
15 KiB
Objective-C
Executable file
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
|