├── demo.gif
├── UnzipAction
├── en.lproj
│ └── Localizable.strings
├── UZArchiveViewController.h
├── UZOpenInActivity.h
├── UIAlertController+UZError.h
├── UZGlyphFactory.h
├── UZExtensionViewController.h
├── UZExtensionTableViewController.h
├── UZNodeTableViewCell.h
├── UZPreviewViewController.h
├── UZPreviewPageViewController.h
├── UZNodeTableViewCell.m
├── UIAlertController+UZError.m
├── UZNodeViewController.h
├── UZNode.h
├── UZUnzipCoordinator.h
├── UZNodeViewControllerSubclass.h
├── UZUnzipOperation.h
├── UZExtensionViewController.m
├── UZExtensionTableViewController.m
├── Info.plist
├── UZOpenInActivity.m
├── UZArchiveViewController.m
├── MainInterface.storyboard
├── UZGlyphFactory.m
├── UZUnzipOperation.m
├── UZPreviewPageViewController.m
├── UZNode.m
├── UZNodeTableViewCell.xib
├── UZPreviewViewController.m
├── UZPreviewViewController.xib
├── UZUnzipCoordinator.m
└── UZNodeViewController.m
├── Unzip.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
├── xcuserdata
│ └── Karunaratne.xcuserdatad
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── Unzip.xcscheme
└── project.pbxproj
├── Podfile
├── Unzip
├── ViewController.h
├── AppDelegate.h
├── main.m
├── Images.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── LaunchImage.launchimage
│ │ └── Contents.json
├── ViewController.m
├── Info.plist
├── Base.lproj
│ └── Main.storyboard
└── AppDelegate.m
├── .gitignore
├── LICENSE
├── README.md
├── Podfile.lock
└── ACKNOWLEDGEMENTS
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indragiek/Unzip/HEAD/demo.gif
--------------------------------------------------------------------------------
/UnzipAction/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/indragiek/Unzip/HEAD/UnzipAction/en.lproj/Localizable.strings
--------------------------------------------------------------------------------
/Unzip.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, "8.0"
2 |
3 | target "Unzip" do
4 |
5 | end
6 |
7 | target "UnzipTests" do
8 |
9 | end
10 |
11 | target "UnzipAction" do
12 | pod "zipzap", "~> 7.0"
13 | pod "libextobjc", "~> 0.4"
14 | end
15 |
16 |
--------------------------------------------------------------------------------
/Unzip/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UIViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/UnzipAction/UZArchiveViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZArchiveViewController.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZNodeViewController.h"
10 |
11 | @interface UZArchiveViewController : UZNodeViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | Unzip.xcworkspace/
23 | Pods/
--------------------------------------------------------------------------------
/Unzip/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/UnzipAction/UZOpenInActivity.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZOpenInActivity.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UZOpenInActivity : UIActivity
12 |
13 | - (instancetype)initWithBarButtonItem:(UIBarButtonItem *)barButtonItem;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/UnzipAction/UIAlertController+UZError.h:
--------------------------------------------------------------------------------
1 | //
2 | // UIAlertController+UZError.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UIAlertController (UZError)
12 |
13 | + (instancetype)uz_alertControllerWithError:(NSError *)error;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/Unzip/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/UnzipAction/UZGlyphFactory.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZGlyphFactory.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/16/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #ifndef UZGlyphFactory_h
12 | #define UZGlyphFactory_h
13 |
14 | UIImage * UZDirectoryGlyphImage(UIColor *tintColor);
15 | UIImage * UZFileGlyphImage(NSString *fileName, UIColor *tintColor);
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/Unzip/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "40x40",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "60x60",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/UnzipAction/UZExtensionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZExtensionViewController.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UZExtensionViewController : UIViewController
12 |
13 | - (instancetype)initWithExtensionContext:(NSExtensionContext *)extensionContext;
14 |
15 | @property (nonatomic, strong, readonly) NSExtensionContext *uz_extensionContext;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/UnzipAction/UZExtensionTableViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZExtensionTableViewController.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UZExtensionTableViewController : UITableViewController
12 |
13 | - (instancetype)initWithStyle:(UITableViewStyle)style extensionContext:(NSExtensionContext *)extensionContext;
14 |
15 | @property (nonatomic, strong, readonly) NSExtensionContext *uz_extensionContext;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/UnzipAction/UZNodeTableViewCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZNodeTableViewCell.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UZNodeTableViewCell : UITableViewCell
12 |
13 | @property (nonatomic, weak) IBOutlet UIImageView *glyphImageView;
14 | @property (nonatomic, weak) IBOutlet UILabel *fileNameLabel;
15 | @property (nonatomic, weak) IBOutlet UILabel *fileSizeLabel;
16 |
17 | + (NSString *)reuseIdentifier;
18 | + (CGFloat)rowHeight;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/Unzip/Images.xcassets/LaunchImage.launchimage/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "orientation" : "portrait",
5 | "idiom" : "iphone",
6 | "extent" : "full-screen",
7 | "minimum-system-version" : "7.0",
8 | "scale" : "2x"
9 | },
10 | {
11 | "orientation" : "portrait",
12 | "idiom" : "iphone",
13 | "subtype" : "retina4",
14 | "extent" : "full-screen",
15 | "minimum-system-version" : "7.0",
16 | "scale" : "2x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
--------------------------------------------------------------------------------
/Unzip/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 |
11 | @interface ViewController ()
12 |
13 | @end
14 |
15 | @implementation ViewController
16 |
17 | - (void)viewDidLoad {
18 | [super viewDidLoad];
19 | // Do any additional setup after loading the view, typically from a nib.
20 | }
21 |
22 | - (void)didReceiveMemoryWarning {
23 | [super didReceiveMemoryWarning];
24 | // Dispose of any resources that can be recreated.
25 | }
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/UnzipAction/UZPreviewViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZPreviewViewController.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZExtensionViewController.h"
10 |
11 | @class UZNode;
12 | @class UZUnzipCoordinator;
13 |
14 | @interface UZPreviewViewController : UZExtensionViewController
15 |
16 | - (instancetype)initWithNode:(UZNode *)node
17 | password:(NSString *)password
18 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
19 | extensionContext:(NSExtensionContext *)extensionContext;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/UnzipAction/UZPreviewPageViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZPreviewPageViewController.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/8/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class UZNode;
12 | @class UZUnzipCoordinator;
13 |
14 | @interface UZPreviewPageViewController : UIPageViewController
15 |
16 | - (instancetype)initWithRootNode:(UZNode *)rootNode
17 | startingChildNode:(UZNode *)startingChildNode
18 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
19 | extensionContext:(NSExtensionContext *)extensionContext;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/UnzipAction/UZNodeTableViewCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZNodeTableViewCell.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZNodeTableViewCell.h"
10 |
11 | @implementation UZNodeTableViewCell
12 |
13 | + (NSString *)reuseIdentifier
14 | {
15 | return NSStringFromClass(self.class);
16 | }
17 |
18 | + (CGFloat)rowHeight
19 | {
20 | return 52.0;
21 | }
22 |
23 | #pragma mark - UITableViewCell
24 |
25 | - (void)prepareForReuse
26 | {
27 | self.fileNameLabel.text = nil;
28 | self.fileSizeLabel.text = nil;
29 | self.glyphImageView.image = nil;
30 | [super prepareForReuse];
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/UnzipAction/UIAlertController+UZError.m:
--------------------------------------------------------------------------------
1 | //
2 | // UIAlertController+UZError.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UIAlertController+UZError.h"
10 |
11 | @implementation UIAlertController (UZError)
12 |
13 | + (instancetype)uz_alertControllerWithError:(NSError *)error
14 | {
15 | UIAlertController *alert = [self alertControllerWithTitle:error.localizedDescription message:error.localizedRecoverySuggestion preferredStyle:UIAlertControllerStyleAlert];
16 | [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:nil]];
17 | return alert;
18 | }
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/UnzipAction/UZNodeViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZNodeViewController.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZExtensionTableViewController.h"
10 |
11 | @class UZNode;
12 | @class UZUnzipCoordinator;
13 |
14 | @interface UZNodeViewController : UZExtensionTableViewController
15 |
16 | - (instancetype)initWithRootNode:(UZNode *)rootNode
17 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
18 | extensionContext:(NSExtensionContext *)extensionContext;
19 |
20 | @property (nonatomic, strong, readonly) UZNode *rootNode;
21 | @property (nonatomic, strong, readonly) UZUnzipCoordinator *unzipCoordinator;
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/UnzipAction/UZNode.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZNode.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class ZZArchiveEntry;
12 | @class ZZArchive;
13 |
14 | @interface UZNode : NSObject
15 |
16 | @property (nonatomic, strong, readonly) NSArray *children;
17 | @property (nonatomic, assign, readonly, getter=isDirectory) BOOL directory;
18 | @property (nonatomic, assign, readonly, getter=isEncrypted) BOOL encrypted;
19 | @property (nonatomic, assign, readonly) NSUInteger uncompressedSize;
20 | @property (nonatomic, copy, readonly) NSString *fileName;
21 |
22 | + (instancetype)nodeWithArchive:(ZZArchive *)archive;
23 |
24 | - (NSInputStream *)streamWithPassword:(NSString *)password error:(NSError **)error;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/UnzipAction/UZUnzipCoordinator.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZUnzipCoordinator.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class ZZArchive;
12 | @class UZNode;
13 |
14 | @interface UZUnzipOperationToken : NSObject
15 | @end
16 |
17 | @interface UZUnzipCoordinator : NSObject
18 |
19 | - (instancetype)initWithArchive:(ZZArchive *)archive;
20 |
21 | - (UZUnzipOperationToken *)unzipNode:(UZNode *)node
22 | password:(NSString *)password
23 | progressHandler:(void (^)(float progress))progressHandler
24 | completionHandler:(void (^)(NSURL *fileURL, NSError *error))completionHandler;
25 |
26 | - (void)cancelUnzipOperationWithToken:(UZUnzipOperationToken *)token;
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/UnzipAction/UZNodeViewControllerSubclass.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZNodeViewControllerSubclass.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #ifndef Unzip_UZNodeViewControllerSubclass_h
10 | #define Unzip_UZNodeViewControllerSubclass_h
11 |
12 | @interface UZNodeViewController ()
13 | @property (nonatomic, strong, readwrite) UZNode *rootNode;
14 | @property (nonatomic, strong, readwrite) UZUnzipCoordinator *unzipCoordinator;
15 | @property (nonatomic, strong) NSString *searchQuery;
16 |
17 | - (instancetype)initWithRootNode:(UZNode *)rootNode
18 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
19 | extensionContext:(NSExtensionContext *)extensionContext
20 | parentNodeViewController:(UZNodeViewController *)parentNodeViewController;
21 |
22 | @end
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/UnzipAction/UZUnzipOperation.h:
--------------------------------------------------------------------------------
1 | //
2 | // UZUnzipOperation.h
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class UZNode;
12 |
13 | extern NSString * const UZUnzipOperationErrorDomain;
14 |
15 | extern const NSInteger UZUnzipOperationErrorCodeFailedToOpen;
16 | extern const NSInteger UZUnzipOperationErrorCodeFailedToWrite;
17 |
18 | @interface UZUnzipOperation : NSOperation
19 |
20 | @property (nonatomic, strong, readonly) UZNode *node;
21 | @property (nonatomic, strong, readonly) NSError *error;
22 | @property (nonatomic, strong, readonly) NSURL *fileURL;
23 | @property (nonatomic, copy) void (^progressHandler)(float progress);
24 |
25 | - (instancetype)initWithNode:(UZNode *)node
26 | password:(NSString *)password
27 | temporaryDirectoryURL:(NSURL *)temporaryDirectoryURL;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/Unzip.xcodeproj/xcuserdata/Karunaratne.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Unzip.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 | UnzipAction.xcscheme
13 |
14 | orderHint
15 | 1
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | 7218C47C19916F4B00D7C757
21 |
22 | primary
23 |
24 |
25 | 7218C49219916F4C00D7C757
26 |
27 | primary
28 |
29 |
30 | 7218C4A619916F5E00D7C757
31 |
32 | primary
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Indragie Karunaratne
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Unzip
2 | ### iOS 8 Action Extension for browsing ZIP files
3 |
4 | 
5 |
6 | This was going to become a real product until I found out that [iOS 7 added native support for ZIP files](http://www.macworld.com/article/2049370/ios-7-adds-support-for-zipped-attachments-in-mail-messages-with-quick-look.html). Nonetheless, it's a good example of how action extensions can be used to not only extend the functionality of standalone apps, but to extend the functionality of the OS as well.
7 |
8 | ### Getting Started
9 |
10 | Requires [CocoaPods](http://cocoapods.org) to manage dependencies.
11 |
12 | ```
13 | $ cd Unzip
14 | $ pod install
15 | ```
16 |
17 | Open **Unzip.xcworkspace**. The **Unzip** app itself doesn't contain anything, everything is implemented in **UnzipAction**.
18 |
19 | ### Icons
20 |
21 | The icons shown in the image above are from the [Glyphish 8](http://www.glyphish.com) icon set. They could not be included in this repository due to license incompatibility.
22 |
23 | ### Contact
24 |
25 | * Indragie Karunaratne
26 | * [@indragie](http://twitter.com/indragie)
27 | * [http://indragie.com](http://indragie.com)
28 |
29 | ### License
30 |
31 | Unzip is licensed under the MIT License.
--------------------------------------------------------------------------------
/Unzip/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.indragie.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UIMainStoryboardFile
26 | Main
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/UnzipAction/UZExtensionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZExtensionViewController.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZExtensionViewController.h"
10 |
11 | @implementation UZExtensionViewController
12 | @synthesize uz_extensionContext = _uz_extensionContext;
13 |
14 | - (instancetype)initWithExtensionContext:(NSExtensionContext *)extensionContext
15 | {
16 | if ((self = [super initWithNibName:nil bundle:nil])) {
17 | _uz_extensionContext = extensionContext;
18 | }
19 | return self;
20 | }
21 |
22 | - (void)viewDidLoad
23 | {
24 | [super viewDidLoad];
25 | if (self.uz_extensionContext != nil) {
26 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Close", nil) style:UIBarButtonItemStylePlain target:self action:@selector(close)];
27 | }
28 | }
29 |
30 | - (NSExtensionContext *)uz_extensionContext
31 | {
32 | return self.extensionContext ?: _uz_extensionContext;
33 | }
34 |
35 | + (NSSet *)keyPathsForValuesAffectingUz_extensionContext
36 | {
37 | return [NSSet setWithObject:@"extensionContext"];
38 | }
39 |
40 | - (void)close
41 | {
42 | [self.uz_extensionContext completeRequestReturningItems:self.uz_extensionContext.inputItems completionHandler:nil];
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/UnzipAction/UZExtensionTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZExtensionTableViewController.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZExtensionTableViewController.h"
10 |
11 | @implementation UZExtensionTableViewController
12 | @synthesize uz_extensionContext = _uz_extensionContext;
13 |
14 | - (instancetype)initWithStyle:(UITableViewStyle)style extensionContext:(NSExtensionContext *)extensionContext
15 | {
16 | if ((self = [super initWithStyle:style])) {
17 | _uz_extensionContext = extensionContext;
18 | }
19 | return self;
20 | }
21 |
22 | - (void)viewDidLoad
23 | {
24 | [super viewDidLoad];
25 | if (self.uz_extensionContext != nil) {
26 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Close", nil) style:UIBarButtonItemStylePlain target:self action:@selector(close)];
27 | }
28 | }
29 |
30 | - (NSExtensionContext *)uz_extensionContext
31 | {
32 | return self.extensionContext ?: _uz_extensionContext;
33 | }
34 |
35 | + (NSSet *)keyPathsForValuesAffectingUz_extensionContext
36 | {
37 | return [NSSet setWithObject:@"extensionContext"];
38 | }
39 |
40 | - (void)close
41 | {
42 | [self.uz_extensionContext completeRequestReturningItems:self.uz_extensionContext.inputItems completionHandler:nil];
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - libextobjc (0.4):
3 | - libextobjc/EXTADT
4 | - libextobjc/EXTConcreteProtocol
5 | - libextobjc/EXTKeyPathCoding
6 | - libextobjc/EXTNil
7 | - libextobjc/EXTSafeCategory
8 | - libextobjc/EXTScope
9 | - libextobjc/EXTSelectorChecking
10 | - libextobjc/EXTSynthesize
11 | - libextobjc/NSInvocation+EXT
12 | - libextobjc/NSMethodSignature+EXT
13 | - libextobjc/RuntimeExtensions
14 | - libextobjc/UmbrellaHeader
15 | - libextobjc/EXTADT (0.4):
16 | - libextobjc/RuntimeExtensions
17 | - libextobjc/EXTConcreteProtocol (0.4):
18 | - libextobjc/RuntimeExtensions
19 | - libextobjc/EXTKeyPathCoding (0.4):
20 | - libextobjc/RuntimeExtensions
21 | - libextobjc/EXTNil (0.4):
22 | - libextobjc/RuntimeExtensions
23 | - libextobjc/EXTSafeCategory (0.4):
24 | - libextobjc/RuntimeExtensions
25 | - libextobjc/EXTScope (0.4):
26 | - libextobjc/RuntimeExtensions
27 | - libextobjc/EXTSelectorChecking (0.4):
28 | - libextobjc/RuntimeExtensions
29 | - libextobjc/EXTSynthesize (0.4):
30 | - libextobjc/RuntimeExtensions
31 | - libextobjc/NSInvocation+EXT (0.4):
32 | - libextobjc/RuntimeExtensions
33 | - libextobjc/NSMethodSignature+EXT (0.4):
34 | - libextobjc/RuntimeExtensions
35 | - libextobjc/RuntimeExtensions (0.4)
36 | - libextobjc/UmbrellaHeader (0.4)
37 | - zipzap (7.0)
38 |
39 | DEPENDENCIES:
40 | - libextobjc (~> 0.4)
41 | - zipzap (~> 7.0)
42 |
43 | SPEC CHECKSUMS:
44 | libextobjc: ba42e4111f433273a886cd54f0ddaddb7f62f82f
45 | zipzap: 1c85484d8f89388fba8fb5824b2eae15b9ce8092
46 |
47 | COCOAPODS: 0.33.1
48 |
--------------------------------------------------------------------------------
/Unzip/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/UnzipAction/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | Unzip
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | com.indragie.Unzip.$(PRODUCT_NAME:rfc1034identifier)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | XPC!
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | NSExtension
26 |
27 | NSExtensionAttributes
28 |
29 | NSExtensionActivationRule
30 |
31 | NSExtensionActivationSupportsFileWithMaxCount
32 | 1
33 | NSExtensionActivationSupportsImageWithMaxCount
34 | 0
35 | NSExtensionActivationSupportsMovieWithMaxCount
36 | 0
37 | NSExtensionActivationSupportsText
38 |
39 | NSExtensionActivationSupportsWebURLWithMaxCount
40 | 0
41 |
42 | NSExtensionPointName
43 | com.apple.ui-services
44 | NSExtensionPointVersion
45 | 1.0
46 |
47 | NSExtensionMainStoryboard
48 | MainInterface
49 | NSExtensionPointIdentifier
50 | com.apple.ui-services
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/UnzipAction/UZOpenInActivity.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZOpenInActivity.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZOpenInActivity.h"
10 |
11 | @interface UZOpenInActivity ()
12 | @property (nonatomic, weak, readonly) UIBarButtonItem *barButtonItem;
13 | @property (nonatomic, strong) NSURL *documentURL;
14 | @property (nonatomic, strong) UIDocumentInteractionController *docInteractionController;
15 | @end
16 |
17 | @implementation UZOpenInActivity
18 |
19 | - (instancetype)initWithBarButtonItem:(UIBarButtonItem *)barButtonItem
20 | {
21 | if ((self = [super init])) {
22 | _barButtonItem = barButtonItem;
23 | }
24 | return self;
25 | }
26 |
27 | #pragma mark - UIActivity
28 |
29 | + (UIActivityCategory)activityCategory
30 | {
31 | return UIActivityCategoryAction;
32 | }
33 |
34 | - (NSString *)activityType
35 | {
36 | return NSStringFromClass(self.class);
37 | }
38 |
39 | - (NSString *)activityTitle
40 | {
41 | return NSLocalizedString(@"Open In", nil);
42 | }
43 |
44 | - (UIImage *)activityImage
45 | {
46 | return nil; // TODO: Put it an icon
47 | }
48 |
49 | - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems
50 | {
51 | if (activityItems.count != 1) return NO;
52 | return [activityItems[0] isKindOfClass:NSURL.class];
53 | }
54 |
55 | - (void)prepareWithActivityItems:(NSArray *)activityItems
56 | {
57 | self.documentURL = activityItems[0];
58 | }
59 |
60 | - (void)performActivity
61 | {
62 | self.docInteractionController = [UIDocumentInteractionController interactionControllerWithURL:self.documentURL];
63 | self.docInteractionController.delegate = self;
64 | [self.docInteractionController presentOpenInMenuFromBarButtonItem:self.barButtonItem animated:YES];
65 | }
66 |
67 | #pragma mark - UIDocumentInteractionControllerDelegate
68 |
69 | - (void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller
70 | {
71 | self.docInteractionController = nil;
72 | [self activityDidFinish:YES];
73 | }
74 |
75 | @end
76 |
--------------------------------------------------------------------------------
/Unzip/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 | return YES;
21 | }
22 |
23 | - (void)applicationWillResignActive:(UIApplication *)application {
24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
26 | }
27 |
28 | - (void)applicationDidEnterBackground:(UIApplication *)application {
29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
31 | }
32 |
33 | - (void)applicationWillEnterForeground:(UIApplication *)application {
34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
35 | }
36 |
37 | - (void)applicationDidBecomeActive:(UIApplication *)application {
38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39 | }
40 |
41 | - (void)applicationWillTerminate:(UIApplication *)application {
42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
43 | }
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/UnzipAction/UZArchiveViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZArchiveViewController.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZArchiveViewController.h"
10 | #import "UZNodeViewControllerSubclass.h"
11 | #import "UZNode.h"
12 | #import "UZUnzipCoordinator.h"
13 | #import "UIAlertController+UZError.h"
14 |
15 | #import
16 | #import
17 |
18 | static void GetZipURLInItems(NSArray *inputItems, void (^completionHandler)(NSURL *URL, NSError *error))
19 | {
20 | BOOL zipFound = YES;
21 | for (NSExtensionItem *item in inputItems) {
22 | for (NSItemProvider *itemProvider in item.attachments) {
23 | if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeZipArchive]) {
24 | [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeZipArchive options:nil completionHandler:completionHandler];
25 | zipFound = YES;
26 | break;
27 | }
28 | }
29 | if (zipFound) break;
30 | }
31 | }
32 |
33 | @interface UZArchiveViewController ()
34 | @property (nonatomic, strong) ZZArchive *archive;
35 | @end
36 |
37 | @implementation UZArchiveViewController
38 |
39 | #pragma mark - View Controller Lifecycle
40 |
41 | - (void)viewDidLoad
42 | {
43 | [super viewDidLoad];
44 | GetZipURLInItems(self.extensionContext.inputItems, ^(NSURL *URL, NSError *error) {
45 | if (error == nil) {
46 | self.archive = [ZZArchive archiveWithContentsOfURL:URL];
47 | } else {
48 | UIAlertController *alert = [UIAlertController uz_alertControllerWithError:error];
49 | [self presentViewController:alert animated:YES completion:nil];
50 | }
51 | });
52 | }
53 |
54 | #pragma mark - Accessors
55 |
56 | - (void)setArchive:(ZZArchive *)archive
57 | {
58 | if (_archive != archive) {
59 | _archive = archive;
60 |
61 | self.rootNode = [UZNode nodeWithArchive:_archive];
62 | self.unzipCoordinator = [[UZUnzipCoordinator alloc] initWithArchive:_archive];
63 | self.navigationItem.title = _archive.URL.lastPathComponent;
64 | }
65 | }
66 |
67 | @end
68 |
--------------------------------------------------------------------------------
/ACKNOWLEDGEMENTS:
--------------------------------------------------------------------------------
1 | Unzip uses code from the following projects:
2 |
3 | zipzap
4 | Copyright (c) 2012, Pixelglow Software.
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 |
11 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
12 |
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14 |
15 | ===================
16 |
17 | libextobjc
18 | Copyright (c) 2012 - 2014 Justin Spahr-Summers
19 |
20 | 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:
21 |
22 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
23 |
24 | 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.
25 |
--------------------------------------------------------------------------------
/UnzipAction/MainInterface.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/UnzipAction/UZGlyphFactory.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZGlyphFactory.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/16/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZGlyphFactory.h"
10 | #import
11 |
12 | static NSMutableDictionary *_tintedImages = nil;
13 |
14 | static NSString * FileTypeForUTI(CFStringRef UTI)
15 | {
16 | NSString *fileType = nil;
17 | if (UTTypeConformsTo(UTI, kUTTypeArchive)) {
18 | fileType = @"Archive";
19 | } else if (UTTypeConformsTo(UTI, kUTTypeAudio)) {
20 | fileType = @"Audio";
21 | } else if (UTTypeConformsTo(UTI, kUTTypeSourceCode)) {
22 | fileType = @"Code";
23 | } else if (UTTypeConformsTo(UTI, kUTTypeDirectory)) {
24 | fileType = @"Directory";
25 | } else if (UTTypeConformsTo(UTI, kUTTypeFont)) {
26 | fileType = @"Font";
27 | } else if (UTTypeConformsTo(UTI, kUTTypeImage)) {
28 | fileType = @"Image";
29 | } else if (UTTypeConformsTo(UTI, kUTTypePresentation)) {
30 | fileType = @"Presentation";
31 | } else if (UTTypeConformsTo(UTI, kUTTypeSpreadsheet)) {
32 | fileType = @"Spreadsheet";
33 | } else if (UTTypeConformsTo(UTI, kUTTypeVideo)) {
34 | fileType = @"Video";
35 | } else if (UTTypeConformsTo(UTI, kUTTypeXML) || UTTypeConformsTo(UTI, kUTTypeHTML)) {
36 | fileType = @"XML";
37 | } else {
38 | fileType = @"Generic";
39 | }
40 | return fileType;
41 | }
42 |
43 | static UIImage * MaskImageForUTI(CFStringRef UTI)
44 | {
45 | return [UIImage imageNamed:[NSString stringWithFormat:@"FileType%@", FileTypeForUTI(UTI)]];
46 | }
47 |
48 | static UIImage * TintedImageFromMask(UIImage *mask, UIColor *tintColor)
49 | {
50 | UIGraphicsBeginImageContextWithOptions(mask.size, NO, mask.scale);
51 |
52 | CGContextRef ctx = UIGraphicsGetCurrentContext();
53 | const CGRect bounds = (CGRect){ .size = mask.size };
54 |
55 | CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, CGRectGetHeight(bounds));
56 | CGContextConcatCTM(ctx, flipVertical);
57 |
58 | CGContextClipToMask(ctx, bounds, mask.CGImage);
59 | [tintColor set];
60 | UIRectFill(bounds);
61 |
62 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
63 | UIGraphicsEndImageContext();
64 | return image;
65 | }
66 |
67 | static UIColor * SystemDefaultTintColor()
68 | {
69 | static UIColor *tintColor = nil;
70 | static dispatch_once_t onceToken;
71 | dispatch_once(&onceToken, ^{
72 | tintColor = [[[UIView alloc] initWithFrame:CGRectZero] tintColor];
73 | });
74 | return tintColor;
75 | }
76 |
77 | static UIImage * GlyphImageForUTI(CFStringRef UTI)
78 | {
79 | NSCAssert([NSThread isMainThread], @"This function can only be called from the main thread.");
80 |
81 | UIImage *image = _tintedImages[(__bridge NSString *)UTI];
82 | if (image == nil) {
83 | image = TintedImageFromMask(MaskImageForUTI(UTI), SystemDefaultTintColor());
84 | if (_tintedImages == nil) {
85 | _tintedImages = [[NSMutableDictionary alloc] init];
86 | }
87 | _tintedImages[(__bridge NSString *)UTI] = image;
88 | }
89 | return image;
90 | }
91 |
92 | UIImage * UZDirectoryGlyphImage(UIColor *tintColor)
93 | {
94 | return GlyphImageForUTI(kUTTypeDirectory);
95 | }
96 |
97 | UIImage * UZFileGlyphImage(NSString *fileName, UIColor *tintColor)
98 | {
99 | CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileName.pathExtension, NULL);
100 | UIImage *image = GlyphImageForUTI(UTI);
101 | CFRelease(UTI);
102 | return image;
103 | }
104 |
--------------------------------------------------------------------------------
/UnzipAction/UZUnzipOperation.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZUnzipOperation.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZUnzipOperation.h"
10 | #import "UZNode.h"
11 | #import
12 |
13 | NSString * const UZUnzipOperationErrorDomain = @"UZUnzipOperationErrorDomain";
14 | const NSInteger UZUnzipOperationErrorCodeFailedToOpen = 1;
15 | const NSInteger UZUnzipOperationErrorCodeFailedToWrite = 2;
16 |
17 | @interface UZUnzipOperation ()
18 | @property (nonatomic, copy, readwrite) NSString *password;
19 | @property (nonatomic, strong, readonly) NSInputStream *stream;
20 | @property (nonatomic, strong, readonly) NSURL *temporaryDirectoryURL;
21 | @property (nonatomic, strong, readwrite) NSError *error;
22 | @property (nonatomic, strong, readwrite) NSURL *fileURL;
23 | @end
24 |
25 | @implementation UZUnzipOperation
26 |
27 | - (instancetype)initWithNode:(UZNode *)node
28 | password:(NSString *)password
29 | temporaryDirectoryURL:(NSURL *)temporaryDirectoryURL
30 | {
31 | NSParameterAssert(node);
32 | NSParameterAssert(temporaryDirectoryURL);
33 |
34 | if ((self = [super init])) {
35 | _node = node;
36 | _password = [password copy];
37 | _temporaryDirectoryURL = temporaryDirectoryURL;
38 |
39 | NSError *error = nil;
40 | NSInputStream *stream = [self.node streamWithPassword:_password error:&error];
41 | if (stream == nil) {
42 | self.error = error;
43 | } else {
44 | _stream = stream;
45 | }
46 | }
47 | return self;
48 | }
49 |
50 | - (void)main
51 | {
52 | if (self.error != nil) return;
53 |
54 | @autoreleasepool {
55 | NSURL *subdirectoryURL = [self.temporaryDirectoryURL URLByAppendingPathComponent:[[NSUUID UUID] UUIDString] isDirectory:YES];
56 | NSURL *fileURL = [subdirectoryURL URLByAppendingPathComponent:self.node.fileName isDirectory:NO];
57 |
58 | NSFileManager *fm = [[NSFileManager alloc] init];
59 | NSError *error = nil;
60 | if (![fm createDirectoryAtURL:subdirectoryURL withIntermediateDirectories:YES attributes:nil error:&error]) {
61 | self.error = error;
62 | return;
63 | }
64 |
65 | FILE *fd = fopen(fileURL.path.UTF8String, "w");
66 | @onExit {
67 | fclose(fd);
68 | };
69 |
70 | if (fd == NULL) {
71 | self.error = [NSError errorWithDomain:UZUnzipOperationErrorDomain code:UZUnzipOperationErrorCodeFailedToOpen userInfo:nil];
72 | return;
73 | }
74 |
75 | [self.stream open];
76 | @onExit {
77 | [self.stream close];
78 | };
79 |
80 | NSUInteger totalBytesRead = 0;
81 | const NSUInteger totalSize = self.node.uncompressedSize;
82 |
83 | while (totalBytesRead < totalSize && !self.cancelled) {
84 | const NSUInteger remainingBytes = totalSize - totalBytesRead;
85 | uint8_t *bytes = malloc(sizeof(uint8_t) * remainingBytes);
86 | @onExit {
87 | free(bytes);
88 | };
89 |
90 | NSInteger bytesRead = [self.stream read:bytes maxLength:remainingBytes];
91 |
92 | if (bytesRead > 0) {
93 | if (fwrite(bytes, sizeof(uint8_t), bytesRead, fd) == bytesRead) {
94 | totalBytesRead += bytesRead;
95 |
96 | if (self.progressHandler != nil) {
97 | self.progressHandler((float)totalBytesRead / totalSize);
98 | }
99 | } else {
100 | self.error = [NSError errorWithDomain:UZUnzipOperationErrorDomain code:UZUnzipOperationErrorCodeFailedToWrite userInfo:nil];
101 | break;
102 | }
103 | } else {
104 | self.error = self.stream.streamError;
105 | break;
106 | }
107 | }
108 |
109 | if (self.error == nil && !self.cancelled) {
110 | self.fileURL = fileURL;
111 | } else {
112 | [fm removeItemAtURL:fileURL error:nil];
113 | }
114 | }
115 | }
116 |
117 | @end
118 |
--------------------------------------------------------------------------------
/UnzipAction/UZPreviewPageViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZPreviewPageViewController.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/8/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZPreviewPageViewController.h"
10 | #import "UZPreviewViewController.h"
11 | #import "UZNode.h"
12 | #import
13 |
14 | static void * kUZPreviewIndexKey = &kUZPreviewIndexKey;
15 |
16 | @interface UZPreviewViewController (UZIndexing)
17 | @property (nonatomic, assign) NSUInteger uz_index;
18 | @end
19 |
20 | @implementation UZPreviewViewController (UZIndexing)
21 |
22 | - (NSUInteger)uz_index
23 | {
24 | return [objc_getAssociatedObject(self, kUZPreviewIndexKey) unsignedIntegerValue];
25 | }
26 |
27 | - (void)setUz_index:(NSUInteger)uz_index
28 | {
29 | objc_setAssociatedObject(self, kUZPreviewIndexKey, @(uz_index), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
30 | }
31 |
32 | @end
33 |
34 | @interface UZPreviewPageViewController ()
35 | @property (nonatomic, strong, readonly) NSExtensionContext *uz_extensionContext;
36 | @property (nonatomic, strong, readwrite) UZUnzipCoordinator *unzipCoordinator;
37 | @property (nonatomic, strong, readonly) NSArray *unencryptedChildren;
38 | @property (nonatomic, assign) NSUInteger startingIndex;
39 | @end
40 |
41 | @implementation UZPreviewPageViewController
42 | @synthesize uz_extensionContext = _uz_extensionContext;
43 |
44 | #pragma mark - Lifecycle
45 |
46 | - (instancetype)initWithRootNode:(UZNode *)rootNode
47 | startingChildNode:(UZNode *)startingChildNode
48 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
49 | extensionContext:(NSExtensionContext *)extensionContext
50 | {
51 | if ((self = [super initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil])) {
52 | self.dataSource = self;
53 | self.delegate = self;
54 |
55 | _uz_extensionContext = extensionContext;
56 | _unzipCoordinator = unzipCoordinator;
57 | _unencryptedChildren = [rootNode.children filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(UZNode *child, NSDictionary *bindings) {
58 | return !child.encrypted;
59 | }]];
60 | _startingIndex = [_unencryptedChildren indexOfObject:startingChildNode];
61 |
62 | UZPreviewViewController *viewController = [self previewViewControllerForNodeAtIndex:_startingIndex];
63 | [self setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
64 | }
65 | return self;
66 | }
67 |
68 | - (void)viewDidLoad
69 | {
70 | [super viewDidLoad];
71 | if (self.uz_extensionContext != nil) {
72 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Close", nil) style:UIBarButtonItemStylePlain target:self action:@selector(close)];
73 | }
74 | }
75 |
76 | #pragma mark - UIPageViewControllerDataSource
77 |
78 | - (UZPreviewViewController *)previewViewControllerForNodeAtIndex:(NSUInteger)index
79 | {
80 | UZPreviewViewController *viewController = [[UZPreviewViewController alloc] initWithNode:self.unencryptedChildren[index] password:nil unzipCoordinator:self.unzipCoordinator extensionContext:self.uz_extensionContext];
81 | viewController.uz_index = index;
82 | return viewController;
83 | }
84 |
85 | - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UZPreviewViewController *)viewController
86 | {
87 | return [self previewViewControllerForNodeAtIndex:viewController.uz_index - 1];
88 | }
89 |
90 | - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UZPreviewViewController *)viewController
91 | {
92 | return [self previewViewControllerForNodeAtIndex:viewController.uz_index + 1];
93 | }
94 |
95 | #pragma mark - Extension Context
96 |
97 | - (NSExtensionContext *)uz_extensionContext
98 | {
99 | return self.extensionContext ?: _uz_extensionContext;
100 | }
101 |
102 | + (NSSet *)keyPathsForValuesAffectingUz_extensionContext
103 | {
104 | return [NSSet setWithObject:@"extensionContext"];
105 | }
106 |
107 | - (void)close
108 | {
109 | [self.uz_extensionContext completeRequestReturningItems:self.uz_extensionContext.inputItems completionHandler:nil];
110 | }
111 |
112 | @end
113 |
--------------------------------------------------------------------------------
/Unzip.xcodeproj/xcuserdata/Karunaratne.xcuserdatad/xcschemes/Unzip.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
94 |
100 |
101 |
102 |
103 |
105 |
106 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/UnzipAction/UZNode.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZNode.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZNode.h"
10 |
11 | #import
12 |
13 | @interface UZNodeEntryContainer : NSObject
14 | @property (nonatomic, strong) ZZArchiveEntry *entry;
15 | @property (nonatomic, strong, readonly) NSMutableArray *mutableChildren;
16 | @end
17 |
18 | @implementation UZNodeEntryContainer
19 |
20 | - (instancetype)initWithEntry:(ZZArchiveEntry *)entry
21 | {
22 | if ((self = [super init])) {
23 | _entry = entry;
24 | _mutableChildren = [[NSMutableArray alloc] init];
25 | }
26 | return self;
27 | }
28 |
29 | @end
30 |
31 | @interface UZNode ()
32 | - (instancetype)initWithEntry:(ZZArchiveEntry *)entry level:(NSUInteger)level children:(NSArray *)children;
33 | @property (nonatomic, strong, readonly) ZZArchiveEntry *archiveEntry;
34 | @end
35 |
36 | static BOOL EntryIsDirectory(ZZArchiveEntry *entry)
37 | {
38 | return (entry.uncompressedSize == 0) && !entry.compressed;
39 | }
40 |
41 | static NSArray * IgnoredFilenames()
42 | {
43 | static NSArray *filenames = nil;
44 | static dispatch_once_t onceToken;
45 | dispatch_once(&onceToken, ^{
46 | filenames = @[@"__MACOSX",
47 | @".DS_Store"];
48 | });
49 | return filenames;
50 | }
51 |
52 | static UZNode * NodeForEntries(NSArray *entries, ZZArchiveEntry *parent, NSUInteger level)
53 | {
54 | NSArray *ignoredFilenames = IgnoredFilenames();
55 | NSMutableDictionary *nameToEntryContainerMapping = [[NSMutableDictionary alloc] init];
56 | NSMutableArray *containers = [[NSMutableArray alloc] init];
57 |
58 | for (ZZArchiveEntry *entry in entries) {
59 | NSArray *components = entry.fileName.pathComponents;
60 | if (components.count == 0) continue;
61 |
62 | NSString *fileName = components[level];
63 | if ([ignoredFilenames containsObject:fileName]) continue;
64 |
65 | UZNodeEntryContainer *container = nameToEntryContainerMapping[fileName];
66 | if (container == nil) {
67 | container = [[UZNodeEntryContainer alloc] initWithEntry:entry];
68 | nameToEntryContainerMapping[fileName] = container;
69 | [containers addObject:container];
70 | } else {
71 | [container.mutableChildren addObject:entry];
72 | }
73 | }
74 |
75 | NSMutableArray *children = [[NSMutableArray alloc] init];
76 | for (UZNodeEntryContainer *container in containers) {
77 | UZNode *node = NodeForEntries(container.mutableChildren, container.entry, level + 1);
78 | [children addObject:node];
79 | }
80 |
81 | return [[UZNode alloc] initWithEntry:parent level:level children:children];
82 | }
83 |
84 | static NSString * IndentationString(NSUInteger level)
85 | {
86 | NSMutableString *string = [[NSMutableString alloc] init];
87 | for (NSInteger i = 0; i < level; i++) {
88 | [string appendString:@"----"];
89 | }
90 | return string;
91 | }
92 |
93 | static void PrintPrettyHierarchicalRepresentation(UZNode *node, NSMutableString *string, NSUInteger level)
94 | {
95 | if (node.fileName.length != 0) {
96 | [string appendString:IndentationString(level)];
97 | [string appendFormat:@" %@\n", node.fileName];
98 | }
99 |
100 | for (UZNode *child in node.children) {
101 | PrintPrettyHierarchicalRepresentation(child, string, level + 1);
102 | }
103 | }
104 |
105 | @implementation UZNode
106 |
107 | - (instancetype)initWithEntry:(ZZArchiveEntry *)entry level:(NSUInteger)level children:(NSArray *)children
108 | {
109 | if ((self = [super init])) {
110 | _directory = EntryIsDirectory(entry);
111 | _encrypted = entry.encrypted;
112 | _uncompressedSize = entry.uncompressedSize;
113 | if (level >= 1) {
114 | _fileName = entry.fileName.pathComponents[level - 1];
115 | }
116 | _children = children;
117 | _archiveEntry = entry;
118 | }
119 | return self;
120 | }
121 |
122 | + (instancetype)nodeWithArchive:(ZZArchive *)archive
123 | {
124 | return NodeForEntries(archive.entries, nil, 0);
125 | }
126 |
127 | - (NSInputStream *)streamWithPassword:(NSString *)password error:(NSError **)error
128 | {
129 | return [self.archiveEntry newStreamWithPassword:password error:error];
130 | }
131 |
132 | #pragma mark - NSObject
133 |
134 | - (NSString *)description
135 | {
136 | NSMutableString *description = [[NSMutableString alloc] init];
137 | PrintPrettyHierarchicalRepresentation(self, description, 0);
138 | return description;
139 | }
140 |
141 | @end
142 |
--------------------------------------------------------------------------------
/UnzipAction/UZNodeTableViewCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
28 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/UnzipAction/UZPreviewViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZPreviewViewController.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZPreviewViewController.h"
10 | #import "UZNode.h"
11 | #import "UZUnzipCoordinator.h"
12 | #import "UZOpenInActivity.h"
13 |
14 | #import
15 |
16 | @interface UZQuickLookPreviewItem : NSObject
17 | @property (nonatomic, strong, readonly) NSURL *fileURL;
18 | @end
19 |
20 | @interface UZPreviewViewController ()
21 | @property (nonatomic, copy, readonly) NSString *password;
22 | @property (nonatomic, strong, readonly) UZNode *node;
23 | @property (nonatomic, strong, readonly) UZUnzipCoordinator *unzipCoordinator;
24 | @property (nonatomic, strong) UZUnzipOperationToken *unzipToken;
25 | @property (nonatomic, strong) UZQuickLookPreviewItem *previewItem;
26 | @property (nonatomic, strong) QLPreviewController *previewController;
27 |
28 | @property (nonatomic, weak) IBOutlet UIView *containerView;
29 | @property (nonatomic, weak) IBOutlet UILabel *progressLabel;
30 | @property (nonatomic, weak) IBOutlet UIProgressView *progressView;
31 | @end
32 |
33 | @implementation UZQuickLookPreviewItem
34 |
35 | - (instancetype)initWithFileURL:(NSURL *)fileURL
36 | {
37 | if ((self = [super init])) {
38 | _fileURL = fileURL;
39 | }
40 | return self;
41 | }
42 |
43 | #pragma mark - QLPreviewItem
44 |
45 | - (NSURL *)previewItemURL
46 | {
47 | return self.fileURL;
48 | }
49 |
50 | @end
51 |
52 | @implementation UZPreviewViewController
53 |
54 | #pragma mark - Lifecycle
55 |
56 | - (instancetype)initWithNode:(UZNode *)node
57 | password:(NSString *)password
58 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
59 | extensionContext:(NSExtensionContext *)extensionContext
60 | {
61 | if ((self = [super initWithExtensionContext:extensionContext])) {
62 | _node = node;
63 | _password = [password copy];
64 | _unzipCoordinator = unzipCoordinator;
65 |
66 | self.navigationItem.title = node.fileName;
67 | }
68 | return self;
69 | }
70 |
71 | - (void)viewDidLoad
72 | {
73 | [super viewDidLoad];
74 | self.progressLabel.text = self.node.fileName;
75 | }
76 |
77 | - (void)viewWillAppear:(BOOL)animated
78 | {
79 | [super viewWillAppear:animated];
80 | if (self.previewController != nil) return;
81 |
82 | self.unzipToken = [self.unzipCoordinator unzipNode:self.node password:self.password progressHandler:^(float progress) {
83 | dispatch_async(dispatch_get_main_queue(), ^{
84 | self.progressView.progress = progress;
85 | });
86 | } completionHandler:^(NSURL *fileURL, NSError *error) {
87 | dispatch_async(dispatch_get_main_queue(), ^{
88 | if (error == nil) {
89 | [self showQuickLookPreviewWithURL:fileURL];
90 | } else {
91 | NSLog(@"%@", error);
92 | }
93 | });
94 | }];
95 | }
96 |
97 | - (void)viewDidDisappear:(BOOL)animated
98 | {
99 | [super viewDidDisappear:animated];
100 | [self.unzipCoordinator cancelUnzipOperationWithToken:self.unzipToken];
101 | self.unzipToken = nil;
102 | }
103 |
104 | - (void)showQuickLookPreviewWithURL:(NSURL *)fileURL
105 | {
106 | self.previewItem = [[UZQuickLookPreviewItem alloc] initWithFileURL:fileURL];
107 | self.previewController = [[QLPreviewController alloc] init];
108 | self.previewController.dataSource = self;
109 | [self.previewController reloadData];
110 | }
111 |
112 | #pragma mark - Actions
113 |
114 | - (IBAction)performAction:(id)sender
115 | {
116 | if (self.previewItem == nil) return;
117 |
118 | UZOpenInActivity *openInActivity = [[UZOpenInActivity alloc] initWithBarButtonItem:sender];
119 | UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[self.previewItem.fileURL] applicationActivities:@[openInActivity]];
120 | [self presentViewController:activityViewController animated:YES completion:nil];
121 | }
122 |
123 | #pragma mark - Accessors
124 |
125 | - (void)setPreviewController:(QLPreviewController *)previewController
126 | {
127 | if (_previewController != previewController) {
128 | [_previewController willMoveToParentViewController:nil];
129 | [_previewController.view removeFromSuperview];
130 | [_previewController removeFromParentViewController];
131 |
132 | _previewController = previewController;
133 |
134 | UIView *previewView = _previewController.view;
135 | previewView.translatesAutoresizingMaskIntoConstraints = NO;
136 |
137 | [self addChildViewController:_previewController];
138 |
139 | [self.containerView addSubview:previewView];
140 | NSDictionary *views = NSDictionaryOfVariableBindings(previewView);
141 | [self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[previewView]|" options:0 metrics:nil views:views]];
142 | [self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[previewView]|" options:0 metrics:nil views:views]];
143 |
144 | [_previewController didMoveToParentViewController:self];
145 | }
146 | }
147 |
148 | #pragma mark - QLPreviewControllerDataSource
149 |
150 | - (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller
151 | {
152 | return 1;
153 | }
154 |
155 | - (id)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
156 | {
157 | return self.previewItem;
158 | }
159 |
160 | @end
161 |
--------------------------------------------------------------------------------
/UnzipAction/UZPreviewViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/UnzipAction/UZUnzipCoordinator.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZUnzipCoordinator.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/6/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZUnzipCoordinator.h"
10 | #import "UZUnzipOperation.h"
11 | #import "UZNode.h"
12 |
13 | @interface UZUnzipCoordinator ()
14 | @property (nonatomic, strong, readonly) ZZArchive *archive;
15 | @property (nonatomic, strong, readonly) NSURL *temporaryDirectoryURL;
16 | @property (nonatomic, strong, readonly) NSMutableDictionary *unarchivedURLs;
17 | @property (nonatomic, strong, readonly) NSMutableDictionary *operationSubscribers;
18 | @property (nonatomic, strong, readonly) NSMutableSet *nodesForInProgressOperations;
19 | @property (nonatomic, strong, readonly) NSOperationQueue *operationQueue;
20 | @property (nonatomic, readonly) dispatch_queue_t stateQueue;
21 | @end
22 |
23 | @interface UZUnzipOperationSubscriber : NSObject
24 | @property (nonatomic, copy, readonly) void (^progressHandler)(float);
25 | @property (nonatomic, copy, readonly) void (^completionHandler)(NSURL *, NSError *);
26 | @end
27 |
28 | @implementation UZUnzipOperationSubscriber
29 |
30 | - (instancetype)initWithProgressHandler:(void (^)(float progress))progressHandler completionHandler:(void (^)(NSURL *fileURL, NSError *error))completionHandler
31 | {
32 | if ((self = [super init])) {
33 | _progressHandler = [progressHandler copy];
34 | _completionHandler = [completionHandler copy];
35 | }
36 | return self;
37 | }
38 |
39 | @end
40 |
41 | @interface UZUnzipOperationToken ()
42 | @property (nonatomic, strong, readonly) UZNode *node;
43 | @property (nonatomic, strong, readonly) UZUnzipOperationSubscriber *subscriber;
44 | @end
45 |
46 | @implementation UZUnzipOperationToken
47 |
48 | - (instancetype)initWithNode:(UZNode *)node subscriber:(UZUnzipOperationSubscriber *)subscriber
49 | {
50 | if ((self = [super init])) {
51 | _node = node;
52 | _subscriber = subscriber;
53 | }
54 | return self;
55 | }
56 |
57 | @end
58 |
59 | @implementation UZUnzipCoordinator
60 |
61 | - (instancetype)initWithArchive:(ZZArchive *)archive
62 | {
63 | if ((self = [super init])) {
64 | _archive = archive;
65 | _temporaryDirectoryURL = [[NSURL fileURLWithPath:NSTemporaryDirectory() isDirectory:YES] URLByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
66 | _unarchivedURLs = [[NSMutableDictionary alloc] init];
67 | _operationSubscribers = [[NSMutableDictionary alloc] init];
68 | _nodesForInProgressOperations = [[NSMutableSet alloc] init];
69 | _operationQueue = [[NSOperationQueue alloc] init];
70 | _stateQueue = dispatch_queue_create("com.indragie.UZUnzipCoordinator.StateQueue", DISPATCH_QUEUE_CONCURRENT);
71 | }
72 | return self;
73 | }
74 |
75 | - (void)dealloc
76 | {
77 | [[NSFileManager defaultManager] removeItemAtURL:_temporaryDirectoryURL error:nil];
78 | }
79 |
80 | - (UZUnzipOperationToken *)unzipNode:(UZNode *)node
81 | password:(NSString *)password
82 | progressHandler:(void (^)(float progress))progressHandler
83 | completionHandler:(void (^)(NSURL *fileURL, NSError *error))completionHandler
84 | {
85 | NSURL *fileURL = [self fileURLForNode:node];
86 | if (fileURL != nil) {
87 | if (completionHandler) {
88 | completionHandler(fileURL, nil);
89 | }
90 | return nil;
91 | }
92 |
93 | UZUnzipOperationSubscriber *subscriber = [[UZUnzipOperationSubscriber alloc] initWithProgressHandler:progressHandler completionHandler:completionHandler];
94 | [self addSubscriber:subscriber forNode:node];
95 |
96 | UZUnzipOperationToken *token = [[UZUnzipOperationToken alloc] initWithNode:node subscriber:subscriber];
97 | if ([self isOperationInProgressForNode:node]) return token;
98 |
99 | UZUnzipOperation *operation = [[UZUnzipOperation alloc] initWithNode:node password:password temporaryDirectoryURL:self.temporaryDirectoryURL];
100 |
101 | operation.progressHandler = ^(float progress) {
102 | NSArray *subscribers = [self subscribersForNode:node];
103 | for (UZUnzipOperationSubscriber *subscriber in subscribers) {
104 | if (subscriber.progressHandler) {
105 | subscriber.progressHandler(progress);
106 | }
107 | }
108 | };
109 |
110 | __weak UZUnzipOperation *weakOperation = operation;
111 | operation.completionBlock = ^{
112 | NSArray *subscribers = [self subscribersForNode:node];
113 | for (UZUnzipOperationSubscriber *subscriber in subscribers) {
114 | if (subscriber.completionHandler) {
115 | subscriber.completionHandler(weakOperation.fileURL, weakOperation.error);
116 | }
117 | }
118 | [self setFileURL:weakOperation.fileURL forNode:node];
119 | [self setOperationInProgress:NO forNode:node];
120 | };
121 |
122 | [self.operationQueue addOperation:operation];
123 | [self setOperationInProgress:YES forNode:node];
124 |
125 | return token;
126 | }
127 |
128 | - (void)cancelUnzipOperationWithToken:(UZUnzipOperationToken *)token
129 | {
130 | if (token == nil) return;
131 |
132 | [self removeSubscriber:token.subscriber forNode:token.node];
133 | if ([self subscribersForNode:token.node].count == 0) {
134 | for (UZUnzipOperation *operation in self.operationQueue.operations) {
135 | if ([operation.node isEqual:token.node]) {
136 | [operation cancel];
137 | }
138 | }
139 | }
140 | }
141 |
142 | #pragma mark - Private
143 |
144 | - (void)setFileURL:(NSURL *)URL forNode:(UZNode *)node
145 | {
146 | dispatch_barrier_async(self.stateQueue, ^{
147 | self.unarchivedURLs[node.fileName] = URL;
148 | });
149 | }
150 |
151 | - (NSURL *)fileURLForNode:(UZNode *)node
152 | {
153 | __block NSURL *URL = nil;
154 | dispatch_sync(self.stateQueue, ^{
155 | URL = self.unarchivedURLs[node.fileName];
156 | });
157 | return URL;
158 | }
159 |
160 | - (void)addSubscriber:(UZUnzipOperationSubscriber *)subscriber forNode:(UZNode *)node
161 | {
162 | dispatch_barrier_async(self.stateQueue, ^{
163 | NSMutableArray *subscribers = self.operationSubscribers[node.fileName];
164 | if (subscribers == nil) {
165 | subscribers = [[NSMutableArray alloc] init];
166 | self.operationSubscribers[node.fileName] = subscribers;
167 | }
168 | [subscribers addObject:subscriber];
169 | });
170 | }
171 |
172 | - (NSArray *)subscribersForNode:(UZNode *)node
173 | {
174 | __block NSArray *subscribers = nil;
175 | dispatch_sync(self.stateQueue, ^{
176 | subscribers = self.operationSubscribers[node.fileName];
177 | });
178 | return subscribers ?: @[];
179 | }
180 |
181 | - (void)removeAllSubscribersForNode:(UZNode *)node
182 | {
183 | dispatch_barrier_async(self.stateQueue, ^{
184 | [self.operationSubscribers removeObjectForKey:node.fileName];
185 | });
186 | }
187 |
188 | - (void)removeSubscriber:(UZUnzipOperationSubscriber *)subscriber forNode:(UZNode *)node
189 | {
190 | dispatch_barrier_async(self.stateQueue, ^{
191 | NSMutableArray *subscribers = self.operationSubscribers[node.fileName];
192 | [subscribers removeObject:subscriber];
193 | });
194 | }
195 |
196 | - (void)setOperationInProgress:(BOOL)operationInProgress forNode:(UZNode *)node
197 | {
198 | dispatch_barrier_async(self.stateQueue, ^{
199 | if (operationInProgress) {
200 | [self.nodesForInProgressOperations addObject:node];
201 | } else {
202 | [self.nodesForInProgressOperations removeObject:node];
203 | }
204 | });
205 | }
206 |
207 | - (BOOL)isOperationInProgressForNode:(UZNode *)node
208 | {
209 | __block BOOL operationInProgress = NO;
210 | dispatch_sync(self.stateQueue, ^{
211 | operationInProgress = [self.nodesForInProgressOperations containsObject:node];
212 | });
213 | return operationInProgress;
214 | }
215 |
216 | @end
217 |
--------------------------------------------------------------------------------
/UnzipAction/UZNodeViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // UZNodeViewController.m
3 | // Unzip
4 | //
5 | // Created by Indragie on 8/5/14.
6 | // Copyright (c) 2014 Indragie Karunaratne. All rights reserved.
7 | //
8 |
9 | #import "UZNodeViewController.h"
10 | #import "UZNodeViewControllerSubclass.h"
11 | #import "UZNodeTableViewCell.h"
12 | #import "UZPreviewViewController.h"
13 | #import "UZNode.h"
14 | #import "UZUnzipCoordinator.h"
15 | #import "UZGlyphFactory.h"
16 |
17 | const CGFloat kSearchBarHeight = 44.0;
18 |
19 | @interface UZNodeViewController ()
20 | @property (nonatomic, strong) NSArray *sections;
21 | @property (nonatomic, strong, readonly) UILocalizedIndexedCollation *collation;
22 | @property (nonatomic, strong, readonly) NSByteCountFormatter *byteCountFormatter;
23 |
24 | @property (nonatomic, weak, readonly) UZNodeViewController *parentNodeViewController;
25 | @property (nonatomic, strong) UISearchController *searchController;
26 | @property (nonatomic, assign, readonly, getter=isSearchResultsController) BOOL searchResultsController;
27 | @property (nonatomic, assign, readonly, getter=isSearching) BOOL searching;
28 | @property (nonatomic, strong) NSString *previousSearchQuery;
29 | @property (nonatomic, strong) NSArray *filteredResults;
30 | @end
31 |
32 | static NSArray * SectionsForNode(NSArray *children, UILocalizedIndexedCollation *collation)
33 | {
34 | NSMutableArray *sections = [[NSMutableArray alloc] init];
35 | const SEL stringSelector = @selector(fileName);
36 | const NSUInteger titleCount = collation.sectionIndexTitles.count;
37 |
38 | for (NSUInteger i = 0; i < titleCount; i++) {
39 | [sections addObject:[[NSMutableArray alloc] init]];
40 | }
41 |
42 | for (UZNode *child in children) {
43 | NSInteger sectionIndex = [collation sectionForObject:child collationStringSelector:stringSelector];
44 | [sections[sectionIndex] addObject:child];
45 | }
46 |
47 | for (NSUInteger i = 0; i < titleCount; i++) {
48 | NSArray *sortedChildren = [collation sortedArrayFromArray:sections[i] collationStringSelector:stringSelector];
49 | [sections replaceObjectAtIndex:i withObject:sortedChildren];
50 | }
51 |
52 | return sections;
53 | }
54 |
55 | static NSPredicate * FilterPredicate(NSString *searchQuery)
56 | {
57 | return [NSPredicate predicateWithBlock:^BOOL(UZNode *node, NSDictionary *bindings) {
58 | NSRange range = [node.fileName rangeOfString:searchQuery options:NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch];
59 | return (range.location != NSNotFound);
60 | }];
61 | }
62 |
63 | static NSArray * FilteredChildren(NSArray *children, NSString *searchQuery)
64 | {
65 | return [children filteredArrayUsingPredicate:FilterPredicate(searchQuery)];
66 | }
67 |
68 | @implementation UZNodeViewController
69 |
70 | - (instancetype)initWithRootNode:(UZNode *)rootNode
71 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
72 | extensionContext:(NSExtensionContext *)extensionContext
73 | {
74 | return [self initWithRootNode:rootNode unzipCoordinator:unzipCoordinator extensionContext:extensionContext parentNodeViewController:nil];
75 | }
76 |
77 | - (instancetype)initWithRootNode:(UZNode *)rootNode
78 | unzipCoordinator:(UZUnzipCoordinator *)unzipCoordinator
79 | extensionContext:(NSExtensionContext *)extensionContext
80 | parentNodeViewController:(UZNodeViewController *)parentNodeViewController
81 | {
82 | if ((self = [self initWithStyle:UITableViewStylePlain extensionContext:extensionContext parentNodeViewController:parentNodeViewController])) {
83 | self.unzipCoordinator = unzipCoordinator;
84 | self.rootNode = rootNode;
85 | }
86 | return self;
87 | }
88 |
89 | - (instancetype)initWithStyle:(UITableViewStyle)style
90 | extensionContext:(NSExtensionContext *)extensionContext
91 | parentNodeViewController:(UZNodeViewController *)parentNodeViewController
92 | {
93 | if ((self = [super initWithStyle:style extensionContext:extensionContext])) {
94 | _parentNodeViewController = parentNodeViewController;
95 | [self commonInit_UZNodeViewController];
96 | }
97 | return self;
98 | }
99 |
100 | - (instancetype)initWithCoder:(NSCoder *)aDecoder
101 | {
102 | if ((self = [super initWithCoder:aDecoder])) {
103 | [self commonInit_UZNodeViewController];
104 | }
105 | return self;
106 | }
107 |
108 | - (void)commonInit_UZNodeViewController
109 | {
110 | _collation = UILocalizedIndexedCollation.currentCollation;
111 | _byteCountFormatter = [[NSByteCountFormatter alloc] init];
112 | self.definesPresentationContext = YES;
113 | }
114 |
115 | - (void)viewDidLoad
116 | {
117 | [super viewDidLoad];
118 |
119 | UIView *backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
120 | backgroundView.backgroundColor = UIColor.whiteColor;
121 | self.tableView.backgroundView = backgroundView;
122 |
123 | UINib *nib = [UINib nibWithNibName:NSStringFromClass(UZNodeTableViewCell.class) bundle:nil];
124 | [self.tableView registerNib:nib forCellReuseIdentifier:UZNodeTableViewCell.reuseIdentifier];
125 | self.tableView.rowHeight = UZNodeTableViewCell.rowHeight;
126 |
127 | [self configureAndDisplaySearchBar];
128 | }
129 |
130 | - (void)viewWillAppear:(BOOL)animated
131 | {
132 | [super viewWillAppear:animated];
133 |
134 | if (self.searchController != nil) {
135 | self.tableView.contentOffset = (CGPoint){ .y = kSearchBarHeight };
136 | }
137 | }
138 |
139 | #pragma mark - Accessors
140 |
141 | - (void)setRootNode:(UZNode *)rootNode
142 | {
143 | if (_rootNode != rootNode) {
144 | self.searchController = nil;
145 |
146 | _rootNode = rootNode;
147 |
148 | if (![self isSearchResultsController]) {
149 | [self createSearchController];
150 | }
151 |
152 | self.navigationItem.title = _rootNode.fileName;
153 | [self rebuildSections];
154 | }
155 | }
156 |
157 | - (void)setSearchQuery:(NSString *)searchQuery
158 | {
159 | if (_searchQuery != searchQuery) {
160 | if (searchQuery.length) {
161 | self.previousSearchQuery = _searchQuery;
162 | } else {
163 | self.previousSearchQuery = nil;
164 | }
165 |
166 | _searchQuery = searchQuery;
167 | [self rebuildSections];
168 | }
169 | }
170 |
171 | - (BOOL)isSearching
172 | {
173 | return (self.searchQuery.length != 0);
174 | }
175 |
176 | + (NSSet *)keyPathsForValuesAffectingSearching
177 | {
178 | return [NSSet setWithObject:@"searchQuery"];
179 | }
180 |
181 | - (BOOL)isSearchResultsController
182 | {
183 | return (self.parentNodeViewController != nil);
184 | }
185 |
186 | + (NSSet *)keyPathsForValuesAffectingSearchResultsController
187 | {
188 | return [NSSet setWithObject:@"parentNodeViewController"];
189 | }
190 |
191 | #pragma mark - UITableViewDataSource
192 |
193 | - (UZNode *)nodeAtIndexPath:(NSIndexPath *)indexPath
194 | {
195 | NSArray *children = self.sections[indexPath.section];
196 | return children[indexPath.row];
197 | }
198 |
199 | - (void)rebuildSections
200 | {
201 | NSArray *children = nil;
202 | if (self.searching) {
203 | if (self.previousSearchQuery != nil && [self.searchQuery hasPrefix:self.previousSearchQuery]) {
204 | children = FilteredChildren(self.filteredResults, self.searchQuery);
205 | } else {
206 | children = FilteredChildren(self.rootNode.children, self.searchQuery);
207 | self.filteredResults = children;
208 | }
209 | } else {
210 | children = self.rootNode.children;
211 | self.filteredResults = nil;
212 | }
213 |
214 | self.sections = SectionsForNode(children, self.collation);
215 | [self.tableView reloadData];
216 | }
217 |
218 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
219 | {
220 | return self.sections.count;
221 | }
222 |
223 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
224 | {
225 | return [self.sections[section] count];
226 | }
227 |
228 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
229 | {
230 | if ([self.sections[section] count] != 0) {
231 | return self.collation.sectionTitles[section];
232 | }
233 | return nil;
234 | }
235 |
236 | - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
237 | {
238 | return self.collation.sectionIndexTitles;
239 | }
240 |
241 | - (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
242 | {
243 | return [self.collation sectionForSectionIndexTitleAtIndex:index];
244 | }
245 |
246 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
247 | {
248 | UZNodeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:UZNodeTableViewCell.reuseIdentifier];
249 | UZNode *node = [self nodeAtIndexPath:indexPath];
250 |
251 | cell.fileNameLabel.text = node.fileName;
252 | if (node.directory) {
253 | cell.fileNameLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
254 | cell.fileSizeLabel.text = nil;
255 | cell.glyphImageView.image = UZDirectoryGlyphImage(nil);
256 | } else {
257 | cell.fileNameLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
258 | cell.fileSizeLabel.text = [self.byteCountFormatter stringFromByteCount:node.uncompressedSize];
259 | cell.glyphImageView.image = UZFileGlyphImage(node.fileName, UIColor.blueColor);
260 | }
261 |
262 | return cell;
263 | }
264 |
265 | #pragma mark - UITableViewDelegate
266 |
267 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
268 | {
269 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
270 |
271 | UZNode *node = [self nodeAtIndexPath:indexPath];
272 | if (node.directory) {
273 | UZNodeViewController *viewController = [[self.class alloc] initWithRootNode:node unzipCoordinator:self.unzipCoordinator extensionContext:self.uz_extensionContext];
274 | [self pushViewController:viewController animated:YES];
275 | } else if (node.encrypted) {
276 | [self presentPasswordAlertForNode:node completionHandler:^(NSString *password) {
277 | if (password != nil) {
278 | [self pushPreviewControllerWithNode:node password:password];
279 | }
280 | }];
281 | } else {
282 | [self pushPreviewControllerWithNode:node password:nil];
283 | }
284 | }
285 |
286 | - (void)pushPreviewControllerWithNode:(UZNode *)node password:(NSString *)password
287 | {
288 | UZPreviewViewController *viewController = [[UZPreviewViewController alloc] initWithNode:node password:password unzipCoordinator:self.unzipCoordinator extensionContext:self.uz_extensionContext];
289 | [self pushViewController:viewController animated:YES];
290 | }
291 |
292 | - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
293 | {
294 | UINavigationController *navigationController = self.navigationController ?: self.parentNodeViewController.navigationController;
295 | [navigationController pushViewController:viewController animated:animated];
296 | }
297 |
298 | #pragma mark - Search
299 |
300 | - (void)createSearchController
301 | {
302 | UZNodeViewController *searchResultsController = [[UZNodeViewController alloc] initWithRootNode:_rootNode unzipCoordinator:self.unzipCoordinator extensionContext:nil parentNodeViewController:self];
303 | self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
304 | self.searchController.searchResultsUpdater = searchResultsController;
305 | [self configureAndDisplaySearchBar];
306 | }
307 |
308 | - (void)configureAndDisplaySearchBar
309 | {
310 | if (self.tableView.tableHeaderView != nil || self.searchController == nil) return;
311 |
312 | UISearchBar *searchBar = self.searchController.searchBar;
313 | searchBar.searchBarStyle = UISearchBarStyleMinimal;
314 |
315 | CGRect searchBarFrame = searchBar.frame;
316 | searchBarFrame.size.height = kSearchBarHeight;
317 | searchBar.frame = searchBarFrame;
318 |
319 | self.tableView.tableHeaderView = searchBar;
320 | }
321 |
322 | #pragma mark - UISearchResultsUpdating
323 |
324 | - (void)updateSearchResultsForSearchController:(UISearchController *)searchController
325 | {
326 | UZNodeViewController *viewController = (UZNodeViewController *)searchController.searchResultsController;
327 | viewController.searchQuery = searchController.searchBar.text;
328 | }
329 |
330 | #pragma mark - Encryption
331 |
332 | - (void)presentPasswordAlertForNode:(UZNode *)node completionHandler:(void (^)(NSString *password))completionHandler
333 | {
334 | NSParameterAssert(completionHandler);
335 |
336 | NSString *message = [NSString stringWithFormat:NSLocalizedString(@"EncryptionAlertMessage", nil), node.fileName];
337 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"EncryptionAlertTitle", nil) message:message preferredStyle:UIAlertControllerStyleAlert];
338 | [alert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
339 | textField.secureTextEntry = YES;
340 | }];
341 |
342 | __weak UIAlertController *weakAlert = alert;
343 | [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
344 | completionHandler([weakAlert.textFields[0] text]);
345 | [self dismissViewControllerAnimated:YES completion:nil];
346 | }]];
347 | [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
348 | completionHandler(nil);
349 | [self dismissViewControllerAnimated:YES completion:nil];
350 | }]];
351 |
352 | [self presentViewController:alert animated:YES completion:nil];
353 | }
354 |
355 | @end
356 |
--------------------------------------------------------------------------------
/Unzip.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7218C48319916F4B00D7C757 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C48219916F4B00D7C757 /* main.m */; };
11 | 7218C48619916F4B00D7C757 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C48519916F4B00D7C757 /* AppDelegate.m */; };
12 | 7218C48919916F4B00D7C757 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C48819916F4B00D7C757 /* ViewController.m */; };
13 | 7218C48C19916F4B00D7C757 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7218C48A19916F4B00D7C757 /* Main.storyboard */; };
14 | 7218C48E19916F4B00D7C757 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7218C48D19916F4B00D7C757 /* Images.xcassets */; };
15 | 7218C4AF19916F5E00D7C757 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7218C4AE19916F5E00D7C757 /* MainInterface.storyboard */; };
16 | 7218C4B219916F5E00D7C757 /* UnzipAction.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7218C4A719916F5E00D7C757 /* UnzipAction.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
17 | 7218C4BB1991748400D7C757 /* UZArchiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C4BA1991748400D7C757 /* UZArchiveViewController.m */; };
18 | 7218C4C1199176B400D7C757 /* UIAlertController+UZError.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C4C0199176B400D7C757 /* UIAlertController+UZError.m */; };
19 | 7218C4C419917A5500D7C757 /* UZNodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C4C319917A5500D7C757 /* UZNodeViewController.m */; };
20 | 7218C4C71991C99700D7C757 /* UZNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C4C61991C99700D7C757 /* UZNode.m */; };
21 | 7218C4CA1991F33100D7C757 /* UZPreviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7218C4C91991F33100D7C757 /* UZPreviewViewController.m */; };
22 | 7218C4CE1991F8B700D7C757 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 7218C4CC1991F8B700D7C757 /* Localizable.strings */; };
23 | 7218C4DB1991FC3800D7C757 /* UZPreviewViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7218C4DA1991FC3800D7C757 /* UZPreviewViewController.xib */; };
24 | 721AE34F1995B34300246FDF /* UZPreviewPageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 721AE34E1995B34300246FDF /* UZPreviewPageViewController.m */; };
25 | 72A4BC1A1992BD8B00884AAC /* UZUnzipOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A4BC191992BD8B00884AAC /* UZUnzipOperation.m */; };
26 | 72A4BC201992CA9F00884AAC /* UZNodeTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A4BC1F1992CA9F00884AAC /* UZNodeTableViewCell.m */; };
27 | 72A4BC231992DD1800884AAC /* UZUnzipCoordinator.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A4BC221992DD1800884AAC /* UZUnzipCoordinator.m */; };
28 | 72A4BC271993286E00884AAC /* UZExtensionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A4BC261993286E00884AAC /* UZExtensionViewController.m */; };
29 | 72A4BC2A1993290D00884AAC /* UZExtensionTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A4BC291993290D00884AAC /* UZExtensionTableViewController.m */; };
30 | 72A4BC2D1993314E00884AAC /* UZOpenInActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 72A4BC2C1993314E00884AAC /* UZOpenInActivity.m */; };
31 | 72B3C10419A04B6900801EF9 /* UZGlyphFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 72B3C10319A04B6900801EF9 /* UZGlyphFactory.m */; };
32 | 72B3C10819A050E500801EF9 /* UZNodeTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 72B3C10719A050E500801EF9 /* UZNodeTableViewCell.xib */; };
33 | 91B01368CAFB453181A38E86 /* libPods-UnzipAction.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B27AF6F9FDC447882016106 /* libPods-UnzipAction.a */; };
34 | /* End PBXBuildFile section */
35 |
36 | /* Begin PBXContainerItemProxy section */
37 | 7218C4B019916F5E00D7C757 /* PBXContainerItemProxy */ = {
38 | isa = PBXContainerItemProxy;
39 | containerPortal = 7218C47519916F4B00D7C757 /* Project object */;
40 | proxyType = 1;
41 | remoteGlobalIDString = 7218C4A619916F5E00D7C757;
42 | remoteInfo = UnzipAction;
43 | };
44 | 7218C4B319916F5E00D7C757 /* PBXContainerItemProxy */ = {
45 | isa = PBXContainerItemProxy;
46 | containerPortal = 7218C47519916F4B00D7C757 /* Project object */;
47 | proxyType = 1;
48 | remoteGlobalIDString = 7218C4A619916F5E00D7C757;
49 | remoteInfo = UnzipAction;
50 | };
51 | /* End PBXContainerItemProxy section */
52 |
53 | /* Begin PBXCopyFilesBuildPhase section */
54 | 7218C4B819916F5E00D7C757 /* Embed App Extensions */ = {
55 | isa = PBXCopyFilesBuildPhase;
56 | buildActionMask = 2147483647;
57 | dstPath = "";
58 | dstSubfolderSpec = 13;
59 | files = (
60 | 7218C4B219916F5E00D7C757 /* UnzipAction.appex in Embed App Extensions */,
61 | );
62 | name = "Embed App Extensions";
63 | runOnlyForDeploymentPostprocessing = 0;
64 | };
65 | /* End PBXCopyFilesBuildPhase section */
66 |
67 | /* Begin PBXFileReference section */
68 | 1B27AF6F9FDC447882016106 /* libPods-UnzipAction.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-UnzipAction.a"; sourceTree = BUILT_PRODUCTS_DIR; };
69 | 637E3FFF75B74F979BBAAAC9 /* Pods-UnzipAction.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-UnzipAction.xcconfig"; path = "Pods/Pods-UnzipAction.xcconfig"; sourceTree = ""; };
70 | 7218C47D19916F4B00D7C757 /* Unzip.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Unzip.app; sourceTree = BUILT_PRODUCTS_DIR; };
71 | 7218C48119916F4B00D7C757 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
72 | 7218C48219916F4B00D7C757 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
73 | 7218C48419916F4B00D7C757 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
74 | 7218C48519916F4B00D7C757 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
75 | 7218C48719916F4B00D7C757 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
76 | 7218C48819916F4B00D7C757 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
77 | 7218C48B19916F4B00D7C757 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
78 | 7218C48D19916F4B00D7C757 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
79 | 7218C4A719916F5E00D7C757 /* UnzipAction.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = UnzipAction.appex; sourceTree = BUILT_PRODUCTS_DIR; };
80 | 7218C4AA19916F5E00D7C757 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
81 | 7218C4AE19916F5E00D7C757 /* MainInterface.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = MainInterface.storyboard; sourceTree = ""; };
82 | 7218C4B91991748400D7C757 /* UZArchiveViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZArchiveViewController.h; sourceTree = ""; };
83 | 7218C4BA1991748400D7C757 /* UZArchiveViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZArchiveViewController.m; sourceTree = ""; };
84 | 7218C4BF199176B400D7C757 /* UIAlertController+UZError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIAlertController+UZError.h"; sourceTree = ""; };
85 | 7218C4C0199176B400D7C757 /* UIAlertController+UZError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIAlertController+UZError.m"; sourceTree = ""; };
86 | 7218C4C219917A5500D7C757 /* UZNodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZNodeViewController.h; sourceTree = ""; };
87 | 7218C4C319917A5500D7C757 /* UZNodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZNodeViewController.m; sourceTree = ""; };
88 | 7218C4C51991C99700D7C757 /* UZNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZNode.h; sourceTree = ""; };
89 | 7218C4C61991C99700D7C757 /* UZNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZNode.m; sourceTree = ""; };
90 | 7218C4C81991F33100D7C757 /* UZPreviewViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZPreviewViewController.h; sourceTree = ""; };
91 | 7218C4C91991F33100D7C757 /* UZPreviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZPreviewViewController.m; sourceTree = ""; };
92 | 7218C4CD1991F8B700D7C757 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Localizable.strings; sourceTree = ""; };
93 | 7218C4DA1991FC3800D7C757 /* UZPreviewViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UZPreviewViewController.xib; sourceTree = ""; };
94 | 721AE34D1995B34300246FDF /* UZPreviewPageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZPreviewPageViewController.h; sourceTree = ""; };
95 | 721AE34E1995B34300246FDF /* UZPreviewPageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZPreviewPageViewController.m; sourceTree = ""; };
96 | 72A4BC181992BD8B00884AAC /* UZUnzipOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZUnzipOperation.h; sourceTree = ""; };
97 | 72A4BC191992BD8B00884AAC /* UZUnzipOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZUnzipOperation.m; sourceTree = ""; };
98 | 72A4BC1E1992CA9F00884AAC /* UZNodeTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZNodeTableViewCell.h; sourceTree = ""; };
99 | 72A4BC1F1992CA9F00884AAC /* UZNodeTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZNodeTableViewCell.m; sourceTree = ""; };
100 | 72A4BC211992DD1800884AAC /* UZUnzipCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZUnzipCoordinator.h; sourceTree = ""; };
101 | 72A4BC221992DD1800884AAC /* UZUnzipCoordinator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZUnzipCoordinator.m; sourceTree = ""; };
102 | 72A4BC2419931B2700884AAC /* UZNodeViewControllerSubclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZNodeViewControllerSubclass.h; sourceTree = ""; };
103 | 72A4BC251993286E00884AAC /* UZExtensionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZExtensionViewController.h; sourceTree = ""; };
104 | 72A4BC261993286E00884AAC /* UZExtensionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZExtensionViewController.m; sourceTree = ""; };
105 | 72A4BC281993290D00884AAC /* UZExtensionTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZExtensionTableViewController.h; sourceTree = ""; };
106 | 72A4BC291993290D00884AAC /* UZExtensionTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZExtensionTableViewController.m; sourceTree = ""; };
107 | 72A4BC2B1993314E00884AAC /* UZOpenInActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZOpenInActivity.h; sourceTree = ""; };
108 | 72A4BC2C1993314E00884AAC /* UZOpenInActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZOpenInActivity.m; sourceTree = ""; };
109 | 72B3C10219A04B6900801EF9 /* UZGlyphFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UZGlyphFactory.h; sourceTree = ""; };
110 | 72B3C10319A04B6900801EF9 /* UZGlyphFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UZGlyphFactory.m; sourceTree = ""; };
111 | 72B3C10719A050E500801EF9 /* UZNodeTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = UZNodeTableViewCell.xib; sourceTree = ""; };
112 | /* End PBXFileReference section */
113 |
114 | /* Begin PBXFrameworksBuildPhase section */
115 | 7218C47A19916F4B00D7C757 /* Frameworks */ = {
116 | isa = PBXFrameworksBuildPhase;
117 | buildActionMask = 2147483647;
118 | files = (
119 | );
120 | runOnlyForDeploymentPostprocessing = 0;
121 | };
122 | 7218C4A419916F5E00D7C757 /* Frameworks */ = {
123 | isa = PBXFrameworksBuildPhase;
124 | buildActionMask = 2147483647;
125 | files = (
126 | 91B01368CAFB453181A38E86 /* libPods-UnzipAction.a in Frameworks */,
127 | );
128 | runOnlyForDeploymentPostprocessing = 0;
129 | };
130 | /* End PBXFrameworksBuildPhase section */
131 |
132 | /* Begin PBXGroup section */
133 | 343F61C7A7264F1592D4DCA4 /* Frameworks */ = {
134 | isa = PBXGroup;
135 | children = (
136 | 1B27AF6F9FDC447882016106 /* libPods-UnzipAction.a */,
137 | );
138 | name = Frameworks;
139 | sourceTree = "";
140 | };
141 | 7218C47419916F4B00D7C757 = {
142 | isa = PBXGroup;
143 | children = (
144 | 7218C47F19916F4B00D7C757 /* Unzip */,
145 | 7218C4A819916F5E00D7C757 /* UnzipAction */,
146 | 7218C47E19916F4B00D7C757 /* Products */,
147 | 637E3FFF75B74F979BBAAAC9 /* Pods-UnzipAction.xcconfig */,
148 | 343F61C7A7264F1592D4DCA4 /* Frameworks */,
149 | );
150 | sourceTree = "";
151 | };
152 | 7218C47E19916F4B00D7C757 /* Products */ = {
153 | isa = PBXGroup;
154 | children = (
155 | 7218C47D19916F4B00D7C757 /* Unzip.app */,
156 | 7218C4A719916F5E00D7C757 /* UnzipAction.appex */,
157 | );
158 | name = Products;
159 | sourceTree = "";
160 | };
161 | 7218C47F19916F4B00D7C757 /* Unzip */ = {
162 | isa = PBXGroup;
163 | children = (
164 | 7218C48419916F4B00D7C757 /* AppDelegate.h */,
165 | 7218C48519916F4B00D7C757 /* AppDelegate.m */,
166 | 7218C48719916F4B00D7C757 /* ViewController.h */,
167 | 7218C48819916F4B00D7C757 /* ViewController.m */,
168 | 7218C48A19916F4B00D7C757 /* Main.storyboard */,
169 | 7218C48D19916F4B00D7C757 /* Images.xcassets */,
170 | 7218C48019916F4B00D7C757 /* Supporting Files */,
171 | );
172 | path = Unzip;
173 | sourceTree = "";
174 | };
175 | 7218C48019916F4B00D7C757 /* Supporting Files */ = {
176 | isa = PBXGroup;
177 | children = (
178 | 7218C48119916F4B00D7C757 /* Info.plist */,
179 | 7218C48219916F4B00D7C757 /* main.m */,
180 | );
181 | name = "Supporting Files";
182 | sourceTree = "";
183 | };
184 | 7218C4A819916F5E00D7C757 /* UnzipAction */ = {
185 | isa = PBXGroup;
186 | children = (
187 | 7218C4BF199176B400D7C757 /* UIAlertController+UZError.h */,
188 | 7218C4C0199176B400D7C757 /* UIAlertController+UZError.m */,
189 | 7218C4C51991C99700D7C757 /* UZNode.h */,
190 | 7218C4C61991C99700D7C757 /* UZNode.m */,
191 | 7218C4B91991748400D7C757 /* UZArchiveViewController.h */,
192 | 7218C4BA1991748400D7C757 /* UZArchiveViewController.m */,
193 | 72A4BC251993286E00884AAC /* UZExtensionViewController.h */,
194 | 72A4BC261993286E00884AAC /* UZExtensionViewController.m */,
195 | 72A4BC281993290D00884AAC /* UZExtensionTableViewController.h */,
196 | 72A4BC291993290D00884AAC /* UZExtensionTableViewController.m */,
197 | 7218C4C219917A5500D7C757 /* UZNodeViewController.h */,
198 | 7218C4C319917A5500D7C757 /* UZNodeViewController.m */,
199 | 72A4BC2419931B2700884AAC /* UZNodeViewControllerSubclass.h */,
200 | 72A4BC1E1992CA9F00884AAC /* UZNodeTableViewCell.h */,
201 | 72A4BC1F1992CA9F00884AAC /* UZNodeTableViewCell.m */,
202 | 72B3C10719A050E500801EF9 /* UZNodeTableViewCell.xib */,
203 | 7218C4C81991F33100D7C757 /* UZPreviewViewController.h */,
204 | 7218C4C91991F33100D7C757 /* UZPreviewViewController.m */,
205 | 7218C4DA1991FC3800D7C757 /* UZPreviewViewController.xib */,
206 | 721AE34D1995B34300246FDF /* UZPreviewPageViewController.h */,
207 | 721AE34E1995B34300246FDF /* UZPreviewPageViewController.m */,
208 | 72A4BC181992BD8B00884AAC /* UZUnzipOperation.h */,
209 | 72A4BC191992BD8B00884AAC /* UZUnzipOperation.m */,
210 | 72A4BC211992DD1800884AAC /* UZUnzipCoordinator.h */,
211 | 72A4BC221992DD1800884AAC /* UZUnzipCoordinator.m */,
212 | 72A4BC2B1993314E00884AAC /* UZOpenInActivity.h */,
213 | 72A4BC2C1993314E00884AAC /* UZOpenInActivity.m */,
214 | 72B3C10219A04B6900801EF9 /* UZGlyphFactory.h */,
215 | 72B3C10319A04B6900801EF9 /* UZGlyphFactory.m */,
216 | 7218C4AE19916F5E00D7C757 /* MainInterface.storyboard */,
217 | 7218C4CB1991F8B700D7C757 /* en.lproj */,
218 | 7218C4A919916F5E00D7C757 /* Supporting Files */,
219 | );
220 | path = UnzipAction;
221 | sourceTree = "";
222 | };
223 | 7218C4A919916F5E00D7C757 /* Supporting Files */ = {
224 | isa = PBXGroup;
225 | children = (
226 | 7218C4AA19916F5E00D7C757 /* Info.plist */,
227 | );
228 | name = "Supporting Files";
229 | sourceTree = "";
230 | };
231 | 7218C4CB1991F8B700D7C757 /* en.lproj */ = {
232 | isa = PBXGroup;
233 | children = (
234 | 7218C4CC1991F8B700D7C757 /* Localizable.strings */,
235 | );
236 | path = en.lproj;
237 | sourceTree = "";
238 | };
239 | /* End PBXGroup section */
240 |
241 | /* Begin PBXNativeTarget section */
242 | 7218C47C19916F4B00D7C757 /* Unzip */ = {
243 | isa = PBXNativeTarget;
244 | buildConfigurationList = 7218C49D19916F4C00D7C757 /* Build configuration list for PBXNativeTarget "Unzip" */;
245 | buildPhases = (
246 | 7218C47919916F4B00D7C757 /* Sources */,
247 | 7218C47A19916F4B00D7C757 /* Frameworks */,
248 | 7218C47B19916F4B00D7C757 /* Resources */,
249 | 7218C4B819916F5E00D7C757 /* Embed App Extensions */,
250 | );
251 | buildRules = (
252 | );
253 | dependencies = (
254 | 7218C4B119916F5E00D7C757 /* PBXTargetDependency */,
255 | 7218C4B419916F5E00D7C757 /* PBXTargetDependency */,
256 | );
257 | name = Unzip;
258 | productName = Unzip;
259 | productReference = 7218C47D19916F4B00D7C757 /* Unzip.app */;
260 | productType = "com.apple.product-type.application";
261 | };
262 | 7218C4A619916F5E00D7C757 /* UnzipAction */ = {
263 | isa = PBXNativeTarget;
264 | buildConfigurationList = 7218C4B519916F5E00D7C757 /* Build configuration list for PBXNativeTarget "UnzipAction" */;
265 | buildPhases = (
266 | C9828A3B9C0E46ADB7F5E583 /* Check Pods Manifest.lock */,
267 | 7218C4A319916F5E00D7C757 /* Sources */,
268 | 7218C4A419916F5E00D7C757 /* Frameworks */,
269 | 7218C4A519916F5E00D7C757 /* Resources */,
270 | AF6063905CEC4BBB89105E0E /* Copy Pods Resources */,
271 | );
272 | buildRules = (
273 | );
274 | dependencies = (
275 | );
276 | name = UnzipAction;
277 | productName = UnzipAction;
278 | productReference = 7218C4A719916F5E00D7C757 /* UnzipAction.appex */;
279 | productType = "com.apple.product-type.app-extension";
280 | };
281 | /* End PBXNativeTarget section */
282 |
283 | /* Begin PBXProject section */
284 | 7218C47519916F4B00D7C757 /* Project object */ = {
285 | isa = PBXProject;
286 | attributes = {
287 | LastUpgradeCheck = 0600;
288 | ORGANIZATIONNAME = "Indragie Karunaratne";
289 | TargetAttributes = {
290 | 7218C47C19916F4B00D7C757 = {
291 | CreatedOnToolsVersion = 6.0;
292 | };
293 | 7218C4A619916F5E00D7C757 = {
294 | CreatedOnToolsVersion = 6.0;
295 | DevelopmentTeam = H73VKH7W9W;
296 | };
297 | };
298 | };
299 | buildConfigurationList = 7218C47819916F4B00D7C757 /* Build configuration list for PBXProject "Unzip" */;
300 | compatibilityVersion = "Xcode 3.2";
301 | developmentRegion = English;
302 | hasScannedForEncodings = 0;
303 | knownRegions = (
304 | en,
305 | Base,
306 | );
307 | mainGroup = 7218C47419916F4B00D7C757;
308 | productRefGroup = 7218C47E19916F4B00D7C757 /* Products */;
309 | projectDirPath = "";
310 | projectRoot = "";
311 | targets = (
312 | 7218C47C19916F4B00D7C757 /* Unzip */,
313 | 7218C4A619916F5E00D7C757 /* UnzipAction */,
314 | );
315 | };
316 | /* End PBXProject section */
317 |
318 | /* Begin PBXResourcesBuildPhase section */
319 | 7218C47B19916F4B00D7C757 /* Resources */ = {
320 | isa = PBXResourcesBuildPhase;
321 | buildActionMask = 2147483647;
322 | files = (
323 | 7218C48C19916F4B00D7C757 /* Main.storyboard in Resources */,
324 | 7218C48E19916F4B00D7C757 /* Images.xcassets in Resources */,
325 | );
326 | runOnlyForDeploymentPostprocessing = 0;
327 | };
328 | 7218C4A519916F5E00D7C757 /* Resources */ = {
329 | isa = PBXResourcesBuildPhase;
330 | buildActionMask = 2147483647;
331 | files = (
332 | 72B3C10819A050E500801EF9 /* UZNodeTableViewCell.xib in Resources */,
333 | 7218C4AF19916F5E00D7C757 /* MainInterface.storyboard in Resources */,
334 | 7218C4CE1991F8B700D7C757 /* Localizable.strings in Resources */,
335 | 7218C4DB1991FC3800D7C757 /* UZPreviewViewController.xib in Resources */,
336 | );
337 | runOnlyForDeploymentPostprocessing = 0;
338 | };
339 | /* End PBXResourcesBuildPhase section */
340 |
341 | /* Begin PBXShellScriptBuildPhase section */
342 | AF6063905CEC4BBB89105E0E /* Copy Pods Resources */ = {
343 | isa = PBXShellScriptBuildPhase;
344 | buildActionMask = 2147483647;
345 | files = (
346 | );
347 | inputPaths = (
348 | );
349 | name = "Copy Pods Resources";
350 | outputPaths = (
351 | );
352 | runOnlyForDeploymentPostprocessing = 0;
353 | shellPath = /bin/sh;
354 | shellScript = "\"${SRCROOT}/Pods/Pods-UnzipAction-resources.sh\"\n";
355 | showEnvVarsInLog = 0;
356 | };
357 | C9828A3B9C0E46ADB7F5E583 /* Check Pods Manifest.lock */ = {
358 | isa = PBXShellScriptBuildPhase;
359 | buildActionMask = 2147483647;
360 | files = (
361 | );
362 | inputPaths = (
363 | );
364 | name = "Check Pods Manifest.lock";
365 | outputPaths = (
366 | );
367 | runOnlyForDeploymentPostprocessing = 0;
368 | shellPath = /bin/sh;
369 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
370 | showEnvVarsInLog = 0;
371 | };
372 | /* End PBXShellScriptBuildPhase section */
373 |
374 | /* Begin PBXSourcesBuildPhase section */
375 | 7218C47919916F4B00D7C757 /* Sources */ = {
376 | isa = PBXSourcesBuildPhase;
377 | buildActionMask = 2147483647;
378 | files = (
379 | 7218C48919916F4B00D7C757 /* ViewController.m in Sources */,
380 | 7218C48619916F4B00D7C757 /* AppDelegate.m in Sources */,
381 | 7218C48319916F4B00D7C757 /* main.m in Sources */,
382 | );
383 | runOnlyForDeploymentPostprocessing = 0;
384 | };
385 | 7218C4A319916F5E00D7C757 /* Sources */ = {
386 | isa = PBXSourcesBuildPhase;
387 | buildActionMask = 2147483647;
388 | files = (
389 | 72A4BC231992DD1800884AAC /* UZUnzipCoordinator.m in Sources */,
390 | 721AE34F1995B34300246FDF /* UZPreviewPageViewController.m in Sources */,
391 | 7218C4C419917A5500D7C757 /* UZNodeViewController.m in Sources */,
392 | 72A4BC1A1992BD8B00884AAC /* UZUnzipOperation.m in Sources */,
393 | 7218C4C1199176B400D7C757 /* UIAlertController+UZError.m in Sources */,
394 | 72A4BC2A1993290D00884AAC /* UZExtensionTableViewController.m in Sources */,
395 | 7218C4BB1991748400D7C757 /* UZArchiveViewController.m in Sources */,
396 | 72A4BC201992CA9F00884AAC /* UZNodeTableViewCell.m in Sources */,
397 | 7218C4CA1991F33100D7C757 /* UZPreviewViewController.m in Sources */,
398 | 7218C4C71991C99700D7C757 /* UZNode.m in Sources */,
399 | 72A4BC2D1993314E00884AAC /* UZOpenInActivity.m in Sources */,
400 | 72A4BC271993286E00884AAC /* UZExtensionViewController.m in Sources */,
401 | 72B3C10419A04B6900801EF9 /* UZGlyphFactory.m in Sources */,
402 | );
403 | runOnlyForDeploymentPostprocessing = 0;
404 | };
405 | /* End PBXSourcesBuildPhase section */
406 |
407 | /* Begin PBXTargetDependency section */
408 | 7218C4B119916F5E00D7C757 /* PBXTargetDependency */ = {
409 | isa = PBXTargetDependency;
410 | target = 7218C4A619916F5E00D7C757 /* UnzipAction */;
411 | targetProxy = 7218C4B019916F5E00D7C757 /* PBXContainerItemProxy */;
412 | };
413 | 7218C4B419916F5E00D7C757 /* PBXTargetDependency */ = {
414 | isa = PBXTargetDependency;
415 | target = 7218C4A619916F5E00D7C757 /* UnzipAction */;
416 | targetProxy = 7218C4B319916F5E00D7C757 /* PBXContainerItemProxy */;
417 | };
418 | /* End PBXTargetDependency section */
419 |
420 | /* Begin PBXVariantGroup section */
421 | 7218C48A19916F4B00D7C757 /* Main.storyboard */ = {
422 | isa = PBXVariantGroup;
423 | children = (
424 | 7218C48B19916F4B00D7C757 /* Base */,
425 | );
426 | name = Main.storyboard;
427 | sourceTree = "";
428 | };
429 | 7218C4CC1991F8B700D7C757 /* Localizable.strings */ = {
430 | isa = PBXVariantGroup;
431 | children = (
432 | 7218C4CD1991F8B700D7C757 /* en */,
433 | );
434 | name = Localizable.strings;
435 | sourceTree = "";
436 | };
437 | /* End PBXVariantGroup section */
438 |
439 | /* Begin XCBuildConfiguration section */
440 | 7218C49B19916F4C00D7C757 /* Debug */ = {
441 | isa = XCBuildConfiguration;
442 | buildSettings = {
443 | ALWAYS_SEARCH_USER_PATHS = NO;
444 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
445 | CLANG_CXX_LIBRARY = "libc++";
446 | CLANG_ENABLE_MODULES = YES;
447 | CLANG_ENABLE_OBJC_ARC = YES;
448 | CLANG_WARN_BOOL_CONVERSION = YES;
449 | CLANG_WARN_CONSTANT_CONVERSION = YES;
450 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
451 | CLANG_WARN_EMPTY_BODY = YES;
452 | CLANG_WARN_ENUM_CONVERSION = YES;
453 | CLANG_WARN_INT_CONVERSION = YES;
454 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
455 | CLANG_WARN_UNREACHABLE_CODE = YES;
456 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
457 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
458 | COPY_PHASE_STRIP = NO;
459 | ENABLE_STRICT_OBJC_MSGSEND = YES;
460 | GCC_C_LANGUAGE_STANDARD = gnu99;
461 | GCC_DYNAMIC_NO_PIC = NO;
462 | GCC_OPTIMIZATION_LEVEL = 0;
463 | GCC_PREPROCESSOR_DEFINITIONS = (
464 | "DEBUG=1",
465 | "$(inherited)",
466 | );
467 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
468 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
469 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
470 | GCC_WARN_UNDECLARED_SELECTOR = YES;
471 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
472 | GCC_WARN_UNUSED_FUNCTION = YES;
473 | GCC_WARN_UNUSED_VARIABLE = YES;
474 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
475 | MTL_ENABLE_DEBUG_INFO = YES;
476 | ONLY_ACTIVE_ARCH = YES;
477 | SDKROOT = iphoneos;
478 | };
479 | name = Debug;
480 | };
481 | 7218C49C19916F4C00D7C757 /* Release */ = {
482 | isa = XCBuildConfiguration;
483 | buildSettings = {
484 | ALWAYS_SEARCH_USER_PATHS = NO;
485 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
486 | CLANG_CXX_LIBRARY = "libc++";
487 | CLANG_ENABLE_MODULES = YES;
488 | CLANG_ENABLE_OBJC_ARC = YES;
489 | CLANG_WARN_BOOL_CONVERSION = YES;
490 | CLANG_WARN_CONSTANT_CONVERSION = YES;
491 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
492 | CLANG_WARN_EMPTY_BODY = YES;
493 | CLANG_WARN_ENUM_CONVERSION = YES;
494 | CLANG_WARN_INT_CONVERSION = YES;
495 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
496 | CLANG_WARN_UNREACHABLE_CODE = YES;
497 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
498 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
499 | COPY_PHASE_STRIP = YES;
500 | ENABLE_NS_ASSERTIONS = NO;
501 | ENABLE_STRICT_OBJC_MSGSEND = YES;
502 | GCC_C_LANGUAGE_STANDARD = gnu99;
503 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
504 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
505 | GCC_WARN_UNDECLARED_SELECTOR = YES;
506 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
507 | GCC_WARN_UNUSED_FUNCTION = YES;
508 | GCC_WARN_UNUSED_VARIABLE = YES;
509 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
510 | MTL_ENABLE_DEBUG_INFO = NO;
511 | SDKROOT = iphoneos;
512 | VALIDATE_PRODUCT = YES;
513 | };
514 | name = Release;
515 | };
516 | 7218C49E19916F4C00D7C757 /* Debug */ = {
517 | isa = XCBuildConfiguration;
518 | buildSettings = {
519 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
520 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
521 | INFOPLIST_FILE = Unzip/Info.plist;
522 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
523 | PRODUCT_NAME = "$(TARGET_NAME)";
524 | };
525 | name = Debug;
526 | };
527 | 7218C49F19916F4C00D7C757 /* Release */ = {
528 | isa = XCBuildConfiguration;
529 | buildSettings = {
530 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
531 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
532 | INFOPLIST_FILE = Unzip/Info.plist;
533 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
534 | PRODUCT_NAME = "$(TARGET_NAME)";
535 | };
536 | name = Release;
537 | };
538 | 7218C4B619916F5E00D7C757 /* Debug */ = {
539 | isa = XCBuildConfiguration;
540 | baseConfigurationReference = 637E3FFF75B74F979BBAAAC9 /* Pods-UnzipAction.xcconfig */;
541 | buildSettings = {
542 | CODE_SIGN_IDENTITY = "iPhone Developer";
543 | GCC_PREPROCESSOR_DEFINITIONS = (
544 | "DEBUG=1",
545 | "$(inherited)",
546 | );
547 | INFOPLIST_FILE = UnzipAction/Info.plist;
548 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
549 | PRODUCT_NAME = "$(TARGET_NAME)";
550 | SKIP_INSTALL = YES;
551 | };
552 | name = Debug;
553 | };
554 | 7218C4B719916F5E00D7C757 /* Release */ = {
555 | isa = XCBuildConfiguration;
556 | baseConfigurationReference = 637E3FFF75B74F979BBAAAC9 /* Pods-UnzipAction.xcconfig */;
557 | buildSettings = {
558 | CODE_SIGN_IDENTITY = "iPhone Developer";
559 | INFOPLIST_FILE = UnzipAction/Info.plist;
560 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
561 | PRODUCT_NAME = "$(TARGET_NAME)";
562 | SKIP_INSTALL = YES;
563 | };
564 | name = Release;
565 | };
566 | /* End XCBuildConfiguration section */
567 |
568 | /* Begin XCConfigurationList section */
569 | 7218C47819916F4B00D7C757 /* Build configuration list for PBXProject "Unzip" */ = {
570 | isa = XCConfigurationList;
571 | buildConfigurations = (
572 | 7218C49B19916F4C00D7C757 /* Debug */,
573 | 7218C49C19916F4C00D7C757 /* Release */,
574 | );
575 | defaultConfigurationIsVisible = 0;
576 | defaultConfigurationName = Release;
577 | };
578 | 7218C49D19916F4C00D7C757 /* Build configuration list for PBXNativeTarget "Unzip" */ = {
579 | isa = XCConfigurationList;
580 | buildConfigurations = (
581 | 7218C49E19916F4C00D7C757 /* Debug */,
582 | 7218C49F19916F4C00D7C757 /* Release */,
583 | );
584 | defaultConfigurationIsVisible = 0;
585 | defaultConfigurationName = Release;
586 | };
587 | 7218C4B519916F5E00D7C757 /* Build configuration list for PBXNativeTarget "UnzipAction" */ = {
588 | isa = XCConfigurationList;
589 | buildConfigurations = (
590 | 7218C4B619916F5E00D7C757 /* Debug */,
591 | 7218C4B719916F5E00D7C757 /* Release */,
592 | );
593 | defaultConfigurationIsVisible = 0;
594 | defaultConfigurationName = Release;
595 | };
596 | /* End XCConfigurationList section */
597 | };
598 | rootObject = 7218C47519916F4B00D7C757 /* Project object */;
599 | }
600 |
--------------------------------------------------------------------------------