Commit 5296345e by Brent Gulanowski Committed by Dima Bart

Move all product single views into Advanced Sample.

Also update for changes to how models are created, various other changes.
parent 53102c3a
......@@ -7,6 +7,42 @@
objects = {
/* Begin PBXBuildFile section */
842799661CB31498003AD0CE /* PaymentViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 842799651CB31498003AD0CE /* PaymentViewController.m */; };
847612671CAB047600AB17AA /* DisclosureIndicatorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612251CAB047600AB17AA /* DisclosureIndicatorView.m */; };
847612681CAB047600AB17AA /* Theme+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612271CAB047600AB17AA /* Theme+Additions.m */; };
847612691CAB047600AB17AA /* Theme.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612291CAB047600AB17AA /* Theme.m */; };
8476126A1CAB047600AB17AA /* VisualEffectView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476122B1CAB047600AB17AA /* VisualEffectView.m */; };
8476126C1CAB047600AB17AA /* ActionableFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612301CAB047600AB17AA /* ActionableFooterView.m */; };
8476126D1CAB047600AB17AA /* ActionableFooterView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 847612311CAB047600AB17AA /* ActionableFooterView.xib */; };
8476126E1CAB047600AB17AA /* CheckoutButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612331CAB047600AB17AA /* CheckoutButton.m */; };
8476126F1CAB047600AB17AA /* ErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612351CAB047600AB17AA /* ErrorView.m */; };
847612701CAB047600AB17AA /* GradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612371CAB047600AB17AA /* GradientView.m */; };
847612711CAB047600AB17AA /* AsyncImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612391CAB047600AB17AA /* AsyncImageView.m */; };
847612721CAB047600AB17AA /* ProductViewPresentationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476123B1CAB047600AB17AA /* ProductViewPresentationController.m */; };
847612731CAB047600AB17AA /* ProductDescriptionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476123D1CAB047600AB17AA /* ProductDescriptionCell.m */; };
847612741CAB047600AB17AA /* ProductHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476123F1CAB047600AB17AA /* ProductHeaderCell.m */; };
847612751CAB047600AB17AA /* ProductImageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612411CAB047600AB17AA /* ProductImageCell.m */; };
847612761CAB047600AB17AA /* ProductVariantCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612431CAB047600AB17AA /* ProductVariantCell.m */; };
847612771CAB047600AB17AA /* ProductView.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612451CAB047600AB17AA /* ProductView.m */; };
847612781CAB047600AB17AA /* ProductViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612471CAB047600AB17AA /* ProductViewController.m */; };
8476127A1CAB047600AB17AA /* ProductViewHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476124A1CAB047600AB17AA /* ProductViewHeader.m */; };
8476127B1CAB047600AB17AA /* HeaderBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476124C1CAB047600AB17AA /* HeaderBackgroundView.m */; };
8476127C1CAB047600AB17AA /* HeaderOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476124E1CAB047600AB17AA /* HeaderOverlayView.m */; };
8476127D1CAB047600AB17AA /* ProductViewNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612501CAB047600AB17AA /* ProductViewNavigationController.m */; };
8476127E1CAB047600AB17AA /* OptionSelectionNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612531CAB047600AB17AA /* OptionSelectionNavigationController.m */; };
8476127F1CAB047600AB17AA /* OptionSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612551CAB047600AB17AA /* OptionSelectionViewController.m */; };
847612801CAB047600AB17AA /* OptionValueCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612571CAB047600AB17AA /* OptionValueCell.m */; };
847612811CAB047600AB17AA /* VariantSelectionPresentationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612591CAB047600AB17AA /* VariantSelectionPresentationController.m */; };
847612821CAB047600AB17AA /* OptionBreadCrumbsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476125B1CAB047600AB17AA /* OptionBreadCrumbsView.m */; };
847612831CAB047600AB17AA /* VariantOptionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476125D1CAB047600AB17AA /* VariantOptionView.m */; };
847612841CAB047600AB17AA /* VariantSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476125F1CAB047600AB17AA /* VariantSelectionViewController.m */; };
847612961CAB059100AB17AA /* ImageKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612911CAB059100AB17AA /* ImageKit.m */; };
847612971CAB059100AB17AA /* UIButton+PaymentButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612931CAB059100AB17AA /* UIButton+PaymentButton.m */; };
847612981CAB059100AB17AA /* UIImage+PaymentButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 847612951CAB059100AB17AA /* UIImage+PaymentButton.m */; };
847612A01CAB05BE00AB17AA /* UIColor+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476129B1CAB05BE00AB17AA /* UIColor+BUYAdditions.m */; };
847612A11CAB05BE00AB17AA /* UIFont+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476129D1CAB05BE00AB17AA /* UIFont+BUYAdditions.m */; };
847612A21CAB05BE00AB17AA /* UIImage+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8476129F1CAB05BE00AB17AA /* UIImage+BUYAdditions.m */; };
84BA52EE1CB2E83C00AB1560 /* NavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 84BA52ED1CB2E83C00AB1560 /* NavigationController.m */; };
902C9B8C1BB06BF300FC456E /* GetShopOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 902C9B8B1BB06BF300FC456E /* GetShopOperation.m */; };
902C9B8F1BB0729F00FC456E /* ShippingRateTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 902C9B8E1BB0729F00FC456E /* ShippingRateTableViewCell.m */; };
902C9B921BB08FF500FC456E /* SummaryItemsTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 902C9B911BB08FF500FC456E /* SummaryItemsTableViewCell.m */; };
......@@ -83,6 +119,77 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
842799641CB31498003AD0CE /* PaymentViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PaymentViewController.h; sourceTree = "<group>"; };
842799651CB31498003AD0CE /* PaymentViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PaymentViewController.m; sourceTree = "<group>"; };
847612241CAB047600AB17AA /* DisclosureIndicatorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisclosureIndicatorView.h; sourceTree = "<group>"; };
847612251CAB047600AB17AA /* DisclosureIndicatorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DisclosureIndicatorView.m; sourceTree = "<group>"; };
847612261CAB047600AB17AA /* Theme+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Theme+Additions.h"; sourceTree = "<group>"; };
847612271CAB047600AB17AA /* Theme+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "Theme+Additions.m"; sourceTree = "<group>"; };
847612281CAB047600AB17AA /* Theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Theme.h; sourceTree = "<group>"; };
847612291CAB047600AB17AA /* Theme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = Theme.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
8476122A1CAB047600AB17AA /* VisualEffectView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisualEffectView.h; sourceTree = "<group>"; };
8476122B1CAB047600AB17AA /* VisualEffectView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VisualEffectView.m; sourceTree = "<group>"; };
8476122F1CAB047600AB17AA /* ActionableFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ActionableFooterView.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
847612301CAB047600AB17AA /* ActionableFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ActionableFooterView.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
847612311CAB047600AB17AA /* ActionableFooterView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ActionableFooterView.xib; sourceTree = "<group>"; };
847612321CAB047600AB17AA /* CheckoutButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CheckoutButton.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
847612331CAB047600AB17AA /* CheckoutButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = CheckoutButton.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
847612341CAB047600AB17AA /* ErrorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ErrorView.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
847612351CAB047600AB17AA /* ErrorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ErrorView.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
847612361CAB047600AB17AA /* GradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GradientView.h; sourceTree = "<group>"; };
847612371CAB047600AB17AA /* GradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GradientView.m; sourceTree = "<group>"; };
847612381CAB047600AB17AA /* AsyncImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncImageView.h; sourceTree = "<group>"; };
847612391CAB047600AB17AA /* AsyncImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncImageView.m; sourceTree = "<group>"; };
8476123A1CAB047600AB17AA /* ProductViewPresentationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductViewPresentationController.h; sourceTree = "<group>"; };
8476123B1CAB047600AB17AA /* ProductViewPresentationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductViewPresentationController.m; sourceTree = "<group>"; };
8476123C1CAB047600AB17AA /* ProductDescriptionCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductDescriptionCell.h; sourceTree = "<group>"; };
8476123D1CAB047600AB17AA /* ProductDescriptionCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductDescriptionCell.m; sourceTree = "<group>"; };
8476123E1CAB047600AB17AA /* ProductHeaderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductHeaderCell.h; sourceTree = "<group>"; };
8476123F1CAB047600AB17AA /* ProductHeaderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductHeaderCell.m; sourceTree = "<group>"; };
847612401CAB047600AB17AA /* ProductImageCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductImageCell.h; sourceTree = "<group>"; };
847612411CAB047600AB17AA /* ProductImageCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductImageCell.m; sourceTree = "<group>"; };
847612421CAB047600AB17AA /* ProductVariantCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductVariantCell.h; sourceTree = "<group>"; };
847612431CAB047600AB17AA /* ProductVariantCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductVariantCell.m; sourceTree = "<group>"; };
847612441CAB047600AB17AA /* ProductView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ProductView.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
847612451CAB047600AB17AA /* ProductView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ProductView.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
847612461CAB047600AB17AA /* ProductViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductViewController.h; sourceTree = "<group>"; };
847612471CAB047600AB17AA /* ProductViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ProductViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
847612491CAB047600AB17AA /* ProductViewHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ProductViewHeader.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
8476124A1CAB047600AB17AA /* ProductViewHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductViewHeader.m; sourceTree = "<group>"; };
8476124B1CAB047600AB17AA /* HeaderBackgroundView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeaderBackgroundView.h; sourceTree = "<group>"; };
8476124C1CAB047600AB17AA /* HeaderBackgroundView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HeaderBackgroundView.m; sourceTree = "<group>"; };
8476124D1CAB047600AB17AA /* HeaderOverlayView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeaderOverlayView.h; sourceTree = "<group>"; };
8476124E1CAB047600AB17AA /* HeaderOverlayView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HeaderOverlayView.m; sourceTree = "<group>"; };
8476124F1CAB047600AB17AA /* ProductViewNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductViewNavigationController.h; sourceTree = "<group>"; };
847612501CAB047600AB17AA /* ProductViewNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductViewNavigationController.m; sourceTree = "<group>"; };
847612521CAB047600AB17AA /* OptionSelectionNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionSelectionNavigationController.h; sourceTree = "<group>"; };
847612531CAB047600AB17AA /* OptionSelectionNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OptionSelectionNavigationController.m; sourceTree = "<group>"; };
847612541CAB047600AB17AA /* OptionSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionSelectionViewController.h; sourceTree = "<group>"; };
847612551CAB047600AB17AA /* OptionSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OptionSelectionViewController.m; sourceTree = "<group>"; };
847612561CAB047600AB17AA /* OptionValueCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionValueCell.h; sourceTree = "<group>"; };
847612571CAB047600AB17AA /* OptionValueCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OptionValueCell.m; sourceTree = "<group>"; };
847612581CAB047600AB17AA /* VariantSelectionPresentationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariantSelectionPresentationController.h; sourceTree = "<group>"; };
847612591CAB047600AB17AA /* VariantSelectionPresentationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VariantSelectionPresentationController.m; sourceTree = "<group>"; };
8476125A1CAB047600AB17AA /* OptionBreadCrumbsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionBreadCrumbsView.h; sourceTree = "<group>"; };
8476125B1CAB047600AB17AA /* OptionBreadCrumbsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OptionBreadCrumbsView.m; sourceTree = "<group>"; };
8476125C1CAB047600AB17AA /* VariantOptionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariantOptionView.h; sourceTree = "<group>"; };
8476125D1CAB047600AB17AA /* VariantOptionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VariantOptionView.m; sourceTree = "<group>"; };
8476125E1CAB047600AB17AA /* VariantSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariantSelectionViewController.h; sourceTree = "<group>"; };
8476125F1CAB047600AB17AA /* VariantSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VariantSelectionViewController.m; sourceTree = "<group>"; };
847612901CAB059100AB17AA /* ImageKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageKit.h; sourceTree = "<group>"; };
847612911CAB059100AB17AA /* ImageKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageKit.m; sourceTree = "<group>"; };
847612921CAB059100AB17AA /* UIButton+PaymentButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+PaymentButton.h"; sourceTree = "<group>"; };
847612931CAB059100AB17AA /* UIButton+PaymentButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = "UIButton+PaymentButton.m"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
847612941CAB059100AB17AA /* UIImage+PaymentButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+PaymentButton.h"; sourceTree = "<group>"; };
847612951CAB059100AB17AA /* UIImage+PaymentButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+PaymentButton.m"; sourceTree = "<group>"; };
8476129A1CAB05BE00AB17AA /* UIColor+BUYAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+BUYAdditions.h"; sourceTree = "<group>"; };
8476129B1CAB05BE00AB17AA /* UIColor+BUYAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+BUYAdditions.m"; sourceTree = "<group>"; };
8476129C1CAB05BE00AB17AA /* UIFont+BUYAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIFont+BUYAdditions.h"; sourceTree = "<group>"; };
8476129D1CAB05BE00AB17AA /* UIFont+BUYAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIFont+BUYAdditions.m"; sourceTree = "<group>"; };
8476129E1CAB05BE00AB17AA /* UIImage+BUYAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+BUYAdditions.h"; sourceTree = "<group>"; };
8476129F1CAB05BE00AB17AA /* UIImage+BUYAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+BUYAdditions.m"; sourceTree = "<group>"; };
84BA52EC1CB2E83C00AB1560 /* NavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationController.h; sourceTree = "<group>"; };
84BA52ED1CB2E83C00AB1560 /* NavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NavigationController.m; sourceTree = "<group>"; };
902C9B8A1BB06BF300FC456E /* GetShopOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetShopOperation.h; sourceTree = "<group>"; };
902C9B8B1BB06BF300FC456E /* GetShopOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GetShopOperation.m; sourceTree = "<group>"; };
902C9B8D1BB0729F00FC456E /* ShippingRateTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = ShippingRateTableViewCell.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
......@@ -135,6 +242,121 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
847612231CAB047600AB17AA /* Appearance */ = {
isa = PBXGroup;
children = (
847612261CAB047600AB17AA /* Theme+Additions.h */,
847612271CAB047600AB17AA /* Theme+Additions.m */,
847612281CAB047600AB17AA /* Theme.h */,
847612291CAB047600AB17AA /* Theme.m */,
8476122A1CAB047600AB17AA /* VisualEffectView.h */,
8476122B1CAB047600AB17AA /* VisualEffectView.m */,
);
path = Appearance;
sourceTree = "<group>";
};
8476122E1CAB047600AB17AA /* Product View */ = {
isa = PBXGroup;
children = (
8476122F1CAB047600AB17AA /* ActionableFooterView.h */,
847612301CAB047600AB17AA /* ActionableFooterView.m */,
847612311CAB047600AB17AA /* ActionableFooterView.xib */,
847612381CAB047600AB17AA /* AsyncImageView.h */,
847612391CAB047600AB17AA /* AsyncImageView.m */,
847612321CAB047600AB17AA /* CheckoutButton.h */,
847612331CAB047600AB17AA /* CheckoutButton.m */,
847612241CAB047600AB17AA /* DisclosureIndicatorView.h */,
847612251CAB047600AB17AA /* DisclosureIndicatorView.m */,
847612341CAB047600AB17AA /* ErrorView.h */,
847612351CAB047600AB17AA /* ErrorView.m */,
847612361CAB047600AB17AA /* GradientView.h */,
847612371CAB047600AB17AA /* GradientView.m */,
8476124B1CAB047600AB17AA /* HeaderBackgroundView.h */,
8476124C1CAB047600AB17AA /* HeaderBackgroundView.m */,
8476124D1CAB047600AB17AA /* HeaderOverlayView.h */,
8476124E1CAB047600AB17AA /* HeaderOverlayView.m */,
8476123C1CAB047600AB17AA /* ProductDescriptionCell.h */,
8476123D1CAB047600AB17AA /* ProductDescriptionCell.m */,
8476123E1CAB047600AB17AA /* ProductHeaderCell.h */,
8476123F1CAB047600AB17AA /* ProductHeaderCell.m */,
847612401CAB047600AB17AA /* ProductImageCell.h */,
847612411CAB047600AB17AA /* ProductImageCell.m */,
847612421CAB047600AB17AA /* ProductVariantCell.h */,
847612431CAB047600AB17AA /* ProductVariantCell.m */,
847612441CAB047600AB17AA /* ProductView.h */,
847612451CAB047600AB17AA /* ProductView.m */,
847612461CAB047600AB17AA /* ProductViewController.h */,
847612471CAB047600AB17AA /* ProductViewController.m */,
847612491CAB047600AB17AA /* ProductViewHeader.h */,
8476124A1CAB047600AB17AA /* ProductViewHeader.m */,
8476124F1CAB047600AB17AA /* ProductViewNavigationController.h */,
847612501CAB047600AB17AA /* ProductViewNavigationController.m */,
8476123A1CAB047600AB17AA /* ProductViewPresentationController.h */,
8476123B1CAB047600AB17AA /* ProductViewPresentationController.m */,
847612511CAB047600AB17AA /* Variant Selection */,
847612601CAB047600AB17AA /* View Controllers */,
);
path = "Product View";
sourceTree = "<group>";
};
847612511CAB047600AB17AA /* Variant Selection */ = {
isa = PBXGroup;
children = (
8476125A1CAB047600AB17AA /* OptionBreadCrumbsView.h */,
8476125B1CAB047600AB17AA /* OptionBreadCrumbsView.m */,
847612521CAB047600AB17AA /* OptionSelectionNavigationController.h */,
847612531CAB047600AB17AA /* OptionSelectionNavigationController.m */,
847612541CAB047600AB17AA /* OptionSelectionViewController.h */,
847612551CAB047600AB17AA /* OptionSelectionViewController.m */,
847612561CAB047600AB17AA /* OptionValueCell.h */,
847612571CAB047600AB17AA /* OptionValueCell.m */,
8476125C1CAB047600AB17AA /* VariantOptionView.h */,
8476125D1CAB047600AB17AA /* VariantOptionView.m */,
847612581CAB047600AB17AA /* VariantSelectionPresentationController.h */,
847612591CAB047600AB17AA /* VariantSelectionPresentationController.m */,
8476125E1CAB047600AB17AA /* VariantSelectionViewController.h */,
8476125F1CAB047600AB17AA /* VariantSelectionViewController.m */,
);
path = "Variant Selection";
sourceTree = "<group>";
};
847612601CAB047600AB17AA /* View Controllers */ = {
isa = PBXGroup;
children = (
842799641CB31498003AD0CE /* PaymentViewController.h */,
842799651CB31498003AD0CE /* PaymentViewController.m */,
84BA52EC1CB2E83C00AB1560 /* NavigationController.h */,
84BA52ED1CB2E83C00AB1560 /* NavigationController.m */,
);
path = "View Controllers";
sourceTree = "<group>";
};
8476128F1CAB059100AB17AA /* PaymentButton */ = {
isa = PBXGroup;
children = (
847612901CAB059100AB17AA /* ImageKit.h */,
847612911CAB059100AB17AA /* ImageKit.m */,
847612921CAB059100AB17AA /* UIButton+PaymentButton.h */,
847612931CAB059100AB17AA /* UIButton+PaymentButton.m */,
847612941CAB059100AB17AA /* UIImage+PaymentButton.h */,
847612951CAB059100AB17AA /* UIImage+PaymentButton.m */,
);
path = PaymentButton;
sourceTree = "<group>";
};
847612991CAB05BE00AB17AA /* UIKit Additions */ = {
isa = PBXGroup;
children = (
8476129A1CAB05BE00AB17AA /* UIColor+BUYAdditions.h */,
8476129B1CAB05BE00AB17AA /* UIColor+BUYAdditions.m */,
8476129C1CAB05BE00AB17AA /* UIFont+BUYAdditions.h */,
8476129D1CAB05BE00AB17AA /* UIFont+BUYAdditions.m */,
8476129E1CAB05BE00AB17AA /* UIImage+BUYAdditions.h */,
8476129F1CAB05BE00AB17AA /* UIImage+BUYAdditions.m */,
);
path = "UIKit Additions";
sourceTree = "<group>";
};
90B262451BB18BEF006D888F /* Table View Cells */ = {
isa = PBXGroup;
children = (
......@@ -155,9 +377,9 @@
BE3437901BC5C18400C71330 /* Products */ = {
isa = PBXGroup;
children = (
BE34379B1BC5C18400C71330 /* Mobile Buy SDK Tests.xctest */,
BE34379D1BC5C18400C71330 /* Buy.framework */,
BE34379F1BC5C18400C71330 /* Buy.framework */,
BE34379D1BC5C18400C71330 /* Buy.framework */,
BE34379B1BC5C18400C71330 /* Mobile Buy SDK Tests.xctest */,
);
name = Products;
sourceTree = "<group>";
......@@ -183,15 +405,19 @@
BE8B824D1B8CF49D00E3F871 /* Mobile Buy SDK Advanced Sample */ = {
isa = PBXGroup;
children = (
BE5E28451B94F5C300D2ECB5 /* Mobile Buy SDK Advanced Sample.entitlements */,
BE8B82971B8E6A7100E3F871 /* Operations */,
BE8B82961B8E6A6900E3F871 /* View Controllers */,
BE948D4C1B95087A009AB20B /* Images.xcassets */,
BE8B82521B8CF49D00E3F871 /* AppDelegate.h */,
BE8B82531B8CF49D00E3F871 /* AppDelegate.m */,
BE8B825B1B8CF49D00E3F871 /* Main.storyboard */,
847612231CAB047600AB17AA /* Appearance */,
8476128F1CAB059100AB17AA /* PaymentButton */,
BE948D4C1B95087A009AB20B /* Images.xcassets */,
BE8B82601B8CF49D00E3F871 /* LaunchScreen.xib */,
BE8B825B1B8CF49D00E3F871 /* Main.storyboard */,
BE5E28451B94F5C300D2ECB5 /* Mobile Buy SDK Advanced Sample.entitlements */,
BE8B82971B8E6A7100E3F871 /* Operations */,
8476122E1CAB047600AB17AA /* Product View */,
BE8B824E1B8CF49D00E3F871 /* Supporting Files */,
847612991CAB05BE00AB17AA /* UIKit Additions */,
BE8B82961B8E6A6900E3F871 /* View Controllers */,
);
path = "Mobile Buy SDK Advanced Sample";
sourceTree = "<group>";
......@@ -331,6 +557,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8476126D1CAB047600AB17AA /* ActionableFooterView.xib in Resources */,
BE948D4D1B95087A009AB20B /* Images.xcassets in Resources */,
BE8B825D1B8CF49D00E3F871 /* Main.storyboard in Resources */,
BE8B82621B8CF49D00E3F871 /* LaunchScreen.xib in Resources */,
......@@ -344,21 +571,56 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
847612A01CAB05BE00AB17AA /* UIColor+BUYAdditions.m in Sources */,
847612A11CAB05BE00AB17AA /* UIFont+BUYAdditions.m in Sources */,
BE948D491B9500DC009AB20B /* GetCompletionStatusOperation.m in Sources */,
8476127B1CAB047600AB17AA /* HeaderBackgroundView.m in Sources */,
BE8B82951B8E65D700E3F871 /* PreCheckoutViewController.m in Sources */,
8476127F1CAB047600AB17AA /* OptionSelectionViewController.m in Sources */,
8476127C1CAB047600AB17AA /* HeaderOverlayView.m in Sources */,
8476127A1CAB047600AB17AA /* ProductViewHeader.m in Sources */,
847612841CAB047600AB17AA /* VariantSelectionViewController.m in Sources */,
90B2623E1BB0A47B006D888F /* ProductViewControllerThemeStyleTableViewCell.m in Sources */,
847612801CAB047600AB17AA /* OptionValueCell.m in Sources */,
847612821CAB047600AB17AA /* OptionBreadCrumbsView.m in Sources */,
902C9B921BB08FF500FC456E /* SummaryItemsTableViewCell.m in Sources */,
8476127D1CAB047600AB17AA /* ProductViewNavigationController.m in Sources */,
8476126F1CAB047600AB17AA /* ErrorView.m in Sources */,
847612811CAB047600AB17AA /* VariantSelectionPresentationController.m in Sources */,
847612781CAB047600AB17AA /* ProductViewController.m in Sources */,
8476126A1CAB047600AB17AA /* VisualEffectView.m in Sources */,
847612721CAB047600AB17AA /* ProductViewPresentationController.m in Sources */,
902C9B8C1BB06BF300FC456E /* GetShopOperation.m in Sources */,
847612731CAB047600AB17AA /* ProductDescriptionCell.m in Sources */,
8476126C1CAB047600AB17AA /* ActionableFooterView.m in Sources */,
902C9B8F1BB0729F00FC456E /* ShippingRateTableViewCell.m in Sources */,
BE8B829A1B8E72CC00E3F871 /* CheckoutViewController.m in Sources */,
847612681CAB047600AB17AA /* Theme+Additions.m in Sources */,
847612831CAB047600AB17AA /* VariantOptionView.m in Sources */,
847612981CAB059100AB17AA /* UIImage+PaymentButton.m in Sources */,
8476126E1CAB047600AB17AA /* CheckoutButton.m in Sources */,
8476127E1CAB047600AB17AA /* OptionSelectionNavigationController.m in Sources */,
847612971CAB059100AB17AA /* UIButton+PaymentButton.m in Sources */,
847612761CAB047600AB17AA /* ProductVariantCell.m in Sources */,
847612691CAB047600AB17AA /* Theme.m in Sources */,
847612701CAB047600AB17AA /* GradientView.m in Sources */,
90B262441BB18B10006D888F /* ProductViewControllerThemeTintColorTableViewCell.m in Sources */,
90B262411BB0A726006D888F /* ProductViewControllerToggleTableViewCell.m in Sources */,
847612961CAB059100AB17AA /* ImageKit.m in Sources */,
847612A21CAB05BE00AB17AA /* UIImage+BUYAdditions.m in Sources */,
847612771CAB047600AB17AA /* ProductView.m in Sources */,
9079F5F41BB1AAA100CB1B35 /* CollectionListViewController.m in Sources */,
BE8B82541B8CF49D00E3F871 /* AppDelegate.m in Sources */,
BE8B827B1B8CFF0E00E3F871 /* GetShippingRatesOperation.m in Sources */,
842799661CB31498003AD0CE /* PaymentViewController.m in Sources */,
847612671CAB047600AB17AA /* DisclosureIndicatorView.m in Sources */,
BE8B82571B8CF49D00E3F871 /* ProductListViewController.m in Sources */,
BE8B82511B8CF49D00E3F871 /* main.m in Sources */,
BE8B82921B8E612700E3F871 /* ShippingRatesTableViewController.m in Sources */,
847612711CAB047600AB17AA /* AsyncImageView.m in Sources */,
84BA52EE1CB2E83C00AB1560 /* NavigationController.m in Sources */,
847612751CAB047600AB17AA /* ProductImageCell.m in Sources */,
847612741CAB047600AB17AA /* ProductHeaderCell.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
//
// BUYTheme+Additions.h
// Theme+Additions.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,52 +24,13 @@
// THE SOFTWARE.
//
#import "BUYTheme.h"
#import "BUYPaymentButton.h"
#import "Theme.h"
#define BUY_RGB(r, g, b) BUY_RGBA(r, g, b, 1)
#define BUY_RGBA(r, g, b, a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]
@interface BUYTheme (Additions)
@interface Theme (Additions)
#pragma mark - Colors
/**
* The product view background color used in various views based on the theme
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)backgroundColor;
/**
* The background color for selected table view cells based on the theme
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)selectedBackgroundColor;
/**
* The product view's table view separator color based on the theme
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)separatorColor;
/**
* The product view's table view disclosure indicator color based on the theme
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)disclosureIndicatorColor;
/**
* The Checkout button's text color based on the theme
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)checkoutButtonTextColor;
/**
* Top gradient color
*
* @return A dark color
......@@ -77,82 +38,33 @@
+ (UIColor*)topGradientViewTopColor;
/**
* The background color for the error toast view in the product view
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)errorTintOverlayColor;
/**
* The navigation bar's title color based on the theme
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)navigationBarTitleColor;
/**
* The variant selection's navigation bar's title color based on the theme
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)navigationBarTitleVariantSelectionColor;
/**
* The color for the product title text
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)productTitleColor;
/**
* The color for the product "compare at" text
*
* @return The color appropriate for the BUYThemeStyle
* @return The color appropriate for the ThemeStyle
*/
+ (UIColor*)comparePriceTextColor;
/**
* The color for the product's description text
*
* @return The color appropriate for the BUYThemeStyle
* @return The color appropriate for the ThemeStyle
*/
+ (UIColor*)descriptionTextColor;
/**
* The color for the variant option name text
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)variantOptionNameTextColor;
/**
* The color for the variant price text
*
* @return The color appropriate for the BUYThemeStyle
* @return The color appropriate for the ThemeStyle
*/
+ (UIColor*)variantPriceTextColor;
/**
* The color for the variant "sold out" text
*
* @return The color appropriate for the BUYThemeStyle
* @return The color appropriate for the ThemeStyle
*/
+ (UIColor*)variantSoldOutTextColor;
/**
* The background color for the variant selection bread crumb view
*
* @return The color appropriate for the BUYThemeStyle
*/
- (UIColor*)variantBreadcrumbsBackground;
/**
* The text color for the variant selection bread crumb view
*
* @return The color appropriate for the BUYThemeStyle
*/
+ (UIColor*)variantBreadcrumbsTextColor;
#pragma mark - Padding and Sizes
/**
......@@ -258,34 +170,4 @@ extern CGFloat const kBuyBottomGradientHeightWithoutPageControl;
*/
+ (UIFont*)errorLabelFont;
#pragma mark - Misc
/**
* Blur effect style for for the product view
*
* @return The blur effect appropriate for the theme
*/
- (UIBlurEffect*)blurEffect;
/**
* Activity indicator style for the product view when loading a product
*
* @return The activity indicator style appropriate for the theme
*/
- (UIActivityIndicatorViewStyle)activityIndicatorViewStyle;
/**
* Navigation bar style for the product view
*
* @return The navigation bar style appropriate for the theme
*/
- (UIBarStyle)navigationBarStyle;
/**
* Apple Pay button style for the product view
*
* @return The button style appropriate for the theme
*/
- (BUYPaymentButtonStyle)paymentButtonStyle;
@end
//
// BUYTheme+Additions.m
// Theme+Additions.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,63 +24,19 @@
// THE SOFTWARE.
//
#import "BUYTheme+Additions.h"
#import "Theme+Additions.h"
#import "UIFont+BUYAdditions.h"
#import "UIColor+BUYAdditions.h"
@implementation BUYTheme (Additions)
@implementation Theme (Additions)
#pragma mark - Colors
- (UIColor*)backgroundColor
{
return self.style == BUYThemeStyleDark ? BUY_RGB(26, 26, 26) : [UIColor whiteColor];
}
- (UIColor*)selectedBackgroundColor
{
return self.style == BUYThemeStyleDark ? BUY_RGB(60, 60, 60) : BUY_RGB(242, 242, 242);
}
- (UIColor*)separatorColor
{
return self.style == BUYThemeStyleDark ? BUY_RGB(76, 76, 76) : BUY_RGB(217, 217, 217);
}
- (UIColor*)disclosureIndicatorColor
{
return self.style == BUYThemeStyleDark ? BUY_RGB(76, 76, 76) : BUY_RGB(191, 191, 191);
}
- (UIColor*)checkoutButtonTextColor
{
return self.style == BUYThemeStyleLight ? [UIColor whiteColor] : [UIColor blackColor];
}
+ (UIColor*)topGradientViewTopColor
{
return [UIColor colorWithWhite:0 alpha:0.25f];
}
- (UIColor*)errorTintOverlayColor
{
return self.style == BUYThemeStyleDark ? BUY_RGBA(255, 66, 66, 0.75f) : BUY_RGBA(209, 44, 44, 0.75f);
}
- (UIColor*)navigationBarTitleColor
{
return self.style == BUYThemeStyleDark ? [UIColor whiteColor] : [UIColor blackColor];
}
- (UIColor*)navigationBarTitleVariantSelectionColor
{
return self.style == BUYThemeStyleDark ? BUY_RGB(229, 229, 229) : [UIColor blackColor];
}
- (UIColor*)productTitleColor
{
return self.style == BUYThemeStyleDark ? [UIColor whiteColor] : [UIColor blackColor];
}
+ (UIColor*)comparePriceTextColor
{
return [UIColor colorWithWhite:0.4f alpha:1];
......@@ -91,11 +47,6 @@
return [UIColor colorWithWhite:0.4f alpha:1];
}
- (UIColor*)variantOptionNameTextColor
{
return self.style == BUYThemeStyleDark ? BUY_RGB(76, 76, 76) : BUY_RGB(191, 191, 191);
}
+ (UIColor*)variantPriceTextColor
{
return BUY_RGB(140, 140, 140);
......@@ -106,16 +57,6 @@
return BUY_RGB(220, 96, 96);
}
- (UIColor*)variantBreadcrumbsBackground
{
return self.style == BUYThemeStyleDark ? BUY_RGB(13, 13, 13) : BUY_RGB(229, 229, 229);
}
+ (UIColor*)variantBreadcrumbsTextColor
{
return BUY_RGB(140, 140, 140);
}
#pragma mark - Padding and Sizes
CGFloat const kBuyPaddingSmall = 8.0f;
......@@ -180,26 +121,4 @@ CGFloat const kBuyBottomGradientHeightWithoutPageControl = 20.0f;
return [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
}
#pragma mark - Misc
- (UIBlurEffect*)blurEffect
{
return [UIBlurEffect effectWithStyle:self.style == BUYThemeStyleDark ? UIBlurEffectStyleDark : UIBlurEffectStyleLight];
}
- (UIActivityIndicatorViewStyle)activityIndicatorViewStyle
{
return self.style == BUYThemeStyleDark ? UIActivityIndicatorViewStyleWhite : UIActivityIndicatorViewStyleGray;
}
- (UIBarStyle)navigationBarStyle
{
return self.style == BUYThemeStyleDark ? UIBarStyleBlack : UIBarStyleDefault;
}
- (BUYPaymentButtonStyle)paymentButtonStyle
{
return self.style == BUYThemeStyleLight ? BUYPaymentButtonStyleBlack : BUYPaymentButtonStyleWhite;
}
@end
//
// BUYTheme.h
// Theme.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -29,49 +29,38 @@
/**
* The theme style for the BUYProductViewController
*/
typedef NS_ENUM(NSInteger, BUYThemeStyle){
typedef NS_ENUM(NSInteger, ThemeStyle) {
/**
* Light theme style, providing light backgrounds and light styled UIVisualEffectViews
*/
BUYThemeStyleLight,
ThemeStyleLight,
/**
* Dark theme style, providing dark backgrounds and dark styled UIVisualEffectViews
*/
BUYThemeStyleDark
ThemeStyleDark
};
/**
* This class provides properties used for theming the BUYProductViewController UI elements.
*/
@interface BUYTheme : NSObject
@interface Theme : NSObject
/**
* Used for the highlight color
* Used for the highlight color. Default is the tintColor of the app's keyWindow if not nil,
* other falls back to a "Shopify green" color
*/
@property (nonatomic, strong) UIColor *tintColor;
/**
* Theme style for the views
*/
@property (nonatomic, assign) BUYThemeStyle style;
@property (nonatomic, assign) ThemeStyle style;
/**
* Determines whether a blurred scaled-up product image should appear behind the product details. Default is YES
*/
@property (nonatomic, assign) BOOL showsProductImageBackground;
@end
/**
* Protocol to enable theming for any class
*/
@protocol BUYThemeable <NSObject>
/**
* Sets the theme for the view, and its subviews
*
* @param theme The new theme to apply
*/
- (void)setTheme:(BUYTheme *)theme;
- (void)styleProductViewController;
@end
//
// Theme.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "DisclosureIndicatorView.h"
#import "ErrorView.h"
#import "NavigationController.h"
#import "OptionSelectionNavigationController.h"
#import "OptionValueCell.h"
#import "ProductDescriptionCell.h"
#import "ProductHeaderCell.h"
#import "ProductVariantCell.h"
#import "OptionBreadCrumbsView.h"
#import "HeaderOverlayView.h"
#import "ProductViewNavigationController.h"
#import "ProductViewController.h"
#import "ProductView.h"
#import "Theme.h"
#import "Theme+Additions.h"
#import "VariantOptionView.h"
#import "VisualEffectView.h"
#import "UIColor+BUYAdditions.h"
#import "CheckoutButton.h"
@implementation Theme
- (instancetype)init
{
self = [super init];
if (self) {
self.style = ThemeStyleLight;
self.showsProductImageBackground = YES;
}
return self;
}
- (void)styleProductViewController
{
UIColor *contentBackgroundColor = self.style == ThemeStyleDark ? BUY_RGB(26, 26, 26) : [UIColor whiteColor];
UIColor *contentBackgroundSelectedColor = self.style == ThemeStyleDark ? BUY_RGB(60, 60, 60) : BUY_RGB(242, 242, 242);
UIColor *contentBackgroundComplimentaryColor = self.style == ThemeStyleDark ? [UIColor whiteColor] : [UIColor blackColor];
UIColor *primaryColor = self.tintColor;
UIColor *secondaryLightColor = self.style == ThemeStyleDark ? BUY_RGB(13, 13, 13) : BUY_RGB(229, 229, 229);
UIColor *secondaryMediumColor = self.style == ThemeStyleDark ? BUY_RGB(76, 76, 76) : BUY_RGB(217, 217, 217);
UIColor *secondaryDarkColor = self.style == ThemeStyleDark ? BUY_RGB(76, 76, 76) : BUY_RGB(191, 191, 191);
UIBarStyle barStyle = self.style == ThemeStyleDark ? UIBarStyleBlack : UIBarStyleDefault;
UIColor *errorColor = self.style == ThemeStyleDark ? BUY_RGBA(255, 66, 66, 0.75f) : BUY_RGBA(209, 44, 44, 0.75f);
UIBlurEffectStyle blurEffectStyle = self.style == ThemeStyleDark ? UIBlurEffectStyleDark : UIBlurEffectStyleLight;
UIScrollViewIndicatorStyle scrollViewIndicatorStyle = self.style == ThemeStyleDark ? UIScrollViewIndicatorStyleWhite : UIScrollViewIndicatorStyleDefault;
// Add some Theme-specific styling:
UIColor *navigationBarTitleColor = self.style == ThemeStyleDark ? [UIColor whiteColor] : [UIColor blackColor];
UIColor *navigationBarTitleVariantSelectionColor = self.style == ThemeStyleDark ? BUY_RGB(229, 229, 229) : [UIColor blackColor];
if ([[UINavigationBar class] respondsToSelector:@selector(appearanceWhenContainedInInstancesOfClasses:)]) {
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[OptionSelectionNavigationController class]]] setTitleTextAttributes:@{ NSForegroundColorAttributeName : navigationBarTitleVariantSelectionColor }];
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[NavigationController class]]] setTitleTextAttributes:@{ NSForegroundColorAttributeName : navigationBarTitleColor }];
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[NavigationController class]]] setTintColor:primaryColor];
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[NavigationController class]]] setBarStyle:barStyle];
[[UITableView appearanceWhenContainedInInstancesOfClasses:@[[NavigationController class]]] setBackgroundColor:contentBackgroundColor];
[[UITableView appearanceWhenContainedInInstancesOfClasses:@[[NavigationController class]]] setSeparatorColor:secondaryMediumColor];
[[UIScrollView appearanceWhenContainedInInstancesOfClasses:@[[NavigationController class]]] setIndicatorStyle:scrollViewIndicatorStyle];
[[UIActivityIndicatorView appearanceWhenContainedInInstancesOfClasses:@[[ProductViewController class]]] setColor:primaryColor];
} else {
[[UINavigationBar appearanceWhenContainedIn:[OptionSelectionNavigationController class], nil] setTitleTextAttributes:@{ NSForegroundColorAttributeName : navigationBarTitleVariantSelectionColor }];
[[UINavigationBar appearanceWhenContainedIn:[NavigationController class], nil] setTitleTextAttributes:@{ NSForegroundColorAttributeName : navigationBarTitleColor }];
[[UINavigationBar appearanceWhenContainedIn:[NavigationController class], nil] setTintColor:primaryColor];
[[UINavigationBar appearanceWhenContainedIn:[NavigationController class], nil] setBarStyle:barStyle];
[[UITableView appearanceWhenContainedIn:[NavigationController class], nil] setBackgroundColor:contentBackgroundColor];
[[UITableView appearanceWhenContainedIn:[NavigationController class], nil] setSeparatorColor:secondaryMediumColor];
[[UIScrollView appearanceWhenContainedIn:[NavigationController class], nil] setIndicatorStyle:scrollViewIndicatorStyle];
[[UIActivityIndicatorView appearanceWhenContainedIn:[ProductViewController class], nil] setColor:primaryColor];
}
[[ProductView appearance] setTintColor:primaryColor];
[[ProductView appearance] setShowsProductImageBackground:self.showsProductImageBackground];
[[VariantOptionView appearance] setOptionNameTextColor:self.style == ThemeStyleDark ? BUY_RGB(76, 76, 76) : BUY_RGB(191, 191, 191)];
[[VisualEffectView appearance] setBlurEffectStyle:blurEffectStyle];
[[CheckoutButton appearance] setBackgroundColor:primaryColor];
[[CheckoutButton appearance] setTextColor:contentBackgroundColor];
[[DisclosureIndicatorView appearance] setTintColor:secondaryDarkColor];
[[ErrorView appearance] setOverlayColor:errorColor];
[[ProductView appearance] setBackgroundColor:contentBackgroundColor];
[[ProductHeaderCell appearance] setProductTitleColor:contentBackgroundComplimentaryColor];
[[ProductHeaderCell appearance] setBackgroundColor:contentBackgroundColor];
[[ProductDescriptionCell appearance] setBackgroundColor:contentBackgroundColor];
[[ProductVariantCell appearance] setBackgroundColor:contentBackgroundColor];
[[ProductVariantCell appearance] setSelectedBackgroundViewBackgroundColor:contentBackgroundSelectedColor];
[[VariantOptionView appearance] setBackgroundColor:contentBackgroundColor];
[[OptionValueCell appearance] setTintColor:primaryColor];
[[OptionValueCell appearance] setBackgroundColor:contentBackgroundColor];
[[OptionValueCell appearance] setSelectedBackgroundViewBackgroundColor:contentBackgroundSelectedColor];
[[HeaderOverlayView appearance] setOverlayBackgroundColor:contentBackgroundColor];
[[OptionBreadCrumbsView appearance] setBackgroundColor:secondaryLightColor];
[[OptionBreadCrumbsView appearance] setVariantOptionTextColor:BUY_RGB(140, 140, 140)];
}
@end
//
// VisualEffectView.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import UIKit;
@interface VisualEffectView : UIVisualEffectView
- (void)setBlurEffectStyle:(UIBlurEffectStyle)blurEffectStyle UI_APPEARANCE_SELECTOR;
@end
//
// VisualEffectView.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "VisualEffectView.h"
@implementation VisualEffectView
- (void)setBlurEffectStyle:(UIBlurEffectStyle)blurEffectStyle
{
self.effect = [UIBlurEffect effectWithStyle:blurEffectStyle];
}
@end
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="rS3-R9-Ivy">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="rS3-R9-Ivy">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
</dependencies>
<scenes>
<!--Master-->
......@@ -11,6 +11,7 @@
<navigationController title="Master" id="rS3-R9-Ivy" sceneMemberID="viewController">
<navigationBar key="navigationBar" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="yXu-0R-QUA">
<autoresizingMask key="autoresizingMask"/>
<animations/>
</navigationBar>
<connections>
<segue destination="pGg-6v-bdr" kind="relationship" relationship="rootViewController" id="RxB-wf-QIq"/>
......@@ -27,6 +28,7 @@
<tableView key="view" opaque="NO" clipsSubviews="YES" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="mLL-gJ-YKr">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="calibratedRGB"/>
<sections/>
<connections>
......
......@@ -25,8 +25,9 @@
//
@import UIKit;
@class BUYCheckout;
@class BUYClient;
@import Buy;
@import PassKit;
@import SafariServices;
extern NSString * const CheckoutCallbackNotification;
......
......@@ -27,13 +27,10 @@
#import "CheckoutViewController.h"
#import "GetCompletionStatusOperation.h"
#import "SummaryItemsTableViewCell.h"
#import "ProductListViewController.h"
@import Buy;
@import PassKit;
@import SafariServices;
#import "UIButton+PaymentButton.h"
NSString * const CheckoutCallbackNotification = @"CheckoutCallbackNotification";
NSString * const MerchantId = @"";
@interface CheckoutViewController () <GetCompletionStatusOperationDelegate, SFSafariViewControllerDelegate, PKPaymentAuthorizationViewControllerDelegate>
......@@ -87,7 +84,7 @@ NSString * const CheckoutCallbackNotification = @"CheckoutCallbackNotification";
[webCheckoutButton addTarget:self action:@selector(checkoutOnWeb) forControlEvents:UIControlEventTouchUpInside];
[footerView addSubview:webCheckoutButton];
UIButton *applePayButton = [BUYPaymentButton buttonWithType:BUYPaymentButtonTypeBuy style:BUYPaymentButtonStyleBlack];
UIButton *applePayButton = [UIButton paymentButtonWithType:PaymentButtonTypeBuy style:PaymentButtonStyleBlack];
applePayButton.translatesAutoresizingMaskIntoConstraints = NO;
[applePayButton addTarget:self action:@selector(checkoutWithApplePay) forControlEvents:UIControlEventTouchUpInside];
[footerView addSubview:applePayButton];
......@@ -292,7 +289,7 @@ NSString * const CheckoutCallbackNotification = @"CheckoutCallbackNotification";
{
PKPaymentRequest *paymentRequest = [[PKPaymentRequest alloc] init];
[paymentRequest setMerchantIdentifier:MERCHANT_ID];
[paymentRequest setMerchantIdentifier:MerchantId];
[paymentRequest setRequiredBillingAddressFields:PKAddressFieldAll];
[paymentRequest setRequiredShippingAddressFields:self.checkout.requiresShipping ? PKAddressFieldAll : PKAddressFieldEmail|PKAddressFieldPhone];
[paymentRequest setSupportedNetworks:@[PKPaymentNetworkVisa, PKPaymentNetworkMasterCard]];
......
//
// ImageKit.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import Foundation;
@import UIKit;
/**
* Image generator for a variety of images using the BUYProductViewController.
*/
@interface ImageKit : NSObject
/**
* Generates a close button image for the variant selection navigation bar.
*
* @param frame The frame size of the image
*
* @return A close button image
*/
+ (UIImage*)imageOfVariantCloseImageWithFrame: (CGRect)frame;
/**
* Generates a checkmark image for use of displaying the previously selected variant
*
* @param frame The frame size of the image
*
* @return A checkmark for the previous variant selection
*/
+ (UIImage*)imageOfPreviousSelectionIndicatorImageWithFrame: (CGRect)frame;
/**
* Generates a custom disclosure indicator image
*
* @param frame The frame size of the image
* @param color The color for the disclosure indicator
*
* @return A disclusore indicator image
*/
+ (UIImage*)imageOfDisclosureIndicatorImageWithFrame: (CGRect)frame color:(UIColor*)color;
/**
* Generates a close button image for the product view's navigation bar
*
* @param frame The frame size of the image
* @param color The color for the close button image
* @param hasShadow True if the X should have a drop shadow
*
* @return A close button image
*/
+ (UIImage*)imageOfProductViewCloseImageWithFrame: (CGRect)frame color:(UIColor*)color hasShadow:(BOOL)hasShadow;
/**
* Generates a custom back button image for the variant selection navigation bar
*
* @param frame The frame size of the image
*
* @return A custom back button image
*/
+ (UIImage*)imageOfVariantBackImageWithFrame: (CGRect)frame;
@end
//
// ImageKit.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "ImageKit.h"
@implementation ImageKit
#pragma mark Drawing Methods
+ (void)drawVariantCloseImageWithFrame: (CGRect)frame
{
//// Color Declarations
UIColor* closeColor = [UIColor colorWithRed: 0.596f green: 0.596f blue: 0.596f alpha: 1];
//// Variant Close Icon Drawing
UIBezierPath* variantCloseIconPath = UIBezierPath.bezierPath;
[variantCloseIconPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.13971f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.16669f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.93886f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.87988f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.86029f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.95000f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.06114f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.23681f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.13971f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.16669f * CGRectGetHeight(frame))];
[variantCloseIconPath closePath];
[variantCloseIconPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.86029f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.16669f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.93886f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.23681f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.13971f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.95000f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.06114f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.87988f * CGRectGetHeight(frame))];
[variantCloseIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.86029f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.16669f * CGRectGetHeight(frame))];
[variantCloseIconPath closePath];
[closeColor setFill];
[variantCloseIconPath fill];
}
+ (void)drawPreviousSelectionIndicatorImageWithFrame: (CGRect)frame
{
//// Color Declarations
UIColor* indicatorColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
//// Previous Selection Indicator Drawing
UIBezierPath* previousSelectionIndicatorPath = UIBezierPath.bezierPath;
[previousSelectionIndicatorPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.50000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 1.00000f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.00000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50000f * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.22386f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 1.00000f * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.00000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.77614f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.50000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.00000f * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.00000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.22386f * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.22386f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.00000f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 1.00000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50000f * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 0.77614f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.00000f * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 1.00000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.22386f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addCurveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.50000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 1.00000f * CGRectGetHeight(frame)) controlPoint1: CGPointMake(CGRectGetMinX(frame) + 1.00000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.77614f * CGRectGetHeight(frame)) controlPoint2: CGPointMake(CGRectGetMinX(frame) + 0.77614f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 1.00000f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath closePath];
[previousSelectionIndicatorPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.74926f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.28003f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.40000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.62929f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.25074f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.48003f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.18002f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.55074f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.39926f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.76997f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.40000f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.76924f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.40073f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.76997f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.81997f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.35074f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.74926f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.28003f * CGRectGetHeight(frame))];
[previousSelectionIndicatorPath closePath];
[indicatorColor setFill];
[previousSelectionIndicatorPath fill];
}
+ (void)drawDisclosureIndicatorImageWithFrame: (CGRect)frame color:(UIColor*)arrowColor
{
//// Disclosure Indicator Drawing
UIBezierPath* disclosureIndicatorPath = UIBezierPath.bezierPath;
[disclosureIndicatorPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.25149f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.06878f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.93995f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.49908f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79854f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.58746f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.11004f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.15717f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.25149f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.06878f * CGRectGetHeight(frame))];
[disclosureIndicatorPath closePath];
[disclosureIndicatorPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79854f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.41253f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.93995f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50092f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.25149f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.93121f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.11004f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.84282f * CGRectGetHeight(frame))];
[disclosureIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79854f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.41253f * CGRectGetHeight(frame))];
[disclosureIndicatorPath closePath];
[arrowColor setFill];
[disclosureIndicatorPath fill];
}
+ (void)drawProductViewCloseImageWithFrame: (CGRect)frame color:(UIColor *)closeColor2 hasShadow:(BOOL)hasShadow
{
//// General Declarations
CGContextRef context = UIGraphicsGetCurrentContext();
//// Color Declarations
UIColor* closeShadowColor = [UIColor colorWithRed: 0 green: 0 blue: 0 alpha: 1];
//// Shadow Declarations
NSShadow* closeDropShadow = [[NSShadow alloc] init];
[closeDropShadow setShadowColor: [closeShadowColor colorWithAlphaComponent: 0.15f]];
[closeDropShadow setShadowOffset: CGSizeMake(0.1f, 1.1f)];
[closeDropShadow setShadowBlurRadius: 2];
//// Close Icon Drawing
UIBezierPath* closeIconPath = UIBezierPath.bezierPath;
[closeIconPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.11431f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.09548f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.85907f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.84024f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79479f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.90452f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.05002f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.15976f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.11431f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.09548f * CGRectGetHeight(frame))];
[closeIconPath closePath];
[closeIconPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79479f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.09548f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.85907f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.15976f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.11431f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.90452f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.05002f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.84024f * CGRectGetHeight(frame))];
[closeIconPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.79479f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.09548f * CGRectGetHeight(frame))];
[closeIconPath closePath];
CGContextSaveGState(context);
if (hasShadow) {
CGContextSetShadowWithColor(context, closeDropShadow.shadowOffset, closeDropShadow.shadowBlurRadius, [closeDropShadow.shadowColor CGColor]);
}
[closeColor2 setFill];
[closeIconPath fill];
CGContextRestoreGState(context);
}
+ (void)drawVariantBackImageWithFrame: (CGRect)frame
{
//// Color Declarations
UIColor* indicatorColor3 = [UIColor colorWithRed: 0.596f green: 0.596f blue: 0.596f alpha: 1];
//// Variant Back Indicator Drawing
UIBezierPath* variantBackIndicatorPath = UIBezierPath.bezierPath;
[variantBackIndicatorPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.20956f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.42225f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.86663f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.86029f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.74878f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.93886f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.09171f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.50082f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.20956f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.42225f * CGRectGetHeight(frame))];
[variantBackIndicatorPath closePath];
[variantBackIndicatorPath moveToPoint: CGPointMake(CGRectGetMinX(frame) + 0.74878f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.06114f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.86663f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.13971f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.20956f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.57775f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.09171f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.49918f * CGRectGetHeight(frame))];
[variantBackIndicatorPath addLineToPoint: CGPointMake(CGRectGetMinX(frame) + 0.74878f * CGRectGetWidth(frame), CGRectGetMinY(frame) + 0.06114f * CGRectGetHeight(frame))];
[variantBackIndicatorPath closePath];
[indicatorColor3 setFill];
[variantBackIndicatorPath fill];
}
#pragma mark Generated Images
+ (UIImage*)imageOfVariantCloseImageWithFrame: (CGRect)frame
{
UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0.0f);
[ImageKit drawVariantCloseImageWithFrame: frame];
UIImage* imageOfVariantCloseImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageOfVariantCloseImage;
}
+ (UIImage*)imageOfPreviousSelectionIndicatorImageWithFrame: (CGRect)frame
{
UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0.0f);
[ImageKit drawPreviousSelectionIndicatorImageWithFrame: frame];
UIImage* imageOfPreviousSelectionIndicatorImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageOfPreviousSelectionIndicatorImage;
}
+ (UIImage*)imageOfDisclosureIndicatorImageWithFrame: (CGRect)frame color:(UIColor*)color;
{
UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0.0f);
[ImageKit drawDisclosureIndicatorImageWithFrame: frame color:color];
UIImage* imageOfDisclosureIndicatorImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageOfDisclosureIndicatorImage;
}
+ (UIImage*)imageOfProductViewCloseImageWithFrame: (CGRect)frame color:(UIColor*)color hasShadow:(BOOL)hasShadow;
{
UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0.0f);
[ImageKit drawProductViewCloseImageWithFrame: frame color:color hasShadow:hasShadow];
UIImage* imageOfProductViewCloseImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageOfProductViewCloseImage;
}
+ (UIImage*)imageOfVariantBackImageWithFrame: (CGRect)frame
{
UIGraphicsBeginImageContextWithOptions(frame.size, NO, 0.0f);
[ImageKit drawVariantBackImageWithFrame: frame];
UIImage* imageOfVariantBackImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageOfVariantBackImage;
}
@end
//
// UIButton+PaymentButton.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import UIKit;
typedef NS_ENUM(NSInteger, PaymentButtonStyle) {
PaymentButtonStyleWhite = 0,
PaymentButtonStyleWhiteOutline,
PaymentButtonStyleBlack
};
typedef NS_ENUM(NSInteger, PaymentButtonType) {
PaymentButtonTypePlain = 0,
PaymentButtonTypeBuy,
PaymentButtonTypeSetup NS_ENUM_AVAILABLE_IOS(9_0)
};
@interface UIButton (PaymentButton)
+ (UIButton *)paymentButtonWithType:(PaymentButtonType)buttonType style:(PaymentButtonStyle)buttonStyle;
@end
//
// UIButton+PaymentButton.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import PassKit;
#import "CheckoutButton.h"
#import "UIImage+BUYAdditions.h"
#import "UIImage+PaymentButton.h"
#import "UIButton+PaymentButton.h"
@implementation UIButton (PaymentButton)
+ (UIButton *)paymentButtonWithType:(PaymentButtonType)buttonType style:(PaymentButtonStyle)buttonStyle
{
if ([PKPaymentButton class]) {
return [PKPaymentButton buttonWithType:(PKPaymentButtonType)buttonType style:(PKPaymentButtonStyle)buttonStyle];
}
UIButton *button = [CheckoutButton new];
UIColor *fillColor;
UIColor *strokeColor;
switch (buttonStyle) {
case PaymentButtonStyleBlack:
fillColor = [UIColor blackColor];
break;
case PaymentButtonStyleWhite:
fillColor = [UIColor whiteColor];
break;
case PaymentButtonStyleWhiteOutline:
fillColor = [UIColor whiteColor];
strokeColor = [UIColor blackColor];
break;
}
UIImage *backgroundImage = [[UIImage templateImageWithFill:fillColor stroke:strokeColor edgeInsets:UIEdgeInsetsMake(4.0f, 4.0f, 4.0f, 4.0f)] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
[button setBackgroundImage:backgroundImage forState:UIControlStateNormal];
UIImage *image = [UIImage paymentButtonImageWithFrame:CGRectMake(0, 0, 120.0f, 44.0f) style:buttonStyle type:buttonType];
[button setImage:image forState:UIControlStateNormal];
return button;
}
@end
//
// UIImage+PaymentButton.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <UIKit/UIKit.h>
#import "UIButton+PaymentButton.h"
@interface UIImage (PaymentButton)
+ (UIImage *)paymentButtonImageWithFrame:(CGRect)originalFrame style:(PaymentButtonStyle)style type:(PaymentButtonType)type;
@end
......@@ -53,7 +53,7 @@ typedef NS_ENUM(NSInteger, UITableViewDiscountGiftCardSection) {
@implementation PreCheckoutViewController
- (instancetype)initWithClient:(BUYClient *)client checkout:(BUYCheckout *)checkout;
- (instancetype)initWithClient:(BUYClient *)client checkout:(BUYCheckout *)checkout
{
NSParameterAssert(client);
NSParameterAssert(checkout);
......@@ -68,7 +68,8 @@ typedef NS_ENUM(NSInteger, UITableViewDiscountGiftCardSection) {
return self;
}
- (void)viewDidLoad {
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"Add Discount or Gift Card(s)";
......@@ -192,7 +193,7 @@ typedef NS_ENUM(NSInteger, UITableViewDiscountGiftCardSection) {
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
BUYDiscount *discount = [[BUYDiscount alloc] initWithCode:[alertController.textFields[0] text]];
BUYDiscount *discount = [self.client.modelManager discountWithCode:[alertController.textFields[0] text]];
self.checkout.discount = discount;
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
......
//
// ActionableFooterView.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import UIKit;
#import "CheckoutButton.h"
#import "UIButton+PaymentButton.h"
@interface ActionableFooterView : UIView
- (void)setApplePayAvailable:(BOOL)applePayAvailable requiresSetup:(BOOL)requiresSetup;
@property (nonatomic, readonly) CheckoutButton *actionButton;
/**
* On iOS 8.3+ this will be a PKPaymentButton
*/
@property (nonatomic, readonly) UIButton *paymentButton;
@property (nonatomic) BOOL buttonsEnabled;
/**
* A view which sits above the buttons.
* Can be used to add a description or other content to the footer.
*/
@property (nonatomic, readonly) UIView *extensionView;
@property (nonatomic) PaymentButtonStyle paymentButtonStyle UI_APPEARANCE_SELECTOR;
@property (nonatomic) UIColor *separatorColor UI_APPEARANCE_SELECTOR;
@end
//
// ActionableFooterView.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "ActionableFooterView.h"
@interface ActionableFooterView()
@property (nonatomic) BOOL applePayAvailable;
@property (nonatomic) BOOL applePayRequiresSetup;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *applePayLeadingConstraint;
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *firstButtonTrailingConstraint;
@property (strong, nonatomic) IBOutlet CheckoutButton *actionButton;
@property (strong, nonatomic) IBOutlet UIView *paymentButtonContainer;
@property (strong, nonatomic) IBOutlet UIView *extensionView;
@property (strong, nonatomic) UIButton *paymentButton;
@end
@implementation ActionableFooterView
- (instancetype)init
{
return [[NSBundle bundleForClass:self.class] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil].firstObject;
}
- (void)awakeFromNib
{
[super awakeFromNib];
self.actionButton.backgroundColor = nil;
[self.actionButton setTitle:nil forState:UIControlStateNormal];
self.paymentButtonStyle = PaymentButtonStyleBlack;
self.paymentButtonContainer.backgroundColor = nil;
}
- (void)setApplePayAvailable:(BOOL)applePayAvailable requiresSetup:(BOOL)requiresSetup
{
_applePayAvailable = applePayAvailable;
_applePayRequiresSetup = requiresSetup;
self.paymentButtonContainer.hidden = !applePayAvailable;
PaymentButtonType type = self.applePayRequiresSetup ? PaymentButtonTypeSetup : PaymentButtonTypeBuy;
if (!self.paymentButton) {
_paymentButton = [UIButton paymentButtonWithType:type style:self.paymentButtonStyle];
[self.paymentButtonContainer addSubview:self.paymentButton];
self.paymentButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.paymentButtonContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_paymentButton]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_paymentButton)]];
[self.paymentButtonContainer addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_paymentButton]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_paymentButton)]];
}
[self setNeedsUpdateConstraints];
}
- (void)setLayoutMargins:(UIEdgeInsets)layoutMargins
{
[super setLayoutMargins:layoutMargins];
self.applePayLeadingConstraint.constant = self.layoutMargins.left;
}
- (void)layoutSubviews
{
[super layoutSubviews];
[self setNeedsUpdateConstraints];
}
- (void)setButtonsEnabled:(BOOL)buttonsEnabled
{
self.actionButton.enabled = buttonsEnabled;
self.paymentButton.enabled = buttonsEnabled;
self.paymentButton.alpha = buttonsEnabled ? 1.0f : 0.5f;
}
- (void)updateConstraints
{
if (self.applePayAvailable) {
CGFloat trailingConstant = (CGRectGetWidth(self.bounds) - self.layoutMargins.right) * 0.5f;
self.firstButtonTrailingConstraint.constant = trailingConstant;
} else {
self.firstButtonTrailingConstraint.constant = 0.0f;
}
[super updateConstraints];
}
- (void)setSeparatorColor:(UIColor *)separatorColor
{
self.layer.shadowColor = separatorColor.CGColor;
self.layer.shadowOffset = CGSizeMake(0, - 1 / [UIScreen mainScreen].scale);
self.layer.shadowRadius = 0.0f;
self.layer.shadowOpacity = 1.0f;
}
@end
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB" customClass="ActionableFooterView">
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<visualEffectView opaque="NO" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2he-LW-1Mz">
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" id="tOf-FE-2kG">
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jjm-5z-kCD" userLabel="paymentContainer">
<rect key="frame" x="165" y="46" width="145" height="44"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Eoe-n5-0iT" customClass="CheckoutButton">
<rect key="frame" x="10" y="46" width="145" height="44"/>
<color key="backgroundColor" red="0.00059560901718214154" green="0.70855957269668579" blue="0.99971479177474976" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="Yod-FN-PBJ"/>
</constraints>
<state key="normal" title="Add to Cart">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QbM-Nc-TSH">
<rect key="frame" x="0.0" y="10" width="320" height="36"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="Eoe-n5-0iT" secondAttribute="trailing" constant="155" id="4jE-2h-gr6"/>
<constraint firstItem="Eoe-n5-0iT" firstAttribute="leading" secondItem="tOf-FE-2kG" secondAttribute="leadingMargin" id="ACp-Cb-o3A"/>
<constraint firstItem="jjm-5z-kCD" firstAttribute="height" secondItem="Eoe-n5-0iT" secondAttribute="height" id="DoE-w1-naR"/>
<constraint firstItem="QbM-Nc-TSH" firstAttribute="leading" secondItem="tOf-FE-2kG" secondAttribute="leading" id="Q7m-41-SnI"/>
<constraint firstItem="QbM-Nc-TSH" firstAttribute="top" secondItem="tOf-FE-2kG" secondAttribute="topMargin" id="Tbz-Z9-Xyu"/>
<constraint firstItem="jjm-5z-kCD" firstAttribute="leading" secondItem="Eoe-n5-0iT" secondAttribute="trailing" constant="10" id="UrY-kJ-C6C"/>
<constraint firstAttribute="bottomMargin" secondItem="Eoe-n5-0iT" secondAttribute="bottom" id="WHF-0k-ScU"/>
<constraint firstItem="jjm-5z-kCD" firstAttribute="width" secondItem="Eoe-n5-0iT" secondAttribute="width" id="fop-kv-C9D"/>
<constraint firstItem="jjm-5z-kCD" firstAttribute="centerY" secondItem="Eoe-n5-0iT" secondAttribute="centerY" id="g86-Vu-ZpD"/>
<constraint firstItem="Eoe-n5-0iT" firstAttribute="top" secondItem="QbM-Nc-TSH" secondAttribute="bottom" id="pwX-zC-1fR"/>
<constraint firstAttribute="trailing" secondItem="QbM-Nc-TSH" secondAttribute="trailing" id="yYy-IX-gUN"/>
</constraints>
</view>
<blurEffect style="extraLight"/>
</visualEffectView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="2he-LW-1Mz" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="9VD-ID-fkE"/>
<constraint firstItem="2he-LW-1Mz" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="EFC-N3-UwK"/>
<constraint firstItem="2he-LW-1Mz" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="nzn-ri-Fq0"/>
<constraint firstItem="2he-LW-1Mz" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="xUR-8Z-blk"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<edgeInsets key="layoutMargins" top="10" left="10" bottom="10" right="10"/>
<connections>
<outlet property="actionButton" destination="Eoe-n5-0iT" id="slV-do-iC5"/>
<outlet property="applePayLeadingConstraint" destination="UrY-kJ-C6C" id="CBg-TA-i3I"/>
<outlet property="extensionView" destination="QbM-Nc-TSH" id="1rQ-Kd-AvH"/>
<outlet property="firstButtonTrailingConstraint" destination="4jE-2h-gr6" id="kTF-KV-LGT"/>
<outlet property="paymentButtonContainer" destination="jjm-5z-kCD" id="tgu-5h-QO3"/>
</connections>
<point key="canvasLocation" x="142" y="525"/>
</view>
</objects>
</document>
//
// BUYImageView.h
// AsyncImageView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,14 +25,14 @@
//
@import UIKit;
#import "BUYTheme.h"
@import Buy;
extern float const imageDuration;
/**
* Provides an easy way to asynchronously load images from a URL
*/
@interface BUYImageView : UIImageView <BUYThemeable>
@interface AsyncImageView : UIImageView
@property (nonatomic, assign) BOOL showsActivityIndicator;
......@@ -65,4 +65,13 @@ extern float const imageDuration;
*/
- (BOOL)isPortraitOrSquare;
/**
* Load an image asynchronously from an BUYImageLink and animate the transition. Will use the optimal image size for the ImageView
*
* @param imageLink the BUYImageLink that points to the image asset to use
* @param animateChange YES to animation the image transition
* @param completion Completion block returning the image or an error
*/
- (void)loadImageLink:(BUYImageLink *)imageLink animateChange:(BOOL)animateChange completion:(void (^)(UIImage *image, NSError *error))completion;
@end
//
// BUYImageView.m
// AsyncImageView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,19 +24,47 @@
// THE SOFTWARE.
//
#import "BUYImageView.h"
#import "BUYTheme+Additions.h"
#import "AsyncImageView.h"
float const imageDuration = 0.1f;
@interface BUYImageView ()
static NSUInteger const memoryCacheSize = 10 * 1024 * 1024; // 10 MB
static NSUInteger const diskCacheSize = 50 * 1024 * 1024; // 50 MB
@interface NSURLSession (BUYImageSession)
+ (instancetype)buy_sharedImageSession;
@end
@implementation NSURLSession (BUYImageSession)
+ (instancetype)buy_sharedImageSession
{
static NSURLSession *_sharedSession = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.URLCache = [[NSURLCache alloc] initWithMemoryCapacity:memoryCacheSize diskCapacity:diskCacheSize diskPath:nil];
_sharedSession = [NSURLSession sessionWithConfiguration:config];
});
return _sharedSession;
}
@end
@interface AsyncImageView ()
@property (nonatomic, strong) NSURLSessionDataTask *task;
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;
@end
@implementation BUYImageView
@implementation AsyncImageView
- (instancetype)init
{
......@@ -104,7 +132,7 @@ float const imageDuration = 0.1f;
if (self.showsActivityIndicator) {
[self.activityIndicatorView startAnimating];
}
self.task = [[NSURLSession sharedSession] dataTaskWithURL:imageURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
self.task = [[NSURLSession buy_sharedImageSession] dataTaskWithURL:imageURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:data];
if (setImage) {
......@@ -119,19 +147,23 @@ float const imageDuration = 0.1f;
[self.task resume];
}
- (void)cancelImageTask {
- (void)cancelImageTask
{
[self.task cancel];
self.task = nil;
}
- (void)setTheme:(BUYTheme *)theme
- (BOOL)isPortraitOrSquare
{
self.activityIndicatorView.activityIndicatorViewStyle = [theme activityIndicatorViewStyle];
return self.image.size.height >= self.image.size.width;
}
- (BOOL)isPortraitOrSquare
- (void)loadImageLink:(BUYImageLink *)imageLink animateChange:(BOOL)animateChange completion:(void (^)(UIImage *image, NSError *error))completion;
{
return self.image.size.height >= self.image.size.width;
BUYImageURLSize size = [self buy_imageSize];
NSURL *url = [imageLink imageURLWithSize:size];
[self loadImageWithURL:url animateChange:animateChange completion:completion];
}
@end
//
// BUYProductViewFooter.h
// CheckoutButton.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,49 +25,31 @@
//
@import UIKit;
@class BUYProductVariant;
@class BUYTheme;
#import "BUYPaymentButton.h"
#import "BUYCheckoutButton.h"
@interface BUYProductViewFooter : UIView
/**
* A footer view for the BUYProductView that includes a checkout button and an Apple Pay button (if available)
*
* @param theme The theme for the footer view
* @param showApplePaySetup Show Apple Pay button with 'Set Up Apple Pay' text as determined by the presenter
*
* @return A footer view with a checkout and Apple Pay button
* A themed UIButton that includes a UIActivityIndicator
*/
- (instancetype)initWithTheme:(BUYTheme *)theme showApplePaySetup:(BOOL)showApplePaySetup;
@interface CheckoutButton : UIButton
/**
* A checkout button themed with the BUYTheme tintColor.
* This button is used for web checkout
*/
@property (nonatomic, strong) BUYCheckoutButton *checkoutButton;
/**
* An Apple Pay button, shown if Apple Pay is enabled and available on the device.
* The BUYPaymentButton is a PKPaymentButton on iOS 8.3 and greater.
* Styled to match the given theme.
* Creates a checkout button with UIButtonTypeSystem which inherits its color from the superview's tintColor
*
* @return A CheckoutButton with UIButtonTypeSystem
*/
@property (nonatomic, strong) BUYPaymentButton *buyPaymentButton;
+(instancetype)checkoutButton;
/**
* Sets the Apple Pay visible (or hides it). This updates the layout for the buttons.
* Show a UIActivityIndicator in place of text while loading
*
* @param isApplePayAvailable True when the Apple Pay button is visible
* @param show Show or hide the UIActivityIndicator
*/
- (void)setApplePayButtonVisible:(BOOL)isApplePayAvailable;
- (void)showActivityIndicator:(BOOL)show;
/**
* Lowers the alpha and disable the buttons if the `available` property on the
* BUYProductVariant is false.
* Sets the button text color
*
* @param productVariant The selected product variant that determines availability and functionality of the buttons.
* @param color The color for the button
*/
- (void)updateButtonsForProductVariant:(BUYProductVariant *)productVariant;
- (void)setTextColor:(UIColor*)color UI_APPEARANCE_SELECTOR;
@end
//
// BUYCheckoutButton.m
// CheckoutButton.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,39 +24,61 @@
// THE SOFTWARE.
//
#import "BUYCheckoutButton.h"
#import "BUYTheme+Additions.h"
#import "CheckoutButton.h"
#import "UIColor+BUYAdditions.h"
#import "UIImage+BUYAdditions.h"
@interface BUYCheckoutButton ()
@interface CheckoutButton ()
@property (nonatomic, weak) BUYTheme *theme;
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
@property (nonatomic, strong) UIColor *textColor;
@end
@implementation BUYCheckoutButton
@implementation CheckoutButton
- (void)setHighlighted:(BOOL)highlighted
+ (instancetype)checkoutButton
{
[super setHighlighted:highlighted];
self.backgroundColor = highlighted ? [self.theme.tintColor colorWithAlphaComponent:0.4f] : self.theme.tintColor;
CheckoutButton *checkoutButton = [super buttonWithType:UIButtonTypeSystem];
[checkoutButton commonInit];
return checkoutButton;
}
- (void)setTheme:(BUYTheme *)theme
- (instancetype)initWithFrame:(CGRect)frame
{
_theme = theme;
self.tintColor = theme.tintColor;
self.backgroundColor = self.tintColor;
UIColor *textColor = [theme checkoutButtonTextColor];
[self setTitleColor:textColor forState:UIControlStateNormal];
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self commonInit];
}
return self;
}
- (void)commonInit
{
[self setBackgroundImage:[UIImage templateButtonBackgroundImage] forState:UIControlStateNormal];
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self setTitleColor:[[UIColor whiteColor] colorWithAlphaComponent:0.5f] forState:UIControlStateDisabled];
}
- (void)setTextColor:(UIColor*)color
{
_textColor = color;
[self setTitleColor:color forState:UIControlStateNormal];
}
- (UIActivityIndicatorView *)activityIndicator
{
if (_activityIndicator == nil) {
UIActivityIndicatorViewStyle style = self.theme.style == BUYThemeStyleLight ? UIActivityIndicatorViewStyleWhite : UIActivityIndicatorViewStyleGray;
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:style];
_activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
_activityIndicator.translatesAutoresizingMaskIntoConstraints = NO;
_activityIndicator.hidesWhenStopped = YES;
[self addSubview:_activityIndicator];
......@@ -77,7 +99,7 @@
}
else {
[self.activityIndicator stopAnimating];
[self setTheme:self.theme];
[self setTitleColor:self.textColor forState:UIControlStateNormal];
}
}
......
//
// DisclosureIndicatorView.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import UIKit;
@interface DisclosureIndicatorView : UIImageView
@end
//
// BUYTheme.m
// DisclosureIndicatorView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,20 +24,17 @@
// THE SOFTWARE.
//
#import "BUYTheme.h"
#import "DisclosureIndicatorView.h"
#import "ImageKit.h"
@implementation BUYTheme
@implementation DisclosureIndicatorView
- (instancetype)init
{
self = [super init];
if (self) {
self.tintColor = [UIColor colorWithRed:0.48f green:0.71f blue:0.36f alpha:1.0f];
self.style = BUYThemeStyleLight;
self.showsProductImageBackground = YES;
self.image = [[ImageKit imageOfDisclosureIndicatorImageWithFrame:CGRectMake(0, 0, 10, 16) color:[UIColor blackColor]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
}
return self;
}
......
//
// BUYProductViewErrorView.h
// ErrorView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,12 +25,11 @@
//
@import UIKit;
@class BUYTheme;
/**
* A customer toast error view to use in the BUYProductView.
* A customer toast error view to use in the ProductView.
*/
@interface BUYProductViewErrorView : UIView
@interface ErrorView : UIView
/**
* The label containing the error message.
......@@ -47,13 +46,8 @@
*/
@property (nonatomic, strong) NSLayoutConstraint *visibleConstraint;
/**
* Initializer that create an error view with a theme.
*
* @param theme The theme for the error view.
*
* @return An error view.
*/
- (instancetype)initWithTheme:(BUYTheme*)theme;
- (void)setOverlayColor:(UIColor*)color UI_APPEARANCE_SELECTOR;
- (void)presentErrorViewWithMessage:(NSString *)errorMessage completion:(void (^)(void))callback;
@end
//
// BUYProductViewErrorView.m
// ErrorView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,18 +24,24 @@
// THE SOFTWARE.
//
#import "BUYProductViewErrorView.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "ErrorView.h"
@implementation BUYProductViewErrorView
static CGFloat const kPaddingMedium = 12.0f;
static CGFloat const kPaddingExtraLarge = 16.0f;
- (instancetype)initWithTheme:(BUYTheme*)theme
@interface ErrorView ()
@property (nonatomic, strong) UIView *overlayView;
@end
@implementation ErrorView
- (instancetype)init
{
self = [super init];
if (self) {
UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] init];
visualEffectView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:visualEffectView];
......@@ -48,29 +54,28 @@
metrics:nil
views:NSDictionaryOfVariableBindings(visualEffectView)]];
UIView *redTintOverlayView = [[UIView alloc] init];
redTintOverlayView.translatesAutoresizingMaskIntoConstraints = NO;
redTintOverlayView.backgroundColor = [theme errorTintOverlayColor];
[visualEffectView.contentView addSubview:redTintOverlayView];
[visualEffectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[redTintOverlayView]|"
_overlayView = [[UIView alloc] init];
_overlayView.translatesAutoresizingMaskIntoConstraints = NO;
[visualEffectView.contentView addSubview:_overlayView];
[visualEffectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_overlayView]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(redTintOverlayView)]];
[visualEffectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[redTintOverlayView]|"
views:NSDictionaryOfVariableBindings(_overlayView)]];
[visualEffectView.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_overlayView]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(redTintOverlayView)]];
views:NSDictionaryOfVariableBindings(_overlayView)]];
_errorLabel = [[UILabel alloc] init];
_errorLabel.translatesAutoresizingMaskIntoConstraints = NO;
_errorLabel.textAlignment = NSTextAlignmentCenter;
_errorLabel.font = [BUYTheme errorLabelFont];
_errorLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
_errorLabel.textColor = [UIColor whiteColor];
_errorLabel.backgroundColor = [UIColor clearColor];
_errorLabel.numberOfLines = 0;
[visualEffectView.contentView addSubview:_errorLabel];
NSDictionary *metricsDictionary = @{ @"paddingExtraLarge" : @(kBuyPaddingExtraLarge), @"paddingMedium" : @(kBuyPaddingMedium) };
NSDictionary *metricsDictionary = @{ @"paddingExtraLarge" : @(kPaddingExtraLarge), @"paddingMedium" : @(kPaddingMedium) };
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(paddingExtraLarge)-[_errorLabel]-(paddingExtraLarge)-|"
options:0
......@@ -84,4 +89,38 @@
return self;
}
- (void)setOverlayColor:(UIColor*)color
{
self.overlayView.backgroundColor = color;
}
- (void)presentErrorViewWithMessage:(NSString *)errorMessage completion:(void (^)(void))callback
{
self.errorLabel.text = errorMessage;
[NSLayoutConstraint deactivateConstraints:@[self.hiddenConstraint]];
[NSLayoutConstraint activateConstraints:@[self.visibleConstraint]];
[UIView animateWithDuration:0.3f
delay:0
usingSpringWithDamping:0.8f
initialSpringVelocity:10
options:0
animations:^{
self.alpha = 1;
[self layoutIfNeeded];
}
completion:^(BOOL finished) {
[NSLayoutConstraint deactivateConstraints:@[self.visibleConstraint]];
[NSLayoutConstraint activateConstraints:@[self.hiddenConstraint]];
[UIView animateWithDuration:0.3f delay:3.0f options:0 animations:^{
self.alpha = 0;
[self layoutIfNeeded];
} completion:^(BOOL finished) {
[self removeFromSuperview];
if (callback) callback();
}];
}];
}
@end
//
// BUYGradientView.h
// GradientView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -29,7 +29,7 @@
/**
* Easily create a view with a vertical gradient with two colors
*/
@interface BUYGradientView : UIView
@interface GradientView : UIView
/**
* The color of the top part of the gradient
......
//
// BUYGradientView.m
// GradientView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,9 +24,9 @@
// THE SOFTWARE.
//
#import "BUYGradientView.h"
#import "GradientView.h"
@implementation BUYGradientView
@implementation GradientView
- (instancetype)init
{
......@@ -34,14 +34,16 @@
if (self) {
self.backgroundColor = [UIColor clearColor];
self.topColor = [UIColor colorWithWhite:0 alpha:0.5f];
self.bottomColor = [UIColor clearColor];
self.bottomColor = [UIColor colorWithWhite:0 alpha:0];
}
return self;
}
- (void)drawRect:(CGRect)rect {
- (void)drawRect:(CGRect)rect
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = UIGraphicsGetCurrentContext();
NSArray *gradientColors = [NSArray arrayWithObjects:(id)self.topColor.CGColor, (id)self.bottomColor.CGColor, nil];
CGFloat gradientLocations[] = {0, 1};
......
//
// BUYProductViewHeaderBackgroundImageView.h
// HeaderBackgroundView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,24 +25,14 @@
//
@import UIKit;
@class BUYImageView;
@class BUYTheme;
@class AsyncImageView;
@class BUYImageLink;
/**
* A background for the product view that displays the currently displayed
* product or variant image behind a blurry UIVisualEffectView.
*/
@interface BUYProductViewHeaderBackgroundImageView : UIView
/**
* Initializer that takes a BUYTheme
*
* @param theme The product view theme
*
* @return An instance of BUYProductViewHeaderBackgroundImageView
*/
- (instancetype)initWithTheme:(BUYTheme*)theme;
@interface HeaderBackgroundView : UIView
/**
* Set the product image on the image view
......
//
// BUYProductViewHeaderBackgroundImageView.m
// HeaderBackgroundView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,25 +24,23 @@
// THE SOFTWARE.
//
#import "BUYProductViewHeaderBackgroundImageView.h"
#import "BUYTheme.h"
#import "BUYImageView.h"
#import "BUYImageLink.h"
#import "BUYTheme+Additions.h"
#import "AsyncImageView.h"
#import "HeaderBackgroundView.h"
#import "VisualEffectView.h"
@interface BUYProductViewHeaderBackgroundImageView ()
@interface HeaderBackgroundView ()
@property (nonatomic, strong) BUYImageView *productImageView;
@property (nonatomic, strong) AsyncImageView *productImageView;
@end
@implementation BUYProductViewHeaderBackgroundImageView
@implementation HeaderBackgroundView
- (instancetype)initWithTheme:(BUYTheme*)theme
- (instancetype)init
{
self = [super init];
if (self) {
self.productImageView = [[BUYImageView alloc] init];
self.productImageView = [[AsyncImageView alloc] init];
self.productImageView.clipsToBounds = YES;
self.productImageView.translatesAutoresizingMaskIntoConstraints = NO;
self.productImageView.backgroundColor = [UIColor clearColor];
......@@ -64,7 +62,7 @@
multiplier:1.0
constant:0.0]];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:[theme blurEffect]];
VisualEffectView *visualEffectView = [[VisualEffectView alloc] init];
visualEffectView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:visualEffectView];
......@@ -88,8 +86,7 @@
- (void)setBackgroundProductImage:(BUYImageLink *)image
{
NSString *string = [image.src stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@".%@", [image.src pathExtension]] withString:[NSString stringWithFormat:@"_small.%@", [image.src pathExtension]]];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@", string]];
NSURL *url = [image imageURLWithSize:BUYImageURLSize100x100];
[self.productImageView loadImageWithURL:url animateChange:YES completion:NULL];
}
......
//
// BUYProductViewHeaderOverlay.h
// HeaderOverlayView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,23 +25,15 @@
//
@import UIKit;
@class BUYTheme;
/**
* An overlay + blur effect when the product view scrolls up
* to hide the image view and create a nice transition into
* the navigation bar.
*/
@interface BUYProductViewHeaderOverlay : UIView
@interface HeaderOverlayView : UIView
/**
* Initializer that takes a BUYTheme
*
* @param theme The product view theme
*
* @return An instance of BUYProductViewHeaderOverlay
*/
- (instancetype)initWithTheme:(BUYTheme*)theme;
@property (nonatomic) UIColor *overlayBackgroundColor UI_APPEARANCE_SELECTOR;
/**
* Used to determine the current visibility of the effect based on content offset and the navigationbar height.
......
//
// BUYProductViewHeaderOverlay.m
// HeaderOverlayView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,20 +24,19 @@
// THE SOFTWARE.
//
#import "BUYProductViewHeaderOverlay.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "HeaderOverlayView.h"
#import "VisualEffectView.h"
@interface BUYProductViewHeaderOverlay ()
@interface HeaderOverlayView ()
@property (nonatomic, strong) UIView *overlayView;
@property (nonatomic, strong) UIView *visualEffectContainerView;
@end
@implementation BUYProductViewHeaderOverlay
@implementation HeaderOverlayView
- (instancetype)initWithTheme:(BUYTheme*)theme
- (instancetype)init
{
self = [super init];
if (self) {
......@@ -51,7 +50,7 @@
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_visualEffectContainerView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_visualEffectContainerView)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_visualEffectContainerView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_visualEffectContainerView)]];
UIVisualEffectView *visualEffectView = [[UIVisualEffectView alloc] initWithEffect:[theme blurEffect]];
VisualEffectView *visualEffectView = [[VisualEffectView alloc] init];
visualEffectView.translatesAutoresizingMaskIntoConstraints = NO;
[_visualEffectContainerView addSubview:visualEffectView];
......@@ -60,7 +59,6 @@
_overlayView = [[UIView alloc] init];
_overlayView.alpha = 0;
_overlayView.backgroundColor = [theme backgroundColor];
_overlayView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_overlayView];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_overlayView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_overlayView)]];
......@@ -69,6 +67,11 @@
return self;
}
-(void)setOverlayBackgroundColor:(UIColor *)overlayBackgroundColor
{
_overlayView.backgroundColor = overlayBackgroundColor;
}
static CGFloat visualEffectViewThreshold = 200.0f;
static CGFloat overlayViewThreshold = 100.0f;
......
//
// BUYProductDescriptionCell.h
// ProductDescriptionCell.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,12 +25,11 @@
//
@import UIKit;
#import "BUYTheme.h"
/**
* Table view cell containing the product description
*/
@interface BUYProductDescriptionCell : UITableViewCell <BUYThemeable>
@interface ProductDescriptionCell : UITableViewCell
/**
* Converts the product description from HTML to an attributed string
......
//
// BUYProductDescriptionCell.m
// ProductDescriptionCell.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,18 +24,16 @@
// THE SOFTWARE.
//
#import "BUYProductDescriptionCell.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "ProductDescriptionCell.h"
#import "Theme+Additions.h"
@interface BUYProductDescriptionCell ()
@interface ProductDescriptionCell ()
@property (nonatomic, strong) UIColor *textColor;
@property (nonatomic, strong) UILabel *descriptionLabel;
@property (nonatomic, strong) BUYTheme *theme;
@end
@implementation BUYProductDescriptionCell
@implementation ProductDescriptionCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
......@@ -54,7 +52,7 @@
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_descriptionLabel]-|" options:0 metrics:nil views:views]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_descriptionLabel]-|" options:0 metrics:nil views:views]];
_textColor = [BUYTheme descriptionTextColor];
_textColor = [Theme descriptionTextColor];
}
return self;
......@@ -85,10 +83,9 @@
return self.descriptionLabel.attributedText.string;
}
- (void)setTheme:(BUYTheme *)theme
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
_theme = theme;
self.backgroundColor = [theme backgroundColor];
[super setBackgroundColor:backgroundColor];
self.descriptionLabel.backgroundColor = self.backgroundColor;
}
......
//
// BUYProductHeaderCell.h
// ProductHeaderCell.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,13 +25,12 @@
//
@import UIKit;
#import "BUYTheme.h"
@class BUYProductVariant;
@import Buy;
/**
* Table view cell containing the product title, price and compare-at/sold out text
*/
@interface BUYProductHeaderCell : UITableViewCell <BUYThemeable>
@interface ProductHeaderCell : UITableViewCell
/**
* Sets the title, price and optionally compare-at/sold out texts
......@@ -41,4 +40,6 @@
*/
- (void)setProductVariant:(BUYProductVariant *)productVariant withCurrencyFormatter:(NSNumberFormatter*)currencyFormatter;
- (void)setProductTitleColor:(UIColor*)color UI_APPEARANCE_SELECTOR;
@end
//
// BUYProductHeaderCell.m
// ProductHeaderCell.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,23 +24,20 @@
// THE SOFTWARE.
//
#import "BUYProductHeaderCell.h"
#import "BUYProductVariant.h"
#import "BUYProduct.h"
#import "ProductHeaderCell.h"
#import "UIFont+BUYAdditions.h"
#import "BUYTheme+Additions.h"
#import "Theme+Additions.h"
@interface BUYProductHeaderCell ()
@interface ProductHeaderCell ()
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *priceLabel;
@property (nonatomic, strong) UILabel *comparePriceLabel;
@property (nonatomic, strong) BUYTheme *theme;
@property (nonatomic, strong) BUYProductVariant *productVariant;
@end
@implementation BUYProductHeaderCell
@implementation ProductHeaderCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
......@@ -52,7 +49,7 @@
_titleLabel = [[UILabel alloc] init];
_titleLabel.textColor = [UIColor blackColor];
_titleLabel.font = [BUYTheme productTitleFont];
_titleLabel.font = [Theme productTitleFont];
_titleLabel.numberOfLines = 0;
_titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:_titleLabel];
......@@ -62,7 +59,7 @@
[self.contentView addSubview:priceView];
_priceLabel = [[UILabel alloc] init];
_priceLabel.font = [BUYTheme productPriceFont];
_priceLabel.font = [Theme productPriceFont];
_priceLabel.translatesAutoresizingMaskIntoConstraints = NO;
_priceLabel.textAlignment = NSTextAlignmentRight;
[_priceLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
......@@ -70,9 +67,9 @@
[priceView addSubview:_priceLabel];
_comparePriceLabel = [[UILabel alloc] init];
_comparePriceLabel.textColor = [BUYTheme comparePriceTextColor];
_comparePriceLabel.textColor = [Theme comparePriceTextColor];
_comparePriceLabel.textAlignment = NSTextAlignmentRight;
_comparePriceLabel.font = [BUYTheme productComparePriceFont];
_comparePriceLabel.font = [Theme productComparePriceFont];
_comparePriceLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_comparePriceLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[_comparePriceLabel setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
......@@ -105,14 +102,14 @@
self.priceLabel.text = [currencyFormatter stringFromNumber:productVariant.price];
}
if (productVariant.available.boolValue && productVariant.compareAtPrice) {
if (productVariant.availableValue == YES && productVariant.compareAtPrice) {
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[currencyFormatter stringFromNumber:productVariant.compareAtPrice]
attributes:@{NSStrikethroughStyleAttributeName: @(NSUnderlineStyleSingle)}];
self.comparePriceLabel.attributedText = attributedString;
self.comparePriceLabel.textColor = [BUYTheme comparePriceTextColor];
self.comparePriceLabel.textColor = [Theme comparePriceTextColor];
} else if (productVariant.available == NO) {
self.comparePriceLabel.text = @"Sold Out";
self.comparePriceLabel.textColor = [BUYTheme variantSoldOutTextColor];
self.comparePriceLabel.text = NSLocalizedString(@"Sold Out", @"Sold out text displayed on product view");
self.comparePriceLabel.textColor = [Theme variantSoldOutTextColor];
} else {
self.comparePriceLabel.attributedText = nil;
}
......@@ -121,12 +118,10 @@
[self layoutIfNeeded];
}
- (void)setTheme:(BUYTheme *)theme
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
_theme = theme;
self.backgroundColor = [theme backgroundColor];
[super setBackgroundColor:backgroundColor];
self.titleLabel.backgroundColor = self.priceLabel.backgroundColor = self.comparePriceLabel.backgroundColor = self.backgroundColor;
self.titleLabel.textColor = [theme productTitleColor];
}
- (void)tintColorDidChange
......@@ -135,4 +130,9 @@
self.priceLabel.textColor = self.tintColor;
}
- (void)setProductTitleColor:(UIColor*)color
{
self.titleLabel.textColor = color;
}
@end
//
// BUYProductImageCollectionViewCell.h
// ProductImageCell.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,17 +25,17 @@
//
@import UIKit;
@class BUYImageView;
@class AsyncImageView;
/**
* A custom collection view cell for the BUYProductViewController's product image(s)
*/
@interface BUYProductImageCollectionViewCell : UICollectionViewCell
@interface ProductImageCell : UICollectionViewCell
/**
* The image view containing a product image
*/
@property (nonatomic, strong) BUYImageView *productImageView;
@property (nonatomic, strong) AsyncImageView *productImageView;
/**
* The height to display the product image
......
//
// BUYProductImageCollectionViewCell.m
// ProductImageCell.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,10 +24,10 @@
// THE SOFTWARE.
//
#import "BUYProductImageCollectionViewCell.h"
#import "BUYImageView.h"
#import "ProductImageCell.h"
#import "AsyncImageView.h"
@implementation BUYProductImageCollectionViewCell
@implementation ProductImageCell
- (instancetype)initWithFrame:(CGRect)frame
{
......@@ -38,7 +38,7 @@
self.contentView.backgroundColor = [UIColor clearColor];
_productImageView = [[BUYImageView alloc] init];
_productImageView = [[AsyncImageView alloc] init];
_productImageView.clipsToBounds = YES;
_productImageView.translatesAutoresizingMaskIntoConstraints = NO;
_productImageView.backgroundColor = [UIColor clearColor];
......
//
// BUYProductVariantCell.h
// ProductVariantCell.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,13 +25,12 @@
//
@import UIKit;
#import "BUYTheme.h"
@class BUYProductVariant;
@import Buy;
/**
* Table view cell containing the product's variant options
*/
@interface BUYProductVariantCell : UITableViewCell <BUYThemeable>
@interface ProductVariantCell : UITableViewCell
/**
* Set the options for a product variant
......@@ -40,4 +39,6 @@
*/
- (void)setOptionsForProductVariant:(BUYProductVariant *)productVariant;
- (void)setSelectedBackgroundViewBackgroundColor:(UIColor *)selectedBackgroundViewBackgroundColor UI_APPEARANCE_SELECTOR;
@end
//
// BUYProductVariantCell.m
// ProductVariantCell.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,23 +24,24 @@
// THE SOFTWARE.
//
#import "BUYProductVariantCell.h"
#import "BUYVariantOptionView.h"
#import "BUYProductVariant.h"
#import "BUYOptionValue.h"
#import "BUYImageKit.h"
#import "DisclosureIndicatorView.h"
#import "ImageKit.h"
#import "ProductVariantCell.h"
#import "Theme+Additions.h"
#import "VariantOptionView.h"
@interface BUYProductVariantCell ()
@property (nonatomic, strong) BUYVariantOptionView *optionView1;
@property (nonatomic, strong) BUYVariantOptionView *optionView2;
@property (nonatomic, strong) BUYVariantOptionView *optionView3;
@interface ProductVariantCell ()
@property (nonatomic, strong) VariantOptionView *optionView1;
@property (nonatomic, strong) VariantOptionView *optionView2;
@property (nonatomic, strong) VariantOptionView *optionView3;
@property (nonatomic, strong) NSArray *disclosureConstraints;
@property (nonatomic, strong) NSArray *noDisclosureConstraints;
@property (nonatomic, strong) UIImageView *disclosureIndicatorImageView;
@property (nonatomic, strong) BUYTheme *theme;
@property (nonatomic, strong) DisclosureIndicatorView *disclosureIndicatorImageView;
@end
@implementation BUYProductVariantCell
@implementation ProductVariantCell
CGFloat const buttonWidth = 10.0f;
......@@ -53,22 +54,22 @@ CGFloat const buttonWidth = 10.0f;
UIView *backgroundView = [[UIView alloc] init];
[self setSelectedBackgroundView:backgroundView];
_optionView1 = [[BUYVariantOptionView alloc] init];
_optionView1 = [[VariantOptionView alloc] init];
_optionView1.translatesAutoresizingMaskIntoConstraints = NO;
[_optionView1 setContentCompressionResistancePriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal];
[self.contentView addSubview:_optionView1];
_optionView2 = [[BUYVariantOptionView alloc] init];
_optionView2 = [[VariantOptionView alloc] init];
_optionView2.translatesAutoresizingMaskIntoConstraints = NO;
[_optionView3 setContentCompressionResistancePriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal];
[self.contentView addSubview:_optionView2];
_optionView3 = [[BUYVariantOptionView alloc] init];
_optionView3 = [[VariantOptionView alloc] init];
_optionView3.translatesAutoresizingMaskIntoConstraints = NO;
[_optionView3 setContentCompressionResistancePriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal];
[self.contentView addSubview:_optionView3];
_disclosureIndicatorImageView = [[UIImageView alloc] init];
_disclosureIndicatorImageView = [[DisclosureIndicatorView alloc] init];
_disclosureIndicatorImageView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:_disclosureIndicatorImageView];
......@@ -97,7 +98,7 @@ CGFloat const buttonWidth = 10.0f;
- (void)setOptionsForProductVariant:(BUYProductVariant *)productVariant
{
NSArray *productOptions = productVariant.options.allObjects;
NSArray *productOptions = [productVariant.options allObjects];
switch (productVariant.options.count) {
case 3:
......@@ -137,16 +138,9 @@ CGFloat const buttonWidth = 10.0f;
}
}
- (void)setTheme:(BUYTheme *)theme
- (void)setSelectedBackgroundViewBackgroundColor:(UIColor *)selectedBackgroundViewBackgroundColor
{
_theme = theme;
self.backgroundColor = [theme backgroundColor];
self.selectedBackgroundView.backgroundColor = [theme selectedBackgroundColor];
self.disclosureIndicatorImageView.image = [BUYImageKit imageOfDisclosureIndicatorImageWithFrame:CGRectMake(0, 0, buttonWidth, 16) color:[theme disclosureIndicatorColor]];
[self.optionView1 setTheme:theme];
[self.optionView2 setTheme:theme];
[self.optionView3 setTheme:theme];
self.selectedBackgroundView.backgroundColor = selectedBackgroundViewBackgroundColor;
}
@end
//
// BUYProductView.h
// ProductView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,18 +25,16 @@
//
@import UIKit;
@class BUYProductViewHeader;
@class BUYProductViewHeaderBackgroundImageView;
@class BUYProductViewFooter;
@class BUYGradientView;
@class BUYTheme;
@class BUYImageLink;
@class BUYProduct;
@import Buy;
@class ActionableFooterView;
@class GradientView;
@class ProductViewHeader;
@class HeaderBackgroundView;
/**
* The BUYProductViewController's main view, containing everything needed to display the UI for the product
*/
@interface BUYProductView : UIView
@interface ProductView : UIView
/**
* The table view containg the product's image(s) in the tableHeaderView, title, price,
......@@ -64,24 +62,19 @@
/**
* The tableHeaderView containting the product image(s) (if available)
*/
@property (nonatomic, strong) BUYProductViewHeader *productViewHeader;
@property (nonatomic, strong) BUYProductViewHeaderBackgroundImageView *backgroundImageView;
@property (nonatomic, strong) ProductViewHeader *productViewHeader;
@property (nonatomic, strong) HeaderBackgroundView *backgroundImageView;
/**
* The footer view containing the Checkout button, and - if enabled - Apple Pay button.
*/
@property (nonatomic, strong) BUYProductViewFooter *productViewFooter;
@property (nonatomic, strong) ActionableFooterView *productViewFooter;
/**
* A gradient view that sits at the top of the product images (if available).
* This view is invisible when the navigation bar is visible.
*/
@property (nonatomic, strong) BUYGradientView *topGradientView;
/**
* The theme of the product view.
*/
@property (nonatomic, weak) BUYTheme *theme;
@property (nonatomic, strong) GradientView *topGradientView;
/**
* Helps determine logic for setting up product images in the BUYProductViewController
......@@ -91,14 +84,14 @@
/**
* Initializer for the product view using a rect, product to display and theme
*
* @param rect The rect is needed for the UICollectionView in the BUYProductViewHeader to setup the cell's bounds
* @param rect The rect is needed for the UICollectionView in the ProductViewHeader to setup the cell's bounds
* @param product The product to display in the product view. Only used in the initializer to
* @param theme The theme for the product view
* @param showApplePaySetup Show Apple Pay button with 'Set Up Apple Pay' text as determined by the presenter
*
* @return An instance of the BUYProductView
* @return An instance of the ProductView
*/
- (instancetype)initWithFrame:(CGRect)rect product:(BUYProduct*)product theme:(BUYTheme*)theme shouldShowApplePaySetup:(BOOL)showApplePaySetup;
- (instancetype)initWithFrame:(CGRect)rect product:(BUYProduct*)product shouldShowApplePaySetup:(BOOL)showApplePaySetup;
/**
* The BUYProductViewController is the UITableViewDelegate, so it receives the UIScrollView delegate method calls.
......@@ -138,4 +131,6 @@
*/
- (void)setTopInset:(CGFloat)topInset;
- (void)setShowsProductImageBackground:(BOOL)showsProductImageBackground UI_APPEARANCE_SELECTOR;
@end
//
// BUYProductView.m
// ProductView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,38 +24,32 @@
// THE SOFTWARE.
//
#import "BUYProductView.h"
#import "BUYProductViewHeader.h"
#import "BUYProductViewHeaderBackgroundImageView.h"
#import "BUYProductViewFooter.h"
#import "BUYGradientView.h"
#import "BUYProductVariantCell.h"
#import "BUYProductDescriptionCell.h"
#import "BUYProductHeaderCell.h"
#import "BUYImageLink.h"
#import "BUYImageView.h"
#import "BUYProduct.h"
#import "BUYProductViewErrorView.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "ProductView.h"
#import "ProductViewHeader.h"
#import "HeaderBackgroundView.h"
#import "ActionableFooterView.h"
#import "GradientView.h"
#import "ProductVariantCell.h"
#import "ProductDescriptionCell.h"
#import "ProductHeaderCell.h"
#import "AsyncImageView.h"
#import "ErrorView.h"
#import "Theme+Additions.h"
@interface BUYProductView ()
@interface ProductView ()
@property (nonatomic, strong) UILabel *poweredByShopifyLabel;
@property (nonatomic, strong) NSLayoutConstraint *poweredByShopifyLabelConstraint;
@property (nonatomic, strong) BUYProductViewErrorView *errorView;
@property (nonatomic, strong) ErrorView *errorView;
@property (nonatomic, strong) NSLayoutConstraint *topInsetConstraint;
@end
@implementation BUYProductView
@implementation ProductView
- (instancetype)initWithFrame:(CGRect)rect product:(BUYProduct*)product theme:(BUYTheme*)theme shouldShowApplePaySetup:(BOOL)showApplePaySetup
- (instancetype)initWithFrame:(CGRect)rect product:(BUYProduct*)product shouldShowApplePaySetup:(BOOL)showApplePaySetup
{
self = [super initWithFrame:rect];
if (self) {
_backgroundImageView = [[BUYProductViewHeaderBackgroundImageView alloc] initWithTheme:theme];
_backgroundImageView.hidden = theme.showsProductImageBackground == NO;
_backgroundImageView = [[HeaderBackgroundView alloc] init];
_backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_backgroundImageView];
......@@ -75,7 +69,6 @@
constant:0.0]];
_stickyFooterView = [UIView new];
_stickyFooterView.backgroundColor = [theme backgroundColor];
_stickyFooterView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_stickyFooterView];
......@@ -114,9 +107,9 @@
_tableView.layoutMargins = UIEdgeInsetsMake(_tableView.layoutMargins.top, kBuyPaddingExtraLarge, _tableView.layoutMargins.bottom, kBuyPaddingMedium);
[self addSubview:_tableView];
[_tableView registerClass:[BUYProductHeaderCell class] forCellReuseIdentifier:@"headerCell"];
[_tableView registerClass:[BUYProductVariantCell class] forCellReuseIdentifier:@"variantCell"];
[_tableView registerClass:[BUYProductDescriptionCell class] forCellReuseIdentifier:@"descriptionCell"];
[_tableView registerClass:[ProductHeaderCell class] forCellReuseIdentifier:@"headerCell"];
[_tableView registerClass:[ProductVariantCell class] forCellReuseIdentifier:@"variantCell"];
[_tableView registerClass:[ProductDescriptionCell class] forCellReuseIdentifier:@"descriptionCell"];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_tableView]|"
options:0
......@@ -138,35 +131,13 @@
CGFloat size = MIN(CGRectGetWidth(rect), CGRectGetHeight(rect));
if ([product.images count] > 0) {
_productViewHeader = [[BUYProductViewHeader alloc] initWithFrame:CGRectMake(0, 0, size, size) theme:theme];
_productViewHeader = [[ProductViewHeader alloc] initWithFrame:CGRectMake(0, 0, size, size)];
_tableView.tableHeaderView = self.productViewHeader;
} else {
_tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)];
}
_poweredByShopifyLabel = [[UILabel alloc] init];
_poweredByShopifyLabel.translatesAutoresizingMaskIntoConstraints = NO;
_poweredByShopifyLabel.backgroundColor = [UIColor clearColor];
_poweredByShopifyLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
_poweredByShopifyLabel.text = @"Powered by Shopify";
_poweredByShopifyLabel.textAlignment = NSTextAlignmentCenter;
[self addSubview:_poweredByShopifyLabel];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_poweredByShopifyLabel]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_poweredByShopifyLabel)]];
_poweredByShopifyLabelConstraint = [NSLayoutConstraint constraintWithItem:_poweredByShopifyLabel
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0.0];
[self addConstraint:_poweredByShopifyLabelConstraint];
_productViewFooter = [[BUYProductViewFooter alloc] initWithTheme:theme showApplePaySetup:showApplePaySetup];
_productViewFooter = [ActionableFooterView new];
_productViewFooter.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_productViewFooter];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_productViewFooter]|"
......@@ -179,8 +150,8 @@
views:NSDictionaryOfVariableBindings(_productViewFooter)]];
if (_productViewHeader) {
_topGradientView = [[BUYGradientView alloc] init];
_topGradientView.topColor = [BUYTheme topGradientViewTopColor];
_topGradientView = [[GradientView alloc] init];
_topGradientView.topColor = [Theme topGradientViewTopColor];
_topGradientView.translatesAutoresizingMaskIntoConstraints = NO;
_topGradientView.userInteractionEnabled = NO;
[self addSubview:_topGradientView];
......@@ -194,8 +165,6 @@
metrics:@{ @"height" : @(kBuyTopGradientViewHeight) }
views:NSDictionaryOfVariableBindings(_topGradientView)]];
}
self.theme = theme;
}
return self;
}
......@@ -206,17 +175,6 @@
[self setInsets:UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, CGRectGetHeight(self.bounds) - CGRectGetMinY(self.productViewFooter.frame), self.tableView.contentInset.right) appendToCurrentInset:NO];
}
- (void)setTheme:(BUYTheme *)theme
{
_theme = theme;
self.tintColor = _theme.tintColor;
self.tableView.separatorColor = [theme separatorColor];
self.backgroundColor = [theme backgroundColor];
self.stickyFooterView.backgroundColor = self.backgroundColor;
self.backgroundImageView.hidden = theme.showsProductImageBackground == NO;
self.poweredByShopifyLabel.textColor = self.tableView.separatorColor;
}
- (void)updateBackgroundImage:(NSArray *)images
{
if ([images count] > 0) {
......@@ -253,17 +211,14 @@
CGFloat opaqueOffset = CGRectGetHeight(self.productViewHeader.bounds);
CGFloat whiteStartingOffset = opaqueOffset - CGRectGetHeight(self.topGradientView.bounds);
self.topGradientView.alpha = -(scrollView.contentOffset.y - whiteStartingOffset) / (opaqueOffset - whiteStartingOffset);
CGFloat labelOffset = scrollView.contentSize.height - (scrollView.contentOffset.y + CGRectGetHeight(scrollView.bounds));
self.poweredByShopifyLabelConstraint.constant = (CGRectGetHeight(scrollView.bounds) / 3) + labelOffset;
}
#pragma mark - Error Handling
- (BUYProductViewErrorView *)errorView
- (ErrorView *)errorView
{
if (_errorView == nil) {
_errorView = [[BUYProductViewErrorView alloc] initWithTheme:self.theme];
_errorView = [[ErrorView alloc] init];
_errorView.alpha = 0;
_errorView.translatesAutoresizingMaskIntoConstraints = NO;
[self insertSubview:_errorView belowSubview:self.productViewFooter];
......@@ -298,36 +253,9 @@
- (void)showErrorWithMessage:(NSString*)errorMessage
{
self.errorView.errorLabel.text = errorMessage;
[NSLayoutConstraint deactivateConstraints:@[self.errorView.hiddenConstraint]];
[NSLayoutConstraint activateConstraints:@[self.errorView.visibleConstraint]];
[UIView animateWithDuration:0.3f
delay:0
usingSpringWithDamping:0.8f
initialSpringVelocity:10
options:0
animations:^{
self.errorView.alpha = 1;
[self.errorView layoutIfNeeded];
}
completion:^(BOOL finished) {
[NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(removeErrorView) userInfo:nil repeats:NO];
}];
}
- (void)removeErrorView
{
[NSLayoutConstraint deactivateConstraints:@[self.errorView.visibleConstraint]];
[NSLayoutConstraint activateConstraints:@[self.errorView.hiddenConstraint]];
[UIView animateWithDuration:0.3f
animations:^{
self.errorView.alpha = 0;
[self.errorView layoutIfNeeded];
}
completion:^(BOOL finished) {
[self.errorView removeFromSuperview];
self.errorView = nil;
}];
[self.errorView presentErrorViewWithMessage:errorMessage completion:^{
self.errorView = nil;
}];
}
- (void)setInsets:(UIEdgeInsets)edgeInsets appendToCurrentInset:(BOOL)appendToCurrentInset
......@@ -344,4 +272,16 @@
self.topInsetConstraint.constant = topInset;
}
#pragma mark - Appearance
- (void)setBackgroundColor:(UIColor *)backgroundColor {
[super setBackgroundColor:backgroundColor];
_stickyFooterView.backgroundColor = backgroundColor;
}
- (void)setShowsProductImageBackground:(BOOL)showsProductImageBackground
{
_backgroundImageView.hidden = showsProductImageBackground == NO;
}
@end
//
// BUYProductViewController.h
// ProductViewController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,11 +24,13 @@
// THE SOFTWARE.
//
#import "BUYTheme.h"
#import "BUYViewController.h"
#import "BUYClient.h"
@import UIKit;
@import Buy;
@interface BUYProductViewController : BUYViewController <BUYThemeable>
#import "Theme.h"
#import "PaymentViewController.h"
@interface ProductViewController : PaymentViewController
/**
* Creates a BUYProductViewController with a BUYClient and a theme
......@@ -37,11 +39,21 @@
* use `initWithClient:`
*
* @param client A BUYClient configured to your shop
* @param theme A BUYTheme
* @param theme A Theme
*
* @return A PaymentViewController
*/
- (instancetype)initWithClient:(BUYClient *)client theme:(Theme *)theme;
/**
* Creates a BUYProductViewController with a BUYClient and a cart
*
* @param client A BUYClient configured to your shop
* @param cart A cart that enables a "Add to cart" button instead of the web checout button
*
* @return A BUYViewController
* @return A PaymentViewController with an "Add to cart" button
*/
- (instancetype)initWithClient:(BUYClient *)client theme:(BUYTheme *)theme;
- (instancetype)initWithClient:(BUYClient *)client cart:(BUYCart *)cart;
/**
* Loads the product details
......
//
// ProductViewController.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "ProductViewController.h"
#import "GradientView.h"
#import "AsyncImageView.h"
#import "OptionSelectionNavigationController.h"
#import "ProductViewPresentationController.h"
#import "ImageKit.h"
#import "ProductView.h"
#import "ProductHeaderCell.h"
#import "ProductVariantCell.h"
#import "ProductDescriptionCell.h"
#import "ProductViewHeader.h"
#import "ProductImageCell.h"
#import "HeaderBackgroundView.h"
#import "HeaderOverlayView.h"
#import "ProductViewNavigationController.h"
#import "Theme+Additions.h"
#import "VariantSelectionViewController.h"
#import "CheckoutButton.h"
#import "ActionableFooterView.h"
CGFloat const BUYMaxProductViewWidth = 414.0; // We max out to the width of the iPhone 6+
CGFloat const BUYMaxProductViewHeight = 640.0;
@interface ProductViewController (Private)
@property (nonatomic, strong) BUYWebCheckoutPaymentProvider *webPaymentProvider;
@property (nonatomic, strong) BUYApplePayPaymentProvider *applePayPaymentProvider;
@end
@interface ProductViewController () <UITableViewDataSource, UITableViewDelegate, UIViewControllerTransitioningDelegate, VariantSelectionDelegate, ProductViewNavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) NSString *productId;
@property (nonatomic, strong) BUYProductVariant *selectedProductVariant;
@property (nonatomic, strong) Theme *theme;
@property (nonatomic, assign) BOOL shouldShowVariantSelector;
@property (nonatomic, assign) BOOL shouldEnableVariantSelection;
@property (nonatomic, assign) BOOL shouldShowDescription;
@property (nonatomic, strong) BUYProduct *product;
@property (nonatomic, assign) BOOL isLoading;
@property (nonatomic, strong) NSNumberFormatter *currencyFormatter;
@property (nonatomic, weak) BUYCart *cart;
@property (nonatomic, assign) BOOL isLoadingShop;
// views
@property (nonatomic, strong) ProductView *productView;
@property (nonatomic, weak) UIView *navigationBar;
@property (nonatomic, weak) UILabel *navigationBarTitle;
@property (nonatomic, strong) ProductHeaderCell *headerCell;
@property (nonatomic, strong) ProductVariantCell *variantCell;
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;
// Share items
@property (nonatomic, strong, readonly) NSString *titleForSharing;
@property (nonatomic, strong, readonly) NSURL *URLForSharing;
@property (nonatomic, strong, readonly) UIImage *imageForSharing;
@property (nonatomic, strong, readonly) NSArray *itemsForSharing;
@end
@implementation ProductViewController
- (instancetype)initWithClient:(BUYClient *)client
{
self = [super initWithClient:client];
if (self) {
self.modalPresentationStyle = UIModalPresentationCustom;
self.transitioningDelegate = self;
_activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
_activityIndicatorView.translatesAutoresizingMaskIntoConstraints = NO;
_activityIndicatorView.hidesWhenStopped = YES;
[_activityIndicatorView startAnimating];
[self.view addSubview:_activityIndicatorView];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_activityIndicatorView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_activityIndicatorView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
}
return self;
}
- (instancetype)initWithClient:(BUYClient *)client theme:(Theme *)theme
{
NSParameterAssert(client);
self = [self initWithClient:client];
if (self) {
if (theme == nil) {
theme = [Theme new];
}
[theme styleProductViewController];
}
return self;
}
- (instancetype)initWithClient:(BUYClient *)client cart:(BUYCart *)cart
{
NSParameterAssert(cart);
self = [self initWithClient:client];
if (self) {
self.cart = cart;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
}
- (ProductView *)productView
{
if (_productView == nil && self.product != nil && self.shop != nil) {
_productView = [[ProductView alloc] initWithFrame:CGRectMake(0, 0, self.preferredContentSize.width, self.preferredContentSize.height) product:self.product shouldShowApplePaySetup:self.shouldShowApplePaySetup];
_productView.translatesAutoresizingMaskIntoConstraints = NO;
_productView.hidden = YES;
[self.view addSubview:_productView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_productView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_productView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_productView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_productView)]];
_productView.tableView.delegate = self;
_productView.tableView.dataSource = self;
[_productView.productViewFooter setApplePayAvailable:self.shouldShowApplePayButton requiresSetup:self.shouldShowApplePaySetup];
[_productView.productViewFooter.paymentButton addTarget:self action:@selector(checkoutWithApplePay) forControlEvents:UIControlEventTouchUpInside];
if (self.cart) {
[_productView.productViewFooter.actionButton setTitle:NSLocalizedString(@"Add to Cart", nil) forState:UIControlStateNormal];
[_productView.productViewFooter.actionButton addTarget:self action:@selector(addSelectedVariantToCart) forControlEvents:UIControlEventTouchUpInside];
}
else {
[_productView.productViewFooter.actionButton addTarget:self action:@selector(checkoutWithShopify) forControlEvents:UIControlEventTouchUpInside];
}
_productView.productViewHeader.collectionView.delegate = self;
_productView.productViewHeader.collectionView.dataSource = self;
_productView.layoutMargins = UIEdgeInsetsMake(self.productView.layoutMargins.top, self.productView.layoutMargins.left, self.bottomLayoutGuide.length, self.productView.layoutMargins.right);
}
return _productView;
}
- (CGSize)preferredContentSize
{
return CGSizeMake(MIN(BUYMaxProductViewWidth, self.view.bounds.size.width),
MIN(BUYMaxProductViewHeight, self.view.bounds.size.height));
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self setupNavigationBarAppearance];
[self.navigationController setNavigationBarHidden:(self.presentingViewController && self.isLoading)];
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (self.productView.hasSetVariantOnCollectionView == NO) {
if ([self canCollectionViewDrawProductImages] || [self.product.images count] == 0) {
[self setSelectedProductVariant:self.selectedProductVariant];
self.productView.hasSetVariantOnCollectionView = YES;
}
}
}
- (BOOL)canCollectionViewDrawProductImages
{
return [self.product.images count] > 0 && CGSizeEqualToSize(self.productView.productViewHeader.collectionView.bounds.size, CGSizeZero) == NO;
}
- (void)setupNavigationBarAppearance
{
if (self.navigationBar == nil && _productView && self.presentingViewController != nil) {
[(ProductViewNavigationController*)self.navigationController updateCloseButtonImageWithTintColor:NO duration:0];
for (UIView *view in [self.navigationController.navigationBar subviews]) {
if (CGRectGetHeight(view.bounds) >= 44) {
// Get a reference to the UINavigationBar
self.navigationBar = view;
self.navigationBar.alpha = 0;
continue;
} else if ([view.subviews count] == 1 && [view.subviews[0] isKindOfClass:[UILabel class]]) {
// Get a reference to the UINavigationBar's title
self.navigationBarTitle = view.subviews[0];
self.navigationBarTitle.alpha = 0;
continue;
}
}
// Hide the navigation bar
[self scrollViewDidScroll:self.productView.tableView];
} else if (self.navigationController && _productView && self.presentingViewController == nil) {
[self.productView setTopInset:CGRectGetHeight(self.navigationController.navigationBar.bounds) + self.navigationController.topLayoutGuide.length];
}
}
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
ProductViewPresentationController *presentationController = [[ProductViewPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
presentationController.delegate = presentationController;
presentationController.navigationDelegate = self;
return presentationController;
}
- (void)loadProduct:(NSString *)productId completion:(void (^)(BOOL success, NSError *error))completion
{
if (productId == nil) {
if (completion) {
completion(NO, [NSError errorWithDomain:BUYShopifyError code:BUYShopifyError_NoProductSpecified userInfo:nil]);
}
} else {
self.isLoading = YES;
[self getShopWithCallback:^(BOOL success, NSError *error) {
if (success) {
self.productId = productId;
[self.client getProductById:productId completion:^(BUYProduct *product, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
if (completion) {
completion(NO, error);
}
} else {
self.product = product;
if (completion) {
completion(YES, nil);
}
}
});
}];
} else {
self.isLoading = NO;
if (completion) {
completion(success, error);
}
}
}];
}
}
- (void)loadWithProduct:(BUYProduct *)product completion:(void (^)(BOOL success, NSError *error))completion;
{
if (product == nil) {
completion(NO, [NSError errorWithDomain:BUYShopifyError code:BUYShopifyError_NoProductSpecified userInfo:nil]);
} else {
self.isLoading = YES;
if (self.shop == nil) {
[self getShopWithCallback:^(BOOL success, NSError *error) {
if (success) {
self.product = product;
}
if (completion) {
completion(success, error);
}
}];
} else {
self.product = product;
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(YES, nil);
}
});
}
}
}
- (void)getShopWithCallback:(void (^)(BOOL, NSError *))block
{
// fetch shop details for the currency and country codes
self.isLoadingShop = YES;
[self.client getShop:^(BUYShop *shop, NSError *error) {
if (error == nil) {
self.shop = shop;
}
else {
if ([self.delegate respondsToSelector:@selector(controllerFailedToStartApplePayProcess:)]) {
[self.delegate controllerFailedToStartApplePayProcess:self];
}
}
self.isLoadingShop = NO;
if (block) block((error == nil), error);
}];
}
- (void)setProduct:(BUYProduct *)product
{
self.isLoading = NO;
_product = product;
self.navigationItem.title = _product.title;
self.selectedProductVariant = [_product.variants firstObject];
self.shouldShowVariantSelector = [_product isDefaultVariant] == NO;
self.shouldEnableVariantSelection = self.shouldShowVariantSelector && [_product.variants count] > 1;
self.shouldShowDescription = ([_product.htmlDescription length] == 0) == NO;
self.productView.hidden = NO;
[self setupNavigationBarAppearance];
[self.activityIndicatorView stopAnimating];
[self setNeedsStatusBarAppearanceUpdate];
if (self.presentingViewController) {
[self.navigationController setNavigationBarHidden:NO];
}
if (self.product.publicURL) {
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareLink)];
NSArray *rightButtons = [@[rightButton] arrayByAddingObjectsFromArray:self.navigationItem.rightBarButtonItems];
self.navigationItem.rightBarButtonItems = rightButtons;
}
}
- (void)setShop:(BUYShop *)shop
{
[super setShop:shop];
self.currencyFormatter = [[NSNumberFormatter alloc] init];
self.currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
self.currencyFormatter.currencyCode = shop.currency;
[self.productView.productViewFooter setApplePayAvailable:self.shouldShowApplePaySetup requiresSetup:self.shouldShowApplePaySetup];
[self.productView.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = 0;
if (self.product) {
rows += 1; // product title and price
rows += self.shouldShowVariantSelector;
rows += self.shouldShowDescription;
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *theCell = nil;
if (indexPath.row == 0) {
ProductHeaderCell *cell = [tableView dequeueReusableCellWithIdentifier:@"headerCell"];
[cell setProductVariant:self.selectedProductVariant withCurrencyFormatter:self.currencyFormatter];
self.headerCell = cell;
theCell = cell;
} else if (indexPath.row == 1 && self.shouldShowVariantSelector) {
ProductVariantCell *cell = [tableView dequeueReusableCellWithIdentifier:@"variantCell"];
[cell setOptionsForProductVariant:self.selectedProductVariant];
cell.accessoryType = self.shouldEnableVariantSelection ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
self.variantCell = cell;
theCell = cell;
} else if ((indexPath.row == 2 && self.shouldShowDescription) || (indexPath.row == 1 && self.shouldShowVariantSelector == NO && self.shouldShowDescription)) {
ProductDescriptionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"descriptionCell"];
cell.descriptionHTML = self.product.htmlDescription;
cell.separatorInset = UIEdgeInsetsMake(0, CGRectGetWidth(self.productView.tableView.bounds), 0, 0);
theCell = cell;
}
return theCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1 && self.shouldEnableVariantSelection) {
[self.productView.tableView deselectRowAtIndexPath:indexPath animated:YES];
VariantSelectionViewController *optionSelectionViewController = [[VariantSelectionViewController alloc] initWithProduct:self.product];
optionSelectionViewController.selectedProductVariant = self.selectedProductVariant;
optionSelectionViewController.delegate = self;
optionSelectionViewController.currencyFormatter = self.currencyFormatter;
OptionSelectionNavigationController *optionSelectionNavigationController = [[OptionSelectionNavigationController alloc] initWithRootViewController:optionSelectionViewController];
[self presentViewController:optionSelectionNavigationController animated:YES completion:nil];
}
}
#pragma mark - BUYVariantSelectionViewControllerDelegate
- (void)variantSelectionController:(VariantSelectionViewController *)controller didSelectVariant:(BUYProductVariant *)variant
{
if (self.selectedProductVariant != variant) {
self.selectedProductVariant = variant;
[self.productView.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[self dismissViewControllerAnimated:YES completion:^{
[self setNeedsStatusBarAppearanceUpdate];
[self scrollViewDidScroll:self.productView.tableView];
}];
}
- (void)variantSelectionControllerDidCancelVariantSelection:(VariantSelectionViewController *)controller atOptionIndex:(NSUInteger)optionIndex
{
[self dismissViewControllerAnimated:YES completion:^{
[self setNeedsStatusBarAppearanceUpdate];
}];
}
- (void)setSelectedProductVariant:(BUYProductVariant *)selectedProductVariant {
_selectedProductVariant = selectedProductVariant;
if (self.headerCell) {
[self.headerCell setProductVariant:selectedProductVariant withCurrencyFormatter:self.currencyFormatter];
[self.variantCell setOptionsForProductVariant:self.selectedProductVariant];
}
if (self.productView.productViewHeader.collectionView) {
[self.productView.productViewHeader setImageForSelectedVariant:_selectedProductVariant withImages:[self.product.images array]];
[self.productView updateBackgroundImage:[self.product.images array]];
}
if (self.productView.productViewFooter) {
self.productView.productViewFooter.actionButton.enabled = selectedProductVariant.available.boolValue;
self.productView.productViewFooter.paymentButton.enabled = selectedProductVariant.available.boolValue;
}
if (self.productView.tableView) {
[self scrollViewDidScroll:self.productView.tableView];
}
}
#pragma mark Scroll view delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ([scrollView isKindOfClass:[UITableView class]]) {
if (self.productView.productViewHeader) {
[self.productView scrollViewDidScroll:scrollView];
if (self.navigationBar) {
CGFloat duration = 0.3f;
if (self.navigationBar.alpha != 1 && [self navigationBarThresholdReached] == YES) {
[(ProductViewNavigationController*)self.navigationController updateCloseButtonImageWithTintColor:YES duration:duration];
[UIView animateWithDuration:duration
delay:0
options:(UIViewAnimationOptionCurveLinear | UIViewKeyframeAnimationOptionBeginFromCurrentState)
animations:^{
[self setNeedsStatusBarAppearanceUpdate];
self.navigationBar.alpha = 1;
self.navigationBarTitle.alpha = 1;
}
completion:NULL];
} else if (self.navigationBar.alpha != 0 && [self navigationBarThresholdReached] == NO) {
duration = 0.2f;
[(ProductViewNavigationController*)self.navigationController updateCloseButtonImageWithTintColor:NO duration:duration];
[UIView animateWithDuration:duration
delay:0
options:(UIViewAnimationOptionCurveLinear | UIViewKeyframeAnimationOptionBeginFromCurrentState)
animations:^{
[self setNeedsStatusBarAppearanceUpdate];
self.navigationBar.alpha = 0;
self.navigationBarTitle.alpha = 0;
}
completion:NULL];
}
[self.productView.productViewHeader.productViewHeaderOverlay scrollViewDidScroll:scrollView withNavigationBarHeight:CGRectGetHeight(self.navigationBar.bounds)];
}
} else if (self.productView.productViewHeader == nil && self.navigationBar && self.navigationBar.alpha == 0) {
[(ProductViewNavigationController*)self.navigationController updateCloseButtonImageWithTintColor:YES duration:0];
self.navigationBar.alpha = 1;
self.navigationBarTitle.alpha = 1;
CGFloat topInset = 0;
if (self.presentingViewController) {
topInset = CGRectGetHeight([[(UINavigationController*)self.presentingViewController navigationBar] bounds]) + self.presentingViewController.topLayoutGuide.length;
}
[self.productView setInsets:UIEdgeInsetsMake(topInset, 0, 0, 0) appendToCurrentInset:YES];
}
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if ([scrollView isKindOfClass:[UICollectionView class]]) {
[self.productView updateBackgroundImage:[self.product.images array]];
}
}
#pragma mark Checkout
- (void)addSelectedVariantToCart
{
[self.cart addVariant:self.selectedProductVariant];
}
- (void)checkoutWithApplePay
{
if (self.isApplePayAvailable) {
self.checkout = [self checkoutWithVariant:self.selectedProductVariant];
[self startApplePayCheckout:self.checkout];
} else {
[[[PKPassLibrary alloc] init] openPaymentSetup];
}
}
- (void)checkoutWithShopify
{
self.checkout = [self checkoutWithVariant:self.selectedProductVariant];
[self startWebCheckout:self.checkout];
}
- (BUYCheckout *)checkoutWithVariant:(BUYProductVariant *)variant
{
BUYModelManager *modelManager = self.client.modelManager;
BUYCart *cart = [modelManager insertCartWithJSONDictionary:nil];
[cart addVariant:variant];
return [modelManager checkoutWithCart:cart];
}
#pragma mark UIStatusBar appearance
- (UIStatusBarStyle)preferredStatusBarStyle
{
if (self.navigationController.navigationBar.barStyle == UIBarStyleBlack || ([self navigationBarThresholdReached] == NO && self.isLoading == NO && self.productView.productViewHeader)) {
return UIStatusBarStyleLightContent;
} else if (self.isLoading == YES && self.navigationController.navigationBar.barStyle == UIBarStyleBlack && self.productView.productViewHeader) {
return UIStatusBarStyleLightContent;
} else {
return UIStatusBarStyleDefault;
}
}
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
return UIStatusBarAnimationFade;
}
- (BOOL)navigationBarThresholdReached
{
return self.productView.tableView.contentOffset.y > CGRectGetHeight(self.productView.productViewHeader.bounds) - CGRectGetHeight(self.navigationBar.bounds);
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate {
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}
- (void)presentationControllerWillDismiss:(UIPresentationController *)presentationController
{
}
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
{
if ([self.delegate respondsToSelector:@selector(didDismissViewController:)]) {
[self.delegate didDismissViewController:self];
}
_product = nil;
_productId = nil;
[_productView removeFromSuperview];
_productView = nil;
}
#pragma mark - Collection View Delegate and Datasource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [self.product.images count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
ProductImageCell *cell = (ProductImageCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
BUYImageLink *image = self.product.images[indexPath.row];
[cell.productImageView loadImageWithURL:image.sourceURL completion:NULL];
[cell setContentOffset:self.productView.tableView.contentOffset];
return cell;
}
- (void)presentPortraitInViewController:(UIViewController *)controller
{
ProductViewNavigationController *navController = [[ProductViewNavigationController alloc] initWithRootViewController:self];
navController.modalPresentationStyle = [ProductViewPresentationController adaptivePresentationStyle];
navController.navigationDelegate = self;
[controller presentViewController:navController animated:YES completion:nil];
}
#pragma mark - Share sheet
- (void)shareLink
{
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:self.itemsForSharing applicationActivities:nil];
[self presentViewController:activityController animated:YES completion:nil];
}
- (NSString *)titleForSharing
{
return self.product.title;
}
- (NSURL *)URLForSharing
{
return self.product.publicURL;
}
- (UIImage *)ImageForSharing
{
UICollectionView *collectionView = self.productView.productViewHeader.collectionView;
NSIndexPath *selectedIndex = collectionView.indexPathsForVisibleItems.firstObject;
ProductImageCell *cell = (ProductImageCell *)[collectionView cellForItemAtIndexPath:selectedIndex];
return cell.productImageView.image;
}
- (NSArray *)itemsForSharing
{
return [NSArray arrayWithObjects:self.titleForSharing, self.URLForSharing, self.imageForSharing, nil];
}
#pragma mark - Payment delegate methods
- (void)willStartCheckout
{
[_productView.productViewFooter.actionButton showActivityIndicator:NO];
if ([self.delegate respondsToSelector:@selector(controllerWillCheckoutViaWeb:)]) {
[self.delegate controllerWillCheckoutViaWeb:self];
}
}
- (void)didFailCheckoutWithError:(NSError *)error
{
[_productView.productViewFooter.actionButton showActivityIndicator:NO];
[self.productView showErrorWithMessage:@"Could not checkout at this time"];
if ([self.delegate respondsToSelector:@selector(controller:failedToCreateCheckout:)]) {
[self.delegate controller:self failedToCreateCheckout:error];
}
}
@end
//
// BUYProductViewHeader.h
// ProductViewHeader.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,16 +25,17 @@
//
@import UIKit;
@class BUYImageView;
@import Buy;
@class AsyncImageView;
@class BUYProductVariant;
@class BUYTheme;
@class BUYProductViewHeaderOverlay;
@class HeaderOverlayView;
/**
* The tableHeaderView containing a horizontally scrolling collection view
* that display product images.
*/
@interface BUYProductViewHeader : UIView
@interface ProductViewHeader : UIView
/**
* A horiztonally scrolling collection view containing product images.
......@@ -45,7 +46,7 @@
* An overlay view containing effects views (light or dark view and a UIVisualEffectsView) that becomes
* visible as the user scrolls the contents up. This provides a more seamless transition for the navigation bar.
*/
@property (nonatomic, strong) BUYProductViewHeaderOverlay *productViewHeaderOverlay;
@property (nonatomic, strong) HeaderOverlayView *productViewHeaderOverlay;
/**
* Initializer with a frame to setup the product image collection view and theme the header
......@@ -55,11 +56,11 @@
*
* @return The product view header to display in the BUYProductViewController's table view tableHeaderView
*/
- (instancetype)initWithFrame:(CGRect)frame theme:(BUYTheme*)theme;
- (instancetype)initWithFrame:(CGRect)frame;
/**
* A method to set the content offset of the table view and calculate the height of the image
* used to set the correct height and offset for the stickyFooterView in the BUYProductView.
* used to set the correct height and offset for the stickyFooterView in the ProductView.
*
* @param scrollView The table view being scrolled
*
......
//
// BUYProductViewHeader.m
// ProductViewHeader.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,29 +24,26 @@
// THE SOFTWARE.
//
#import "BUYProductViewHeader.h"
#import "BUYImageView.h"
#import "BUYGradientView.h"
#import "BUYProductImageCollectionViewCell.h"
#import "BUYImageLink.h"
#import "BUYProductVariant.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "BUYProductViewHeaderOverlay.h"
#import "ProductViewHeader.h"
#import "AsyncImageView.h"
#import "GradientView.h"
#import "ProductImageCell.h"
#import "Theme+Additions.h"
#import "HeaderOverlayView.h"
@interface BUYProductViewHeader ()
@interface ProductViewHeader ()
@property (nonatomic, strong) UIPageControl *pageControl;
@property (nonatomic, strong) UIView *bottomGradientContainerView;
@property (nonatomic, strong) BUYGradientView *bottomGradientView;
@property (nonatomic, strong) GradientView *bottomGradientView;
@property (nonatomic, strong) NSLayoutConstraint *bottomGradientViewLayoutConstraintHeight;
@property (nonatomic, strong) NSLayoutConstraint *bottomGradientViewBottomContraint;
@end
@implementation BUYProductViewHeader
@implementation ProductViewHeader
- (instancetype)initWithFrame:(CGRect)frame theme:(BUYTheme*)theme
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
......@@ -63,7 +60,7 @@
_collectionView.pagingEnabled = YES;
_collectionView.clipsToBounds = NO;
_collectionView.translatesAutoresizingMaskIntoConstraints = NO;
[_collectionView registerClass:[BUYProductImageCollectionViewCell class] forCellWithReuseIdentifier:@"Cell"];
[_collectionView registerClass:[ProductImageCell class] forCellWithReuseIdentifier:@"Cell"];
[self addSubview:_collectionView];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_collectionView]|"
......@@ -101,7 +98,7 @@
constant:kBuyBottomGradientHeightWithoutPageControl];
[self addConstraint:_bottomGradientViewLayoutConstraintHeight];
_bottomGradientView = [[BUYGradientView alloc] init];
_bottomGradientView = [[GradientView alloc] init];
_bottomGradientView.userInteractionEnabled = NO;
_bottomGradientView.topColor = [UIColor clearColor];
_bottomGradientView.bottomColor = [UIColor colorWithWhite:0 alpha:0.05f];
......@@ -160,7 +157,7 @@
multiplier:1.0
constant:kBuyPageControlHeight]];
_productViewHeaderOverlay = [[BUYProductViewHeaderOverlay alloc] initWithTheme:theme];
_productViewHeaderOverlay = [[HeaderOverlayView alloc] init];
_productViewHeaderOverlay.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_productViewHeaderOverlay];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_productViewHeaderOverlay]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_productViewHeaderOverlay)]];
......@@ -192,7 +189,7 @@
CGRect visibleRect = (CGRect){.origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
BUYProductImageCollectionViewCell *cell = (BUYProductImageCollectionViewCell*)[self.collectionView cellForItemAtIndexPath:visibleIndexPath];
ProductImageCell *cell = (ProductImageCell*)[self.collectionView cellForItemAtIndexPath:visibleIndexPath];
if (cell) {
[cell setContentOffset:scrollView.contentOffset];
return cell.productImageViewConstraintHeight.constant;
......
//
// BUYNavigationController.h
// ProductViewNavigationController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,10 +24,9 @@
// THE SOFTWARE.
//
@import UIKit;
#import "BUYTheme.h"
#import "NavigationController.h"
@protocol BUYNavigationControllerDelegate <NSObject>
@protocol ProductViewNavigationControllerDelegate <NSObject>
/**
* Delegate callback when the BUYProductViewController will dismiss
......@@ -45,10 +44,7 @@
@end
/**
* A custom navigation controller used in the BUYProductViewController, adding a close button and the ability to theme the navigation bar
*/
@interface BUYNavigationController : UINavigationController <BUYThemeable>
@interface ProductViewNavigationController : NavigationController
/**
* The close button has two styles; white or tint color. This methods updates the button image with the preferred style.
......@@ -60,9 +56,8 @@
- (void)updateCloseButtonImageWithTintColor:(BOOL)tintColor duration:(CGFloat)duration;
/**
* The BUYNavigationControllerDelegate
* The SmoothNavigationControllerDelegate
*/
@property (nonatomic, weak) id <BUYNavigationControllerDelegate> navigationDelegate;
@property (nonatomic, weak) id <ProductViewNavigationControllerDelegate> navigationDelegate;
@end
//
// BUYNavigationController.m
// ProductViewNavigationController.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,16 +24,12 @@
// THE SOFTWARE.
//
#import "BUYNavigationController.h"
#import "BUYImageKit.h"
#import "BUYTheme+Additions.h"
#import "BUYProductViewController.h"
#import "ProductViewNavigationController.h"
#import "ImageKit.h"
#import "Theme+Additions.h"
#import "ProductViewController.h"
@interface BUYNavigationController ()
@property (nonatomic, strong) BUYTheme *theme;
@end
@implementation BUYNavigationController
@implementation ProductViewNavigationController
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
......@@ -45,18 +41,23 @@
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithCustomView:closeButton];
self.topViewController.navigationItem.leftBarButtonItem = barButtonItem;
if ([[UINavigationBar class] respondsToSelector:@selector(appearanceWhenContainedInInstancesOfClasses:)]) {
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[BUYNavigationController class]]] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[ProductViewNavigationController class]]] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
} else {
[[UINavigationBar appearanceWhenContainedIn:[BUYNavigationController class], nil] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
[[UINavigationBar appearanceWhenContainedIn:[ProductViewNavigationController class], nil] setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
}
[self updateCloseButtonImageWithTintColor:YES duration:0];
return self;
}
- (void)updateCloseButtonImageWithTintColor:(BOOL)tintColor duration:(CGFloat)duration
{
UIButton *button = (UIButton*)self.topViewController.navigationItem.leftBarButtonItem.customView;
UIImage *newButtonImage = [BUYImageKit imageOfProductViewCloseImageWithFrame:button.bounds color:tintColor ? self.theme.tintColor : [UIColor whiteColor] hasShadow:tintColor == NO];
UIImage *newButtonImage = [ImageKit imageOfProductViewCloseImageWithFrame:button.bounds color:[UIColor whiteColor] hasShadow:tintColor == NO];
if (tintColor) {
newButtonImage = [newButtonImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
}
[UIView transitionWithView:button.imageView
duration:duration
options:(UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionBeginFromCurrentState)
......@@ -86,18 +87,6 @@
return self.topViewController.shouldAutorotate;
}
- (void)setTheme:(BUYTheme *)theme
{
_theme = theme;
self.navigationBar.barStyle = [theme navigationBarStyle];
[self updateCloseButtonImageWithTintColor:NO duration:0];
if ([[UINavigationBar class] respondsToSelector:@selector(appearanceWhenContainedInInstancesOfClasses:)]) {
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[BUYNavigationController class]]] setTitleTextAttributes:@{ NSForegroundColorAttributeName: [theme navigationBarTitleColor] }];
} else {
[[UINavigationBar appearanceWhenContainedIn:[BUYNavigationController class], nil] setTitleTextAttributes:@{ NSForegroundColorAttributeName: [theme navigationBarTitleColor] }];
}
}
-(UIViewController *)childViewControllerForStatusBarStyle
{
return [self childViewController];
......@@ -110,7 +99,7 @@
-(UIViewController*)childViewController
{
if ([self.visibleViewController isKindOfClass:[BUYProductViewController class]] == NO) {
if ([self.visibleViewController isKindOfClass:[ProductViewController class]] == NO) {
return self.viewControllers[0];
}
return self.visibleViewController;
......
//
// BUYPresentationControllerWithNavigationController.h
// ProductViewPresentationController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,16 +25,15 @@
//
@import UIKit;
#import "BUYTheme.h"
@protocol BUYPresentationControllerWithNavigationControllerDelegate;
@protocol ProductViewNavigationControllerDelegate;
/**
* Initialized the BUYProductViewController inside a navigation controller (`BUYNavigationController`).
* Initialized the BUYProductViewController inside a navigation controller (`ProductViewNavigationController`).
*/
@interface BUYPresentationControllerWithNavigationController : UIPresentationController <UIAdaptivePresentationControllerDelegate, BUYThemeable>
@interface ProductViewPresentationController : UIPresentationController <UIAdaptivePresentationControllerDelegate>
@property (nonatomic, weak) id <BUYNavigationControllerDelegate> navigationDelegate;
@property (nonatomic, weak) id <ProductViewNavigationControllerDelegate> navigationDelegate;
/**
* The desired presentation style
......
//
// BUYPresentationControllerWithNavigationController.m
// ProductViewPresentationController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,23 +24,16 @@
// THE SOFTWARE.
//
#import "BUYNavigationController.h"
#import "BUYOptionSelectionNavigationController.h"
#import "BUYPresentationControllerWithNavigationController.h"
#import "BUYImageKit.h"
#import "OptionSelectionNavigationController.h"
#import "ProductViewPresentationController.h"
#import "ProductViewNavigationController.h"
@interface BUYPresentationControllerWithNavigationController ()
@property (nonatomic, strong) BUYTheme *theme;
@end
@implementation BUYPresentationControllerWithNavigationController
@implementation ProductViewPresentationController
- (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style
{
BUYNavigationController *navigationController = [[BUYNavigationController alloc] initWithRootViewController:controller.presentedViewController];
ProductViewNavigationController *navigationController = [[ProductViewNavigationController alloc] initWithRootViewController:controller.presentedViewController];
navigationController.navigationDelegate = self.navigationDelegate;
[navigationController setTheme:self.theme];
return navigationController;
}
......@@ -59,11 +52,4 @@
return (traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) ? UIModalPresentationFullScreen : UIModalPresentationFormSheet;
}
- (void)setTheme:(BUYTheme *)theme
{
_theme = theme;
BUYNavigationController *navigationController = (BUYNavigationController*)self.presentedViewController;
[navigationController setTheme:theme];
}
@end
//
// BUYVariantOptionBreadCrumbsView.h
// OptionBreadCrumbsView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,12 +25,11 @@
//
@import UIKit;
#import "BUYTheme.h"
/**
* A view containing the current selection of variant option values that sits below the navigation controller for the variant selection.
*/
@interface BUYVariantOptionBreadCrumbsView : UIView <BUYThemeable>
@interface OptionBreadCrumbsView : UIView
/**
* Auto Layout constraint for setting the bread crumbs as hidden
......@@ -49,4 +48,9 @@
*/
- (void)setSelectedBuyOptionValues:(NSArray*)optionValues;
/**
* The color of the labels
*/
-(void)setVariantOptionTextColor:(UIColor*)color UI_APPEARANCE_SELECTOR;
@end
//
// BUYVariantOptionBreadCrumbsView.m
// OptionBreadCrumbsView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,10 +24,10 @@
// THE SOFTWARE.
//
#import "BUYVariantOptionBreadCrumbsView.h"
#import "BUYTheme+Additions.h"
#import "OptionBreadCrumbsView.h"
#import "Theme+Additions.h"
@interface BUYVariantOptionBreadCrumbsView ()
@interface OptionBreadCrumbsView ()
@property (nonatomic, strong) UILabel *optionOneLabel;
@property (nonatomic, strong) UILabel *optionTwoLabel;
......@@ -37,7 +37,7 @@
@end
@implementation BUYVariantOptionBreadCrumbsView
@implementation OptionBreadCrumbsView
- (instancetype)init
{
......@@ -47,15 +47,13 @@
_optionOneLabel = [UILabel new];
_optionOneLabel.translatesAutoresizingMaskIntoConstraints = NO;
_optionOneLabel.font = [BUYTheme variantBreadcrumbsFont];
_optionOneLabel.textColor = [BUYTheme variantBreadcrumbsTextColor];
_optionOneLabel.text = @"Selected: ";
_optionOneLabel.font = [Theme variantBreadcrumbsFont];
_optionOneLabel.text = NSLocalizedString(@"Selected: ", @"Prefix for selected option value in variant selector");
[self addSubview:_optionOneLabel];
_optionTwoLabel = [UILabel new];
_optionTwoLabel.translatesAutoresizingMaskIntoConstraints = NO;
_optionTwoLabel.font = [BUYTheme variantBreadcrumbsFont];
_optionTwoLabel.textColor = [BUYTheme variantBreadcrumbsTextColor];
_optionTwoLabel.font = [Theme variantBreadcrumbsFont];
_optionTwoLabel.alpha = 0;
[_optionTwoLabel setContentHuggingPriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal];
[self addSubview:_optionTwoLabel];
......@@ -78,11 +76,6 @@
return self;
}
- (void)setTheme:(BUYTheme *)theme
{
self.backgroundColor = [theme variantBreadcrumbsBackground];
}
- (void)setSelectedBuyOptionValues:(NSArray*)optionValues
{
if ([optionValues count] == 1) {
......@@ -128,4 +121,16 @@
}];
}
-(void)setBackgroundColor:(UIColor *)backgroundColor
{
[super setBackgroundColor:backgroundColor];
self.optionOneLabel.backgroundColor = self.optionTwoLabel.backgroundColor = self.backgroundColor;
}
-(void)setVariantOptionTextColor:(UIColor*)color
{
self.optionOneLabel.textColor = self.optionTwoLabel.textColor = color;
}
@end
//
// BUYNavigationController.h
// OptionSelectionNavigationController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,14 +25,13 @@
//
@import UIKit;
#import "BUYNavigationController.h"
#import "BUYTheme.h"
#import "BUYVariantOptionBreadCrumbsView.h"
#import "NavigationController.h"
#import "OptionBreadCrumbsView.h"
/**
* Custom navigation controller for variant option selection
*/
@interface BUYOptionSelectionNavigationController : BUYNavigationController <BUYThemeable>
@interface OptionSelectionNavigationController : NavigationController
/**
* Used to set whether to dismiss with dropping animation when variant selection is cancelled instead of confirmed
......@@ -42,6 +41,6 @@
/**
* The bread crumbs view for variant option selections
*/
@property (nonatomic, strong) BUYVariantOptionBreadCrumbsView *breadsCrumbsView;
@property (nonatomic, strong) OptionBreadCrumbsView *breadsCrumbsView;
@end
//
// BUYNavigationController.m
// OptionSelectionNavigationController.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,16 +24,15 @@
// THE SOFTWARE.
//
#import "BUYOptionSelectionNavigationController.h"
#import "BUYPresentationControllerForVariantSelection.h"
#import "BUYImageKit.h"
#import "BUYTheme+Additions.h"
#import "OptionSelectionNavigationController.h"
#import "VariantSelectionPresentationController.h"
#import "ImageKit.h"
@interface BUYOptionSelectionNavigationController () <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>
@interface OptionSelectionNavigationController () <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>
@end
@implementation BUYOptionSelectionNavigationController
@implementation OptionSelectionNavigationController
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
......@@ -46,18 +45,18 @@
self.view.clipsToBounds = YES;
// Add custom back button
UIImage *buttonImage = [[BUYImageKit imageOfVariantBackImageWithFrame:CGRectMake(0, 0, 12, 18)] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImage *buttonImage = [[ImageKit imageOfVariantBackImageWithFrame:CGRectMake(0, 0, 12, 18)] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
if ([[UIBarButtonItem class] respondsToSelector:@selector(appearanceWhenContainedInInstancesOfClasses:)]) {
[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[BUYNavigationController class]]] setBackButtonBackgroundImage:[buttonImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 0)]
[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[NavigationController class]]] setBackButtonBackgroundImage:[buttonImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 0)]
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
} else {
[[UIBarButtonItem appearanceWhenContainedIn:[BUYNavigationController class], nil] setBackButtonBackgroundImage:[buttonImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 0)]
[[UIBarButtonItem appearanceWhenContainedIn:[NavigationController class], nil] setBackButtonBackgroundImage:[buttonImage resizableImageWithCapInsets:UIEdgeInsetsMake(0, 12, 0, 0)]
forState:UIControlStateNormal
barMetrics:UIBarMetricsDefault];
}
_breadsCrumbsView = [BUYVariantOptionBreadCrumbsView new];
_breadsCrumbsView = [OptionBreadCrumbsView new];
_breadsCrumbsView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:_breadsCrumbsView];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_breadsCrumbsView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
......@@ -71,19 +70,11 @@
return self;
}
- (void)setTheme:(BUYTheme *)theme
{
[self.breadsCrumbsView setTheme:theme];
self.navigationBar.barStyle = [theme navigationBarStyle];
[self.navigationBar setTitleTextAttributes:@{ NSForegroundColorAttributeName : [theme navigationBarTitleVariantSelectionColor] }];
self.navigationBar.tintColor = theme.tintColor;
}
#pragma mark - Transitioning Delegate Methods
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
BUYPresentationControllerForVariantSelection *presentationController = [[BUYPresentationControllerForVariantSelection alloc] initWithPresentedViewController:presented presentingViewController:presenting];
VariantSelectionPresentationController *presentationController = [[VariantSelectionPresentationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
return presentationController;
}
......@@ -126,7 +117,7 @@
UIView *dismissedView = [transitionContext viewForKey:UITransitionContextFromViewKey];
CGRect frame = dismissedView.frame;
CGAffineTransform transform;
BUYOptionSelectionNavigationController *optionSelectionNavigationController = (BUYOptionSelectionNavigationController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
OptionSelectionNavigationController *optionSelectionNavigationController = (OptionSelectionNavigationController *)[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
if (optionSelectionNavigationController.dismissWithCancelAnimation) {
frame.origin.y += 150;
int angle = arc4random_uniform(20) - 10;
......
//
// BUYOptionSelectionViewController.h
// OptionSelectionViewController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,12 +25,10 @@
//
@import UIKit;
#import "BUYTheme.h"
@import Buy;
@class OptionSelectionViewController;
@class BUYOptionValue;
@class BUYOptionSelectionViewController;
@protocol BUYOptionSelectionDelegate <NSObject>
@protocol OptionSelectionDelegate <NSObject>
/**
* Called when a user selected an option value
......@@ -38,21 +36,21 @@
* @param controller The BUYOptionSelectionViewController
* @param optionValue The selected BUYOptionValue
*/
- (void)optionSelectionController:(BUYOptionSelectionViewController *)controller didSelectOptionValue:(BUYOptionValue *)optionValue;
- (void)optionSelectionController:(OptionSelectionViewController *)controller didSelectOptionValue:(BUYOptionValue *)optionValue;
/**
* Called when a user pops the navigation controller and backs out of the current option
*
* @param controller The BUYOptionSelectionViewController
*/
- (void)optionSelectionControllerDidBackOutOfChoosingOption:(BUYOptionSelectionViewController *)controller;
- (void)optionSelectionControllerDidBackOutOfChoosingOption:(OptionSelectionViewController *)controller;
@end
/**
* The view controller containing a table view with variant options for selection
*/
@interface BUYOptionSelectionViewController : UITableViewController <BUYThemeable>
@interface OptionSelectionViewController : UITableViewController
/**
* Initalizer for the BUYOptionSelectionViewController
......@@ -92,6 +90,6 @@
/**
* Delegate to inform about option selections and cancellations
*/
@property (nonatomic, weak) id <BUYOptionSelectionDelegate> delegate;
@property (nonatomic, weak) id <OptionSelectionDelegate> delegate;
@end
//
// BUYOptionSelectionViewController.m
// OptionSelectionViewController.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,20 +24,19 @@
// THE SOFTWARE.
//
#import "BUYImageKit.h"
#import "BUYOptionSelectionViewController.h"
#import "BUYOptionValue.h"
#import "BUYOptionValueCell.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "ImageKit.h"
#import "OptionSelectionViewController.h"
#import "OptionValueCell.h"
#import "Theme+Additions.h"
@interface OptionSelectionViewController ()
@interface BUYOptionSelectionViewController ()
@property (nonatomic, strong) NSArray *optionValues;
@property (nonatomic, weak) BUYTheme *theme;
@property (nonatomic, strong) NSArray *filteredProductVariantsForSelectionOption;
@end
@implementation BUYOptionSelectionViewController
@implementation OptionSelectionViewController
- (instancetype)initWithOptionValues:(NSArray *)optionValues filteredProductVariantsForSelectionOption:(NSArray*)filteredProductVariantsForSelectionOption
{
......@@ -55,18 +54,10 @@
return self;
}
- (void)setTheme:(BUYTheme *)theme
{
_theme = theme;
self.view.backgroundColor = [theme backgroundColor];
self.tableView.backgroundColor = self.view.backgroundColor;
self.tableView.separatorColor = [theme separatorColor];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[BUYOptionValueCell class] forCellReuseIdentifier:@"Cell"];
[self.tableView registerClass:[OptionValueCell class] forCellReuseIdentifier:@"Cell"];
self.tableView.tableFooterView = [UIView new];
}
......@@ -97,15 +88,15 @@
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BUYOptionValue *optionValue = self.optionValues[indexPath.row];
BUYOptionValueCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
OptionValueCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
cell.selectedImageView.hidden = ![optionValue isEqual:self.selectedOptionValue];
if (self.isLastOption) {
cell.accessoryType = UITableViewCellAccessoryNone;
BUYProductVariant *productVariant = (BUYProductVariant*)self.filteredProductVariantsForSelectionOption[indexPath.row];
[cell setOptionValue:optionValue productVariant:productVariant currencyFormatter:self.currencyFormatter theme:self.theme];
[cell setOptionValue:optionValue productVariant:productVariant currencyFormatter:self.currencyFormatter];
} else {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[cell setOptionValue:optionValue productVariant:nil currencyFormatter:nil theme:self.theme];
[cell setOptionValue:optionValue productVariant:nil currencyFormatter:nil];
}
[cell setNeedsLayout];
[cell layoutIfNeeded];
......
//
// BUYOptionValueCell.h
// OptionValueCell.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,14 +25,12 @@
//
@import UIKit;
@class BUYTheme;
@class BUYOptionValue;
@class BUYProductVariant;
@import Buy;
/**
* A table view cell displaying the option value
*/
@interface BUYOptionValueCell : UITableViewCell
@interface OptionValueCell : UITableViewCell
/**
* Image view containing a checkmark for current option value selection
......@@ -45,9 +43,10 @@
* @param optionValue The option value to display
* @param productVariant The product variant matching the option value
* @param currencyFormatter A formatter with the shop's currency
* @param theme The current theme
*/
- (void)setOptionValue:(BUYOptionValue *)optionValue productVariant:(BUYProductVariant*)productVariant currencyFormatter:(NSNumberFormatter*)currencyFormatter theme:(BUYTheme *)theme;
- (void)setOptionValue:(BUYOptionValue *)optionValue productVariant:(BUYProductVariant*)productVariant currencyFormatter:(NSNumberFormatter*)currencyFormatter;
- (void)setSelectedBackgroundViewBackgroundColor:(UIColor *)selectedBackgroundViewBackgroundColor UI_APPEARANCE_SELECTOR;
@end
//
// BUYOptionValueCell.m
// OptionValueCell.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,24 +24,24 @@
// THE SOFTWARE.
//
#import "BUYOptionValueCell.h"
#import "BUYImageKit.h"
#import "BUYOptionValue.h"
#import "BUYProductVariant.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "DisclosureIndicatorView.h"
#import "ImageKit.h"
#import "OptionValueCell.h"
#import "Theme+Additions.h"
@interface OptionValueCell()
@interface BUYOptionValueCell()
@property (nonatomic, strong) NSArray *priceConstraints;
@property (nonatomic, strong) NSArray *noPriceConstraints;
@property (nonatomic, strong) NSArray *disclosureConstraints;
@property (nonatomic, strong) NSArray *noDisclosureConstraints;
@property (nonatomic, strong) UIImageView *disclosureIndicatorImageView;
@property (nonatomic, strong) DisclosureIndicatorView *disclosureIndicatorImageView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *priceLabel;
@end
@implementation BUYOptionValueCell
@implementation OptionValueCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
......@@ -50,7 +50,6 @@
UIView *backgroundView = [[UIView alloc] init];
[self setSelectedBackgroundView:backgroundView];
self.textLabel.backgroundColor = [UIColor clearColor];
self.layoutMargins = UIEdgeInsetsMake(kBuyPaddingLarge, kBuyPaddingExtraLarge, kBuyPaddingLarge, kBuyPaddingLarge);
UIView *labelContainerView = [[UIView alloc] init];
......@@ -60,15 +59,15 @@
_titleLabel = [[UILabel alloc] init];
_titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_titleLabel setFont:[BUYTheme variantOptionValueFont]];
[_titleLabel setFont:[Theme variantOptionValueFont]];
[labelContainerView addSubview:_titleLabel];
_priceLabel = [[UILabel alloc] init];
_priceLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_priceLabel setFont:[BUYTheme variantOptionPriceFont]];
[_priceLabel setFont:[Theme variantOptionPriceFont]];
[labelContainerView addSubview:_priceLabel];
UIImage *selectedImage = [BUYImageKit imageOfPreviousSelectionIndicatorImageWithFrame:CGRectMake(0, 0, 20, 20)];
UIImage *selectedImage = [ImageKit imageOfPreviousSelectionIndicatorImageWithFrame:CGRectMake(0, 0, 20, 20)];
selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_selectedImageView = [[UIImageView alloc] initWithImage:selectedImage];
......@@ -77,7 +76,7 @@
[_selectedImageView setContentHuggingPriority:UILayoutPriorityFittingSizeLevel forAxis:UILayoutConstraintAxisHorizontal];
[self.contentView addSubview:_selectedImageView];
_disclosureIndicatorImageView = [[UIImageView alloc] init];
_disclosureIndicatorImageView = [[DisclosureIndicatorView alloc] init];
_disclosureIndicatorImageView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:_disclosureIndicatorImageView];
......@@ -127,23 +126,28 @@
}
}
- (void)setOptionValue:(BUYOptionValue *)optionValue productVariant:(BUYProductVariant*)productVariant currencyFormatter:(NSNumberFormatter*)currencyFormatter theme:(BUYTheme *)theme
-(void)tintColorDidChange
{
[super tintColorDidChange];
self.titleLabel.textColor = self.tintColor;
}
- (void)setSelectedBackgroundViewBackgroundColor:(UIColor *)selectedBackgroundViewBackgroundColor
{
self.selectedBackgroundView.backgroundColor = selectedBackgroundViewBackgroundColor;
}
- (void)setOptionValue:(BUYOptionValue *)optionValue productVariant:(BUYProductVariant*)productVariant currencyFormatter:(NSNumberFormatter*)currencyFormatter
{
self.titleLabel.textColor = theme.tintColor;
self.selectedImageView.tintColor = theme.tintColor;
self.backgroundColor = [theme backgroundColor];
self.selectedBackgroundView.backgroundColor = [theme selectedBackgroundColor];
self.disclosureIndicatorImageView.image = [BUYImageKit imageOfDisclosureIndicatorImageWithFrame:CGRectMake(0, 0, 10, 16) color:[theme disclosureIndicatorColor]];
self.titleLabel.text = optionValue.value;
if (productVariant) {
if (productVariant.available) {
self.priceLabel.text = [currencyFormatter stringFromNumber:productVariant.price];
self.priceLabel.textColor = [BUYTheme variantPriceTextColor];
self.priceLabel.textColor = [Theme variantPriceTextColor];
} else {
self.priceLabel.text = @"Sold Out";
self.priceLabel.textColor = [BUYTheme variantSoldOutTextColor];
self.priceLabel.text = NSLocalizedString(@"Sold Out", @"Sold out string displayed on option selector");
self.priceLabel.textColor = [Theme variantSoldOutTextColor];
}
[NSLayoutConstraint activateConstraints:self.priceConstraints];
[NSLayoutConstraint deactivateConstraints:self.noPriceConstraints];
......
//
// BUYVariantOptionView.h
// VariantOptionView.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -26,13 +26,11 @@
@import UIKit;
@class BUYOptionValue;
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
/**
* A view that contains a variant option name and option value for use to display the selected product variant
*/
@interface BUYVariantOptionView : UIView <BUYThemeable>
@interface VariantOptionView : UIView
/**
* Sets the text on the labels for the option value
......@@ -41,4 +39,6 @@
*/
- (void)setTextForOptionValue:(BUYOptionValue*)optionValue;
- (void)setOptionNameTextColor:(UIColor*)color UI_APPEARANCE_SELECTOR;
@end
//
// BUYVariantOptionView.m
// VariantOptionView.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,18 +24,21 @@
// THE SOFTWARE.
//
#import "BUYVariantOptionView.h"
#import "BUYOptionValue.h"
@import UIKit;
@import Buy;
#import "Theme+Additions.h"
#import "VariantOptionView.h"
#import "UIFont+BUYAdditions.h"
@interface BUYVariantOptionView ()
@interface VariantOptionView ()
@property (nonatomic, strong) UILabel *optionNameLabel;
@property (nonatomic, strong) UILabel *optionValueLabel;
@end
@implementation BUYVariantOptionView
@implementation VariantOptionView
- (instancetype)initWithFrame:(CGRect)frame
{
......@@ -47,7 +50,7 @@
_optionNameLabel = [[UILabel alloc] init];
_optionNameLabel.textColor = [UIColor colorWithWhite:0.6f alpha:1];
_optionNameLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_optionNameLabel setFont:[BUYTheme variantOptionNameFont]];
[_optionNameLabel setFont:[Theme variantOptionNameFont]];
[self addSubview:_optionNameLabel];
// Configure option value label
......@@ -55,7 +58,7 @@
_optionValueLabel.textColor = self.tintColor;
_optionValueLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_optionValueLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[_optionValueLabel setFont:[BUYTheme variantOptionValueFont]];
[_optionValueLabel setFont:[Theme variantOptionValueFont]];
[self addSubview:_optionValueLabel];
NSDictionary *views = NSDictionaryOfVariableBindings(_optionNameLabel, _optionValueLabel);
......@@ -82,12 +85,16 @@
self.optionValueLabel.textColor = self.tintColor;
}
- (void)setTheme:(BUYTheme *)theme
- (void)setBackgroundColor:(UIColor *)backgroundColor
{
self.optionNameLabel.textColor = [theme variantOptionNameTextColor];
self.backgroundColor = [theme backgroundColor];
[super setBackgroundColor:backgroundColor];
self.optionNameLabel.backgroundColor = self.backgroundColor;
self.optionValueLabel.backgroundColor = self.backgroundColor;
}
- (void)setOptionNameTextColor:(UIColor*)color
{
self.optionNameLabel.textColor = color;
}
@end
//
// PresentationController.h
// VariantSelectionPresentationController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -29,7 +29,7 @@
/**
* A presentation controller containing the view controllers for variant selection
*/
@interface BUYPresentationControllerForVariantSelection : UIPresentationController
@interface VariantSelectionPresentationController : UIPresentationController
/**
* Blurred effects view that surrounds the variant selection navigation controller
......
//
// BUYPresentationController.m
// VariantSelectionPresentationController.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,9 +24,9 @@
// THE SOFTWARE.
//
#import "BUYPresentationControllerForVariantSelection.h"
#import "VariantSelectionPresentationController.h"
@implementation BUYPresentationControllerForVariantSelection
@implementation VariantSelectionPresentationController
- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController
{
......
//
// BUYVariantSelectionViewController.h
// VariantSelectionViewController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,13 +25,11 @@
//
@import UIKit;
@import Buy;
@class BUYProduct;
@class BUYVariantSelectionViewController;
@class BUYProductVariant;
@class BUYTheme;
@class VariantSelectionViewController;
@protocol BUYVariantSelectionDelegate <NSObject>
@protocol VariantSelectionDelegate <NSObject>
/**
* Called when a user selects the last option for a product variant
......@@ -39,7 +37,7 @@
* @param controller The displayed variant selection view controller
* @param variant The selected product variant
*/
- (void)variantSelectionController:(BUYVariantSelectionViewController *)controller didSelectVariant:(BUYProductVariant *)variant;
- (void)variantSelectionController:(VariantSelectionViewController *)controller didSelectVariant:(BUYProductVariant *)variant;
/**
* Called when a user cancels out of the flow
......@@ -47,24 +45,23 @@
* @param controller The displayed variant selection view controller
* @param optionIndex The index matching the option value when the user cancelled selection in the flow
*/
- (void)variantSelectionControllerDidCancelVariantSelection:(BUYVariantSelectionViewController *)controller atOptionIndex:(NSUInteger)optionIndex;
- (void)variantSelectionControllerDidCancelVariantSelection:(VariantSelectionViewController *)controller atOptionIndex:(NSUInteger)optionIndex;
@end
/**
* The view controller that manages the option selection view controllers
*/
@interface BUYVariantSelectionViewController : UIViewController
@interface VariantSelectionViewController : UIViewController
/**
* Initalizer that takes a product and theme
* Initalizer that takes a product
*
* @param product The product to display variant options for selection
* @param theme The current theme
*
* @return An instance of BUYVariantSelectionViewController
*/
- (instancetype)initWithProduct:(BUYProduct *)product theme:(BUYTheme*)theme;
- (instancetype)initWithProduct:(BUYProduct *)product;
/**
* The product displaying variant option for
......@@ -84,6 +81,6 @@
/**
* The delegate that informs the product view of selection or cancellation
*/
@property (nonatomic, weak) id <BUYVariantSelectionDelegate> delegate;
@property (nonatomic, weak) id <VariantSelectionDelegate> delegate;
@end
//
// BUYVariantSelectionViewController.m
// VariantSelectionViewController.m
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -24,23 +24,16 @@
// THE SOFTWARE.
//
#import "BUYImageKit.h"
#import "BUYOptionSelectionNavigationController.h"
#import "BUYOptionSelectionViewController.h"
#import "BUYPresentationControllerForVariantSelection.h"
#import "BUYProduct.h"
#import "BUYProductVariant.h"
#import "BUYTheme.h"
#import "BUYTheme+Additions.h"
#import "BUYVariantSelectionViewController.h"
#import "BUYVariantOptionBreadCrumbsView.h"
#import "BUYOption.h"
#import "BUYOptionValue.h"
@interface BUYVariantSelectionViewController () <BUYOptionSelectionDelegate>
#import "ImageKit.h"
#import "OptionSelectionNavigationController.h"
#import "OptionSelectionViewController.h"
#import "VariantSelectionPresentationController.h"
#import "VariantSelectionViewController.h"
#import "OptionBreadCrumbsView.h"
@interface VariantSelectionViewController () <OptionSelectionDelegate>
@property (nonatomic, strong) BUYProduct *product;
@property (nonatomic, weak) BUYTheme *theme;
@property (nonatomic, strong) NSMutableDictionary *selectedOptions;
@property (nonatomic, assign) BOOL changedOptionSelection;
@property (nonatomic, strong) NSArray *filteredProductVariantsForSelectionOption;
......@@ -48,9 +41,9 @@
@end
@implementation BUYVariantSelectionViewController
@implementation VariantSelectionViewController
- (instancetype)initWithProduct:(BUYProduct *)product theme:(BUYTheme*)theme
- (instancetype)initWithProduct:(BUYProduct *)product
{
NSParameterAssert(product);
......@@ -60,7 +53,6 @@
self.product = product;
self.selectedOptions = [NSMutableDictionary new];
self.optionValueNames = [NSMutableArray new];
self.theme = theme;
}
return self;
......@@ -70,23 +62,23 @@
{
[super viewDidLoad];
BUYOptionSelectionViewController *controller = [self nextOptionSelectionController];
OptionSelectionViewController *controller = [self nextOptionSelectionController];
// Add close button
UIImage *closeButton = [[BUYImageKit imageOfVariantCloseImageWithFrame:CGRectMake(0, 0, 18, 20)] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIImage *closeButton = [[ImageKit imageOfVariantCloseImageWithFrame:CGRectMake(0, 0, 18, 20)] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithImage:closeButton style:UIBarButtonItemStylePlain target:self action:@selector(dismissPopover)];
controller.navigationItem.leftBarButtonItem = barButtonItem;
[self.navigationController pushViewController:controller animated:NO];
BUYOptionSelectionNavigationController *navigationController = (BUYOptionSelectionNavigationController*)self.navigationController;
UIVisualEffectView *backgroundView = [(BUYPresentationControllerForVariantSelection*)navigationController.presentationController backgroundView];
OptionSelectionNavigationController *navigationController = (OptionSelectionNavigationController*)self.navigationController;
UIVisualEffectView *backgroundView = [(VariantSelectionPresentationController*)navigationController.presentationController backgroundView];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissPopover)];
[backgroundView addGestureRecognizer:tapGestureRecognizer];
}
- (void)presentNextOption
{
BUYOptionSelectionViewController *controller = [self nextOptionSelectionController];
OptionSelectionViewController *controller = [self nextOptionSelectionController];
[self.navigationController pushViewController:controller animated:YES];
}
......@@ -107,37 +99,36 @@
return [[self.selectedOptions allKeys] count] == 1;
}
- (BUYOptionSelectionViewController *)nextOptionSelectionController
- (OptionSelectionViewController *)nextOptionSelectionController
{
NSUInteger index = [[self.selectedOptions allKeys] count];
BUYOption *option = self.product.options[index];
NSArray *options = [self.product valuesForOption:option variants:self.filteredProductVariantsForSelectionOption];
BUYOptionSelectionViewController *optionController = [[BUYOptionSelectionViewController alloc] initWithOptionValues:options filteredProductVariantsForSelectionOption:self.filteredProductVariantsForSelectionOption];
optionController.theme = self.theme;
OptionSelectionViewController *optionController = [[OptionSelectionViewController alloc] initWithOptionValues:options filteredProductVariantsForSelectionOption:self.filteredProductVariantsForSelectionOption];
optionController.delegate = self;
optionController.selectedOptionValue = self.changedOptionSelection ? nil : [self.selectedProductVariant optionValueForName:option.name];
optionController.isLastOption = [self isLastOption];
optionController.currencyFormatter = self.currencyFormatter;
optionController.title = option.name;
if (index > 0) {
[[(BUYOptionSelectionNavigationController*)self.navigationController breadsCrumbsView] setSelectedBuyOptionValues:[self.optionValueNames copy]];
optionController.tableView.contentInset = optionController.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(optionController.tableView.contentInset.top + CGRectGetHeight([[(BUYOptionSelectionNavigationController*)self.navigationController breadsCrumbsView] bounds]), optionController.tableView.contentInset.left, optionController.tableView.contentInset.bottom, optionController.tableView.contentInset.right);
[[(OptionSelectionNavigationController*)self.navigationController breadsCrumbsView] setSelectedBuyOptionValues:[self.optionValueNames copy]];
optionController.tableView.contentInset = optionController.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(optionController.tableView.contentInset.top + CGRectGetHeight([[(OptionSelectionNavigationController*)self.navigationController breadsCrumbsView] bounds]), optionController.tableView.contentInset.left, optionController.tableView.contentInset.bottom, optionController.tableView.contentInset.right);
}
return optionController;
}
- (void)dismissPopover
{
[(BUYOptionSelectionNavigationController*)self.navigationController setDismissWithCancelAnimation:YES];
[(OptionSelectionNavigationController*)self.navigationController setDismissWithCancelAnimation:YES];
if ([self.delegate respondsToSelector:@selector(variantSelectionControllerDidCancelVariantSelection:atOptionIndex:)]) {
[self.delegate variantSelectionControllerDidCancelVariantSelection:self atOptionIndex:self.selectedOptions.count];
}
}
#pragma mark - BUYOptionSelectionDelegate
#pragma mark - OptionSelectionDelegate
- (void)optionSelectionController:(BUYOptionSelectionViewController *)controller didSelectOptionValue:(BUYOptionValue *)optionValue
- (void)optionSelectionController:(OptionSelectionViewController *)controller didSelectOptionValue:(BUYOptionValue *)optionValue
{
self.changedOptionSelection |= ![controller.selectedOptionValue.value isEqualToString:optionValue.value];
self.selectedOptions[optionValue.name] = optionValue;
......@@ -156,13 +147,13 @@
}
}
- (void)optionSelectionControllerDidBackOutOfChoosingOption:(BUYOptionSelectionViewController *)controller
- (void)optionSelectionControllerDidBackOutOfChoosingOption:(OptionSelectionViewController *)controller
{
BUYOption *option = [controller.optionValues firstObject];
[self.selectedOptions removeObjectForKey:option.name];
[self.optionValueNames removeLastObject];
self.filteredProductVariantsForSelectionOption = controller.filteredProductVariantsForSelectionOption;
[[(BUYOptionSelectionNavigationController*)self.navigationController breadsCrumbsView] setSelectedBuyOptionValues:[self.optionValueNames copy]];
[[(OptionSelectionNavigationController*)self.navigationController breadsCrumbsView] setSelectedBuyOptionValues:[self.optionValueNames copy]];
}
- (NSArray*)filteredProductVariantsForSelectionOption
......
//
// BUYCheckoutButton.h
// NavigationController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,18 +25,13 @@
//
@import UIKit;
#import "BUYTheme.h"
/**
* A themed UIButton that includes a UIActivityIndicator
* A custom navigation controller used in the BUYProductViewController, adding a close button and the ability to theme the navigation bar
*/
@interface BUYCheckoutButton : UIButton <BUYThemeable>
@interface NavigationController : UINavigationController
/**
* Show a UIActivityIndicator in place of text while loading
*
* @param show Show or hide the UIActivityIndicator
*/
- (void)showActivityIndicator:(BOOL)show;
@property (nonatomic) BOOL automaticallyMasksSeparator;
@end
//
// NavigationController.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "NavigationController.h"
static CGFloat const kSeperatorVisibilityCurve = 0.01f;
static void *kObservationContext = &kObservationContext;
@interface NavigationController() <UINavigationBarDelegate>
@property (strong, nonatomic) UIView *separatorMask;
@property (readonly) UIScrollView *scrollView;
@end
@implementation NavigationController
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if (self) {
UINavigationBar *navigationBar = self.navigationBar;
self.separatorMask = [UIView new];
self.separatorMask.backgroundColor = [UIColor whiteColor];
self.separatorMask.hidden = YES;
[navigationBar addSubview:self.separatorMask];
}
return self;
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGFloat height = 1.0f / [UIScreen mainScreen].scale;
UINavigationBar *navigationBar = self.navigationBar;
self.separatorMask.frame = CGRectMake(CGRectGetMinX(navigationBar.bounds), CGRectGetMaxY(navigationBar.bounds), CGRectGetWidth(navigationBar.bounds), height);
}
- (void)setAutomaticallyMasksSeparator:(BOOL)automaticallyMasksSeparator
{
self.separatorMask.hidden = !automaticallyMasksSeparator;
}
- (void)dealloc
{
[self.scrollView removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentOffset))];
}
- (UIScrollView *)scrollView
{
UIView *view = self.topViewController.view;
if ([view isKindOfClass:[UIScrollView class]]) {
return (id)view;
} else {
return [view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
return [evaluatedObject isKindOfClass:[UIScrollView class]];
}]].firstObject;
}
}
- (CGFloat)seperatorAlphaWithOffset:(CGFloat)offset
{
CGFloat alpha = offset + CGRectGetMaxY(self.navigationBar.frame);
alpha *= kSeperatorVisibilityCurve;
return 1.0f - alpha;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if (context == kObservationContext) {
UIScrollView *scrollView = object;
if (scrollView != self.scrollView) {
[scrollView removeObserver:self forKeyPath:keyPath];
} else {
CGFloat alpha = [self seperatorAlphaWithOffset:self.scrollView.contentOffset.y];
self.separatorMask.alpha = alpha;
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)updateObservedValues
{
if (!self.scrollView) {
return;
}
NSString *keyPath = NSStringFromSelector(@selector(contentOffset));
[self.scrollView addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:kObservationContext];
}
#pragma mark - UINavigationBarDelegate
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item
{
[self updateObservedValues];
}
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item
{
[self updateObservedValues];
}
@end
//
// BUYViewController.h
// PaymentViewController.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -26,69 +26,69 @@
@import UIKit;
@import PassKit;
#import "BUYClient.h"
#import "BUYCart.h"
#import "BUYCheckout.h"
@import Buy;
@class BUYViewController;
@class BUYCheckout;
@class BUYPaymentController;
@class PaymentViewController;
@protocol BUYViewControllerDelegate <NSObject>
@protocol PaymentViewControllerDelegate <NSObject>
@optional
// Look into having this protocol inherit from a generic one
/**
* This is called if there is an error in creating the BUYCheckout. These problems include not being connected to the Internet,
* or if there is a validation error in the checkout.
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
* @param error An NSError describing the failure
*/
- (void)controller:(BUYViewController *)controller failedToCreateCheckout:(NSError *)error;
- (void)controller:(PaymentViewController *)controller failedToCreateCheckout:(NSError *)error;
/**
* This failure occurs when either the application is not properly configured to handle Apple Pay,
* or if the user does not have any credit cards configured in PassBook or cannot add any credit cards.
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
*/
- (void)controllerFailedToStartApplePayProcess:(BUYViewController *)controller;
- (void)controllerFailedToStartApplePayProcess:(PaymentViewController *)controller;
/**
* This failure occurs whenever an update to BUYCheckout fails (shipping address, billing address, etc.)
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
* @param checkout The BUYCheckout
* @param error An NSError describing the failure
*/
- (void)controller:(BUYViewController *)controller failedToUpdateCheckout:(BUYCheckout *)checkout withError:(NSError *)error;
- (void)controller:(PaymentViewController *)controller failedToUpdateCheckout:(BUYCheckout *)checkout withError:(NSError *)error;
/**
* This failure occurs when shipping rates cannot be retrieved.
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
* @param checkout The BUYCheckout
* @param error An NSError describing the failure
*/
- (void)controller:(BUYViewController *)controller failedToGetShippingRates:(BUYCheckout *)checkout withError:(NSError *)error;
- (void)controller:(PaymentViewController *)controller failedToGetShippingRates:(BUYCheckout *)checkout withError:(NSError *)error;
/**
* This failure occurs whenever completing a checkout fails.
* This can occur if there is missing payment information or if the shop is improperly configured.
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
* @param checkout The BUYCheckout
* @param error An NSError describing the failure
*/
- (void)controller:(BUYViewController *)controller failedToCompleteCheckout:(BUYCheckout *)checkout withError:(NSError *)error;
- (void)controller:(PaymentViewController *)controller failedToCompleteCheckout:(BUYCheckout *)checkout withError:(NSError *)error;
/**
* This is called whenever the checkout fully completes, success or failure.
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
* @param checkout The BUYCheckout
* @param status Checkout status BUYStatus
*/
- (void)controller:(BUYViewController *)controller didCompleteCheckout:(BUYCheckout *)checkout status:(BUYStatus)status;
- (void)controller:(PaymentViewController *)controller didCompleteCheckout:(BUYCheckout *)checkout status:(BUYStatus)status;
/**
* This is called when the Apple Pay Authorization View Controller has been dismissed.
......@@ -98,25 +98,25 @@
* Note: If the PKPaymentAuthorizationStatus is not PKPaymentAuthorizationStatusSuccess we will expire the checkout by
* calling `expireCheckout:completion:` to release the hold on the product inventory.
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
* @param checkout The BUYCheckout
*/
- (void)controller:(BUYViewController *)controller didDismissApplePayControllerWithStatus:(PKPaymentAuthorizationStatus)status forCheckout:(BUYCheckout *)checkout;
- (void)controller:(PaymentViewController *)controller didDismissApplePayControllerWithStatus:(PKPaymentAuthorizationStatus)status forCheckout:(BUYCheckout *)checkout;
/**
* This is called when the SFSafariViewController has been dismissed before checkout completion.
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
* @param checkout The BUYCheckout
*/
- (void)controller:(BUYViewController *)controller didDismissWebCheckout:(BUYCheckout *)checkout;
- (void)controller:(PaymentViewController *)controller didDismissWebCheckout:(BUYCheckout *)checkout;
/**
* The view controller has been dismissed
*
* @param controller The BUYViewController
* @param controller The PaymentViewController
*/
- (void)didDismissViewController:(BUYViewController *)controller;
- (void)didDismissViewController:(PaymentViewController *)controller;
@optional
......@@ -125,26 +125,26 @@
*
* @param viewController the view controller
*/
- (void)controllerWillCheckoutViaWeb:(BUYViewController *)viewController;
- (void)controllerWillCheckoutViaWeb:(PaymentViewController *)viewController;
/**
* Called when the user chooses to checkout via Apple Pay
*
* @param viewController the view controller
*/
- (void)controllerWillCheckoutViaApplePay:(BUYViewController *)viewController;
- (void)controllerWillCheckoutViaApplePay:(PaymentViewController *)viewController;
@end
/**
* This base class guides you through the entire Apple Pay process.
*/
@interface BUYViewController : UIViewController <PKPaymentAuthorizationViewControllerDelegate>
@interface PaymentViewController : UIViewController <BUYPaymentProviderDelegate>
/**
* Register yourself as a BUYViewControllerDelegate to handle all errors, and status changes.
* Register yourself as a PaymentViewControllerDelegate to handle all errors, and status changes.
*/
@property (nonatomic, weak) id <BUYViewControllerDelegate> delegate;
@property (nonatomic, weak) id <PaymentViewControllerDelegate> delegate;
/**
* Set the BUYClient using the provided initializer method `initWithClient:` or
......@@ -203,14 +203,15 @@
/**
* The current checkout object
*/
@property (nonatomic, strong, readonly) BUYCheckout *checkout;
@property (nonatomic, strong) BUYCheckout *checkout;
/**
* Loads the shop details
*
* @param block callback block called on completion
*/
- (void)loadShopWithCallback:(void (^)(BOOL, NSError *))block;
- (void)loadShopWithCallback:(void (^)(BOOL, NSError *))block NS_DEPRECATED_IOS(8_0, 9_0);
#pragma mark - Apple Pay Overrides
......@@ -235,11 +236,11 @@
- (instancetype)init NS_UNAVAILABLE;
/**
* Creates a BUYViewController using your
* Creates a PaymentViewController using your
*
* @param client A BUYClient configured to your shop
*
* @return A BUYViewController
* @return A PaymentViewController
*/
- (instancetype)initWithClient:(BUYClient *)client;
......@@ -285,4 +286,6 @@
*/
+ (void)completeCheckoutFromLaunchURL:(NSURL *)url;
@property (nonatomic, strong) BUYPaymentController *paymentController;
@end
//
// PaymentViewController.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import AddressBook;
@import UIKit;
@import Buy;
#import "PaymentViewController.h"
@implementation PaymentViewController
@synthesize client = _client;
- (instancetype)initWithClient:(BUYClient *)client
{
self = [super init];
if (self) {
self.client = client;
}
return self;
}
- (BUYClient*)client
{
if (_client == nil) {
NSLog(@"`BUYClient` has not been initialized. Please initialize PaymentViewController with `initWithClient:` or set a `BUYClient` after Storyboard initialization");
}
return _client;
}
- (void)loadShopWithCallback:(void (^)(BOOL, NSError *))block
{
// Deprecated
}
- (BOOL)canShowApplePaySetup
{
return self.applePayPaymentProvider.canShowApplePaySetup;
}
- (BOOL)isApplePayAvailable
{
return self.applePayPaymentProvider.available;
}
- (BOOL)shouldShowApplePayButton {
return self.applePayPaymentProvider.available || [self canShowApplePaySetup];
}
- (BOOL)shouldShowApplePaySetup
{
return self.applePayPaymentProvider.available == NO && [self canShowApplePaySetup];
}
#pragma mark - Payment
- (void)startApplePayCheckout:(BUYCheckout *)checkout
{
[self.paymentController startCheckout:checkout withProviderType:BUYApplePayPaymentProviderId];
}
- (void)startWebCheckout:(BUYCheckout *)checkout
{
[self.paymentController startCheckout:checkout withProviderType:BUYWebPaymentProviderId];
}
- (BUYPaymentController *)paymentController
{
if (_paymentController == nil) {
_paymentController = [[BUYPaymentController alloc] init];
BUYWebCheckoutPaymentProvider *webPaymentProvider = [[BUYWebCheckoutPaymentProvider alloc] initWithClient:self.client];
webPaymentProvider.delegate = self;
[_paymentController addPaymentProvider:webPaymentProvider];
if (self.merchantId.length) {
BUYApplePayPaymentProvider *applePayPaymentProvider = [[BUYApplePayPaymentProvider alloc] initWithClient:self.client merchantID:self.merchantId];
applePayPaymentProvider.delegate = self;
[_paymentController addPaymentProvider:applePayPaymentProvider];
}
}
return _paymentController;
}
- (BUYWebCheckoutPaymentProvider *)webPaymentProvider
{
return (BUYWebCheckoutPaymentProvider*)[self.paymentController providerForType:BUYWebPaymentProviderId];
}
- (BUYApplePayPaymentProvider *)applePayPaymentProvider
{
return (BUYApplePayPaymentProvider*)[self.paymentController providerForType:BUYApplePayPaymentProviderId];
}
#pragma mark - Creating a Checkout using a Cart Token
- (void)startCheckoutWithCartToken:(NSString *)token
{
[self.client createCheckoutWithCartToken:token completion:^(BUYCheckout *checkout, NSError *error) {
[self handleCheckoutCompletion:checkout error:error];
}];
}
- (void)handleCheckoutCompletion:(BUYCheckout *)checkout error:(NSError *)error
{
if (checkout && error == nil) {
self.checkout = checkout;
[self.applePayPaymentProvider startCheckout:checkout];
}
else {
if ([self.delegate respondsToSelector:@selector(controller:failedToCreateCheckout:)]) {
[self.delegate controller:self failedToCreateCheckout:error];
}
}
}
- (void)checkoutCompleted:(BUYCheckout *)checkout status:(BUYStatus)status
{
if ([self.delegate respondsToSelector:@selector(controller:didCompleteCheckout:status:)]) {
[self.delegate controller:self didCompleteCheckout:checkout status:status];
}
}
#pragma mark - Payment delegate methods
+ (void)completeCheckoutFromLaunchURL:(NSURL *)url
{
[[NSNotificationCenter defaultCenter] postNotificationName:BUYSafariCallbackURLNotification object:nil userInfo:@{BUYURLKey: url}];
}
- (void)paymentProviderWillStartCheckout:(id<BUYPaymentProvider>)provider
{
if ([self.delegate respondsToSelector:@selector(controllerWillCheckoutViaWeb:)]) {
[self.delegate controllerWillCheckoutViaWeb:self];
}
}
- (void)paymentProviderDidDismissCheckout:(id<BUYPaymentProvider>)provider
{
if ([self.delegate respondsToSelector:@selector(controller:didDismissWebCheckout:)]) {
[self.delegate controller:self didDismissWebCheckout:self.checkout];
}
}
- (void)paymentProvider:(id<BUYPaymentProvider>)provider didFailCheckoutWithError:(NSError *)error
{
if ([self.delegate respondsToSelector:@selector(controller:failedToCreateCheckout:)]) {
[self.delegate controller:self failedToCreateCheckout:error];
}
}
- (void)paymentProvider:(id<BUYPaymentProvider>)provider didCompleteCheckout:(BUYCheckout *)checkout withStatus:(BUYStatus)status
{
if ([self.delegate respondsToSelector:@selector(controller:didCompleteCheckout:status:)]) {
[self.delegate controller:self didCompleteCheckout:checkout status:status];
}
}
- (void)paymentProvider:(id<BUYPaymentProvider>)provider wantsControllerPresented:(UIViewController *)controller
{
[self presentViewController:controller animated:YES completion:nil];
}
- (void)paymentProviderWantsControllerDismissed:(id<BUYPaymentProvider>)provider
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(PKPaymentRequest *)paymentRequest
{
return nil;
}
@end
......@@ -27,10 +27,6 @@
@import UIKit;
@import Buy;
#warning - Enter your merchant ID
// Adding a merchant ID will show Apple Pay in the BUYProductViewController (on supported devices)
#define MERCHANT_ID @""
@interface ProductListViewController : UITableViewController
- (instancetype)initWithClient:(BUYClient *)client collection:(BUYCollection*)collection;
......
......@@ -25,11 +25,19 @@
//
#import "ProductListViewController.h"
#import "ProductViewController.h"
#import "Theme.h"
#import "ShippingRatesTableViewController.h"
#import "ProductViewControllerToggleTableViewCell.h"
#import "ProductViewControllerThemeStyleTableViewCell.h"
#import "ProductViewControllerThemeTintColorTableViewCell.h"
#import <Buy/Buy.h>
//#warning - Enter your merchant ID
// Adding a merchant ID will show Apple Pay in the BUYProductViewController (on supported devices)
#define MERCHANT_ID @""
@interface ProductListViewController () <UIViewControllerPreviewingDelegate>
@property (nonatomic, strong) BUYClient *client;
......@@ -39,7 +47,7 @@
@property (nonatomic, strong) NSURLSessionDataTask *checkoutCreationTask;
@property (nonatomic, assign) BOOL demoProductViewController;
@property (nonatomic, assign) BUYThemeStyle themeStyle;
@property (nonatomic, assign) ThemeStyle themeStyle;
@property (nonatomic, strong) NSArray *themeTintColors;
@property (nonatomic, assign) NSInteger themeTintColorSelectedIndex;
@property (nonatomic, assign) BOOL showsProductImageBackground;
......@@ -275,7 +283,7 @@
[self.checkoutCreationTask cancel];
}
BUYCart *cart = [[BUYCart alloc] init];
BUYCart *cart = [self.client.modelManager insertCartWithJSONDictionary:nil];
[cart addVariant:product.variants.firstObject];
BUYCheckout *checkout = [[BUYCheckout alloc] initWithCart:cart];
......@@ -304,7 +312,7 @@
- (void)demoProductViewControllerWithProduct:(BUYProduct*)product
{
BUYProductViewController *productViewController = [self productViewController];
ProductViewController *productViewController = [self productViewController];
[productViewController loadWithProduct:product completion:^(BOOL success, NSError *error) {
if (error == nil) {
if (self.presentViewController) {
......@@ -316,13 +324,13 @@
}];
}
-(BUYProductViewController*)productViewController
-(ProductViewController*)productViewController
{
BUYTheme *theme = [BUYTheme new];
Theme *theme = [Theme new];
theme.style = self.themeStyle;
theme.tintColor = self.themeTintColors[self.themeTintColorSelectedIndex];
theme.showsProductImageBackground = self.showsProductImageBackground;
BUYProductViewController *productViewController = [[BUYProductViewController alloc] initWithClient:self.client theme:theme];
ProductViewController *productViewController = [[ProductViewController alloc] initWithClient:self.client theme:theme];
productViewController.merchantId = MERCHANT_ID;
return productViewController;
}
......@@ -362,7 +370,7 @@
- (BUYAddress *)address
{
BUYAddress *address = [[BUYAddress alloc] init];
BUYAddress *address = [self.client.modelManager insertAddressWithJSONDictionary:nil];
address.address1 = @"150 Elgin Street";
address.address2 = @"8th Floor";
address.city = @"Ottawa";
......@@ -387,7 +395,7 @@
}
BUYProduct *product = self.products[indexPath.row];
BUYProductViewController *productViewController = [self productViewController];
ProductViewController *productViewController = [self productViewController];
[productViewController loadWithProduct:product completion:NULL];
previewingContext.sourceRect = cell.frame;
......
//
// BUYStoreViewController.h
// UIColor+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
......@@ -25,60 +25,35 @@
//
@import UIKit;
#import "BUYViewController.h"
#import "BUYError.h"
typedef NS_ENUM(NSUInteger, BUYCheckoutType){
BUYCheckoutTypeNormal,
BUYCheckoutTypeApplePay,
BUYCheckoutTypeCancel
};
#define BUY_RGB(r, g, b) BUY_RGBA(r, g, b, 1)
#define BUY_RGBA(r, g, b, a) [UIColor colorWithRed:r/255.0f green:g/255.0f blue:b/255.0f alpha:a]
typedef void (^BUYCheckoutTypeBlock)(BUYCheckoutType type);
@class BUYStoreViewController;
/**
* The BUYStoreViewControllerDelegate protocol implements methods related to the checkout process
*/
@protocol BUYStoreViewControllerDelegate <BUYViewControllerDelegate>
@interface UIColor (BUYAdditions)
/**
* Tells the delegate that the user has proceeded to checkout. Use this opportunity to present an interface to a
* user to choose between checking out with Apple Pay or standard webcheckout.
* Note: Before presenting an option for Apple Pay, check if the device is setup to do so by calling `[PKPaymentAuthorizationViewController canMakePayments]`
* Check if the color is light (brightness of colors combined less than .5)
* Supports RGB and grey space colors
*
* @param controller The controller with an embedded WKWebView displaying the Shopify store
* @param completionHandler (^BUYCheckoutTypeBlock)(BUYCheckoutType type);
* @return Returns true if the color is light
*/
- (void)controller:(BUYStoreViewController *)controller shouldProceedWithCheckoutType:(BUYCheckoutTypeBlock)completionHandler;
@end
- (BOOL)isLightColor;
/**
* This controller shows you how to build a controller that embeds a WKWebView (iOS 8+) with your store in it.
* This means that you can show off your store and its sleek responsive design without having to build a full native app to showcase it.
*/
@interface BUYStoreViewController : BUYViewController
/**
* Creates a view controller with an embedded webview to show the shops storefront
* Creates a UIColor from a hex value
*
* @param client The client configured to your shop
* @param url The address where the shop can be viewed
* @param hex the hex value to convert to a UIColor
*
* @return the BUYStoreViewController instance
*/
- (instancetype)initWithClient:(BUYClient *)client url:(NSURL *)url;
/**
* Jumps back to the shops home page
* @return A UIColor object
*/
- (void)reloadHomePage;
+ (UIColor*)colorWithHex:(NSInteger)hex;
+ (UIColor*)colorWithHexString:(NSString *)hexString;
/**
* The BUYStoreViewControllerDelegate
* Creates a string representing the hex value for the color
*
* @return String representing the hex value
*/
@property (nonatomic, weak) id <BUYStoreViewControllerDelegate> delegate;
- (NSString *)hexString;
@end
//
// UIColor+BUYAdditions.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "UIColor+BUYAdditions.h"
@implementation UIColor (BUYAdditions)
-(BOOL)isLightColor
{
CGFloat colorBrightness = 0;
CGColorSpaceRef colorSpace = CGColorGetColorSpace(self.CGColor);
CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
if (colorSpaceModel == kCGColorSpaceModelRGB) {
const CGFloat *componentColors = CGColorGetComponents(self.CGColor);
colorBrightness = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000;
} else {
[self getWhite:&colorBrightness alpha:0];
}
return (colorBrightness >= .5f);
}
+ (UIColor*)colorWithHex:(NSInteger)hex
{
return [UIColor colorWithRed:(((hex & 0xFF0000) >> 16)) / 255.0f
green:(((hex & 0x00FF00) >> 8)) / 255.0f
blue:(((hex & 0x0000FF) >> 0)) / 255.0f
alpha:1.0];
}
+ (UIColor*)colorWithHexString:(NSString *)hexString
{
if ([hexString length] == 0) {
return nil;
}
NSScanner *scanner = [NSScanner scannerWithString:hexString];
unsigned hex;
[scanner scanHexInt:&hex];
return [UIColor colorWithHex:hex];
}
- (NSString *)hexString
{
CGFloat r;
CGFloat g;
CGFloat b;
[self getRed:&r green:&g blue:&b alpha:nil];
return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
lround(r * 255),
lround(g * 255),
lround(b * 255)];
}
@end
//
// BUYFont.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import UIKit;
@interface UIFont (BUYAdditions)
/**
* Class method to allow system fonts to have increased point sizes from the OS default.
*
* @param style The text style for the font.
* @param size A positive value to increase the default font's point size by.
*
* @return A system font with an optionally increased point size.
*/
+ (UIFont *)preferredFontForTextStyle:(NSString *)style increasedPointSize:(CGFloat)size;
@end
//
// BUYFont.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "UIFont+BUYAdditions.h"
@implementation UIFont (BUYAdditions)
+ (UIFont *)preferredFontForTextStyle:(NSString *)style increasedPointSize:(CGFloat)size
{
UIFontDescriptor *descriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:style];
return [UIFont fontWithDescriptor:descriptor size:descriptor.pointSize + size];
}
@end
//
// UIImage+BUYAdditions.h
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import <UIKit/UIKit.h>
@interface UIImage (BUYAdditions)
+ (UIImage *)templateButtonBackgroundImage;
+ (UIImage *)templateImageWithFill:(UIColor *)fill stroke:(UIColor *)stroke edgeInsets:(UIEdgeInsets)edgeInsets;
@end
//
// UIImage+Additions.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "UIImage+BUYAdditions.h"
static const CGFloat kDefaultCornerRadius = 4.0f;
static const CGFloat kDefaultStrokWidth = 1.0f;
@implementation UIImage (BUYAdditions)
+ (UIImage *)templateButtonBackgroundImage
{
UIImage *image = [UIImage templateImageWithFill:[UIColor blackColor] stroke:nil];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
return image;
}
+ (UIImage *)templateImageWithFill:(UIEdgeInsets)edgeInsets
{
UIImage *image = [UIImage templateImageWithFill:[UIColor blackColor] stroke:nil edgeInsets:edgeInsets];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
return image;
}
+ (UIImage *)templateImageWithFill:(UIColor *)fill stroke:(UIColor *)stroke
{
CGFloat defaultInsetAmount = kDefaultCornerRadius + 1.0f;
return [UIImage templateImageWithFill:fill stroke:stroke edgeInsets:UIEdgeInsetsMake(defaultInsetAmount, defaultInsetAmount, defaultInsetAmount, defaultInsetAmount)];
}
+ (UIImage *)templateImageWithFill:(UIColor *)fill stroke:(UIColor *)stroke edgeInsets:(UIEdgeInsets)edgeInsets
{
CGFloat defaultStrokeWidth = kDefaultStrokWidth;
return [self templateImageWithFill:fill stroke:stroke edgeInsets:edgeInsets strokeWidth:defaultStrokeWidth];
}
+ (UIImage *)templateImageWithFill:(UIColor *)fill stroke:(UIColor *)stroke edgeInsets:(UIEdgeInsets)edgeInsets strokeWidth:(CGFloat)width
{
CGRect rect = CGRectMake(0.0f, 0.0f,
edgeInsets.left + edgeInsets.right,
edgeInsets.top + edgeInsets.bottom);
CGFloat strokeOffset = stroke ? kDefaultStrokWidth * 0.5f : 0.0f;
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, strokeOffset, strokeOffset) cornerRadius:edgeInsets.top];
path.lineWidth = width;
CGRect contextRect = CGRectOffset(rect, kDefaultStrokWidth * 0.5f, kDefaultStrokWidth * 0.5f);
UIGraphicsBeginImageContextWithOptions(contextRect.size, NO, 0);
if (fill) {
[fill setFill];
[path fill];
}
if (stroke) {
[stroke setStroke];
[path stroke];
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
image = [image resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch];
return image;
}
@end
......@@ -268,118 +268,60 @@
84DD12D01CC6401400A2442D /* BUYCustomer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D915731CC0416800D334FB /* BUYCustomer.m */; };
9003969B1B601DF400226B73 /* BUYCartLineItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396991B601DF400226B73 /* BUYCartLineItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
9003969C1B601DF400226B73 /* BUYCartLineItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 9003969A1B601DF400226B73 /* BUYCartLineItem.m */; };
900396AC1B627CB900226B73 /* BUYProductView.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396AA1B627CB900226B73 /* BUYProductView.h */; };
900396AD1B627CB900226B73 /* BUYProductView.m in Sources */ = {isa = PBXBuildFile; fileRef = 900396AB1B627CB900226B73 /* BUYProductView.m */; };
900396B01B67BD0A00226B73 /* BUYCheckoutButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396AE1B67BD0A00226B73 /* BUYCheckoutButton.h */; };
900396B11B67BD0A00226B73 /* BUYCheckoutButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 900396AF1B67BD0A00226B73 /* BUYCheckoutButton.m */; };
900E7C841B5DA553006F3C81 /* BUYImageKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 900E7C811B5DA32F006F3C81 /* BUYImageKit.h */; };
900E7C851B5DA559006F3C81 /* BUYImageKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E7C821B5DA32F006F3C81 /* BUYImageKit.m */; };
901930E31BC5B9BC00D1134E /* BUYApplePayHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = BE33B4EE1B15FF4D0067982B /* BUYApplePayHelpers.m */; };
901930E41BC5B9BC00D1134E /* BUYOptionSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9496AF1B4D96D800B38949 /* BUYOptionSelectionViewController.m */; };
901930E51BC5B9BC00D1134E /* BUYVariantOptionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CA21B4D771400E35E45 /* BUYVariantOptionView.m */; };
901930E61BC5B9BC00D1134E /* BUYPresentationControllerForVariantSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB74A201B554BF20005A300 /* BUYPresentationControllerForVariantSelection.m */; };
901930E81BC5B9BC00D1134E /* BUYImageLink.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A7A1A700B0A0087DB2C /* BUYImageLink.m */; };
901930E91BC5B9BC00D1134E /* BUYProductVariant.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A821A700B0A0087DB2C /* BUYProductVariant.m */; };
901930EA1BC5B9BC00D1134E /* BUYProductViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 905ECCC11B4C39710094F336 /* BUYProductViewController.m */; };
901930EC1BC5B9BC00D1134E /* BUYError.m in Sources */ = {isa = PBXBuildFile; fileRef = BE47340E1B66C4EF00AA721A /* BUYError.m */; };
901930ED1BC5B9BC00D1134E /* BUYProductViewHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C861B4C6F7000E35E45 /* BUYProductViewHeader.m */; };
901930EE1BC5B9BC00D1134E /* BUYNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CC21B4F1ED700E35E45 /* BUYNavigationController.m */; };
901930EF1BC5B9BC00D1134E /* BUYVariantSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9496B11B4D96D800B38949 /* BUYVariantSelectionViewController.m */; };
901930F21BC5B9BC00D1134E /* BUYOrder.m in Sources */ = {isa = PBXBuildFile; fileRef = 90E83BC31B9F550E00C95A1B /* BUYOrder.m */; };
901930F41BC5B9BC00D1134E /* BUYProductViewHeaderBackgroundImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90FC31A71B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.m */; };
901930F51BC5B9BC00D1134E /* BUYProductViewHeaderOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 907874981B7276BA0023775B /* BUYProductViewHeaderOverlay.m */; };
901930F61BC5B9BC00D1134E /* BUYProductVariantCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C9A1B4D76D900E35E45 /* BUYProductVariantCell.m */; };
901930F71BC5B9BC00D1134E /* BUYTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CB71B4F0DD500E35E45 /* BUYTheme.m */; };
901930F91BC5B9BC00D1134E /* BUYProductViewErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 903BCC7B1B7D1C2D00C21FEB /* BUYProductViewErrorView.m */; };
901930FA1BC5B9BC00D1134E /* BUYLineItem.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FDA16D19C939FF00AF4E93 /* BUYLineItem.m */; };
901930FB1BC5B9BC00D1134E /* BUYCheckoutButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 900396AF1B67BD0A00226B73 /* BUYCheckoutButton.m */; };
901930FC1BC5B9BC00D1134E /* BUYCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 9089CC5D1BB48D06009726D6 /* BUYCollection.m */; };
901930FD1BC5B9BC00D1134E /* BUYTaxLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 90AFAA5D1B011EA600F21C23 /* BUYTaxLine.m */; };
901930FF1BC5B9BC00D1134E /* BUYVariantOptionBreadCrumbsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DE926F1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.m */; };
901931011BC5B9BC00D1134E /* BUYTheme+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 906EAE421B836DE000976165 /* BUYTheme+Additions.m */; };
901931021BC5B9BC00D1134E /* BUYStoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE1C4DF41AE98FBB00E21624 /* BUYStoreViewController.m */; };
901931031BC5B9BC00D1134E /* BUYOptionValue.m in Sources */ = {isa = PBXBuildFile; fileRef = BEEA83E61B0B76C7000C6483 /* BUYOptionValue.m */; };
901931041BC5B9BC00D1134E /* BUYApplePayAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = F70CE40E1A8BF1D90055BEB8 /* BUYApplePayAdditions.m */; };
901931051BC5B9BC00D1134E /* BUYOptionSelectionNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB74A261B554BFB0005A300 /* BUYOptionSelectionNavigationController.m */; };
901931061BC5B9BC00D1134E /* BUYDiscount.m in Sources */ = {isa = PBXBuildFile; fileRef = 90AFAA691B0139DE00F21C23 /* BUYDiscount.m */; };
901931081BC5B9BC00D1134E /* BUYRuntime.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A741A700AC80087DB2C /* BUYRuntime.m */; };
901931091BC5B9BC00D1134E /* BUYCart.m in Sources */ = {isa = PBXBuildFile; fileRef = F773744819C77A210039681C /* BUYCart.m */; };
9019310A1BC5B9BC00D1134E /* BUYPaymentButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 905AA9701B3B32A500CAE037 /* BUYPaymentButton.m */; };
9019310C1BC5B9BC00D1134E /* BUYGiftCard.m in Sources */ = {isa = PBXBuildFile; fileRef = 42488B331AB8761A005F21A9 /* BUYGiftCard.m */; };
9019310D1BC5B9BC00D1134E /* BUYOptionValueCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BE10079A1B6165EC0031CEE7 /* BUYOptionValueCell.m */; };
9019310E1BC5B9BC00D1134E /* BUYProduct.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A7D1A700B0A0087DB2C /* BUYProduct.m */; };
9019310F1BC5B9BC00D1134E /* BUYImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CAF1B4EC9FE00E35E45 /* BUYImageView.m */; };
901931101BC5B9BC00D1134E /* BUYProductHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C981B4D76D900E35E45 /* BUYProductHeaderCell.m */; };
901931111BC5B9BC00D1134E /* BUYCartLineItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 9003969A1B601DF400226B73 /* BUYCartLineItem.m */; };
901931121BC5B9BC00D1134E /* BUYMaskedCreditCard.m in Sources */ = {isa = PBXBuildFile; fileRef = BE5DC3621B71022D00B2BC1E /* BUYMaskedCreditCard.m */; };
901931131BC5B9BC00D1134E /* BUYCheckout.m in Sources */ = {isa = PBXBuildFile; fileRef = F773749519C77C260039681C /* BUYCheckout.m */; };
901931141BC5B9BC00D1134E /* BUYProductViewFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C7A1B4C589A00E35E45 /* BUYProductViewFooter.m */; };
901931151BC5B9BC00D1134E /* BUYPresentationControllerWithNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CBE1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.m */; };
901931161BC5B9BC00D1134E /* BUYShippingRate.m in Sources */ = {isa = PBXBuildFile; fileRef = 90AFAA651B01398A00F21C23 /* BUYShippingRate.m */; };
901931181BC5B9BC00D1134E /* BUYGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CB31B4EE5E700E35E45 /* BUYGradientView.m */; };
901931191BC5B9BC00D1134E /* BUYViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE1C4DF61AE98FBB00E21624 /* BUYViewController.m */; };
9019311A1BC5B9BC00D1134E /* BUYImageKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 900E7C821B5DA32F006F3C81 /* BUYImageKit.m */; };
9019311C1BC5B9BC00D1134E /* BUYOption.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A801A700B0A0087DB2C /* BUYOption.m */; };
9019311D1BC5B9BC00D1134E /* BUYClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F7FDA17119C93F6F00AF4E93 /* BUYClient.m */; };
9019311E1BC5B9BC00D1134E /* UIFont+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 909944481B71B76800C40A33 /* UIFont+BUYAdditions.m */; };
9019311F1BC5B9BC00D1134E /* BUYProductView.m in Sources */ = {isa = PBXBuildFile; fileRef = 900396AB1B627CB900226B73 /* BUYProductView.m */; };
901931201BC5B9BC00D1134E /* BUYCreditCard.m in Sources */ = {isa = PBXBuildFile; fileRef = F77374AB19C796BD0039681C /* BUYCreditCard.m */; };
901931211BC5B9BC00D1134E /* BUYProductImageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 904606AE1B6BC8D700754173 /* BUYProductImageCollectionViewCell.m */; };
901931221BC5B9BC00D1134E /* BUYShop.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A841A700B0A0087DB2C /* BUYShop.m */; };
901931231BC5B9BC00D1134E /* BUYObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A941A7010B20087DB2C /* BUYObject.m */; };
901931241BC5B9BC00D1134E /* BUYProductDescriptionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C961B4D76D900E35E45 /* BUYProductDescriptionCell.m */; };
901931281BC5B9BC00D1134E /* BUYApplePayHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = BE33B4ED1B15FF4D0067982B /* BUYApplePayHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931291BC5B9BC00D1134E /* BUYStoreViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE1C4DF31AE98FBB00E21624 /* BUYStoreViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019312A1BC5B9BC00D1134E /* BUYCreditCard.h in Headers */ = {isa = PBXBuildFile; fileRef = F77374AA19C796BD0039681C /* BUYCreditCard.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019312B1BC5B9BC00D1134E /* BUYOption.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A7F1A700B0A0087DB2C /* BUYOption.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019312C1BC5B9BC00D1134E /* BUYProductVariantCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C991B4D76D900E35E45 /* BUYProductVariantCell.h */; };
9019312D1BC5B9BC00D1134E /* BUYTheme.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CB61B4F0DD500E35E45 /* BUYTheme.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019312E1BC5B9BC00D1134E /* BUYProductDescriptionCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C951B4D76D900E35E45 /* BUYProductDescriptionCell.h */; };
9019312F1BC5B9BC00D1134E /* BUYLineItem.h in Headers */ = {isa = PBXBuildFile; fileRef = F7FDA16C19C939FF00AF4E93 /* BUYLineItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931311BC5B9BC00D1134E /* BUYProductViewHeaderOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 907874971B7276BA0023775B /* BUYProductViewHeaderOverlay.h */; };
901931341BC5B9BC00D1134E /* BUYViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE1C4DF51AE98FBB00E21624 /* BUYViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931351BC5B9BC00D1134E /* BUYDiscount.h in Headers */ = {isa = PBXBuildFile; fileRef = 90AFAA681B0139DE00F21C23 /* BUYDiscount.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931361BC5B9BC00D1134E /* BUYProductView.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396AA1B627CB900226B73 /* BUYProductView.h */; };
901931371BC5B9BC00D1134E /* BUYTaxLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 90AFAA5C1B011EA600F21C23 /* BUYTaxLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931381BC5B9BC00D1134E /* BUYVariantSelectionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE9496B01B4D96D800B38949 /* BUYVariantSelectionViewController.h */; };
901931391BC5B9BC00D1134E /* BUYOptionValueCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BE1007991B6165EC0031CEE7 /* BUYOptionValueCell.h */; };
9019313A1BC5B9BC00D1134E /* BUYImageLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A791A700B0A0087DB2C /* BUYImageLink.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019313B1BC5B9BC00D1134E /* BUYOptionValue.h in Headers */ = {isa = PBXBuildFile; fileRef = BEEA83E51B0B76C7000C6483 /* BUYOptionValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019313C1BC5B9BC00D1134E /* BUYShop.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A831A700B0A0087DB2C /* BUYShop.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019313D1BC5B9BC00D1134E /* BUYShippingRate.h in Headers */ = {isa = PBXBuildFile; fileRef = 90AFAA641B01398A00F21C23 /* BUYShippingRate.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019313E1BC5B9BC00D1134E /* BUYApplePayAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = F70CE40D1A8BF1D90055BEB8 /* BUYApplePayAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931401BC5B9BC00D1134E /* BUYTheme+Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 906EAE411B836DE000976165 /* BUYTheme+Additions.h */; };
901931411BC5B9BC00D1134E /* BUYVariantOptionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CA11B4D771400E35E45 /* BUYVariantOptionView.h */; };
901931421BC5B9BC00D1134E /* BUYMaskedCreditCard.h in Headers */ = {isa = PBXBuildFile; fileRef = BE5DC3611B71022D00B2BC1E /* BUYMaskedCreditCard.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931431BC5B9BC00D1134E /* BUYProductViewHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C851B4C6F7000E35E45 /* BUYProductViewHeader.h */; };
901931441BC5B9BC00D1134E /* BUYProductViewHeaderBackgroundImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90FC31A61B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.h */; };
901931451BC5B9BC00D1134E /* UIFont+BUYAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 909944471B71B76800C40A33 /* UIFont+BUYAdditions.h */; };
901931461BC5B9BC00D1134E /* BUYCheckoutButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396AE1B67BD0A00226B73 /* BUYCheckoutButton.h */; };
901931471BC5B9BC00D1134E /* BUYPaymentButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 905AA96F1B3B32A500CAE037 /* BUYPaymentButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931481BC5B9BC00D1134E /* BUYImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CAE1B4EC9FE00E35E45 /* BUYImageView.h */; };
901931491BC5B9BC00D1134E /* BUYGiftCard.h in Headers */ = {isa = PBXBuildFile; fileRef = 42488B321AB8761A005F21A9 /* BUYGiftCard.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019314B1BC5B9BC00D1134E /* BUYNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CC11B4F1ED700E35E45 /* BUYNavigationController.h */; };
9019314D1BC5B9BC00D1134E /* BUYVariantOptionBreadCrumbsView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90DE926E1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.h */; };
9019314E1BC5B9BC00D1134E /* BUYProductViewFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C791B4C589A00E35E45 /* BUYProductViewFooter.h */; };
9019314F1BC5B9BC00D1134E /* BUYOptionSelectionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE9496AE1B4D96D800B38949 /* BUYOptionSelectionViewController.h */; };
901931501BC5B9BC00D1134E /* BUYOrder.h in Headers */ = {isa = PBXBuildFile; fileRef = 90E83BC21B9F550E00C95A1B /* BUYOrder.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931531BC5B9BC00D1134E /* BUYOptionSelectionNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB74A251B554BFB0005A300 /* BUYOptionSelectionNavigationController.h */; };
901931541BC5B9BC00D1134E /* BUYPresentationControllerWithNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CBD1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.h */; };
901931551BC5B9BC00D1134E /* BUYPresentationControllerForVariantSelection.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB74A1F1B554BF20005A300 /* BUYPresentationControllerForVariantSelection.h */; };
901931571BC5B9BC00D1134E /* BUYObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A931A7010B20087DB2C /* BUYObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931581BC5B9BC00D1134E /* BUYRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A731A700AC80087DB2C /* BUYRuntime.h */; };
901931591BC5B9BC00D1134E /* BUYCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB74A8E1B55A3D00005A300 /* BUYCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019315A1BC5B9BC00D1134E /* BUYProductImageCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 904606AD1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h */; };
9019315B1BC5B9BC00D1134E /* BUYImageKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 900E7C811B5DA32F006F3C81 /* BUYImageKit.h */; };
9019315E1BC5B9BC00D1134E /* BUYError.h in Headers */ = {isa = PBXBuildFile; fileRef = BE47340D1B66C4EF00AA721A /* BUYError.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019315F1BC5B9BC00D1134E /* BUYProductHeaderCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C971B4D76D900E35E45 /* BUYProductHeaderCell.h */; };
901931601BC5B9BC00D1134E /* BUYProductViewErrorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 903BCC7A1B7D1C2D00C21FEB /* BUYProductViewErrorView.h */; };
901931611BC5B9BC00D1134E /* BUYClient.h in Headers */ = {isa = PBXBuildFile; fileRef = F7FDA17019C93F6F00AF4E93 /* BUYClient.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931631BC5B9BC00D1134E /* BUYGradientView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CB21B4EE5E700E35E45 /* BUYGradientView.h */; };
901931641BC5B9BC00D1134E /* BUYCartLineItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 900396991B601DF400226B73 /* BUYCartLineItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931661BC5B9BC00D1134E /* BUYCheckout.h in Headers */ = {isa = PBXBuildFile; fileRef = F773749419C77C260039681C /* BUYCheckout.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931671BC5B9BC00D1134E /* BUYCart.h in Headers */ = {isa = PBXBuildFile; fileRef = F773744719C77A210039681C /* BUYCart.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931681BC5B9BC00D1134E /* BUYProductViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 905ECCC01B4C39710094F336 /* BUYProductViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
901931691BC5B9BC00D1134E /* BUYProduct.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A7C1A700B0A0087DB2C /* BUYProduct.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019316A1BC5B9BC00D1134E /* BUYSerializable.h in Headers */ = {isa = PBXBuildFile; fileRef = F76CFF1E19CB7C500079C703 /* BUYSerializable.h */; settings = {ATTRIBUTES = (Public, ); }; };
9019316B1BC5B9BC00D1134E /* BUYProductVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF52A811A700B0A0087DB2C /* BUYProductVariant.h */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -387,16 +329,8 @@
9032F2DB1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 9032F2D81BE9457A00BB9EEF /* BUYCheckoutAttribute.h */; settings = {ATTRIBUTES = (Public, ); }; };
9032F2DC1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 9032F2D91BE9457A00BB9EEF /* BUYCheckoutAttribute.m */; };
9032F2DD1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */ = {isa = PBXBuildFile; fileRef = 9032F2D91BE9457A00BB9EEF /* BUYCheckoutAttribute.m */; };
903BCC7C1B7D1C2D00C21FEB /* BUYProductViewErrorView.h in Headers */ = {isa = PBXBuildFile; fileRef = 903BCC7A1B7D1C2D00C21FEB /* BUYProductViewErrorView.h */; };
903BCC7D1B7D1C2D00C21FEB /* BUYProductViewErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 903BCC7B1B7D1C2D00C21FEB /* BUYProductViewErrorView.m */; };
904606AF1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 904606AD1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h */; };
904606B01B6BC8D700754173 /* BUYProductImageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 904606AE1B6BC8D700754173 /* BUYProductImageCollectionViewCell.m */; };
906CF1AD1B8B5F7D001F7D5B /* BUYNSPersonNameComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = 906CF1AC1B8B5F7D001F7D5B /* BUYNSPersonNameComponents.m */; };
906CF1B11B8B66AE001F7D5B /* BUYCNPostalAddress.m in Sources */ = {isa = PBXBuildFile; fileRef = 906CF1B01B8B66AE001F7D5B /* BUYCNPostalAddress.m */; };
906EAE431B836DE000976165 /* BUYTheme+Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 906EAE411B836DE000976165 /* BUYTheme+Additions.h */; };
906EAE441B836DE000976165 /* BUYTheme+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 906EAE421B836DE000976165 /* BUYTheme+Additions.m */; };
907874991B7276BA0023775B /* BUYProductViewHeaderOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 907874971B7276BA0023775B /* BUYProductViewHeaderOverlay.h */; };
9078749A1B7276BA0023775B /* BUYProductViewHeaderOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 907874981B7276BA0023775B /* BUYProductViewHeaderOverlay.m */; };
9089CC5E1BB48D06009726D6 /* BUYCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 9089CC5D1BB48D06009726D6 /* BUYCollection.m */; };
909944491B71B76800C40A33 /* UIFont+BUYAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 909944471B71B76800C40A33 /* UIFont+BUYAdditions.h */; };
9099444A1B71B76800C40A33 /* UIFont+BUYAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 909944481B71B76800C40A33 /* UIFont+BUYAdditions.m */; };
......@@ -406,8 +340,6 @@
90C856B61BD6B0F400936926 /* Buy.h in Headers */ = {isa = PBXBuildFile; fileRef = 90DA8DF11BC6A82D0027BCB7 /* Buy.h */; settings = {ATTRIBUTES = (Public, ); }; };
90DAEC361BC6E511007555A5 /* Buy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BE9A64281B503C2F0033E558 /* Buy.framework */; };
90DAEC381BC6E736007555A5 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 901931761BC5BC9100D1134E /* libc++.tbd */; };
90DE92701B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90DE926E1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.h */; };
90DE92711B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90DE926F1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.m */; };
90E83BC41B9F550E00C95A1B /* BUYOrder.h in Headers */ = {isa = PBXBuildFile; fileRef = 90E83BC21B9F550E00C95A1B /* BUYOrder.h */; settings = {ATTRIBUTES = (Public, ); }; };
90E83BC51B9F550E00C95A1B /* BUYOrder.m in Sources */ = {isa = PBXBuildFile; fileRef = 90E83BC31B9F550E00C95A1B /* BUYOrder.m */; };
90F593041B0D5F4C0026B382 /* BUYIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 90F592F81B0D5F4C0026B382 /* BUYIntegrationTest.m */; };
......@@ -438,6 +370,7 @@
9A6B03791CDA5D4F0054C26E /* BUYAccountCredentialsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A6B03781CDA5D4F0054C26E /* BUYAccountCredentialsTests.m */; };
BE10079B1B6165EC0031CEE7 /* BUYOptionValueCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BE1007991B6165EC0031CEE7 /* BUYOptionValueCell.h */; };
BE10079C1B6165EC0031CEE7 /* BUYOptionValueCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BE10079A1B6165EC0031CEE7 /* BUYOptionValueCell.m */; };
9A6B03791CDA5D4F0054C26E /* BUYAccountCredentialsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A6B03781CDA5D4F0054C26E /* BUYAccountCredentialsTests.m */; };
BE47340F1B66C4EF00AA721A /* BUYError.h in Headers */ = {isa = PBXBuildFile; fileRef = BE47340D1B66C4EF00AA721A /* BUYError.h */; settings = {ATTRIBUTES = (Public, ); }; };
BE4734101B66C4EF00AA721A /* BUYError.m in Sources */ = {isa = PBXBuildFile; fileRef = BE47340E1B66C4EF00AA721A /* BUYError.m */; };
BE5DC3631B71022D00B2BC1E /* BUYMaskedCreditCard.h in Headers */ = {isa = PBXBuildFile; fileRef = BE5DC3611B71022D00B2BC1E /* BUYMaskedCreditCard.h */; settings = {ATTRIBUTES = (Public, ); }; };
......@@ -484,46 +417,8 @@
BE9A646F1B503D210033E558 /* BUYRuntime.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AF52A741A700AC80087DB2C /* BUYRuntime.m */; };
BE9A64741B503D2E0033E558 /* BUYApplePayHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = BE33B4ED1B15FF4D0067982B /* BUYApplePayHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
BE9A64751B503D370033E558 /* BUYApplePayHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = BE33B4EE1B15FF4D0067982B /* BUYApplePayHelpers.m */; };
BE9A647E1B503D930033E558 /* BUYStoreViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE1C4DF31AE98FBB00E21624 /* BUYStoreViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
BE9A647F1B503D960033E558 /* BUYStoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE1C4DF41AE98FBB00E21624 /* BUYStoreViewController.m */; };
BE9A64801B503D990033E558 /* BUYViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE1C4DF51AE98FBB00E21624 /* BUYViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
BE9A64811B503D9E0033E558 /* BUYViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE1C4DF61AE98FBB00E21624 /* BUYViewController.m */; };
BE9A64821B503DAD0033E558 /* BUYPaymentButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 905AA96F1B3B32A500CAE037 /* BUYPaymentButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
BE9A64831B503DB10033E558 /* BUYPaymentButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 905AA9701B3B32A500CAE037 /* BUYPaymentButton.m */; };
BEB74A221B554BF20005A300 /* BUYPresentationControllerForVariantSelection.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB74A1F1B554BF20005A300 /* BUYPresentationControllerForVariantSelection.h */; };
BEB74A241B554BF20005A300 /* BUYPresentationControllerForVariantSelection.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB74A201B554BF20005A300 /* BUYPresentationControllerForVariantSelection.m */; };
BEB74A281B554BFB0005A300 /* BUYOptionSelectionNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB74A251B554BFB0005A300 /* BUYOptionSelectionNavigationController.h */; };
BEB74A2A1B554BFB0005A300 /* BUYOptionSelectionNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB74A261B554BFB0005A300 /* BUYOptionSelectionNavigationController.m */; };
BEB74A2B1B554C150005A300 /* BUYTheme.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CB61B4F0DD500E35E45 /* BUYTheme.h */; settings = {ATTRIBUTES = (Public, ); }; };
BEB74A2C1B554C370005A300 /* BUYTheme.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CB71B4F0DD500E35E45 /* BUYTheme.m */; };
BEB74A2D1B554E870005A300 /* BUYProductViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 905ECCC01B4C39710094F336 /* BUYProductViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
BEB74A2E1B554E8B0005A300 /* BUYProductViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 905ECCC11B4C39710094F336 /* BUYProductViewController.m */; };
BEB74A651B5563FF0005A300 /* BUYGradientView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CB21B4EE5E700E35E45 /* BUYGradientView.h */; };
BEB74A661B5564030005A300 /* BUYGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CB31B4EE5E700E35E45 /* BUYGradientView.m */; };
BEB74A671B55640C0005A300 /* BUYNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CC11B4F1ED700E35E45 /* BUYNavigationController.h */; };
BEB74A681B55640F0005A300 /* BUYNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CC21B4F1ED700E35E45 /* BUYNavigationController.m */; };
BEB74A691B5564160005A300 /* BUYPresentationControllerWithNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CBD1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.h */; };
BEB74A6A1B5564190005A300 /* BUYPresentationControllerWithNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CBE1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.m */; };
BEB74A6B1B55641B0005A300 /* BUYProductDescriptionCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C951B4D76D900E35E45 /* BUYProductDescriptionCell.h */; };
BEB74A6C1B55641D0005A300 /* BUYProductDescriptionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C961B4D76D900E35E45 /* BUYProductDescriptionCell.m */; };
BEB74A6D1B5564200005A300 /* BUYProductHeaderCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C971B4D76D900E35E45 /* BUYProductHeaderCell.h */; };
BEB74A6E1B5564230005A300 /* BUYProductHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C981B4D76D900E35E45 /* BUYProductHeaderCell.m */; };
BEB74A6F1B5564260005A300 /* BUYProductVariantCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C991B4D76D900E35E45 /* BUYProductVariantCell.h */; };
BEB74A701B5564290005A300 /* BUYProductVariantCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C9A1B4D76D900E35E45 /* BUYProductVariantCell.m */; };
BEB74A711B5564300005A300 /* BUYProductViewFooter.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C791B4C589A00E35E45 /* BUYProductViewFooter.h */; };
BEB74A721B5564320005A300 /* BUYProductViewFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C7A1B4C589A00E35E45 /* BUYProductViewFooter.m */; };
BEB74A731B5564350005A300 /* BUYProductViewHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516C851B4C6F7000E35E45 /* BUYProductViewHeader.h */; };
BEB74A741B5564380005A300 /* BUYProductViewHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516C861B4C6F7000E35E45 /* BUYProductViewHeader.m */; };
BEB74A751B55643B0005A300 /* BUYProductViewHeaderBackgroundImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90FC31A61B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.h */; };
BEB74A761B55643E0005A300 /* BUYProductViewHeaderBackgroundImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90FC31A71B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.m */; };
BEB74A771B55646D0005A300 /* BUYImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CAE1B4EC9FE00E35E45 /* BUYImageView.h */; };
BEB74A781B55646F0005A300 /* BUYImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CAF1B4EC9FE00E35E45 /* BUYImageView.m */; };
BEB74A791B5564790005A300 /* BUYOptionSelectionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE9496AE1B4D96D800B38949 /* BUYOptionSelectionViewController.h */; };
BEB74A7A1B55647C0005A300 /* BUYOptionSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9496AF1B4D96D800B38949 /* BUYOptionSelectionViewController.m */; };
BEB74A7B1B5564810005A300 /* BUYVariantOptionView.h in Headers */ = {isa = PBXBuildFile; fileRef = 90516CA11B4D771400E35E45 /* BUYVariantOptionView.h */; };
BEB74A7C1B5564840005A300 /* BUYVariantOptionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 90516CA21B4D771400E35E45 /* BUYVariantOptionView.m */; };
BEB74A7D1B5564870005A300 /* BUYVariantSelectionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BE9496B01B4D96D800B38949 /* BUYVariantSelectionViewController.h */; };
BEB74A7E1B5564890005A300 /* BUYVariantSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BE9496B11B4D96D800B38949 /* BUYVariantSelectionViewController.m */; };
BEB74A901B55A3D00005A300 /* BUYCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = BEB74A8E1B55A3D00005A300 /* BUYCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
BEB9AE781BA8627B00575F8A /* test_shop_data.json in Resources */ = {isa = PBXBuildFile; fileRef = BEB9AE721BA73E6C00575F8A /* test_shop_data.json */; };
BEB9AE7D1BA885E300575F8A /* BUYClientTestBase.m in Sources */ = {isa = PBXBuildFile; fileRef = BEB9AE7C1BA8685600575F8A /* BUYClientTestBase.m */; };
......@@ -695,55 +590,19 @@
84D915B51CC0417700D334FB /* _BUYTaxLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _BUYTaxLine.m; sourceTree = "<group>"; };
900396991B601DF400226B73 /* BUYCartLineItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYCartLineItem.h; sourceTree = "<group>"; };
9003969A1B601DF400226B73 /* BUYCartLineItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCartLineItem.m; sourceTree = "<group>"; };
900396AA1B627CB900226B73 /* BUYProductView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductView.h; path = "Product View/BUYProductView.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
900396AB1B627CB900226B73 /* BUYProductView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductView.m; path = "Product View/BUYProductView.m"; sourceTree = "<group>"; };
900396AE1B67BD0A00226B73 /* BUYCheckoutButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYCheckoutButton.h; path = "Product View/BUYCheckoutButton.h"; sourceTree = "<group>"; };
900396AF1B67BD0A00226B73 /* BUYCheckoutButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYCheckoutButton.m; path = "Product View/BUYCheckoutButton.m"; sourceTree = "<group>"; };
900E7C811B5DA32F006F3C81 /* BUYImageKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYImageKit.h; sourceTree = "<group>"; };
900E7C821B5DA32F006F3C81 /* BUYImageKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYImageKit.m; sourceTree = "<group>"; };
901931701BC5B9BC00D1134E /* Buy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Buy.framework; sourceTree = BUILT_PRODUCTS_DIR; };
901931761BC5BC9100D1134E /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; };
9032F2D81BE9457A00BB9EEF /* BUYCheckoutAttribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYCheckoutAttribute.h; sourceTree = "<group>"; };
9032F2D91BE9457A00BB9EEF /* BUYCheckoutAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCheckoutAttribute.m; sourceTree = "<group>"; };
903BCC7A1B7D1C2D00C21FEB /* BUYProductViewErrorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductViewErrorView.h; path = "Product View/BUYProductViewErrorView.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
903BCC7B1B7D1C2D00C21FEB /* BUYProductViewErrorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewErrorView.m; path = "Product View/BUYProductViewErrorView.m"; sourceTree = "<group>"; };
904606AD1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductImageCollectionViewCell.h; path = "Product View/BUYProductImageCollectionViewCell.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
904606AE1B6BC8D700754173 /* BUYProductImageCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductImageCollectionViewCell.m; path = "Product View/BUYProductImageCollectionViewCell.m"; sourceTree = "<group>"; };
904FB6001AE03D4500EA1758 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = "Mobile Buy SDK/Info.plist"; sourceTree = "<group>"; };
90516C791B4C589A00E35E45 /* BUYProductViewFooter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductViewFooter.h; path = "Product View/BUYProductViewFooter.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
90516C7A1B4C589A00E35E45 /* BUYProductViewFooter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewFooter.m; path = "Product View/BUYProductViewFooter.m"; sourceTree = "<group>"; };
90516C851B4C6F7000E35E45 /* BUYProductViewHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductViewHeader.h; path = "Product View/BUYProductViewHeader.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
90516C861B4C6F7000E35E45 /* BUYProductViewHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewHeader.m; path = "Product View/BUYProductViewHeader.m"; sourceTree = "<group>"; };
90516C951B4D76D900E35E45 /* BUYProductDescriptionCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYProductDescriptionCell.h; path = "Product View/BUYProductDescriptionCell.h"; sourceTree = "<group>"; };
90516C961B4D76D900E35E45 /* BUYProductDescriptionCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductDescriptionCell.m; path = "Product View/BUYProductDescriptionCell.m"; sourceTree = "<group>"; };
90516C971B4D76D900E35E45 /* BUYProductHeaderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductHeaderCell.h; path = "Product View/BUYProductHeaderCell.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
90516C981B4D76D900E35E45 /* BUYProductHeaderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductHeaderCell.m; path = "Product View/BUYProductHeaderCell.m"; sourceTree = "<group>"; };
90516C991B4D76D900E35E45 /* BUYProductVariantCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYProductVariantCell.h; path = "Product View/BUYProductVariantCell.h"; sourceTree = "<group>"; };
90516C9A1B4D76D900E35E45 /* BUYProductVariantCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductVariantCell.m; path = "Product View/BUYProductVariantCell.m"; sourceTree = "<group>"; };
90516CA11B4D771400E35E45 /* BUYVariantOptionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYVariantOptionView.h; sourceTree = "<group>"; };
90516CA21B4D771400E35E45 /* BUYVariantOptionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYVariantOptionView.m; sourceTree = "<group>"; };
90516CAE1B4EC9FE00E35E45 /* BUYImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYImageView.h; path = "Product View/BUYImageView.h"; sourceTree = "<group>"; };
90516CAF1B4EC9FE00E35E45 /* BUYImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYImageView.m; path = "Product View/BUYImageView.m"; sourceTree = "<group>"; };
90516CB21B4EE5E700E35E45 /* BUYGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYGradientView.h; path = "Product View/BUYGradientView.h"; sourceTree = "<group>"; };
90516CB31B4EE5E700E35E45 /* BUYGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYGradientView.m; path = "Product View/BUYGradientView.m"; sourceTree = "<group>"; };
90516CB61B4F0DD500E35E45 /* BUYTheme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYTheme.h; path = "Product View/BUYTheme.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
90516CB71B4F0DD500E35E45 /* BUYTheme.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYTheme.m; path = "Product View/BUYTheme.m"; sourceTree = "<group>"; };
90516CBD1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYPresentationControllerWithNavigationController.h; path = "Product View/BUYPresentationControllerWithNavigationController.h"; sourceTree = "<group>"; };
90516CBE1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYPresentationControllerWithNavigationController.m; path = "Product View/BUYPresentationControllerWithNavigationController.m"; sourceTree = "<group>"; };
90516CC11B4F1ED700E35E45 /* BUYNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYNavigationController.h; path = "Product View/BUYNavigationController.h"; sourceTree = "<group>"; };
90516CC21B4F1ED700E35E45 /* BUYNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYNavigationController.m; path = "Product View/BUYNavigationController.m"; sourceTree = "<group>"; };
905AA96F1B3B32A500CAE037 /* BUYPaymentButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYPaymentButton.h; path = BUYPaymentButton/BUYPaymentButton.h; sourceTree = "<group>"; };
905AA9701B3B32A500CAE037 /* BUYPaymentButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYPaymentButton.m; path = BUYPaymentButton/BUYPaymentButton.m; sourceTree = "<group>"; };
905ECCC01B4C39710094F336 /* BUYProductViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductViewController.h; path = "Product View/BUYProductViewController.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
905ECCC11B4C39710094F336 /* BUYProductViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewController.m; path = "Product View/BUYProductViewController.m"; sourceTree = "<group>"; };
905AA96F1B3B32A500CAE037 /* BUYPaymentButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYPaymentButton.h; sourceTree = "<group>"; };
905AA9701B3B32A500CAE037 /* BUYPaymentButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYPaymentButton.m; sourceTree = "<group>"; };
906CF1AB1B8B5F7D001F7D5B /* BUYNSPersonNameComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYNSPersonNameComponents.h; sourceTree = "<group>"; };
906CF1AC1B8B5F7D001F7D5B /* BUYNSPersonNameComponents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYNSPersonNameComponents.m; sourceTree = "<group>"; };
906CF1AF1B8B66AE001F7D5B /* BUYCNPostalAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYCNPostalAddress.h; sourceTree = "<group>"; };
906CF1B01B8B66AE001F7D5B /* BUYCNPostalAddress.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCNPostalAddress.m; sourceTree = "<group>"; };
906EAE411B836DE000976165 /* BUYTheme+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "BUYTheme+Additions.h"; path = "Utils/BUYTheme+Additions.h"; sourceTree = "<group>"; };
906EAE421B836DE000976165 /* BUYTheme+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "BUYTheme+Additions.m"; path = "Utils/BUYTheme+Additions.m"; sourceTree = "<group>"; };
907874971B7276BA0023775B /* BUYProductViewHeaderOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYProductViewHeaderOverlay.h; path = "Product View/BUYProductViewHeaderOverlay.h"; sourceTree = "<group>"; };
907874981B7276BA0023775B /* BUYProductViewHeaderOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewHeaderOverlay.m; path = "Product View/BUYProductViewHeaderOverlay.m"; sourceTree = "<group>"; };
9089CC5D1BB48D06009726D6 /* BUYCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYCollection.m; sourceTree = "<group>"; };
909944471B71B76800C40A33 /* UIFont+BUYAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIFont+BUYAdditions.h"; sourceTree = "<group>"; };
909944481B71B76800C40A33 /* UIFont+BUYAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIFont+BUYAdditions.m"; sourceTree = "<group>"; };
......@@ -761,8 +620,6 @@
90C856B71BD6B19D00936926 /* Buy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Buy.h; path = "Mobile Buy SDK/Static Framework/Buy.h"; sourceTree = "<group>"; };
90C856B81BD6B19D00936926 /* Buy.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = Buy.modulemap; path = "Mobile Buy SDK/Static Framework/Buy.modulemap"; sourceTree = "<group>"; };
90DA8DF11BC6A82D0027BCB7 /* Buy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Buy.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
90DE926E1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYVariantOptionBreadCrumbsView.h; sourceTree = "<group>"; };
90DE926F1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYVariantOptionBreadCrumbsView.m; sourceTree = "<group>"; };
90E80E461AFBBB68003A9909 /* AppledocSettings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppledocSettings.plist; path = docs/AppledocSettings.plist; sourceTree = "<group>"; };
90E83BC21B9F550E00C95A1B /* BUYOrder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYOrder.h; sourceTree = "<group>"; };
90E83BC31B9F550E00C95A1B /* BUYOrder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYOrder.m; sourceTree = "<group>"; };
......@@ -777,8 +634,6 @@
90F592FE1B0D5F4C0026B382 /* BUYLineItemTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYLineItemTest.m; sourceTree = "<group>"; };
90F592FF1B0D5F4C0026B382 /* BUYObjectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYObjectTests.m; sourceTree = "<group>"; };
90F593001B0D5F4C0026B382 /* BUYTestConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYTestConstants.h; sourceTree = "<group>"; };
90FC31A61B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = BUYProductViewHeaderBackgroundImageView.h; path = "Product View/BUYProductViewHeaderBackgroundImageView.h"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
90FC31A71B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYProductViewHeaderBackgroundImageView.m; path = "Product View/BUYProductViewHeaderBackgroundImageView.m"; sourceTree = "<group>"; };
9A102D1A1CDD1F960026CC43 /* BUYErrorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYErrorTests.m; sourceTree = "<group>"; };
9A102D1D1CDD25980026CC43 /* BUYOptionValueTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYOptionValueTests.m; sourceTree = "<group>"; };
9A47CEF81CE39EC200A6D5BA /* BUYPaymentToken.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BUYPaymentToken.h; sourceTree = "<group>"; };
......@@ -798,6 +653,7 @@
BE1C4DF41AE98FBB00E21624 /* BUYStoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = BUYStoreViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
BE1C4DF51AE98FBB00E21624 /* BUYViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = BUYViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
BE1C4DF61AE98FBB00E21624 /* BUYViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = BUYViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
9A6B03781CDA5D4F0054C26E /* BUYAccountCredentialsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYAccountCredentialsTests.m; sourceTree = "<group>"; };
BE33B4ED1B15FF4D0067982B /* BUYApplePayHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYApplePayHelpers.h; sourceTree = "<group>"; };
BE33B4EE1B15FF4D0067982B /* BUYApplePayHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYApplePayHelpers.m; sourceTree = "<group>"; };
BE47340D1B66C4EF00AA721A /* BUYError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYError.h; sourceTree = "<group>"; };
......@@ -807,19 +663,11 @@
BE6C07031BB1DE1D00BD9F7B /* OHHTTPStubs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OHHTTPStubs.framework; path = "Mobile Buy SDK Tests/OHHTTPStubs.framework"; sourceTree = "<group>"; };
BE6C07051BB1E46900BD9F7B /* mocked_responses.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = mocked_responses.json; sourceTree = "<group>"; };
BE9496681B45CCF400B38949 /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "usr/lib/libc++.dylib"; sourceTree = SDKROOT; };
BE9496AE1B4D96D800B38949 /* BUYOptionSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = BUYOptionSelectionViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
BE9496AF1B4D96D800B38949 /* BUYOptionSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYOptionSelectionViewController.m; sourceTree = "<group>"; };
BE9496B01B4D96D800B38949 /* BUYVariantSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = BUYVariantSelectionViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
BE9496B11B4D96D800B38949 /* BUYVariantSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BUYVariantSelectionViewController.m; sourceTree = "<group>"; };
BE98DB4E1BB1ED3E00C29564 /* OHHTTPStubs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = OHHTTPStubs; path = "Mobile Buy SDK Tests/OHHTTPStubs"; sourceTree = "<group>"; };
BE98DB501BB1ED5500C29564 /* libOHHTTPStubs.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libOHHTTPStubs.a; path = "Mobile Buy SDK Tests/OHHTTPStubs/libOHHTTPStubs.a"; sourceTree = "<group>"; };
BE98DB5A1BB1F4D000C29564 /* OHHTTPStubsResponse+Helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OHHTTPStubsResponse+Helpers.h"; sourceTree = "<group>"; };
BE98DB5B1BB1F4D000C29564 /* OHHTTPStubsResponse+Helpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "OHHTTPStubsResponse+Helpers.m"; sourceTree = "<group>"; };
BE9A64281B503C2F0033E558 /* Buy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Buy.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BEB74A1F1B554BF20005A300 /* BUYPresentationControllerForVariantSelection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYPresentationControllerForVariantSelection.h; path = "Mobile Buy SDK/Product View/Variant Selection/BUYPresentationControllerForVariantSelection.h"; sourceTree = SOURCE_ROOT; };
BEB74A201B554BF20005A300 /* BUYPresentationControllerForVariantSelection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYPresentationControllerForVariantSelection.m; path = "Mobile Buy SDK/Product View/Variant Selection/BUYPresentationControllerForVariantSelection.m"; sourceTree = SOURCE_ROOT; };
BEB74A251B554BFB0005A300 /* BUYOptionSelectionNavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BUYOptionSelectionNavigationController.h; path = "Mobile Buy SDK/Product View/Variant Selection/BUYOptionSelectionNavigationController.h"; sourceTree = SOURCE_ROOT; };
BEB74A261B554BFB0005A300 /* BUYOptionSelectionNavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BUYOptionSelectionNavigationController.m; path = "Mobile Buy SDK/Product View/Variant Selection/BUYOptionSelectionNavigationController.m"; sourceTree = SOURCE_ROOT; };
BEB74A8E1B55A3D00005A300 /* BUYCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYCollection.h; sourceTree = "<group>"; };
BEB9AE721BA73E6C00575F8A /* test_shop_data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test_shop_data.json; sourceTree = "<group>"; };
BEB9AE7A1BA866D000575F8A /* BUYClientTestBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BUYClientTestBase.h; sourceTree = "<group>"; };
......@@ -1041,6 +889,16 @@
path = "Value Transformers";
sourceTree = "<group>";
};
84B0A7271CE10EAE00253EB0 /* Payment Button */ = {
isa = PBXGroup;
children = (
905AA96F1B3B32A500CAE037 /* BUYPaymentButton.h */,
905AA9701B3B32A500CAE037 /* BUYPaymentButton.m */,
);
name = "Payment Button";
path = BUYPaymentButton;
sourceTree = "<group>";
};
84B0A7281CE10ED900253EB0 /* Payment Providers */ = {
isa = PBXGroup;
children = (
......@@ -1134,68 +992,6 @@
name = "Supporting Files";
sourceTree = "<group>";
};
90FC31AA1B50576400AFAB51 /* Variant Selection */ = {
isa = PBXGroup;
children = (
BEB74A251B554BFB0005A300 /* BUYOptionSelectionNavigationController.h */,
BEB74A261B554BFB0005A300 /* BUYOptionSelectionNavigationController.m */,
BE9496AE1B4D96D800B38949 /* BUYOptionSelectionViewController.h */,
BE9496AF1B4D96D800B38949 /* BUYOptionSelectionViewController.m */,
BEB74A1F1B554BF20005A300 /* BUYPresentationControllerForVariantSelection.h */,
BEB74A201B554BF20005A300 /* BUYPresentationControllerForVariantSelection.m */,
90DE926E1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.h */,
90DE926F1B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.m */,
90516CA11B4D771400E35E45 /* BUYVariantOptionView.h */,
90516CA21B4D771400E35E45 /* BUYVariantOptionView.m */,
BE9496B01B4D96D800B38949 /* BUYVariantSelectionViewController.h */,
BE9496B11B4D96D800B38949 /* BUYVariantSelectionViewController.m */,
BE1007981B6165CD0031CEE7 /* Cells */,
);
name = "Variant Selection";
path = "Product View/Variant Selection";
sourceTree = "<group>";
};
90FC31AB1B50589800AFAB51 /* Product View */ = {
isa = PBXGroup;
children = (
900396AE1B67BD0A00226B73 /* BUYCheckoutButton.h */,
900396AF1B67BD0A00226B73 /* BUYCheckoutButton.m */,
90516CB21B4EE5E700E35E45 /* BUYGradientView.h */,
90516CB31B4EE5E700E35E45 /* BUYGradientView.m */,
90516CAE1B4EC9FE00E35E45 /* BUYImageView.h */,
90516CAF1B4EC9FE00E35E45 /* BUYImageView.m */,
90516CC11B4F1ED700E35E45 /* BUYNavigationController.h */,
90516CC21B4F1ED700E35E45 /* BUYNavigationController.m */,
905AA96F1B3B32A500CAE037 /* BUYPaymentButton.h */,
905AA9701B3B32A500CAE037 /* BUYPaymentButton.m */,
90516CBD1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.h */,
90516CBE1B4F110A00E35E45 /* BUYPresentationControllerWithNavigationController.m */,
904606AD1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h */,
904606AE1B6BC8D700754173 /* BUYProductImageCollectionViewCell.m */,
900396AA1B627CB900226B73 /* BUYProductView.h */,
900396AB1B627CB900226B73 /* BUYProductView.m */,
905ECCC01B4C39710094F336 /* BUYProductViewController.h */,
905ECCC11B4C39710094F336 /* BUYProductViewController.m */,
903BCC7A1B7D1C2D00C21FEB /* BUYProductViewErrorView.h */,
903BCC7B1B7D1C2D00C21FEB /* BUYProductViewErrorView.m */,
90516C791B4C589A00E35E45 /* BUYProductViewFooter.h */,
90516C7A1B4C589A00E35E45 /* BUYProductViewFooter.m */,
90516C851B4C6F7000E35E45 /* BUYProductViewHeader.h */,
90516C861B4C6F7000E35E45 /* BUYProductViewHeader.m */,
90FC31A61B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.h */,
90FC31A71B50371600AFAB51 /* BUYProductViewHeaderBackgroundImageView.m */,
907874971B7276BA0023775B /* BUYProductViewHeaderOverlay.h */,
907874981B7276BA0023775B /* BUYProductViewHeaderOverlay.m */,
90516CB61B4F0DD500E35E45 /* BUYTheme.h */,
90516CB71B4F0DD500E35E45 /* BUYTheme.m */,
906EAE411B836DE000976165 /* BUYTheme+Additions.h */,
906EAE421B836DE000976165 /* BUYTheme+Additions.m */,
BE2E1D371B599039009610DA /* Cells */,
90FC31AA1B50576400AFAB51 /* Variant Selection */,
);
name = "Product View";
sourceTree = "<group>";
};
9A102D1C1CDD257D0026CC43 /* Models Tests */ = {
isa = PBXGroup;
children = (
......@@ -1369,11 +1165,10 @@
841ADDEA1CB6C942000004B0 /* Additions */,
F7FDA16F19C93F6100AF4E93 /* Data */,
F773744419C779C20039681C /* Models */,
90FC31AB1B50589800AFAB51 /* Product View */,
84B0A7271CE10EAE00253EB0 /* Payment Button */,
84B0A7281CE10ED900253EB0 /* Payment Providers */,
F773744519C779C20039681C /* Utils */,
84980F491CB760FA00CFAB58 /* Value Transformers */,
BE1C4DF21AE98F8E00E21624 /* View Controllers */,
);
name = Classes;
sourceTree = "<group>";
......@@ -1425,9 +1220,6 @@
9019312A1BC5B9BC00D1134E /* BUYCreditCard.h in Headers */,
9019312B1BC5B9BC00D1134E /* BUYOption.h in Headers */,
84980F4D1CB7613700CFAB58 /* BUYIdentityTransformer.h in Headers */,
9019312C1BC5B9BC00D1134E /* BUYProductVariantCell.h in Headers */,
9019312D1BC5B9BC00D1134E /* BUYTheme.h in Headers */,
9019312E1BC5B9BC00D1134E /* BUYProductDescriptionCell.h in Headers */,
9019312F1BC5B9BC00D1134E /* BUYLineItem.h in Headers */,
90C856B51BD6B0F300936926 /* Buy.h in Headers */,
8498DCAB1CDD1B2600BD12A8 /* BUYShopifyErrorCodes.h in Headers */,
......@@ -1436,11 +1228,8 @@
901931341BC5B9BC00D1134E /* BUYViewController.h in Headers */,
901931351BC5B9BC00D1134E /* BUYDiscount.h in Headers */,
8498DCB71CDD1B5400BD12A8 /* BUYClient+Customers.h in Headers */,
901931361BC5B9BC00D1134E /* BUYProductView.h in Headers */,
849810931CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h in Headers */,
901931371BC5B9BC00D1134E /* BUYTaxLine.h in Headers */,
901931381BC5B9BC00D1134E /* BUYVariantSelectionViewController.h in Headers */,
901931391BC5B9BC00D1134E /* BUYOptionValueCell.h in Headers */,
84B0A7351CE10ED900253EB0 /* BUYPaymentController.h in Headers */,
9019313A1BC5B9BC00D1134E /* BUYImageLink.h in Headers */,
9019313B1BC5B9BC00D1134E /* BUYOptionValue.h in Headers */,
......@@ -1448,16 +1237,10 @@
9019313C1BC5B9BC00D1134E /* BUYShop.h in Headers */,
9019313D1BC5B9BC00D1134E /* BUYShippingRate.h in Headers */,
9019313E1BC5B9BC00D1134E /* BUYApplePayAdditions.h in Headers */,
901931401BC5B9BC00D1134E /* BUYTheme+Additions.h in Headers */,
84980F531CB7616900CFAB58 /* BUYDecimalNumberTransformer.h in Headers */,
901931411BC5B9BC00D1134E /* BUYVariantOptionView.h in Headers */,
901931421BC5B9BC00D1134E /* BUYMaskedCreditCard.h in Headers */,
901931431BC5B9BC00D1134E /* BUYProductViewHeader.h in Headers */,
901931441BC5B9BC00D1134E /* BUYProductViewHeaderBackgroundImageView.h in Headers */,
8498DCB61CDD1B5400BD12A8 /* BUYClient_Internal.h in Headers */,
901931461BC5B9BC00D1134E /* BUYCheckoutButton.h in Headers */,
901931471BC5B9BC00D1134E /* BUYPaymentButton.h in Headers */,
901931481BC5B9BC00D1134E /* BUYImageView.h in Headers */,
841ADE201CB6C942000004B0 /* NSURL+BUYAdditions.h in Headers */,
841ADE241CB6C942000004B0 /* NSURLComponents+BUYAdditions.h in Headers */,
841ADE141CB6C942000004B0 /* NSException+BUYAdditions.h in Headers */,
......@@ -1475,22 +1258,14 @@
841ADE0C1CB6C942000004B0 /* NSDecimalNumber+BUYAdditions.h in Headers */,
84980F331CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */,
901931491BC5B9BC00D1134E /* BUYGiftCard.h in Headers */,
9019314B1BC5B9BC00D1134E /* BUYNavigationController.h in Headers */,
9019314D1BC5B9BC00D1134E /* BUYVariantOptionBreadCrumbsView.h in Headers */,
9019314E1BC5B9BC00D1134E /* BUYProductViewFooter.h in Headers */,
9019314F1BC5B9BC00D1134E /* BUYOptionSelectionViewController.h in Headers */,
84CD7C2E1CC65D5A00B6EE61 /* _BUYCheckoutAttribute.h in Headers */,
901931501BC5B9BC00D1134E /* BUYOrder.h in Headers */,
901931531BC5B9BC00D1134E /* BUYOptionSelectionNavigationController.h in Headers */,
901931541BC5B9BC00D1134E /* BUYPresentationControllerWithNavigationController.h in Headers */,
84D9154C1CC03F1600D334FB /* BUYManagedObject.h in Headers */,
901931551BC5B9BC00D1134E /* BUYPresentationControllerForVariantSelection.h in Headers */,
84DD12CF1CC6401400A2442D /* BUYCustomer.h in Headers */,
901931571BC5B9BC00D1134E /* BUYObject.h in Headers */,
901931581BC5B9BC00D1134E /* BUYRuntime.h in Headers */,
901931591BC5B9BC00D1134E /* BUYCollection.h in Headers */,
84D915441CC0359700D334FB /* BUYObserver.h in Headers */,
9019315A1BC5B9BC00D1134E /* BUYProductImageCollectionViewCell.h in Headers */,
84980F5F1CB7617E00CFAB58 /* BUYDateTransformer.h in Headers */,
84980F591CB7617500CFAB58 /* BUYURLTransformer.h in Headers */,
9019315B1BC5B9BC00D1134E /* BUYImageKit.h in Headers */,
......@@ -1498,16 +1273,12 @@
9032F2DB1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */,
9019315E1BC5B9BC00D1134E /* BUYError.h in Headers */,
84980F371CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h in Headers */,
9019315F1BC5B9BC00D1134E /* BUYProductHeaderCell.h in Headers */,
901931601BC5B9BC00D1134E /* BUYProductViewErrorView.h in Headers */,
901931611BC5B9BC00D1134E /* BUYClient.h in Headers */,
901931631BC5B9BC00D1134E /* BUYGradientView.h in Headers */,
849810971CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h in Headers */,
901931641BC5B9BC00D1134E /* BUYCartLineItem.h in Headers */,
8498DCAE1CDD1B2F00BD12A8 /* BUYError+BUYAdditions.h in Headers */,
901931661BC5B9BC00D1134E /* BUYCheckout.h in Headers */,
901931671BC5B9BC00D1134E /* BUYCart.h in Headers */,
901931681BC5B9BC00D1134E /* BUYProductViewController.h in Headers */,
901931691BC5B9BC00D1134E /* BUYProduct.h in Headers */,
9019316A1BC5B9BC00D1134E /* BUYSerializable.h in Headers */,
9A47CF041CE3A24600A6D5BA /* BUYApplePayToken.h in Headers */,
......@@ -1548,21 +1319,14 @@
BE9A64551B503CC50033E558 /* BUYCreditCard.h in Headers */,
BE9A645F1B503CE90033E558 /* BUYOption.h in Headers */,
84980F4C1CB7613700CFAB58 /* BUYIdentityTransformer.h in Headers */,
BEB74A6F1B5564260005A300 /* BUYProductVariantCell.h in Headers */,
BEB74A2B1B554C150005A300 /* BUYTheme.h in Headers */,
BEB74A6B1B55641B0005A300 /* BUYProductDescriptionCell.h in Headers */,
BE9A645B1B503CDC0033E558 /* BUYLineItem.h in Headers */,
907874991B7276BA0023775B /* BUYProductViewHeaderOverlay.h in Headers */,
8498DCAA1CDD1B2500BD12A8 /* BUYShopifyErrorCodes.h in Headers */,
9A47CF081CE3ACE100A6D5BA /* BUYPaymentToken.h in Headers */,
BE9A64801B503D990033E558 /* BUYViewController.h in Headers */,
BE9A644F1B503CA90033E558 /* BUYDiscount.h in Headers */,
900396AC1B627CB900226B73 /* BUYProductView.h in Headers */,
8498DCB41CDD1B5400BD12A8 /* BUYClient+Customers.h in Headers */,
BE9A64511B503CB00033E558 /* BUYTaxLine.h in Headers */,
849810921CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.h in Headers */,
BEB74A7D1B5564870005A300 /* BUYVariantSelectionViewController.h in Headers */,
BE10079B1B6165EC0031CEE7 /* BUYOptionValueCell.h in Headers */,
BE9A64591B503CD40033E558 /* BUYImageLink.h in Headers */,
84B0A7341CE10ED900253EB0 /* BUYPaymentController.h in Headers */,
BE9A64681B503D080033E558 /* BUYOptionValue.h in Headers */,
......@@ -1570,17 +1334,11 @@
84B0A7301CE10ED900253EB0 /* BUYApplePayPaymentProvider.h in Headers */,
BE9A644D1B503CA20033E558 /* BUYShippingRate.h in Headers */,
BE9A646C1B503D180033E558 /* BUYApplePayAdditions.h in Headers */,
906EAE431B836DE000976165 /* BUYTheme+Additions.h in Headers */,
BEB74A7B1B5564810005A300 /* BUYVariantOptionView.h in Headers */,
84980F521CB7616900CFAB58 /* BUYDecimalNumberTransformer.h in Headers */,
BE5DC3631B71022D00B2BC1E /* BUYMaskedCreditCard.h in Headers */,
BEB74A731B5564350005A300 /* BUYProductViewHeader.h in Headers */,
BEB74A751B55643B0005A300 /* BUYProductViewHeaderBackgroundImageView.h in Headers */,
90C856B61BD6B0F400936926 /* Buy.h in Headers */,
8498DCB31CDD1B5400BD12A8 /* BUYClient_Internal.h in Headers */,
900396B01B67BD0A00226B73 /* BUYCheckoutButton.h in Headers */,
BE9A64821B503DAD0033E558 /* BUYPaymentButton.h in Headers */,
BEB74A771B55646D0005A300 /* BUYImageView.h in Headers */,
909944491B71B76800C40A33 /* UIFont+BUYAdditions.h in Headers */,
841ADE0F1CB6C942000004B0 /* NSDictionary+BUYAdditions.h in Headers */,
841ADE1F1CB6C942000004B0 /* NSURL+BUYAdditions.h in Headers */,
......@@ -1598,22 +1356,14 @@
841ADE0B1CB6C942000004B0 /* NSDecimalNumber+BUYAdditions.h in Headers */,
84980F321CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.h in Headers */,
BE9A64571B503CCC0033E558 /* BUYGiftCard.h in Headers */,
BEB74A671B55640C0005A300 /* BUYNavigationController.h in Headers */,
90DE92701B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.h in Headers */,
BEB74A711B5564300005A300 /* BUYProductViewFooter.h in Headers */,
BEB74A791B5564790005A300 /* BUYOptionSelectionViewController.h in Headers */,
84CD7C2D1CC65D5A00B6EE61 /* _BUYCheckoutAttribute.h in Headers */,
90E83BC41B9F550E00C95A1B /* BUYOrder.h in Headers */,
BEB74A281B554BFB0005A300 /* BUYOptionSelectionNavigationController.h in Headers */,
BEB74A691B5564160005A300 /* BUYPresentationControllerWithNavigationController.h in Headers */,
84D9154B1CC03F1600D334FB /* BUYManagedObject.h in Headers */,
BEB74A221B554BF20005A300 /* BUYPresentationControllerForVariantSelection.h in Headers */,
84DD12CD1CC6401400A2442D /* BUYCustomer.h in Headers */,
BE9A645D1B503CE30033E558 /* BUYObject.h in Headers */,
BE9A646E1B503D1E0033E558 /* BUYRuntime.h in Headers */,
BEB74A901B55A3D00005A300 /* BUYCollection.h in Headers */,
84D915431CC0359700D334FB /* BUYObserver.h in Headers */,
904606AF1B6BC8D700754173 /* BUYProductImageCollectionViewCell.h in Headers */,
84980F5E1CB7617E00CFAB58 /* BUYDateTransformer.h in Headers */,
84980F581CB7617500CFAB58 /* BUYURLTransformer.h in Headers */,
900E7C841B5DA553006F3C81 /* BUYImageKit.h in Headers */,
......@@ -1621,16 +1371,12 @@
9032F2DA1BE9457A00BB9EEF /* BUYCheckoutAttribute.h in Headers */,
BE47340F1B66C4EF00AA721A /* BUYError.h in Headers */,
84980F361CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.h in Headers */,
BEB74A6D1B5564200005A300 /* BUYProductHeaderCell.h in Headers */,
903BCC7C1B7D1C2D00C21FEB /* BUYProductViewErrorView.h in Headers */,
BE9A64471B503C8B0033E558 /* BUYClient.h in Headers */,
BEB74A651B5563FF0005A300 /* BUYGradientView.h in Headers */,
849810961CB7E07900CFAB58 /* BUYFlatCollectionTransformer.h in Headers */,
9003969B1B601DF400226B73 /* BUYCartLineItem.h in Headers */,
8498DCAC1CDD1B2F00BD12A8 /* BUYError+BUYAdditions.h in Headers */,
BE9A644B1B503C9B0033E558 /* BUYCheckout.h in Headers */,
BE9A64491B503C940033E558 /* BUYCart.h in Headers */,
BEB74A2D1B554E870005A300 /* BUYProductViewController.h in Headers */,
BE9A64611B503CEF0033E558 /* BUYProduct.h in Headers */,
BE9A64651B503CFE0033E558 /* BUYSerializable.h in Headers */,
9A47CF031CE3A24600A6D5BA /* BUYApplePayToken.h in Headers */,
......@@ -1836,17 +1582,13 @@
files = (
901930E31BC5B9BC00D1134E /* BUYApplePayHelpers.m in Sources */,
84DD12AA1CC63FE600A2442D /* _BUYOrder.m in Sources */,
901930E41BC5B9BC00D1134E /* BUYOptionSelectionViewController.m in Sources */,
901930E51BC5B9BC00D1134E /* BUYVariantOptionView.m in Sources */,
841ADE1E1CB6C942000004B0 /* NSString+BUYAdditions.m in Sources */,
84980F5B1CB7617500CFAB58 /* BUYURLTransformer.m in Sources */,
901930E61BC5B9BC00D1134E /* BUYPresentationControllerForVariantSelection.m in Sources */,
84980F611CB7617E00CFAB58 /* BUYDateTransformer.m in Sources */,
901930E81BC5B9BC00D1134E /* BUYImageLink.m in Sources */,
84DD129E1CC63FE600A2442D /* _BUYCollection.m in Sources */,
901930E91BC5B9BC00D1134E /* BUYProductVariant.m in Sources */,
84D9154E1CC03F1600D334FB /* BUYManagedObject.m in Sources */,
901930EA1BC5B9BC00D1134E /* BUYProductViewController.m in Sources */,
84B0A7331CE10ED900253EB0 /* BUYApplePayPaymentProvider.m in Sources */,
841ADE021CB6C942000004B0 /* NSArray+BUYAdditions.m in Sources */,
901930EC1BC5B9BC00D1134E /* BUYError.m in Sources */,
......@@ -1858,31 +1600,21 @@
901930EF1BC5B9BC00D1134E /* BUYVariantSelectionViewController.m in Sources */,
9A47CEFE1CE39F6100A6D5BA /* BUYCreditCardToken.m in Sources */,
901930F21BC5B9BC00D1134E /* BUYOrder.m in Sources */,
901930F41BC5B9BC00D1134E /* BUYProductViewHeaderBackgroundImageView.m in Sources */,
901930F51BC5B9BC00D1134E /* BUYProductViewHeaderOverlay.m in Sources */,
901930F61BC5B9BC00D1134E /* BUYProductVariantCell.m in Sources */,
849810991CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m in Sources */,
84DD12A41CC63FE600A2442D /* _BUYLineItem.m in Sources */,
901930F71BC5B9BC00D1134E /* BUYTheme.m in Sources */,
84DD12CC1CC63FEE00A2442D /* _BUYTaxLine.m in Sources */,
84DD12CA1CC63FEE00A2442D /* _BUYShippingRate.m in Sources */,
901930F91BC5B9BC00D1134E /* BUYProductViewErrorView.m in Sources */,
901930FA1BC5B9BC00D1134E /* BUYLineItem.m in Sources */,
901930FB1BC5B9BC00D1134E /* BUYCheckoutButton.m in Sources */,
849810951CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m in Sources */,
84DD12B01CC63FE600A2442D /* _BUYShop.m in Sources */,
901930FC1BC5B9BC00D1134E /* BUYCollection.m in Sources */,
901930FD1BC5B9BC00D1134E /* BUYTaxLine.m in Sources */,
84980F351CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m in Sources */,
84D915461CC0359700D334FB /* BUYObserver.m in Sources */,
901930FF1BC5B9BC00D1134E /* BUYVariantOptionBreadCrumbsView.m in Sources */,
901931011BC5B9BC00D1134E /* BUYTheme+Additions.m in Sources */,
901931021BC5B9BC00D1134E /* BUYStoreViewController.m in Sources */,
84D73C091CDD194D000F978A /* BUYAddress.m in Sources */,
901931031BC5B9BC00D1134E /* BUYOptionValue.m in Sources */,
84980F551CB7616900CFAB58 /* BUYDecimalNumberTransformer.m in Sources */,
901931041BC5B9BC00D1134E /* BUYApplePayAdditions.m in Sources */,
901931051BC5B9BC00D1134E /* BUYOptionSelectionNavigationController.m in Sources */,
901931061BC5B9BC00D1134E /* BUYDiscount.m in Sources */,
84DD129A1CC63FE600A2442D /* _BUYCart.m in Sources */,
841ADE0A1CB6C942000004B0 /* NSDateFormatter+BUYAdditions.m in Sources */,
......@@ -1898,31 +1630,24 @@
9019310C1BC5B9BC00D1134E /* BUYGiftCard.m in Sources */,
841ADE161CB6C942000004B0 /* NSException+BUYModelAdditions.m in Sources */,
84DD12A01CC63FE600A2442D /* _BUYCustomer.m in Sources */,
9019310D1BC5B9BC00D1134E /* BUYOptionValueCell.m in Sources */,
9019310E1BC5B9BC00D1134E /* BUYProduct.m in Sources */,
84DD12C81CC63FEE00A2442D /* _BUYMaskedCreditCard.m in Sources */,
84DD12AC1CC63FE600A2442D /* _BUYProduct.m in Sources */,
9019310F1BC5B9BC00D1134E /* BUYImageView.m in Sources */,
84DD12A21CC63FE600A2442D /* _BUYImageLink.m in Sources */,
901931101BC5B9BC00D1134E /* BUYProductHeaderCell.m in Sources */,
841ADE1A1CB6C942000004B0 /* NSRegularExpression+BUYAdditions.m in Sources */,
8498DCBE1CDD1FA400BD12A8 /* BUYAccountCredentials.m in Sources */,
9032F2DD1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */,
901931111BC5B9BC00D1134E /* BUYCartLineItem.m in Sources */,
901931121BC5B9BC00D1134E /* BUYMaskedCreditCard.m in Sources */,
901931131BC5B9BC00D1134E /* BUYCheckout.m in Sources */,
901931141BC5B9BC00D1134E /* BUYProductViewFooter.m in Sources */,
84DD12A61CC63FE600A2442D /* _BUYOption.m in Sources */,
841ADE261CB6C942000004B0 /* NSURLComponents+BUYAdditions.m in Sources */,
8498DCAF1CDD1B2F00BD12A8 /* BUYError+BUYAdditions.m in Sources */,
901931151BC5B9BC00D1134E /* BUYPresentationControllerWithNavigationController.m in Sources */,
84DD12D01CC6401400A2442D /* BUYCustomer.m in Sources */,
84980F391CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m in Sources */,
841ADE221CB6C942000004B0 /* NSURL+BUYAdditions.m in Sources */,
901931161BC5B9BC00D1134E /* BUYShippingRate.m in Sources */,
841ADE061CB6C942000004B0 /* NSDate+BUYAdditions.m in Sources */,
901931181BC5B9BC00D1134E /* BUYGradientView.m in Sources */,
901931191BC5B9BC00D1134E /* BUYViewController.m in Sources */,
84B0A7431CE10F8100253EB0 /* BUYClient+Checkout.m in Sources */,
9019311A1BC5B9BC00D1134E /* BUYImageKit.m in Sources */,
84B0A7371CE10ED900253EB0 /* BUYPaymentController.m in Sources */,
......@@ -1931,9 +1656,7 @@
9019311D1BC5B9BC00D1134E /* BUYClient.m in Sources */,
9019311E1BC5B9BC00D1134E /* UIFont+BUYAdditions.m in Sources */,
8498DCB81CDD1B5400BD12A8 /* BUYClient+Customers.m in Sources */,
9019311F1BC5B9BC00D1134E /* BUYProductView.m in Sources */,
901931201BC5B9BC00D1134E /* BUYCreditCard.m in Sources */,
901931211BC5B9BC00D1134E /* BUYProductImageCollectionViewCell.m in Sources */,
84980F4F1CB7613700CFAB58 /* BUYIdentityTransformer.m in Sources */,
84CD7C301CC65D7C00B6EE61 /* _BUYCheckoutAttribute.m in Sources */,
84DD12A81CC63FE600A2442D /* _BUYOptionValue.m in Sources */,
......@@ -1942,7 +1665,6 @@
84DD12C61CC63FEE00A2442D /* _BUYGiftCard.m in Sources */,
84DD12C41CC63FEE00A2442D /* _BUYDiscount.m in Sources */,
84D915591CC040C300D334FB /* Mobile Buy SDK.xcdatamodeld in Sources */,
901931241BC5B9BC00D1134E /* BUYProductDescriptionCell.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -1996,17 +1718,13 @@
files = (
BE9A64751B503D370033E558 /* BUYApplePayHelpers.m in Sources */,
84DD12921CC63FE600A2442D /* _BUYOrder.m in Sources */,
BEB74A7A1B55647C0005A300 /* BUYOptionSelectionViewController.m in Sources */,
BEB74A7C1B5564840005A300 /* BUYVariantOptionView.m in Sources */,
841ADE1D1CB6C942000004B0 /* NSString+BUYAdditions.m in Sources */,
84980F5A1CB7617500CFAB58 /* BUYURLTransformer.m in Sources */,
BEB74A241B554BF20005A300 /* BUYPresentationControllerForVariantSelection.m in Sources */,
84980F601CB7617E00CFAB58 /* BUYDateTransformer.m in Sources */,
BE9A645A1B503CD90033E558 /* BUYImageLink.m in Sources */,
84DD12861CC63FE600A2442D /* _BUYCollection.m in Sources */,
BE9A64641B503CFB0033E558 /* BUYProductVariant.m in Sources */,
84D9154D1CC03F1600D334FB /* BUYManagedObject.m in Sources */,
BEB74A2E1B554E8B0005A300 /* BUYProductViewController.m in Sources */,
84B0A7321CE10ED900253EB0 /* BUYApplePayPaymentProvider.m in Sources */,
841ADE011CB6C942000004B0 /* NSArray+BUYAdditions.m in Sources */,
BE4734101B66C4EF00AA721A /* BUYError.m in Sources */,
......@@ -2018,31 +1736,21 @@
BEB74A7E1B5564890005A300 /* BUYVariantSelectionViewController.m in Sources */,
9A47CEFD1CE39F6000A6D5BA /* BUYCreditCardToken.m in Sources */,
90E83BC51B9F550E00C95A1B /* BUYOrder.m in Sources */,
BEB74A761B55643E0005A300 /* BUYProductViewHeaderBackgroundImageView.m in Sources */,
9078749A1B7276BA0023775B /* BUYProductViewHeaderOverlay.m in Sources */,
BEB74A701B5564290005A300 /* BUYProductVariantCell.m in Sources */,
849810981CB7E07900CFAB58 /* BUYFlatCollectionTransformer.m in Sources */,
84DD128C1CC63FE600A2442D /* _BUYLineItem.m in Sources */,
BEB74A2C1B554C370005A300 /* BUYTheme.m in Sources */,
84DD12BE1CC63FEE00A2442D /* _BUYTaxLine.m in Sources */,
84DD12BC1CC63FEE00A2442D /* _BUYShippingRate.m in Sources */,
903BCC7D1B7D1C2D00C21FEB /* BUYProductViewErrorView.m in Sources */,
BE9A645C1B503CE00033E558 /* BUYLineItem.m in Sources */,
900396B11B67BD0A00226B73 /* BUYCheckoutButton.m in Sources */,
849810941CB7E07900CFAB58 /* BUYDeliveryRangeTransformer.m in Sources */,
84DD12981CC63FE600A2442D /* _BUYShop.m in Sources */,
9089CC5E1BB48D06009726D6 /* BUYCollection.m in Sources */,
BE9A64521B503CB80033E558 /* BUYTaxLine.m in Sources */,
84980F341CB75C2900CFAB58 /* NSEntityDescription+BUYAdditions.m in Sources */,
84D915451CC0359700D334FB /* BUYObserver.m in Sources */,
90DE92711B9897B6002EF4DA /* BUYVariantOptionBreadCrumbsView.m in Sources */,
906EAE441B836DE000976165 /* BUYTheme+Additions.m in Sources */,
BE9A647F1B503D960033E558 /* BUYStoreViewController.m in Sources */,
84D73C071CDD194D000F978A /* BUYAddress.m in Sources */,
BE9A64691B503D0C0033E558 /* BUYOptionValue.m in Sources */,
84980F541CB7616900CFAB58 /* BUYDecimalNumberTransformer.m in Sources */,
BE9A646D1B503D1C0033E558 /* BUYApplePayAdditions.m in Sources */,
BEB74A2A1B554BFB0005A300 /* BUYOptionSelectionNavigationController.m in Sources */,
BE9A64501B503CAD0033E558 /* BUYDiscount.m in Sources */,
84DD12821CC63FE600A2442D /* _BUYCart.m in Sources */,
841ADE091CB6C942000004B0 /* NSDateFormatter+BUYAdditions.m in Sources */,
......@@ -2058,31 +1766,24 @@
BE9A64581B503CD10033E558 /* BUYGiftCard.m in Sources */,
841ADE151CB6C942000004B0 /* NSException+BUYModelAdditions.m in Sources */,
84DD12881CC63FE600A2442D /* _BUYCustomer.m in Sources */,
BE10079C1B6165EC0031CEE7 /* BUYOptionValueCell.m in Sources */,
BE9A64621B503CF40033E558 /* BUYProduct.m in Sources */,
84DD12BA1CC63FEE00A2442D /* _BUYMaskedCreditCard.m in Sources */,
84DD12941CC63FE600A2442D /* _BUYProduct.m in Sources */,
BEB74A781B55646F0005A300 /* BUYImageView.m in Sources */,
84DD128A1CC63FE600A2442D /* _BUYImageLink.m in Sources */,
BEB74A6E1B5564230005A300 /* BUYProductHeaderCell.m in Sources */,
841ADE191CB6C942000004B0 /* NSRegularExpression+BUYAdditions.m in Sources */,
8498DCBD1CDD1FA400BD12A8 /* BUYAccountCredentials.m in Sources */,
9032F2DC1BE9457A00BB9EEF /* BUYCheckoutAttribute.m in Sources */,
9003969C1B601DF400226B73 /* BUYCartLineItem.m in Sources */,
BE5DC3641B71022D00B2BC1E /* BUYMaskedCreditCard.m in Sources */,
BE9A644C1B503C9F0033E558 /* BUYCheckout.m in Sources */,
BEB74A721B5564320005A300 /* BUYProductViewFooter.m in Sources */,
84DD128E1CC63FE600A2442D /* _BUYOption.m in Sources */,
841ADE251CB6C942000004B0 /* NSURLComponents+BUYAdditions.m in Sources */,
8498DCAD1CDD1B2F00BD12A8 /* BUYError+BUYAdditions.m in Sources */,
BEB74A6A1B5564190005A300 /* BUYPresentationControllerWithNavigationController.m in Sources */,
84DD12CE1CC6401400A2442D /* BUYCustomer.m in Sources */,
84980F381CB75C2900CFAB58 /* NSPropertyDescription+BUYAdditions.m in Sources */,
841ADE211CB6C942000004B0 /* NSURL+BUYAdditions.m in Sources */,
BE9A644E1B503CA60033E558 /* BUYShippingRate.m in Sources */,
841ADE051CB6C942000004B0 /* NSDate+BUYAdditions.m in Sources */,
BEB74A661B5564030005A300 /* BUYGradientView.m in Sources */,
BE9A64811B503D9E0033E558 /* BUYViewController.m in Sources */,
84B0A7421CE10F8100253EB0 /* BUYClient+Checkout.m in Sources */,
900E7C851B5DA559006F3C81 /* BUYImageKit.m in Sources */,
84B0A7361CE10ED900253EB0 /* BUYPaymentController.m in Sources */,
......@@ -2091,9 +1792,7 @@
BE9A64481B503C900033E558 /* BUYClient.m in Sources */,
9099444A1B71B76800C40A33 /* UIFont+BUYAdditions.m in Sources */,
8498DCB51CDD1B5400BD12A8 /* BUYClient+Customers.m in Sources */,
900396AD1B627CB900226B73 /* BUYProductView.m in Sources */,
BE9A64561B503CC90033E558 /* BUYCreditCard.m in Sources */,
904606B01B6BC8D700754173 /* BUYProductImageCollectionViewCell.m in Sources */,
84980F4E1CB7613700CFAB58 /* BUYIdentityTransformer.m in Sources */,
84CD7C2F1CC65D7B00B6EE61 /* _BUYCheckoutAttribute.m in Sources */,
84DD12901CC63FE600A2442D /* _BUYOptionValue.m in Sources */,
......@@ -2102,7 +1801,6 @@
84DD12B81CC63FEE00A2442D /* _BUYGiftCard.m in Sources */,
84DD12B61CC63FEE00A2442D /* _BUYDiscount.m in Sources */,
84D915581CC040C300D334FB /* Mobile Buy SDK.xcdatamodeld in Sources */,
BEB74A6C1B55641D0005A300 /* BUYProductDescriptionCell.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -76,10 +76,6 @@ FOUNDATION_EXPORT const unsigned char BuyVersionString[];
#import <Buy/BUYPaymentToken.h>
#import <Buy/BUYPaymentButton.h>
#import <Buy/BUYProductViewController.h>
#import <Buy/BUYStoreViewController.h>
#import <Buy/BUYTheme.h>
#import <Buy/BUYViewController.h>
#import <Buy/NSArray+BUYAdditions.h>
#import <Buy/NSDate+BUYAdditions.h>
......
//
// BUYProductViewController.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import "BUYGradientView.h"
#import "BUYImageView.h"
#import "BUYOptionSelectionNavigationController.h"
#import "BUYPresentationControllerWithNavigationController.h"
#import "BUYProduct.h"
#import "BUYProductViewController.h"
#import "BUYImageKit.h"
#import "BUYImageLink.h"
#import "BUYProductView.h"
#import "BUYProductViewFooter.h"
#import "BUYProductHeaderCell.h"
#import "BUYProductVariantCell.h"
#import "BUYProductDescriptionCell.h"
#import "BUYProductViewHeader.h"
#import "BUYProductImageCollectionViewCell.h"
#import "BUYProductViewHeaderBackgroundImageView.h"
#import "BUYProductViewHeaderOverlay.h"
#import "BUYTheme+Additions.h"
#import "BUYVariantSelectionViewController.h"
#import "BUYError.h"
#import "BUYShop.h"
#import "BUYShopifyErrorCodes.h"
CGFloat const BUYMaxProductViewWidth = 414.0; // We max out to the width of the iPhone 6+
CGFloat const BUYMaxProductViewHeight = 640.0;
@interface BUYProductViewController (Private)
@property (nonatomic, strong) BUYCheckout *checkout;
- (void)handleCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)completion;
- (void)postCheckoutCompletion:(BUYCheckout *)checkout error:(NSError *)error;
@end
@interface BUYProductViewController () <BUYThemeable, UITableViewDataSource, UITableViewDelegate, UIViewControllerTransitioningDelegate, BUYVariantSelectionDelegate, BUYNavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic, strong) NSString *productId;
@property (nonatomic, strong) BUYProductVariant *selectedProductVariant;
@property (nonatomic, strong) BUYTheme *theme;
@property (nonatomic, assign) BOOL shouldShowVariantSelector;
@property (nonatomic, assign) BOOL shouldEnableVariantSelection;
@property (nonatomic, assign) BOOL shouldShowDescription;
@property (nonatomic, strong) BUYProduct *product;
@property (nonatomic, assign) BOOL isLoading;
@property (nonatomic, strong) NSNumberFormatter *currencyFormatter;
// views
@property (nonatomic, strong) BUYProductView *productView;
@property (nonatomic, weak) UIView *navigationBar;
@property (nonatomic, weak) UILabel *navigationBarTitle;
@property (nonatomic, strong) BUYProductHeaderCell *headerCell;
@property (nonatomic, strong) BUYProductVariantCell *variantCell;
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicatorView;
@end
@implementation BUYProductViewController
@synthesize theme = _theme;
- (instancetype)initWithClient:(BUYClient *)client
{
return [self initWithClient:client theme:nil];
}
- (instancetype)initWithClient:(BUYClient *)client theme:(BUYTheme *)theme
{
self = [super initWithClient:client];
if (self) {
self.theme = theme? : [[BUYTheme alloc] init];
self.modalPresentationStyle = UIModalPresentationCustom;
self.transitioningDelegate = self;
self.allowApplePaySetup = YES;
_activityIndicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero];
_activityIndicatorView.translatesAutoresizingMaskIntoConstraints = NO;
_activityIndicatorView.hidesWhenStopped = YES;
[_activityIndicatorView startAnimating];
[self.view addSubview:_activityIndicatorView];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_activityIndicatorView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:0.0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:_activityIndicatorView
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:0.0]];
}
return self;
}
- (BUYProductView *)productView
{
if (_productView == nil && self.product != nil && self.shop != nil) {
_productView = [[BUYProductView alloc] initWithFrame:CGRectMake(0, 0, self.preferredContentSize.width, self.preferredContentSize.height) product:self.product theme:self.theme shouldShowApplePaySetup:self.shouldShowApplePaySetup];
_productView.translatesAutoresizingMaskIntoConstraints = NO;
_productView.hidden = YES;
[self.view addSubview:_productView];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_productView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_productView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_productView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_productView)]];
_productView.tableView.delegate = self;
_productView.tableView.dataSource = self;
[_productView.productViewFooter setApplePayButtonVisible:self.shouldShowApplePayButton];
[_productView.productViewFooter.buyPaymentButton addTarget:self action:@selector(checkoutWithApplePay) forControlEvents:UIControlEventTouchUpInside];
[_productView.productViewFooter.checkoutButton addTarget:self action:@selector(checkoutWithShopify) forControlEvents:UIControlEventTouchUpInside];
_productView.productViewHeader.collectionView.delegate = self;
_productView.productViewHeader.collectionView.dataSource = self;
_productView.layoutMargins = UIEdgeInsetsMake(self.productView.layoutMargins.top, self.productView.layoutMargins.left, self.bottomLayoutGuide.length, self.productView.layoutMargins.right);
}
return _productView;
}
- (CGSize)preferredContentSize
{
return CGSizeMake(MIN(BUYMaxProductViewWidth, self.view.bounds.size.width),
MIN(BUYMaxProductViewHeight, self.view.bounds.size.height));
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self setupNavigationBarAppearance];
[self.navigationController setNavigationBarHidden:self.isLoading];
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (self.productView.hasSetVariantOnCollectionView == NO) {
if ([self canCollectionViewDrawProductImages] || [self.product.images count] == 0) {
[self setSelectedProductVariant:self.selectedProductVariant];
self.productView.hasSetVariantOnCollectionView = YES;
}
}
}
- (BOOL)canCollectionViewDrawProductImages
{
return [self.product.images count] > 0 && CGSizeEqualToSize(self.productView.productViewHeader.collectionView.bounds.size, CGSizeZero) == NO;
}
- (void)setupNavigationBarAppearance
{
if (self.navigationBar == nil && _productView && self.presentingViewController != nil) {
for (UIView *view in [self.navigationController.navigationBar subviews]) {
if (CGRectGetHeight(view.bounds) >= 44) {
// Get a reference to the UINavigationBar
self.navigationBar = view;
self.navigationBar.alpha = 0;
continue;
} else if ([view.subviews count] == 1 && [view.subviews[0] isKindOfClass:[UILabel class]]) {
// Get a reference to the UINavigationBar's title
self.navigationBarTitle = view.subviews[0];
self.navigationBarTitle.alpha = 0;
continue;
}
}
// Hide the navigation bar
[self scrollViewDidScroll:self.productView.tableView];
} else if (self.navigationController && _productView && self.presentingViewController == nil) {
[self.productView setTopInset:CGRectGetHeight(self.navigationController.navigationBar.bounds) + self.navigationController.topLayoutGuide.length];
}
}
- (void)setTheme:(BUYTheme *)theme
{
_theme = theme;
self.view.tintColor = theme.tintColor;
self.view.backgroundColor = [theme backgroundColor];
self.productView.theme = theme;
self.activityIndicatorView.activityIndicatorViewStyle = [theme activityIndicatorViewStyle];
[self setNeedsStatusBarAppearanceUpdate];
}
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
BUYPresentationControllerWithNavigationController *presentationController = [[BUYPresentationControllerWithNavigationController alloc] initWithPresentedViewController:presented presentingViewController:presenting];
presentationController.delegate = presentationController;
presentationController.navigationDelegate = self;
[presentationController setTheme:self.theme];
return presentationController;
}
- (void)loadProduct:(NSString *)productId completion:(void (^)(BOOL success, NSError *error))completion
{
if (productId == nil) {
if (completion) {
completion(NO, [NSError errorWithDomain:BUYShopifyError code:BUYShopifyError_NoProductSpecified userInfo:nil]);
}
}
else {
self.isLoading = YES;
[self loadShopWithCallback:^(BOOL success, NSError *error) {
if (success) {
self.productId = productId;
[self.client getProductById:productId completion:^(BUYProduct *product, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
self.isLoading = NO;
if (error) {
if (completion) {
completion(NO, error);
}
}
else {
self.product = product;
if (completion) {
completion(YES, nil);
}
}
});
}];
}
else {
self.isLoading = NO;
if (completion) {
completion(success, error);
}
}
}];
}
}
- (void)loadWithProduct:(BUYProduct *)product completion:(void (^)(BOOL success, NSError *error))completion;
{
if (product == nil) {
completion(NO, [NSError errorWithDomain:BUYShopifyError code:BUYShopifyError_NoProductSpecified userInfo:nil]);
}
else {
if (self.shop == nil) {
self.isLoading = YES;
[self loadShopWithCallback:^(BOOL success, NSError *error) {
self.product = product;
self.isLoading = NO;
if (completion) {
completion(success, error);
}
}];
}
else {
self.product = product;
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(YES, nil);
}
});
}
}
}
- (void)setProduct:(BUYProduct *)product
{
_product = product;
self.navigationItem.title = _product.title;
self.selectedProductVariant = [_product.variants firstObject];
self.shouldShowVariantSelector = [_product isDefaultVariant] == NO;
self.shouldEnableVariantSelection = self.shouldShowVariantSelector && [_product.variants count] > 1;
self.shouldShowDescription = ([_product.htmlDescription length] == 0) == NO;
self.productView.hidden = NO;
[self setupNavigationBarAppearance];
[self.activityIndicatorView stopAnimating];
[self setNeedsStatusBarAppearanceUpdate];
[self.navigationController setNavigationBarHidden:NO];
}
- (void)setShop:(BUYShop *)shop
{
[super setShop:shop];
self.currencyFormatter = [[NSNumberFormatter alloc] init];
self.currencyFormatter.numberStyle = NSNumberFormatterCurrencyStyle;
self.currencyFormatter.currencyCode = shop.currency;
[self.productView.productViewFooter setApplePayButtonVisible:self.shouldShowApplePayButton];
[self.productView.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationNone];
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = 0;
if (self.product) {
rows += 1; // product title and price
rows += self.shouldShowVariantSelector;
rows += self.shouldShowDescription;
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell <BUYThemeable> *theCell = nil;
if (indexPath.row == 0) {
BUYProductHeaderCell *cell = [tableView dequeueReusableCellWithIdentifier:@"headerCell"];
[cell setProductVariant:self.selectedProductVariant withCurrencyFormatter:self.currencyFormatter];
self.headerCell = cell;
theCell = cell;
} else if (indexPath.row == 1 && self.shouldShowVariantSelector) {
BUYProductVariantCell *cell = [tableView dequeueReusableCellWithIdentifier:@"variantCell"];
[cell setOptionsForProductVariant:self.selectedProductVariant];
cell.accessoryType = self.shouldEnableVariantSelection ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
self.variantCell = cell;
theCell = cell;
} else if ((indexPath.row == 2 && self.shouldShowDescription) || (indexPath.row == 1 && self.shouldShowVariantSelector == NO && self.shouldShowDescription)) {
BUYProductDescriptionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"descriptionCell"];
cell.descriptionHTML = self.product.htmlDescription;
cell.separatorInset = UIEdgeInsetsMake(0, CGRectGetWidth(self.productView.tableView.bounds), 0, 0);
theCell = cell;
}
[theCell setTheme:self.theme];
return theCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 1 && self.shouldEnableVariantSelection) {
[self.productView.tableView deselectRowAtIndexPath:indexPath animated:YES];
BUYVariantSelectionViewController *optionSelectionViewController = [[BUYVariantSelectionViewController alloc] initWithProduct:self.product theme:self.theme];
optionSelectionViewController.selectedProductVariant = self.selectedProductVariant;
optionSelectionViewController.delegate = self;
optionSelectionViewController.currencyFormatter = self.currencyFormatter;
BUYOptionSelectionNavigationController *optionSelectionNavigationController = [[BUYOptionSelectionNavigationController alloc] initWithRootViewController:optionSelectionViewController];
[optionSelectionNavigationController setTheme:self.theme];
[self presentViewController:optionSelectionNavigationController animated:YES completion:nil];
}
}
#pragma mark - BUYVariantSelectionViewControllerDelegate
- (void)variantSelectionController:(BUYVariantSelectionViewController *)controller didSelectVariant:(BUYProductVariant *)variant
{
if (self.selectedProductVariant != variant) {
self.selectedProductVariant = variant;
[self.productView.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[self dismissViewControllerAnimated:YES completion:^{
[self setNeedsStatusBarAppearanceUpdate];
[self scrollViewDidScroll:self.productView.tableView];
}];
}
- (void)variantSelectionControllerDidCancelVariantSelection:(BUYVariantSelectionViewController *)controller atOptionIndex:(NSUInteger)optionIndex
{
[self dismissViewControllerAnimated:YES completion:^{
[self setNeedsStatusBarAppearanceUpdate];
}];
}
- (void)setSelectedProductVariant:(BUYProductVariant *)selectedProductVariant {
_selectedProductVariant = selectedProductVariant;
if (self.headerCell) {
[self.headerCell setProductVariant:selectedProductVariant withCurrencyFormatter:self.currencyFormatter];
[self.variantCell setOptionsForProductVariant:self.selectedProductVariant];
}
if (self.productView.productViewHeader.collectionView) {
NSArray *images = self.product.images.array;
[self.productView.productViewHeader setImageForSelectedVariant:_selectedProductVariant withImages:images];
[self.productView updateBackgroundImage:images];
}
if (self.productView.productViewFooter) {
[self.productView.productViewFooter updateButtonsForProductVariant:selectedProductVariant];
}
if (self.productView.tableView) {
[self scrollViewDidScroll:self.productView.tableView];
}
}
#pragma mark Scroll view delegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ([scrollView isKindOfClass:[UITableView class]]) {
if (self.productView.productViewHeader) {
[self.productView scrollViewDidScroll:scrollView];
if (self.navigationBar) {
CGFloat duration = 0.3f;
if (self.navigationBar.alpha != 1 && [self navigationBarThresholdReached] == YES) {
[(BUYNavigationController*)self.navigationController updateCloseButtonImageWithTintColor:YES duration:duration];
[UIView animateWithDuration:duration
delay:0
options:(UIViewAnimationOptionCurveLinear | UIViewKeyframeAnimationOptionBeginFromCurrentState)
animations:^{
[self setNeedsStatusBarAppearanceUpdate];
self.navigationBar.alpha = 1;
self.navigationBarTitle.alpha = 1;
}
completion:NULL];
} else if (self.navigationBar.alpha != 0 && [self navigationBarThresholdReached] == NO) {
duration = 0.2f;
[(BUYNavigationController*)self.navigationController updateCloseButtonImageWithTintColor:NO duration:duration];
[UIView animateWithDuration:duration
delay:0
options:(UIViewAnimationOptionCurveLinear | UIViewKeyframeAnimationOptionBeginFromCurrentState)
animations:^{
[self setNeedsStatusBarAppearanceUpdate];
self.navigationBar.alpha = 0;
self.navigationBarTitle.alpha = 0;
}
completion:NULL];
}
[self.productView.productViewHeader.productViewHeaderOverlay scrollViewDidScroll:scrollView withNavigationBarHeight:CGRectGetHeight(self.navigationBar.bounds)];
}
} else if (self.productView.productViewHeader == nil && self.navigationBar && self.navigationBar.alpha == 0) {
// If the product view does not contain an image, inset the productView so its not obstructed with the navigation bar
[(BUYNavigationController*)self.navigationController updateCloseButtonImageWithTintColor:YES duration:0];
self.navigationBar.alpha = 1;
self.navigationBarTitle.alpha = 1;
CGFloat topInset = 0;
if (self.presentingViewController) {
topInset = CGRectGetHeight(self.navigationController.navigationBar.bounds) + self.presentingViewController.topLayoutGuide.length;
}
[self.productView setInsets:UIEdgeInsetsMake(topInset, 0, 0, 0) appendToCurrentInset:YES];
}
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
if ([scrollView isKindOfClass:[UICollectionView class]]) {
[self.productView updateBackgroundImage:self.product.images.array];
}
}
#pragma mark Checkout
- (BUYCart *)cart
{
BUYCart *cart = [self.client.modelManager insertCartWithJSONDictionary:nil];
[cart addVariant:self.selectedProductVariant];
return cart;
}
- (void)checkoutWithApplePay
{
if (self.isApplePayAvailable) {
self.checkout = [[BUYCheckout alloc] initWithCart:[self cart]];
[self startApplePayCheckout:self.checkout];
} else {
[[[PKPassLibrary alloc] init] openPaymentSetup];
}
}
- (void)checkoutWithShopify
{
self.checkout = [[BUYCheckout alloc] initWithCart:[self cart]];
[self startWebCheckout:self.checkout];
}
- (void)startWebCheckout:(BUYCheckout *)checkout
{
[_productView.productViewFooter.checkoutButton showActivityIndicator:YES];
[self handleCheckout:checkout completion:^(BUYCheckout *checkout, NSError *error) {
[_productView.productViewFooter.checkoutButton showActivityIndicator:NO];
[self postCheckoutCompletion:checkout error:error];
if (error) {
[self.productView showErrorWithMessage:@"Could not checkout at this time"];
}
}];
}
#pragma mark UIStatusBar appearance
- (UIStatusBarStyle)preferredStatusBarStyle
{
if (self.theme.style == BUYThemeStyleDark || ([self navigationBarThresholdReached] == NO && self.isLoading == NO && self.productView.productViewHeader)) {
return UIStatusBarStyleLightContent;
} else if (self.isLoading == YES && self.theme.style == BUYThemeStyleDark && self.productView.productViewHeader) {
return UIStatusBarStyleLightContent;
} else {
return UIStatusBarStyleDefault;
}
}
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
return UIStatusBarAnimationFade;
}
- (BOOL)navigationBarThresholdReached
{
return self.productView.tableView.contentOffset.y > CGRectGetHeight(self.productView.productViewHeader.bounds) - CGRectGetHeight(self.navigationBar.bounds);
}
#pragma mark BUYPresentationControllerWithNavigationControllerDelegate
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate {
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}
- (void)presentationControllerWillDismiss:(UIPresentationController *)presentationController
{
}
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
{
if ([self.delegate respondsToSelector:@selector(didDismissViewController:)]) {
[self.delegate didDismissViewController:self];
}
_product = nil;
_productId = nil;
[_productView removeFromSuperview];
_productView = nil;
}
#pragma mark - Collection View Delegate and Datasource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [self.product.images count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
BUYProductImageCollectionViewCell *cell = (BUYProductImageCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
BUYImageLink *image = self.product.images[indexPath.row];
NSURL *url = [NSURL URLWithString:image.src];
[cell.productImageView loadImageWithURL:url completion:NULL];
[cell setContentOffset:self.productView.tableView.contentOffset];
return cell;
}
- (void)presentPortraitInViewController:(UIViewController *)controller
{
BUYNavigationController *navController = [[BUYNavigationController alloc] initWithRootViewController:self];
navController.modalPresentationStyle = [BUYPresentationControllerWithNavigationController adaptivePresentationStyle];
navController.navigationDelegate = self;
[navController setTheme:self.theme];
[controller presentViewController:navController animated:YES completion:nil];
}
@end
//
// BUYProductViewFooter.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import PassKit;
#import "BUYProductViewFooter.h"
#import "BUYTheme.h"
#import "BUYProductVariant.h"
#import "BUYTheme+Additions.h"
@interface BUYProductViewFooter ()
@property (nonatomic, strong) UIVisualEffectView *visualEffectView;
@property (nonatomic, strong) NSArray *checkoutLayoutConstraints;
@property (nonatomic, strong) NSArray *applePayLayoutConstraints;
@property (nonatomic, strong) BUYTheme *theme;
@end
@implementation BUYProductViewFooter
- (instancetype)initWithTheme:(BUYTheme *)theme showApplePaySetup:(BOOL)showApplePaySetup
{
self = [super init];
if (self) {
self.backgroundColor = [UIColor clearColor];
self.theme = theme;
self.visualEffectView = [[UIVisualEffectView alloc] initWithEffect:[theme blurEffect]];
self.visualEffectView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:self.visualEffectView];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_visualEffectView]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_visualEffectView)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_visualEffectView]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(_visualEffectView)]];
UIView *separatorLineView = [[UIView alloc] init];
separatorLineView.translatesAutoresizingMaskIntoConstraints = NO;
separatorLineView.backgroundColor = [theme separatorColor];
[self.visualEffectView.contentView addSubview:separatorLineView];
[self.visualEffectView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[separatorLineView]|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(separatorLineView)]];
[self.visualEffectView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[separatorLineView(lineHeight)]"
options:0
metrics:@{ @"lineHeight" : @([[UIScreen mainScreen] scale] / 4) }
views:NSDictionaryOfVariableBindings(separatorLineView)]];
self.checkoutButton = [BUYCheckoutButton buttonWithType:UIButtonTypeCustom];
self.checkoutButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.checkoutButton setTheme:self.theme];
[self.checkoutButton setTitle:@"Checkout" forState:UIControlStateNormal];
self.checkoutButton.layer.cornerRadius = 5;
[self.visualEffectView.contentView addSubview:self.checkoutButton];
BUYPaymentButtonType buttonType = showApplePaySetup ? BUYPaymentButtonTypeSetup : BUYPaymentButtonTypeBuy;
self.buyPaymentButton = [BUYPaymentButton buttonWithType:buttonType style:[self.theme paymentButtonStyle]];
self.buyPaymentButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.visualEffectView.contentView addSubview:self.buyPaymentButton];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_checkoutButton, _buyPaymentButton);
self.applePayLayoutConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_checkoutButton]-[_buyPaymentButton(==_checkoutButton)]-|"
options:0
metrics:nil
views:viewsDictionary];
[self addConstraints:self.applePayLayoutConstraints];
[NSLayoutConstraint deactivateConstraints:self.applePayLayoutConstraints];
self.checkoutLayoutConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[_checkoutButton]-|"
options:0
metrics:nil
views:viewsDictionary];
[self addConstraints:self.checkoutLayoutConstraints];
[NSLayoutConstraint deactivateConstraints:self.checkoutLayoutConstraints];
NSDictionary *metricsDictionary = @{ @"buttonHeight" : @(kBuyCheckoutButtonHeight) };
[self.visualEffectView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_checkoutButton(buttonHeight)]-|"
options:0
metrics:metricsDictionary
views:viewsDictionary]];
[self.visualEffectView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[_buyPaymentButton(==_checkoutButton)]-|"
options:0
metrics:nil
views:viewsDictionary]];
}
return self;
}
- (void)setApplePayButtonVisible:(BOOL)isApplePayAvailable
{
self.buyPaymentButton.hidden = !isApplePayAvailable;
if (isApplePayAvailable) {
[NSLayoutConstraint deactivateConstraints:self.checkoutLayoutConstraints];
[NSLayoutConstraint activateConstraints:self.applePayLayoutConstraints];
} else {
[NSLayoutConstraint deactivateConstraints:self.applePayLayoutConstraints];
[NSLayoutConstraint activateConstraints:self.checkoutLayoutConstraints];
}
}
- (void)tintColorDidChange
{
[super tintColorDidChange];
self.checkoutButton.backgroundColor = self.tintColor;
}
- (void)updateButtonsForProductVariant:(BUYProductVariant *)productVariant {
self.checkoutButton.enabled = productVariant.available;
self.checkoutButton.alpha = productVariant.available ? 1.0f : 0.5f;
self.buyPaymentButton.enabled = productVariant.available;
self.buyPaymentButton.alpha = productVariant.available ? 1.0f : 0.5f;
}
@end
......@@ -73,10 +73,6 @@
#import "BUYPaymentToken.h"
#import "BUYPaymentButton.h"
#import "BUYProductViewController.h"
#import "BUYStoreViewController.h"
#import "BUYTheme.h"
#import "BUYViewController.h"
#import "NSArray+BUYAdditions.h"
#import "NSDateFormatter+BUYAdditions.h"
......
//
// BUYStoreController.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import WebKit;
#import "BUYLineItem.h"
#import "BUYProduct.h"
#import "BUYProductVariant.h"
#import "BUYStoreViewController.h"
#import "BUYError.h"
#import "BUYOrder.h"
#import "BUYShopifyErrorCodes.h"
@interface BUYStoreViewController () <WKNavigationDelegate, WKScriptMessageHandler>
@end
@implementation BUYStoreViewController {
NSURL *_url;
WKWebView *_webView;
UIBarButtonItem *_backButton;
UIBarButtonItem *_forwardButton;
BOOL _skippingAppCheckout;
NSURLRequest *_checkoutRequest;
}
@dynamic delegate;
- (instancetype)initWithClient:(BUYClient *)client url:(NSURL *)url
{
self = [super initWithClient:client];
if (self) {
_url = url;
}
return self;
}
- (instancetype)initWithClient:(BUYClient *)client
{
self = [super initWithClient:client];
if (self) {
_url = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@", client.shopDomain]];
}
return self;
}
- (void)loadView
{
WKWebViewConfiguration *configuration = [self webViewConfiguration];
_webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
_webView.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
_webView.navigationDelegate = self;
self.view = _webView;
_backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back"] style:UIBarButtonItemStylePlain target:_webView action:@selector(goBack)];
_forwardButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"forward"] style:UIBarButtonItemStylePlain target:_webView action:@selector(goForward)];
UIBarButtonItem *shareButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(shareTapped)];
UIBarButtonItem *flexible = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
self.toolbarItems = @[_backButton, flexible, _forwardButton, flexible, shareButton, flexible, flexible, flexible];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[_webView loadRequest:[NSURLRequest requestWithURL:_url]];
[self updateButtons];
}
#pragma mark - Button Presses
- (void)updateButtons
{
_backButton.enabled = [_webView canGoBack];
_forwardButton.enabled = [_webView canGoForward];
}
- (void)shareTapped
{
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[_webView.URL] applicationActivities:nil];
activityViewController.excludedActivityTypes = @[UIActivityTypeAddToReadingList, UIActivityTypeAssignToContact, UIActivityTypePrint, UIActivityTypeSaveToCameraRoll];
[self presentViewController:activityViewController animated:YES completion:nil];
}
#pragma mark - Web View Navigation Delegate Methods
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSString *currentUrlString = [[[navigationAction request] URL] absoluteString];
BOOL checkoutLink = [currentUrlString containsString:@"/checkout"] || [currentUrlString containsString:@"/sessions"];
BOOL thankYouPage = [currentUrlString containsString:@"thank_you"];
if (checkoutLink && thankYouPage == NO) {
if (_skippingAppCheckout) {
decisionHandler(WKNavigationActionPolicyAllow);
}
else {
decisionHandler(WKNavigationActionPolicyCancel);
[self presentCheckoutMethodSelectionMenuWithCheckoutRequest:[navigationAction request]];
}
}
else {
_skippingAppCheckout = NO;
decisionHandler(WKNavigationActionPolicyAllow);
}
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
[self updateButtons];
}
- (void)reloadHomePage
{
[_webView loadRequest:[NSURLRequest requestWithURL:_url]];
}
#pragma mark - Checkout Methods
- (void)presentCheckoutMethodSelectionMenuWithCheckoutRequest:(NSURLRequest *)request
{
_checkoutRequest = request;
if ([self.delegate respondsToSelector:@selector(controller:shouldProceedWithCheckoutType:)]) {
[self.delegate controller:self shouldProceedWithCheckoutType:^(BUYCheckoutType type) {
switch (type) {
case BUYCheckoutTypeNormal:
[self checkoutWithNormalCheckout];
break;
case BUYCheckoutTypeApplePay:
[self checkoutWithApplePay];
break;
default:
break;
}
}];
}
else {
[self checkoutWithNormalCheckout];
}
}
- (void)getProduct:(NSString *)productId withVariantId:(NSString *)variantId completion:(void (^)(BUYProductVariant *variant, NSError *error))completion;
{
[self.client getProductById:productId completion:^(BUYProduct *product, NSError *error) {
BUYProductVariant *selectedVariant = nil;
if (error == nil) {
for (BUYProductVariant *variant in product.variants) {
if ([variant.identifier isEqual:@([variantId longLongValue])]) {
selectedVariant = variant;
break;
}
}
}
else {
NSLog(@"Failed to fetch variant: %@", error);
}
completion(selectedVariant, error);
}];
}
#pragma mark - Checkout Selection Delegate Methods
- (void)checkoutWithApplePay
{
[_webView evaluateJavaScript:@"\
var cartRequest = new XMLHttpRequest();\
cartRequest.open(\"GET\", \"/cart.json\", false);\
cartRequest.onreadystatechange = function() {\
if (cartRequest.readyState == 4 && cartRequest.status == 200) {\
window.webkit.messageHandlers.nativeApp.postMessage(JSON.parse(cartRequest.responseText));\
}\
};\
cartRequest.send(null);"
completionHandler:^(id response, NSError *error) {
}];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
NSDictionary *json = message.body;
NSString *cartToken = json[@"token"];
if (cartToken) {
[self startCheckoutWithCartToken:cartToken];
}
else {
NSError *error = [NSError errorWithDomain:BUYShopifyError code:BUYShopifyError_CartFetchError userInfo:nil];
[self.delegate controller:self failedToCreateCheckout:error];
}
}
- (void)checkoutWithNormalCheckout
{
_skippingAppCheckout = YES;
[_webView loadRequest:_checkoutRequest];
}
#pragma mark - Checkout Completion Handling
- (void)checkoutCompleted:(BUYCheckout *)checkout status:(BUYStatus)status
{
if (status == BUYStatusComplete) {
[self.client getCheckout:checkout completion:^(BUYCheckout *updatedCheckout, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (updatedCheckout.order.statusURL) {
[_webView loadRequest:[NSURLRequest requestWithURL:updatedCheckout.order.statusURL]];
}
else {
NSLog(@"Couldn't redirect to thank you page: %@ (url: %@)", updatedCheckout, updatedCheckout.order.statusURL);
}
});
}];
}
else {
NSError *error = [NSError errorWithDomain:BUYShopifyError code:status userInfo:@{@"checkout": checkout}];
[self.delegate controller:self failedToCompleteCheckout:checkout withError:error];
}
}
#pragma mark - Web View Configuration
- (WKWebViewConfiguration *)webViewConfiguration
{
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = [self userContentConfiguration];
configuration.processPool = [self processPool];
return configuration;
}
- (WKProcessPool *)processPool
{
static WKProcessPool *pool = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
pool = [[WKProcessPool alloc] init];
});
return pool;
}
- (WKUserContentController *)userContentConfiguration
{
//Register our native bridge
WKUserContentController *contentController = [WKUserContentController new];
[contentController addScriptMessageHandler:self name:@"nativeApp"];
return contentController;
}
@end
//
// BUYViewController.m
// Mobile Buy SDK
//
// Created by Shopify.
// Copyright (c) 2015 Shopify Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
@import AddressBook;
@import PassKit;
@import SafariServices;
#import "BUYApplePayAdditions.h"
#import "BUYCart.h"
#import "BUYClient.h"
#import "BUYViewController.h"
#import "BUYApplePayHelpers.h"
#import "BUYDiscount.h"
#import "BUYShop.h"
#import "BUYWebCheckoutPaymentProvider.h"
@interface BUYViewController () <SFSafariViewControllerDelegate>
@property (nonatomic, strong) BUYCheckout *checkout;
@property (nonatomic, strong) BUYApplePayHelpers *applePayHelper;
@property (nonatomic, assign) BOOL isLoadingShop;
@property (nonatomic, assign) PKPaymentAuthorizationStatus paymentAuthorizationStatus;
@end
@implementation BUYViewController
@synthesize client = _client;
- (instancetype)initWithClient:(BUYClient *)client
{
self = [super init];
if (self) {
self.client = client;
}
return self;
}
- (void)setClient:(BUYClient *)client
{
_client = client;
if (&PKPaymentNetworkDiscover != NULL) {
self.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa, PKPaymentNetworkDiscover];
} else {
self.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa];
}
}
- (BUYClient*)client
{
if (_client == nil) {
NSLog(@"`BUYClient` has not been initialized. Please initialize BUYViewController with `initWithClient:` or set a `BUYClient` after Storyboard initialization");
}
return _client;
}
- (void)loadShopWithCallback:(void (^)(BOOL, NSError *))block
{
// fetch shop details for the currency and country codes
self.isLoadingShop = YES;
[self.client getShop:^(BUYShop *shop, NSError *error) {
if (error == nil) {
self.shop = shop;
}
self.isLoadingShop = NO;
if (block) block((error == nil), error);
}];
}
- (BOOL)canShowApplePaySetup
{
PKPassLibrary *passLibrary = [[PKPassLibrary alloc] init];
if (self.allowApplePaySetup == YES &&
// Check that it's running iOS 9.0 or above
[passLibrary respondsToSelector:@selector(canAddPaymentPassWithPrimaryAccountIdentifier:)] &&
// Check if the device can add a payment pass
[PKPaymentAuthorizationViewController canMakePayments] &&
// Check that Apple Pay is enabled for the merchant
[self.merchantId length]) {
return YES;
} else {
return NO;
}
}
- (BOOL)isApplePayAvailable
{
// checks if the client is setup to use Apple Pay
// checks if device hardware is capable of using Apple Pay
// checks if the device has a payment card setup
return (self.merchantId.length &&
[PKPaymentAuthorizationViewController canMakePayments] &&
[PKPaymentAuthorizationViewController canMakePaymentsUsingNetworks:self.supportedNetworks]);
}
- (BOOL)shouldShowApplePayButton {
return self.isApplePayAvailable || [self canShowApplePaySetup];
}
- (BOOL)shouldShowApplePaySetup
{
return self.isApplePayAvailable == NO && [self canShowApplePaySetup];
}
#pragma mark - Checkout Flow Methods
#pragma mark - Step 1 - Creating or updating a Checkout
- (void)startApplePayCheckout:(BUYCheckout *)checkout
{
// Default to the failure state, since cancelling a payment would not update the state and thus appear as a success
self.paymentAuthorizationStatus = PKPaymentAuthorizationStatusFailure;
/**
* To perform an Apple Pay checkout, we need both the BUYShop object, and a BUYCheckout
* We will download both in parallel, and continue with the checkout when they both succeed
*/
dispatch_group_t group = dispatch_group_create();
__block NSError *checkoutError = nil;
// download the shop
if (self.shop == nil) {
dispatch_group_enter(group);
[self loadShopWithCallback:^(BOOL success, NSError *error) {
if (error) {
checkoutError = error;
if ([self.delegate respondsToSelector:@selector(controllerFailedToStartApplePayProcess:)]) {
[self.delegate controllerFailedToStartApplePayProcess:self];
}
}
dispatch_group_leave(group);
}];
}
// create the checkout on Shopify
dispatch_group_enter(group);
[self handleCheckout:checkout completion:^(BUYCheckout *checkout, NSError *error) {
if (error) {
checkoutError = error;
if ([self.delegate respondsToSelector:@selector(controller:failedToCreateCheckout:)]) {
[self.delegate controller:self failedToCreateCheckout:error];
}
}
else {
self.checkout = checkout;
}
dispatch_group_leave(group);
}];
// When we have both the shop and checkout, we can request the payment with Apple Pay
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
if (self.checkout && self.shop) {
if ([self.delegate respondsToSelector:@selector(controllerWillCheckoutViaApplePay:)]) {
[self.delegate controllerWillCheckoutViaApplePay:self];
}
self.applePayHelper = [[BUYApplePayHelpers alloc] initWithClient:self.client checkout:self.checkout shop:self.shop];
[self requestPayment];
}
else {
if ([self.delegate respondsToSelector:@selector(controller:failedToCreateCheckout:)]) {
[self.delegate controller:self failedToCreateCheckout:checkoutError];
}
}
});
}
- (void)startWebCheckout:(BUYCheckout *)checkout
{
[self handleCheckout:checkout completion:^(BUYCheckout *checkout, NSError *error) {
[self postCheckoutCompletion:checkout error:error];
}];
}
- (void)postCheckoutCompletion:(BUYCheckout *)checkout error:(NSError *)error
{
if (error == nil) {
self.checkout = checkout;
if ([self.delegate respondsToSelector:@selector(controllerWillCheckoutViaWeb:)]) {
[self.delegate controllerWillCheckoutViaWeb:self];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveCallbackURLNotification:) name:BUYSafariCallbackURLNotification object:nil];
[self openWebCheckout:checkout];
}
else {
if ([self.delegate respondsToSelector:@selector(controller:failedToCreateCheckout:)]) {
[self.delegate controller:self failedToCreateCheckout:error];
}
}
}
- (void)handleCheckout:(BUYCheckout *)checkout completion:(BUYDataCheckoutBlock)completion
{
if ([checkout.token length] > 0) {
[self.client updateCheckout:checkout completion:completion];
} else {
[self.client createCheckout:checkout completion:completion];
}
}
#pragma mark - Alternative Step 1 - Creating a Checkout using a Cart Token
- (void)startCheckoutWithCartToken:(NSString *)token
{
[self.client createCheckoutWithCartToken:token completion:^(BUYCheckout *checkout, NSError *error) {
self.applePayHelper = [[BUYApplePayHelpers alloc] initWithClient:self.client checkout:checkout];
[self handleCheckoutCompletion:checkout error:error];
}];
}
- (void)handleCheckoutCompletion:(BUYCheckout *)checkout error:(NSError *)error
{
if (checkout && error == nil) {
self.checkout = checkout;
[self requestPayment];
}
else {
if ([self.delegate respondsToSelector:@selector(controller:failedToCreateCheckout:)]) {
[self.delegate controller:self failedToCreateCheckout:error];
}
}
}
#pragma mark - Web Checkout
- (void)openWebCheckout:(BUYCheckout *)checkout
{
if ([SFSafariViewController class]) {
SFSafariViewController *safariViewController = [[SFSafariViewController alloc] initWithURL:checkout.webCheckoutURL];
safariViewController.delegate = self;
[self presentViewController:safariViewController animated:YES completion:nil];
}
else {
[[UIApplication sharedApplication] openURL:checkout.webCheckoutURL];
}
}
#pragma mark - Step 2 - Requesting Payment using Apple Pay
- (void)requestPayment
{
//Step 2 - Request payment from the user by presenting an Apple Pay sheet
if (self.merchantId.length == 0) {
NSLog(@"Merchant ID must be configured to use Apple Pay");
if ([self.delegate respondsToSelector:@selector(controllerFailedToStartApplePayProcess:)]) {
[self.delegate controllerFailedToStartApplePayProcess:self];
}
return;
}
if (self.shop == nil) {
NSLog(@"loadShopWithCallback: must be called before starting an Apple Pay checkout");
if ([self.delegate respondsToSelector:@selector(controllerFailedToStartApplePayProcess:)]) {
[self.delegate controllerFailedToStartApplePayProcess:self];
}
return;
}
PKPaymentRequest *request = [self paymentRequest];
request.paymentSummaryItems = [self.checkout buy_summaryItemsWithShopName:self.shop.name];
PKPaymentAuthorizationViewController *controller = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request];
if (controller) {
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
else {
if ([self.delegate respondsToSelector:@selector(controllerFailedToStartApplePayProcess:)]) {
[self.delegate controllerFailedToStartApplePayProcess:self];
}
}
}
- (void)checkoutCompleted:(BUYCheckout *)checkout status:(BUYStatus)status
{
if ([self.delegate respondsToSelector:@selector(controller:didCompleteCheckout:status:)]) {
[self.delegate controller:self didCompleteCheckout:checkout status:status];
}
}
#pragma mark - PKPaymentAuthorizationViewControllerDelegate Methods
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didAuthorizePayment:(PKPayment *)payment completion:(void (^)(PKPaymentAuthorizationStatus status))completion
{
[self.applePayHelper paymentAuthorizationViewController:controller didAuthorizePayment:payment completion:^(PKPaymentAuthorizationStatus status) {
self.paymentAuthorizationStatus = status;
switch (status) {
case PKPaymentAuthorizationStatusFailure:
if ([self.delegate respondsToSelector:@selector(controller:failedToCompleteCheckout:withError:)]) {
[self.delegate controller:self failedToCompleteCheckout:self.checkout withError:self.applePayHelper.lastError];
}
break;
case PKPaymentAuthorizationStatusInvalidShippingPostalAddress:
if ([self.delegate respondsToSelector:@selector(controller:failedToUpdateCheckout:withError:)]) {
[self.delegate controller:self failedToUpdateCheckout:self.checkout withError:self.applePayHelper.lastError];
}
break;
default: {
if ([self.delegate respondsToSelector:@selector(controller:didCompleteCheckout:status:)]) {
BUYStatus buyStatus = (status == PKPaymentAuthorizationStatusSuccess) ? BUYStatusComplete : BUYStatusFailed;
[self.delegate controller:self didCompleteCheckout:self.checkout status:buyStatus];
}
}
break;
}
completion(status);
}];
}
- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller
{
// The checkout is done at this point, it may have succeeded or failed. You are responsible for dealing with failure/success earlier in the steps.
[self dismissViewControllerAnimated:YES completion:^{
// If Apple Pay is dismissed with Cancel we need to clear the reservation time on the products in the checkout
if (self.paymentAuthorizationStatus != PKPaymentAuthorizationStatusSuccess) {
[self.client removeProductReservationsFromCheckout:self.checkout completion:^(BUYCheckout *checkout, NSError *error) {
self.checkout = checkout;
if ([self.delegate respondsToSelector:@selector(controller:didDismissApplePayControllerWithStatus:forCheckout:)]) {
[self.delegate controller:self didDismissApplePayControllerWithStatus:self.paymentAuthorizationStatus forCheckout:self.checkout];
}
}];
} else {
if ([self.delegate respondsToSelector:@selector(controller:didDismissApplePayControllerWithStatus:forCheckout:)]) {
[self.delegate controller:self didDismissApplePayControllerWithStatus:self.paymentAuthorizationStatus forCheckout:self.checkout];
}
}
}];
}
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingMethod:(nonnull PKShippingMethod *)shippingMethod completion:(nonnull void (^)(PKPaymentAuthorizationStatus, NSArray<PKPaymentSummaryItem *> * _Nonnull))completion
{
[self.applePayHelper paymentAuthorizationViewController:controller didSelectShippingMethod:shippingMethod completion:^(PKPaymentAuthorizationStatus status, NSArray<PKPaymentSummaryItem *> * _Nonnull summaryItems) {
if (status == PKPaymentAuthorizationStatusInvalidShippingPostalAddress) {
if ([self.delegate respondsToSelector:@selector(controller:failedToGetShippingRates:withError:)]) {
[self.delegate controller:self failedToGetShippingRates:self.checkout withError:self.applePayHelper.lastError];
}
}
completion(status, summaryItems);
}];
}
-(void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingAddress:(ABRecordRef)address completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<PKShippingMethod *> * _Nonnull, NSArray<PKPaymentSummaryItem *> * _Nonnull))completion
{
[self.applePayHelper paymentAuthorizationViewController:controller didSelectShippingAddress:address completion:^(PKPaymentAuthorizationStatus status, NSArray<PKShippingMethod *> * _Nonnull shippingMethods, NSArray<PKPaymentSummaryItem *> * _Nonnull summaryItems) {
if (status == PKPaymentAuthorizationStatusInvalidShippingPostalAddress) {
if ([self.delegate respondsToSelector:@selector(controller:failedToUpdateCheckout:withError:)]) {
[self.delegate controller:self failedToUpdateCheckout:self.checkout withError:self.applePayHelper.lastError];
}
}
completion(status, shippingMethods, summaryItems);
}];
}
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller didSelectShippingContact:(PKContact *)contact completion:(void (^)(PKPaymentAuthorizationStatus, NSArray<PKShippingMethod *> * _Nonnull, NSArray<PKPaymentSummaryItem *> * _Nonnull))completion
{
[self.applePayHelper paymentAuthorizationViewController:controller didSelectShippingContact:contact completion:^(PKPaymentAuthorizationStatus status, NSArray<PKShippingMethod *> * _Nonnull shippingMethods, NSArray<PKPaymentSummaryItem *> * _Nonnull summaryItems) {
if (status == PKPaymentAuthorizationStatusInvalidShippingPostalAddress) {
if ([self.delegate respondsToSelector:@selector(controller:failedToUpdateCheckout:withError:)]) {
[self.delegate controller:self failedToUpdateCheckout:self.checkout withError:self.applePayHelper.lastError];
}
}
completion(status, shippingMethods, summaryItems);
}];
}
#pragma mark - Helpers
- (PKPaymentRequest *)paymentRequest
{
PKPaymentRequest *paymentRequest = [[PKPaymentRequest alloc] init];
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
NSString *merchantId = self.client.merchantId ? : self.merchantId;
#pragma GCC diagnostic pop
[paymentRequest setMerchantIdentifier:merchantId];
[paymentRequest setRequiredBillingAddressFields:PKAddressFieldAll];
[paymentRequest setRequiredShippingAddressFields:self.checkout.requiresShipping ? PKAddressFieldAll : PKAddressFieldEmail|PKAddressFieldPhone];
[paymentRequest setSupportedNetworks:self.supportedNetworks];
[paymentRequest setMerchantCapabilities:PKMerchantCapability3DS];
[paymentRequest setCountryCode:self.shop.country];
[paymentRequest setCurrencyCode:self.shop.currency];
return paymentRequest;
}
#pragma mark - Web Checkout delegate methods
- (void)safariViewControllerDidFinish:(SFSafariViewController *)controller;
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:BUYSafariCallbackURLNotification object:nil];
if ([self.delegate respondsToSelector:@selector(controller:didDismissWebCheckout:)]) {
[self.delegate controller:self didDismissWebCheckout:self.checkout];
}
}
- (void)didReceiveCallbackURLNotification:(NSNotification *)notification
{
NSURL *url = notification.userInfo[BUYURLKey];
[self.client getCompletionStatusOfCheckoutURL:url completion:^(BUYStatus status, NSError *error) {
[self checkoutCompleted:_checkout status:status];
[[NSNotificationCenter defaultCenter] removeObserver:self name:BUYSafariCallbackURLNotification object:nil];
}];
if (self.presentedViewController) {
[self dismissViewControllerAnimated:YES completion:nil];
}
}
+ (void)completeCheckoutFromLaunchURL:(NSURL *)url
{
[[NSNotificationCenter defaultCenter] postNotificationName:BUYSafariCallbackURLNotification object:nil userInfo:@{BUYURLKey: url}];
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment