From 5c43f8401362bea19d143de20f64828da2f88e0f Mon Sep 17 00:00:00 2001 From: Guillaume Algis Date: Sun, 12 Jul 2015 00:18:51 +0200 Subject: [PATCH] Cache package list and load it on Alcatraz startup --- Alcatraz.xcodeproj/project.pbxproj | 6 ++ .../Controllers/ATZPluginWindowController.m | 16 +++- Alcatraz/Helpers/ATZCache.h | 31 ++++++++ Alcatraz/Helpers/ATZCache.m | 76 +++++++++++++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 Alcatraz/Helpers/ATZCache.h create mode 100644 Alcatraz/Helpers/ATZCache.m diff --git a/Alcatraz.xcodeproj/project.pbxproj b/Alcatraz.xcodeproj/project.pbxproj index 1f583d6..2cfc2e7 100644 --- a/Alcatraz.xcodeproj/project.pbxproj +++ b/Alcatraz.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ 8ADC22341A2AD5B800DB7BCA /* ATZPreviewImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ADC22331A2AD5B800DB7BCA /* ATZPreviewImageButton.m */; }; 8AF670C919C2DE8A00E1C168 /* ATZSegmentedControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 8AF670C819C2DE8A00E1C168 /* ATZSegmentedControl.m */; }; F0DF961E1B40416400DF68CC /* ATZSegmentedCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F0DF961D1B40416400DF68CC /* ATZSegmentedCell.m */; }; + F0C202121B519CCC001867CF /* ATZCache.m in Sources */ = {isa = PBXBuildFile; fileRef = F0C202111B519CCC001867CF /* ATZCache.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -146,6 +147,8 @@ 8AF670C819C2DE8A00E1C168 /* ATZSegmentedControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ATZSegmentedControl.m; path = Views/ATZSegmentedControl.m; sourceTree = ""; }; F0DF961C1B40416300DF68CC /* ATZSegmentedCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATZSegmentedCell.h; sourceTree = ""; }; F0DF961D1B40416400DF68CC /* ATZSegmentedCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATZSegmentedCell.m; sourceTree = ""; }; + F0C202101B519CCC001867CF /* ATZCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ATZCache.h; sourceTree = ""; }; + F0C202111B519CCC001867CF /* ATZCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ATZCache.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -302,6 +305,8 @@ 8917DA171726B63B00F0B2D2 /* ATZShell.m */, 89B4F2BC172FF5AC001FD2E3 /* ATZPBXProjParser.h */, 89B4F2BD172FF5AC001FD2E3 /* ATZPBXProjParser.m */, + F0C202101B519CCC001867CF /* ATZCache.h */, + F0C202111B519CCC001867CF /* ATZCache.m */, ); path = Helpers; sourceTree = ""; @@ -439,6 +444,7 @@ files = ( 890A4B4E171F031300AFE577 /* Alcatraz.m in Sources */, 89D40AFC1721CBD600A67BB3 /* ATZPluginWindowController.m in Sources */, + F0C202121B519CCC001867CF /* ATZCache.m in Sources */, 8917D9F31726B4EE00F0B2D2 /* ATZColorScheme.m in Sources */, 8917D9F41726B4EE00F0B2D2 /* ATZFileTemplate.m in Sources */, 8917D9F51726B4EE00F0B2D2 /* ATZPackage.m in Sources */, diff --git a/Alcatraz/Controllers/ATZPluginWindowController.m b/Alcatraz/Controllers/ATZPluginWindowController.m index 43e0412..08697bd 100644 --- a/Alcatraz/Controllers/ATZPluginWindowController.m +++ b/Alcatraz/Controllers/ATZPluginWindowController.m @@ -27,6 +27,7 @@ #import "Alcatraz.h" #import "ATZPackageFactory.h" #import "ATZVersion.h" +#import "ATZCache.h" #import "ATZPlugin.h" #import "ATZColorScheme.h" @@ -132,19 +133,30 @@ - (void)keyDown:(NSEvent *)event { } - (IBAction)reloadPackages:(id)sender { + if (!self.packages) { + // No packages loaded yet, display from cache in the meantime + NSDictionary *packageList = [ATZCache loadPackagesFromCache]; + [self displayPackages:packageList]; + } + ATZDownloader *downloader = [ATZDownloader new]; [downloader downloadPackageListWithCompletion:^(NSDictionary *packageList, NSError *error) { if (error) { NSLog(@"Error while downloading packages! %@", error); } else { - self.packages = [ATZPackageFactory createPackagesFromDicts:packageList]; - [self reloadTableView]; + [self displayPackages:packageList]; + [ATZCache cachePackages:packageList]; [self updatePackages]; } }]; } +- (void)displayPackages:(NSDictionary *)packageList { + self.packages = [ATZPackageFactory createPackagesFromDicts:packageList]; + [self reloadTableView]; +} + - (IBAction)updatePackageRepoPath:(id)sender { // present dialog with text field, update repo path, redownload package list NSAlert *alert = [NSAlert new]; diff --git a/Alcatraz/Helpers/ATZCache.h b/Alcatraz/Helpers/ATZCache.h new file mode 100644 index 0000000..390fdd7 --- /dev/null +++ b/Alcatraz/Helpers/ATZCache.h @@ -0,0 +1,31 @@ +// +// ATZCache.h +// +// Copyright (c) 2014 Marin Usalj | supermar.in +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +@interface ATZCache : NSObject + ++ (NSDictionary *)loadPackagesFromCache; ++ (BOOL)cachePackages:(NSDictionary *)packages; + +@end diff --git a/Alcatraz/Helpers/ATZCache.m b/Alcatraz/Helpers/ATZCache.m new file mode 100644 index 0000000..39a9988 --- /dev/null +++ b/Alcatraz/Helpers/ATZCache.m @@ -0,0 +1,76 @@ +// +// ATZCache.m +// +// Copyright (c) 2014 Marin Usalj | supermar.in +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "ATZCache.h" +#import "Alcatraz.h" + +static NSString *const PACKAGES_CACHE_FILENAME = @"packages.plist"; + +@implementation ATZCache + ++ (NSDictionary *)loadPackagesFromCache { + return [NSDictionary dictionaryWithContentsOfURL:[self packagesCacheURL]]; +} + ++ (BOOL)cachePackages:(NSDictionary *)packages { + NSError *error; + + BOOL directoryExists = [self createCacheDirectoryIfNeeded:&error]; + if (!directoryExists) { + NSLog(@"Error while caching packages: %@", error.localizedDescription); + return NO; + } + + NSData *plistData = [NSPropertyListSerialization dataWithPropertyList:packages format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error]; + if (!plistData) { + NSLog(@"Error while serializing packages for caching: %@", error.localizedDescription); + return NO; + } + + return [plistData writeToURL:[self packagesCacheURL] atomically:YES]; +} + ++ (NSURL *)cacheDirectoryURL { + NSURL *mainCacheDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] firstObject]; + NSString *bundleIdentifier = [Alcatraz sharedPlugin].bundle.bundleIdentifier; + NSURL *cacheDirectory = [mainCacheDirectory URLByAppendingPathComponent:bundleIdentifier]; + + return cacheDirectory; +} + ++ (NSURL *)packagesCacheURL { + return [[self cacheDirectoryURL] URLByAppendingPathComponent:PACKAGES_CACHE_FILENAME]; +} + ++ (BOOL)createCacheDirectoryIfNeeded:(NSError **)error { + BOOL created = [[NSFileManager defaultManager] createDirectoryAtURL:[self cacheDirectoryURL] withIntermediateDirectories:YES attributes:nil error:error]; + + if (!created) { + NSString *errorDescription = error ? (*error).localizedDescription : nil; + NSLog(@"Could not find a valid caching directory: %@", errorDescription); + } + + return created; +} + +@end