diff --git a/Dash/Base.lproj/Main.storyboard b/Dash/Base.lproj/Main.storyboard index 7249f9a2..2861cb7a 100644 --- a/Dash/Base.lproj/Main.storyboard +++ b/Dash/Base.lproj/Main.storyboard @@ -13,7 +13,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -37,7 +37,7 @@ - + @@ -120,63 +120,63 @@ - + - + - + - + - + - + - + - + - + @@ -187,21 +187,21 @@ - + - + - + @@ -209,24 +209,24 @@ - + - + - + - + @@ -240,6 +240,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -264,6 +295,9 @@ + + + @@ -288,7 +322,7 @@ - + @@ -300,7 +334,7 @@ - + @@ -350,7 +384,7 @@ - + @@ -362,7 +396,7 @@ - + @@ -403,7 +437,7 @@ - + @@ -415,7 +449,7 @@ - + @@ -459,7 +493,7 @@ - + @@ -489,7 +523,7 @@ - + @@ -536,7 +570,7 @@ - + @@ -605,7 +639,7 @@ - + @@ -625,7 +659,7 @@ - + @@ -638,7 +672,7 @@ - + @@ -681,7 +715,7 @@ - + @@ -702,7 +736,7 @@ - + @@ -748,11 +782,11 @@ - - - - + + + + diff --git a/Dash/DHDocsetBrowser.h b/Dash/DHDocsetBrowser.h index f439afaa..e29521ce 100644 --- a/Dash/DHDocsetBrowser.h +++ b/Dash/DHDocsetBrowser.h @@ -25,12 +25,10 @@ @property (assign) BOOL didFirstReload; @property (strong) DHDBSearchController *searchController; -@property (strong) NSMutableArray *shownDocsets; -@property (strong) NSArray *sections; +@property (strong, readonly) NSArray *shownDocsets; @property (assign) BOOL didLoad; @property (assign) BOOL isSearching; @property (assign) BOOL needsToReloadWhenDoneSearching; -@property (strong) NSMutableArray *keyDocsets; - (IBAction)openSettings:(id)sender; + (NSAttributedString *)titleBarItemAttributedStringTemplate; diff --git a/Dash/DHDocsetBrowser.m b/Dash/DHDocsetBrowser.m index 2f6a871d..5b7d7f18 100644 --- a/Dash/DHDocsetBrowser.m +++ b/Dash/DHDocsetBrowser.m @@ -25,14 +25,28 @@ #import "DHDocsetDownloader.h" #import "DHRemoteBrowser.h" #import "DHWebView.h" +#import "DHDocsetBrowserViewModel.h" static NSAttributedString *_titleBarItemAttributedStringTemplate = nil; +@interface DHDocsetBrowser () +@property (nonatomic, strong) DHDocsetBrowserViewModel *viewModel; +@end + @implementation DHDocsetBrowser +- (NSArray *)shownDocsets { + return self.viewModel.shownDocsets; +} + +- (NSArray *)sections { + return self.viewModel.sections; +} + - (void)viewDidLoad { [super viewDidLoad]; + self.viewModel = [[DHDocsetBrowserViewModel alloc] init]; self.clearsSelectionOnViewWillAppear = NO; self.searchController = [DHDBSearchController searchControllerWithDocsets:nil typeLimit:nil viewController:self]; @@ -40,6 +54,7 @@ - (void)viewDidLoad [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reload:) name:DHDocsetsChangedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reload:) name:DHRemotesChangedNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reload:) name:DHSettingsChangedNotification object:nil]; self.tableView.rowHeight = 44; self.navigationController.delegate = self; self.navigationController.interactivePopGestureRecognizer.delegate = (id)self; @@ -179,7 +194,7 @@ - (void)performURLSearch:(NSNotification *)notification dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.00 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ if(keywordDocsets.count) { - self.keyDocsets = [NSMutableArray arrayWithArray:[keywordDocsets array]]; + self.viewModel.keyDocsets = [NSMutableArray arrayWithArray:[keywordDocsets array]]; } [self.searchDisplayController setActive:YES animated:NO]; self.searchDisplayController.searchBar.text = query; @@ -264,21 +279,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (void)updateSections:(BOOL)withTitleUpdate { - NSMutableArray *sections = [NSMutableArray array]; - if([DHRemoteServer sharedServer].remotes.count) - { - if(!self.isEditing && !self.isSearching) - { - [sections addObject:[DHRemoteServer sharedServer].remotes]; - } - } - NSMutableArray *docsets = (self.isEditing) ? [DHDocsetManager sharedManager].docsets : (self.keyDocsets) ? self.keyDocsets : [DHDocsetManager sharedManager].enabledDocsets; - self.shownDocsets = docsets; - if(docsets.count) - { - [sections addObject:docsets]; - } - self.sections = sections; + [self.viewModel updateSectionsForEditing:self.isEditing andSearching:self.isSearching]; if(withTitleUpdate) { [self updateTitle]; @@ -335,7 +336,7 @@ - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fro - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { - return YES; + return self.viewModel.canMoveRows; } - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath @@ -386,8 +387,8 @@ - (void)tableViewDidBeginEditing:(UITableView *)tableView } // NSArray *current = self.shownDocsets; - NSMutableArray *new = [DHDocsetManager sharedManager].docsets; - self.shownDocsets = new; + NSArray *new = [self.viewModel docsetsForEditing:YES]; + self.viewModel.shownDocsets = new; NSMutableArray *toInsert = [NSMutableArray array]; for(NSInteger i = 0; i < new.count; i++) { @@ -419,7 +420,7 @@ - (void)tableViewDidBeginEditing:(UITableView *)tableView - (void)tableViewDidEndEditing:(UITableView *)tableView { NSArray *current = self.shownDocsets; - self.shownDocsets = [DHDocsetManager sharedManager].enabledDocsets; + self.viewModel.shownDocsets = [self.viewModel docsetsForEditing:NO]; NSMutableArray *toDelete = [NSMutableArray array]; BOOL docsetsShouldBeShown = NO; for(int i = 0; i < current.count; i++) @@ -455,7 +456,7 @@ - (void)tableViewDidEndEditing:(UITableView *)tableView - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller { - if(self.keyDocsets) + if(self.viewModel.keyDocsets) { [self reload:nil]; } @@ -478,9 +479,9 @@ - (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)cont - (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller { self.isSearching = NO; - if(self.needsToReloadWhenDoneSearching || self.keyDocsets) + if(self.needsToReloadWhenDoneSearching || self.viewModel.keyDocsets) { - self.keyDocsets = nil; + self.viewModel.keyDocsets = nil; self.needsToReloadWhenDoneSearching = NO; [self reload:nil]; } diff --git a/Dash/DHDocsetBrowserViewModel.h b/Dash/DHDocsetBrowserViewModel.h new file mode 100644 index 00000000..81b09fa1 --- /dev/null +++ b/Dash/DHDocsetBrowserViewModel.h @@ -0,0 +1,11 @@ + +#import + +@interface DHDocsetBrowserViewModel : NSObject +@property (nonatomic, strong, readonly) NSArray *sections; +@property (nonatomic, strong) NSMutableArray *keyDocsets; +@property (nonatomic, strong) NSArray *shownDocsets; +@property (nonatomic, readonly) BOOL canMoveRows; +- (void)updateSectionsForEditing:(BOOL)editing andSearching:(BOOL)searching; +- (NSArray *)docsetsForEditing:(BOOL)editing; +@end diff --git a/Dash/DHDocsetBrowserViewModel.m b/Dash/DHDocsetBrowserViewModel.m new file mode 100644 index 00000000..6caa0045 --- /dev/null +++ b/Dash/DHDocsetBrowserViewModel.m @@ -0,0 +1,52 @@ + +#import "DHDocsetBrowserViewModel.h" +#import "DHDocsetManager.h" +#import "DHDocsetDownloader.h" + +@interface DHDocsetBrowserViewModel () +@property (nonatomic, strong) NSArray *sections; +@end + +@implementation DHDocsetBrowserViewModel + +- (BOOL)alphabetizing { + return [NSUserDefaults.standardUserDefaults boolForKey:DHDocsetDownloader.defaultsAlphabetizingKey]; +} + +- (BOOL)canMoveRows { + return !self.alphabetizing; +} + +- (NSArray *)sort:(NSArray *)array { + if (self.alphabetizing) { + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]; + array = [array sortedArrayUsingDescriptors:@[sortDescriptor]]; + } + return array; +} + +- (NSArray *)docsetsForEditing:(BOOL)editing { + NSArray *docsets = (editing) ? [DHDocsetManager sharedManager].docsets : (self.keyDocsets) ? self.keyDocsets : [DHDocsetManager sharedManager].enabledDocsets; + return [self sort:docsets]; +} + +- (void)updateSectionsForEditing:(BOOL)editing andSearching:(BOOL)searching +{ + NSMutableArray *sections = [NSMutableArray array]; + if([DHRemoteServer sharedServer].remotes.count) + { + if(!editing && !searching) + { + [sections addObject:[self sort:DHRemoteServer.sharedServer.remotes]]; + } + } + NSArray *docsets = [self docsetsForEditing:editing]; + self.shownDocsets = docsets; + if(docsets.count) + { + [sections addObject:docsets]; + } + self.sections = sections; +} + +@end diff --git a/Dash/DHPreferences.h b/Dash/DHPreferences.h index 061b432e..302712c8 100644 --- a/Dash/DHPreferences.h +++ b/Dash/DHPreferences.h @@ -20,6 +20,9 @@ @interface DHPreferences : UITableViewController @property (assign) IBOutlet UISwitch *updatesSwitch; +@property (assign) IBOutlet UISwitch *alphabetizingSwitch; +@property (assign) IBOutlet UITableViewCell *updatesCell; +@property (assign) IBOutlet UITableViewCell *alphabetizingCell; @property (assign) BOOL didSetUpdateLabelBefore; - (IBAction)updatesSwitchValueChanged:(id)sender; diff --git a/Dash/DHPreferences.m b/Dash/DHPreferences.m index 0bb9fcc1..f664fbb4 100644 --- a/Dash/DHPreferences.m +++ b/Dash/DHPreferences.m @@ -33,6 +33,11 @@ - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.updatesSwitch setOn:[[NSUserDefaults standardUserDefaults] boolForKey:[[DHDocsetDownloader sharedDownloader] defaultsAutomaticallyCheckForUpdatesKey]]]; + [self.alphabetizingSwitch setOn:[NSUserDefaults.standardUserDefaults boolForKey:DHDocsetDownloader.defaultsAlphabetizingKey]]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self updateAlphabetizingSwitchFooterView:nil]; + [self updateUpdatesSwitchFooterView:nil]; + }); } - (void)viewDidAppear:(BOOL)animated @@ -238,16 +243,37 @@ - (IBAction)updatesSwitchValueChanged:(id)sender [self updateUpdatesSwitchFooterView:nil]; } -- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UITableViewHeaderFooterView *)view forSection:(NSInteger)section +- (IBAction)alphabetizingSwitchValueChanged:(id)sender { - [self updateUpdatesSwitchFooterView:view]; + [[NSUserDefaults standardUserDefaults] setBool:[sender isOn] forKey:DHDocsetDownloader.defaultsAlphabetizingKey]; + [NSNotificationCenter.defaultCenter postNotificationName:DHSettingsChangedNotification object:DHDocsetDownloader.defaultsAlphabetizingKey]; + [self updateAlphabetizingSwitchFooterView:nil]; +} + +- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UITableViewHeaderFooterView *)footer forSection:(NSInteger)section +{ + if(section == [tableView indexPathForCell:self.updatesCell].section) + { + [self updateUpdatesSwitchFooterView:footer]; + } + else if(section == [tableView indexPathForCell:self.alphabetizingCell].section) + { + [self updateAlphabetizingSwitchFooterView:footer]; + } } - (void)updateUpdatesSwitchFooterView:(UITableViewHeaderFooterView *)footer { - footer = (footer) ?: [self.tableView footerViewForSection:1]; - [footer textLabel].text = [NSString stringWithFormat:@"Dash %@ notify you when docset updates are available. ", (self.updatesSwitch.isOn) ? @"will" : @"won't"]; - + footer = (footer) ? footer : [self.tableView footerViewForSection:[self.tableView indexPathForCell:self.updatesCell].section]; + [footer textLabel].text = [NSString stringWithFormat:@"Dash %@ notify you when docset updates are available.", (self.updatesSwitch.isOn) ? @"will" : @"won't"]; + [[footer textLabel] sizeToFit]; +} + +- (void)updateAlphabetizingSwitchFooterView:(UITableViewHeaderFooterView *)footer +{ + footer = (footer) ? footer : [self.tableView footerViewForSection:[self.tableView indexPathForCell:self.alphabetizingCell].section]; + [footer textLabel].text = [NSString stringWithFormat:@"Docsets %@ be sorted alphabetically in the docset browser.", (self.alphabetizingSwitch.isOn) ? @"will" : @"won't"]; + [[footer textLabel] sizeToFit]; } - (void)prepareForURLSearch:(id)sender diff --git a/Dash/DHRepo.h b/Dash/DHRepo.h index 9210d6d4..c32ec49a 100644 --- a/Dash/DHRepo.h +++ b/Dash/DHRepo.h @@ -52,6 +52,7 @@ - (void)backgroundCheckForUpdatesIfNeeded; - (NSString *)repoIdentifier; // Used to find a corresponding repo for a installed docset - (NSString *)defaultsAutomaticallyCheckForUpdatesKey; +@property (nonatomic, strong, readonly, class) NSString *defaultsAlphabetizingKey; - (void)emptyTrashAtPath:(NSString *)trashPath; - (NSString *)docsetInstallFolderPath; - (NSString *)uniqueTrashPath; @@ -67,3 +68,5 @@ @end NSInteger compareFeeds(id feed1, id feed2, void *context); + +#define DHSettingsChangedNotification @"DHSettingsChangedNotification" diff --git a/Dash/DHRepo.m b/Dash/DHRepo.m index f3c195eb..af7e922d 100644 --- a/Dash/DHRepo.m +++ b/Dash/DHRepo.m @@ -864,6 +864,10 @@ - (NSString *)defaultsAutomaticallyCheckForUpdatesKey return @"AutomaticallyCheckForUpdates"; } ++ (NSString *)defaultsAlphabetizingKey { + return @"DocSetAlphabetizing"; +} + - (NSString *)defaultsUpdateLastCheckDateKey { return [[self defaultsKey] stringByAppendingString:@"LastUpdateCheck"]; diff --git a/Dash/Dash iOS.xcodeproj/project.pbxproj b/Dash/Dash iOS.xcodeproj/project.pbxproj index e0fe3e7d..e7305f56 100644 --- a/Dash/Dash iOS.xcodeproj/project.pbxproj +++ b/Dash/Dash iOS.xcodeproj/project.pbxproj @@ -232,6 +232,7 @@ 43EE932A19CD079600FFF30C /* libarchive.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 43EE932919CD079600FFF30C /* libarchive.a */; }; 43EED91C1B607DB800F3DC35 /* on_page_load.js in Resources */ = {isa = PBXBuildFile; fileRef = 43EED91B1B607DB800F3DC35 /* on_page_load.js */; }; 43F25F9C19EBDEF30025CDC4 /* DHBlockProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 43F25F9B19EBDEF30025CDC4 /* DHBlockProtocol.m */; }; + 43F31AAE200BB52F0082066C /* DHDocsetBrowserViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C39BFF200A836D00734571 /* DHDocsetBrowserViewModel.m */; }; 43F70AC019CBBD20000849C8 /* Defaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = 43F70ABF19CBBD20000849C8 /* Defaults.plist */; }; 43F7527319CD1C2000D76F58 /* UIButton+DHUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 43F7527219CD1C2000D76F58 /* UIButton+DHUtils.m */; }; 43F7527519CD31D100D76F58 /* DHRepoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 43F7527419CD31D100D76F58 /* DHRepoCell.xib */; }; @@ -249,6 +250,7 @@ 43FD2F0219BB8D87007E594D /* DHWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 43FD2F0119BB8D87007E594D /* DHWebViewController.m */; }; 43FD2F0419BB8D87007E594D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 43FD2F0319BB8D87007E594D /* Images.xcassets */; }; 45D28F8ABD1FC392B1930467 /* libPods-Dash.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A2364AD2032B0714BCD2265 /* libPods-Dash.a */; }; + F5C39C00200A836D00734571 /* DHDocsetBrowserViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C39BFF200A836D00734571 /* DHDocsetBrowserViewModel.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -486,6 +488,8 @@ 9A2364AD2032B0714BCD2265 /* libPods-Dash.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Dash.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 9FB91D369AD27465BED375AD /* libPods-Dash-Dash App Store.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Dash-Dash App Store.a"; sourceTree = BUILT_PRODUCTS_DIR; }; BAE47FF5DEE33300EBFF9AEA /* Pods-Dash.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Dash.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-Dash/Pods-Dash.debug.xcconfig"; sourceTree = ""; }; + F5C39BFE200A836D00734571 /* DHDocsetBrowserViewModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DHDocsetBrowserViewModel.h; sourceTree = ""; }; + F5C39BFF200A836D00734571 /* DHDocsetBrowserViewModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DHDocsetBrowserViewModel.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -664,6 +668,8 @@ 438D58C119E575D600012881 /* DHLoadingCell.xib */, 43FD2EFD19BB8D87007E594D /* DHDocsetBrowser.h */, 43FD2EFE19BB8D87007E594D /* DHDocsetBrowser.m */, + F5C39BFE200A836D00734571 /* DHDocsetBrowserViewModel.h */, + F5C39BFF200A836D00734571 /* DHDocsetBrowserViewModel.m */, 437FE06419E2AC0D0022ADF4 /* DHTypeBrowser.h */, 437FE06519E2AC0D0022ADF4 /* DHTypeBrowser.m */, 439051F719E684160083A55E /* DHEntryBrowser.h */, @@ -1368,6 +1374,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 43F31AAE200BB52F0082066C /* DHDocsetBrowserViewModel.m in Sources */, 43AB65341ED19D2F00A6EC18 /* DHAppDelegate.m in Sources */, 43AB65351ED19D2F00A6EC18 /* DHType.m in Sources */, 43AB65361ED19D2F00A6EC18 /* UIViewController+DHUtils.m in Sources */, @@ -1473,6 +1480,7 @@ 43F25F9C19EBDEF30025CDC4 /* DHBlockProtocol.m in Sources */, 43B0956C19BFD57500F8611B /* DHRepo.m in Sources */, 43D7E4F01BB4C62E00FC1DEF /* DHWindow.m in Sources */, + F5C39C00200A836D00734571 /* DHDocsetBrowserViewModel.m in Sources */, 43BD6BF41DCE379B0005A1E7 /* DHAppUpdateChecker.m in Sources */, 439051FC19E68FE20083A55E /* NSString+GTM.m in Sources */, 43D4F06719E7D68100C22AF5 /* DHDBSearcher.m in Sources */,