2013-06-21 17:48:06 -07:00
//
// 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"
2020-03-28 20:05:55 -07:00
// DJS : Commented out this to avoid UIWebView . Not used by NewsBlur .
// # import "IASKAppSettingsWebViewController.h"
2013-06-21 17:48:06 -07:00
@ interface IASKSpecifier ( )
2013-10-08 16:00:55 -07:00
2013-06-21 17:48:06 -07:00
@ property ( nonatomic , retain ) NSDictionary * multipleValuesDict ;
2015-03-03 15:56:32 -05:00
@ property ( nonatomic , copy ) NSString * radioGroupValue ;
2013-10-08 16:00:55 -07:00
2013-06-21 17:48:06 -07:00
@ end
@ implementation IASKSpecifier
- ( id ) initWithSpecifier : ( NSDictionary * ) specifier {
if ( ( self = [ super init ] ) ) {
[ self setSpecifierDict : specifier ] ;
2015-03-03 15:56:32 -05:00
if ( [ self isMultiValueSpecifierType ] ) {
[ self updateMultiValuesDict ] ;
2013-06-21 17:48:06 -07:00
}
}
return self ;
}
2015-03-03 15:56:32 -05:00
- ( 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 {
2013-06-21 17:48:06 -07:00
NSArray * values = [ _specifierDict objectForKey : kIASKValues ] ;
NSArray * titles = [ _specifierDict objectForKey : kIASKTitles ] ;
2014-05-19 13:33:42 -07:00
NSArray * shortTitles = [ _specifierDict objectForKey : kIASKShortTitles ] ;
2013-10-08 16:00:55 -07:00
NSMutableDictionary * multipleValuesDict = [ NSMutableDictionary new ] ;
2013-06-21 17:48:06 -07:00
if ( values ) {
[ multipleValuesDict setObject : values forKey : kIASKValues ] ;
}
if ( titles ) {
[ multipleValuesDict setObject : titles forKey : kIASKTitles ] ;
}
2015-09-16 16:53:07 -07:00
if ( shortTitles . count ) {
2014-05-19 13:33:42 -07:00
[ multipleValuesDict setObject : shortTitles forKey : kIASKShortTitles ] ;
}
2013-06-21 17:48:06 -07:00
[ self setMultipleValuesDict : multipleValuesDict ] ;
}
2015-09-16 16:53:07 -07:00
- ( 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 ) {
2017-04-11 16:15:18 -07:00
NSString * localizedTitle = [ strongSettingsReader titleForId : obj ] ;
2015-09-16 16:53:07 -07:00
[ 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 ] ;
}
2013-06-21 17:48:06 -07:00
- ( NSString * ) localizedObjectForKey : ( NSString * ) key {
2014-05-19 13:33:42 -07:00
IASKSettingsReader * settingsReader = self . settingsReader ;
2017-04-11 16:15:18 -07:00
return [ settingsReader titleForId : [ _specifierDict objectForKey : key ] ] ;
2013-06-21 17:48:06 -07:00
}
- ( NSString * ) title {
return [ self localizedObjectForKey : kIASKTitle ] ;
}
2015-03-03 15:56:32 -05:00
- ( NSString * ) subtitle {
return [ self localizedObjectForKey : kIASKSubtitle ] ;
}
2017-04-11 16:15:18 -07:00
- ( NSString * ) placeholder {
return [ self localizedObjectForKey : kIASKPlaceholder ] ;
}
2013-06-21 17:48:06 -07:00
- ( NSString * ) footerText {
return [ self localizedObjectForKey : kIASKFooterText ] ;
}
2014-05-19 13:33:42 -07:00
- ( Class ) viewControllerClass {
2020-03-28 20:05:55 -07:00
// DJS : Commented out this to avoid UIWebView . Not used by NewsBlur .
// [ IASKAppSettingsWebViewController class ] ; // make sure this is linked into the binary / library
2017-04-11 16:15:18 -07:00
NSString * classString = [ _specifierDict objectForKey : kIASKViewControllerClass ] ;
return classString ? ( [ self classFromString : classString ] ? : [ NSNull class ] ) : nil ;
2015-03-03 15:56:32 -05:00
}
- ( 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 ;
2013-06-21 17:48:06 -07:00
}
2014-05-19 13:33:42 -07:00
- ( SEL ) viewControllerSelector {
2013-06-21 17:48:06 -07:00
return NSSelectorFromString ( [ _specifierDict objectForKey : kIASKViewControllerSelector ] ) ;
}
2014-05-19 13:33:42 -07:00
- ( NSString * ) viewControllerStoryBoardFile {
return [ _specifierDict objectForKey : kIASKViewControllerStoryBoardFile ] ;
}
- ( NSString * ) viewControllerStoryBoardID {
return [ _specifierDict objectForKey : kIASKViewControllerStoryBoardId ] ;
}
2017-04-11 16:15:18 -07:00
- ( NSString * ) segueIdentifier {
return [ _specifierDict objectForKey : kIASKSegueIdentifier ] ;
}
2014-05-19 13:33:42 -07:00
- ( Class ) buttonClass {
2013-06-21 17:48:06 -07:00
return NSClassFromString ( [ _specifierDict objectForKey : kIASKButtonClass ] ) ;
}
2014-05-19 13:33:42 -07:00
- ( SEL ) buttonAction {
2013-06-21 17:48:06 -07:00
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 ] ;
2014-05-19 13:33:42 -07:00
NSArray * titles = [ self multipleShortTitles ] ;
2015-09-16 16:53:07 -07:00
if ( ! titles ) {
2014-05-19 13:33:42 -07:00
titles = [ self multipleTitles ] ;
2015-09-16 16:53:07 -07:00
}
2013-06-21 17:48:06 -07:00
if ( values . count ! = titles . count ) {
return nil ;
}
NSInteger keyIndex = [ values indexOfObject : currentValue ] ;
if ( keyIndex = = NSNotFound ) {
return nil ;
}
@ try {
2014-05-19 13:33:42 -07:00
IASKSettingsReader * strongSettingsReader = self . settingsReader ;
2017-04-11 16:15:18 -07:00
return [ strongSettingsReader titleForId : [ titles objectAtIndex : keyIndex ] ] ;
2013-06-21 17:48:06 -07:00
}
@ catch ( NSException * e ) { }
return nil ;
}
- ( NSInteger ) multipleValuesCount {
return [ [ _multipleValuesDict objectForKey : kIASKValues ] count ] ;
}
- ( NSArray * ) multipleValues {
return [ _multipleValuesDict objectForKey : kIASKValues ] ;
}
- ( NSArray * ) multipleTitles {
return [ _multipleValuesDict objectForKey : kIASKTitles ] ;
}
2014-05-19 13:33:42 -07:00
- ( NSArray * ) multipleShortTitles {
return [ _multipleValuesDict objectForKey : kIASKShortTitles ] ;
}
2013-06-21 17:48:06 -07:00
- ( 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 ] ) {
2014-05-19 13:33:42 -07:00
return UIKeyboardTypeDecimalPad ;
2013-06-21 17:48:06 -07:00
}
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
{
2014-05-19 13:33:42 -07:00
NSString * imageName = [ _specifierDict objectForKey : kIASKCellImage ] ;
if ( imageName . length = = 0 )
return nil ;
return [ UIImage imageNamed : imageName ] ;
2013-06-21 17:48:06 -07:00
}
- ( UIImage * ) highlightedCellImage
{
2014-05-19 13:33:42 -07:00
NSString * imageName = [ [ _specifierDict objectForKey : kIASKCellImage ] stringByAppendingString : @ "Highlighted" ] ;
if ( imageName . length = = 0 )
return nil ;
return [ UIImage imageNamed : imageName ] ;
2013-06-21 17:48:06 -07:00
}
- ( BOOL ) adjustsFontSizeToFitWidth {
NSNumber * boxedResult = [ _specifierDict objectForKey : kIASKAdjustsFontSizeToFitWidth ] ;
return ! boxedResult || [ boxedResult boolValue ] ;
}
2013-10-08 16:00:55 -07:00
- ( NSTextAlignment ) textAlignment
2013-06-21 17:48:06 -07:00
{
2015-03-03 15:56:32 -05:00
if ( self . subtitle . length || [ [ _specifierDict objectForKey : kIASKTextLabelAlignment ] isEqualToString : kIASKTextLabelAlignmentLeft ] ) {
2013-06-21 17:48:06 -07:00
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 ;
2017-04-11 16:15:18 -07:00
} else if ( [ self . type isEqualToString : kIASKPSMultiValueSpecifier ] || [ self . type isEqualToString : kIASKPSTitleValueSpecifier ] || [ self . type isEqualToString : kIASKTextViewSpecifier ] ) {
2013-06-21 17:48:06 -07:00
return NSTextAlignmentRight ;
}
return NSTextAlignmentLeft ;
}
2014-05-19 13:33:42 -07:00
2015-03-03 15:56:32 -05:00
- ( 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 ;
}
2014-05-19 13:33:42 -07:00
- ( id ) valueForKey : ( NSString * ) key {
return [ _specifierDict objectForKey : key ] ;
}
2013-06-21 17:48:06 -07:00
@ end