Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 26 additions & 28 deletions dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,22 +162,22 @@ commands:
desc: "Apollo GraphQL schema and code generation commands"
subcommands:
download_schema:
desc: "Download GraphQL schema. Usage: dev apollo download_schema <android|swift> [accelerated|swift|all]"
syntax: "<android|swift> [accelerated|swift|all]"
desc: "Download GraphQL schema. Usage: dev apollo download_schema <android|swift> [swift|all]"
syntax: "<android|swift> [swift|all]"
run: |
case "$1" in
android) cd platforms/android && ./scripts/apollo_download_schema ;;
swift) shift; cd platforms/swift && ./Scripts/apollo_download_schema "$@" ;;
*) echo "Usage: dev apollo download_schema <android|swift> [accelerated|swift|all]"; exit 1 ;;
*) echo "Usage: dev apollo download_schema <android|swift> [swift|all]"; exit 1 ;;
esac
codegen:
desc: "Generate Apollo models. Usage: dev apollo codegen <android|swift> [accelerated|swift|all]"
syntax: "<android|swift> [accelerated|swift|all]"
desc: "Generate Apollo models. Usage: dev apollo codegen <android|swift> [swift|all]"
syntax: "<android|swift> [swift|all]"
run: |
case "$1" in
android) cd platforms/android && ./scripts/apollo_codegen ;;
swift) shift; cd platforms/swift && ./Scripts/apollo_codegen "$@" ;;
*) echo "Usage: dev apollo codegen <android|swift> [accelerated|swift|all]"; exit 1 ;;
*) echo "Usage: dev apollo codegen <android|swift> [swift|all]"; exit 1 ;;
esac

# Protocol
Expand Down Expand Up @@ -435,21 +435,21 @@ commands:
desc: "Swift Checkout Kit commands"
subcommands:
build:
desc: Build all Swift packages and sample apps
desc: Build all Swift packages and the sample app
run: |
set -e
cd platforms/swift
# ShopifyCheckoutKit-Package builds every library target in
# Package.swift in one xcodebuild invocation. The sample apps act as
# integration compilation checks against the built libraries.
# Package.swift in one xcodebuild invocation. The sample app acts as
# an integration compilation check against the built libraries.
./Scripts/xcode_run build ShopifyCheckoutKit-Package
./Scripts/build_samples
subcommands:
packages:
desc: Build Swift package targets
run: cd platforms/swift && ./Scripts/xcode_run build ShopifyCheckoutKit-Package
samples:
desc: Build all sample applications to verify integration
desc: Build the sample application to verify integration
run: cd platforms/swift && ./Scripts/build_samples

start:
Expand All @@ -474,10 +474,10 @@ commands:
fi

DERIVED_DATA="$PWD/../../.build/swift-start-simulator"
cd Samples
cd Samples/CheckoutKitSwiftDemo
build_command=(
xcodebuild build
-workspace Samples.xcworkspace
-project CheckoutKitSwiftDemo.xcodeproj
-scheme CheckoutKitSwiftDemo
-sdk iphonesimulator
-destination "id=$DEVICE_ID"
Expand Down Expand Up @@ -538,9 +538,9 @@ commands:

test:
desc: |
`dev swift test` - Run all tests for the ShopifyCheckoutKit-Package and the sample apps.
`dev swift test` - Run all tests for the ShopifyCheckoutKit-Package and sample app.
`dev swift test <test_class_name>` - Run only the specified package test class.
`dev swift test sample [test_class_name]` - Run only the sample app test targets.
`dev swift test sample [test_class_name]` - Run only the sample app test target.
syntax: "[test_class_name]"
run: |
set -e
Expand All @@ -553,7 +553,7 @@ commands:
fi
subcommands:
sample:
desc: Run the sample app test targets
desc: Run the sample app test target
syntax: "[test_class_name]"
run: cd platforms/swift && ./Scripts/test_samples "${1:-}"
api:
Expand Down Expand Up @@ -595,20 +595,18 @@ commands:
# library targets in Package.swift (ShopifyCheckoutKit,
# ShopifyAcceleratedCheckouts, EmbeddedCheckoutProtocol) in one pass.
./Scripts/xcode_run clean ShopifyCheckoutKit-Package
cd Samples
# Sample apps have a "Run Script" build phase that runs during clean
# and exits non-zero when there is nothing to delete. Tolerate it so
# the second sample still gets cleaned.
../Scripts/xcode_run clean CheckoutKitSwiftDemo || true
../Scripts/xcode_run clean ShopifyAcceleratedCheckoutsApp || true
cd Samples/CheckoutKitSwiftDemo
# The sample app has a "Run Script" build phase that runs during clean
# and exits non-zero when there is nothing to delete.
../../Scripts/xcode_run clean CheckoutKitSwiftDemo || true

open:
desc: Open the Swift package or sample app in Xcode
long_desc: |
Opens a Swift workspace in Xcode via `xed`.
Opens the demo Xcode project by default, or the Swift package when requested.

dev swift open Open the demo app workspace (default)
dev swift open demo Open the demo app workspace (aliases: sample, samples)
dev swift open Open the demo app project (default)
dev swift open demo Open the demo app project (aliases: sample, samples)
dev swift open lib Open the ShopifyCheckoutKit Swift package (aliases: library, package, module)
syntax:
optional: "[lib|demo]"
Expand All @@ -621,17 +619,17 @@ commands:

case "${1:-demo}" in
demo|sample|samples)
platforms/swift/Scripts/generate_xcode_projects
workspace="platforms/swift/Samples/Samples.xcworkspace"
platforms/swift/Scripts/generate_xcode_projects --spec Samples/CheckoutKitSwiftDemo/project.yml
target="platforms/swift/Samples/CheckoutKitSwiftDemo/CheckoutKitSwiftDemo.xcodeproj"
;;
lib|library|package|module) workspace="platforms/swift" ;;
lib|library|package|module) target="platforms/swift" ;;
*)
echo "Usage: dev swift open [lib|demo]" >&2
exit 1
;;
esac

xed "$workspace"
xed "$target"

# React Native
react-native:
Expand Down
14 changes: 7 additions & 7 deletions e2e/bitrise.yml
Original file line number Diff line number Diff line change
Expand Up @@ -333,22 +333,22 @@ workflows:
- bundle::bootstrap-mint:
inputs:
- mintfile_dir: platforms/swift
# Both samples build the root package and Apollo iOS from source. Neither changes
# between most pull requests, so DerivedData carries that work across builds. The key
# holds the resolved dependency graph: a pin change rebuilds rather than reuses.
# Xcode's incremental build owns correctness for the source that did change.
# The sample builds the root package and Apollo iOS from source. Those dependencies
# do not change between most pull requests, so DerivedData carries that work across
# builds. The key holds the resolved dependency graph: a pin change rebuilds rather
# than reuses. Xcode's incremental build owns correctness for changed source.
- restore-cache@3:
inputs:
- key: &swift_samples_derived_data_cache_key |-
swift-samples-derived-data-{{ .OS }}-{{ .Arch }}-{{ checksum "Package.resolved" }}
swift-samples-derived-data-{{ .OS }}-{{ .Arch }}-{{ checksum "platforms/swift/Samples/CheckoutKitSwiftDemo/Package.resolved" }}
- script@1:
title: Build and test the Swift sample apps
title: Build and test the Swift sample app
timeout: 5400
no_output_timeout: 1800
inputs:
- content: |-
set -euo pipefail
# The samples only need a well-formed storefront configuration to compile,
# The sample only needs a well-formed storefront configuration to compile,
# so this job runs on placeholders rather than e2e_configure_storefront,
# which asserts the real secrets. Keeping it off them is what lets the job
# run on fork pull requests, where Bitrise withholds secrets.
Expand Down
8 changes: 4 additions & 4 deletions e2e/scripts/build_swift_ios
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ source "$script_dir/ios_build_helpers"

e2e_configure_storefront

e2e_log "Generating Swift sample Xcode projects"
e2e_log "Generating the Swift sample Xcode project"
platforms/swift/Scripts/generate_xcode_projects

cd platforms/swift/Samples

app_name="CheckoutKitSwiftDemo"
workspace="Samples.xcworkspace"
project="$app_name/$app_name.xcodeproj"
scheme="$app_name"

e2e_build_ios_device_ipa \
--workspace "$workspace" \
--project "$project" \
--scheme "$scheme" \
--app-name "$app_name" \
--bundle-id com.shopify.checkoutkit.swiftdemo \
Expand All @@ -34,7 +34,7 @@ simulator_app_zip="$e2e_dir/${app_name}-Simulator.zip"
# Builds the simulator app bundle that is zipped for Tophat simulator installs.
build_simulator_app() {
xcodebuild build \
-workspace "$workspace" \
-project "$project" \
-scheme "$scheme" \
-configuration Release \
-skipPackagePluginValidation \
Expand Down
4 changes: 2 additions & 2 deletions e2e/scripts/build_swift_ios_testflight
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ e2e_reject_ios_signing_overrides

e2e_configure_storefront

e2e_log "Generating Swift sample Xcode projects"
e2e_log "Generating the Swift sample Xcode project"
platforms/swift/Scripts/generate_xcode_projects

app_name="CheckoutKitSwiftDemo"
Expand All @@ -22,7 +22,7 @@ archive_path="$(e2e_deploy_dir)/${app_name}.xcarchive"
cd platforms/swift/Samples

e2e_build_ios_device_ipa \
--workspace Samples.xcworkspace \
--project "$app_name/$app_name.xcodeproj" \
--scheme "$app_name" \
--app-name "$app_name" \
--bundle-id com.shopify.checkoutkit.swiftdemo \
Expand Down
2 changes: 1 addition & 1 deletion e2e/scripts/run_local_e2e
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ build_and_install() {
"$ROOT_DIR/Scripts/generate_xcode_projects"
cd "$ROOT_DIR/Samples"
xcodebuild build \
-workspace Samples.xcworkspace \
-project "$APP_NAME/$APP_NAME.xcodeproj" \
-scheme "$APP_NAME" \
-sdk iphonesimulator \
-destination "id=$DEVICE_ID" \
Expand Down
1 change: 0 additions & 1 deletion platforms/swift/.swiftformat
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@
--exclude Sources/ShopifyCheckoutKit/Models.swift
--exclude Sources/UniversalCommerceProtocol/EmbeddedCheckoutProtocol/Generated
--exclude Samples/CheckoutKitSwiftDemo/CheckoutKitSwiftDemo/Sources/Generated
--exclude Samples/ShopifyAcceleratedCheckoutsApp/ShopifyAcceleratedCheckoutsApp/Generated
3 changes: 1 addition & 2 deletions platforms/swift/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,7 @@ Use `CheckoutProtocol.Client` through `.connect(client)` to observe checkout com

See [Samples](Samples/README.md):

- `CheckoutKitSwiftDemo` demonstrates a Storefront API cart flow, buyer identity modes, Customer Account API, checkout presentation, and protocol events.
- `ShopifyAcceleratedCheckoutsApp` demonstrates Shop Pay and Apple Pay accelerated checkout buttons.
- `CheckoutKitSwiftDemo` demonstrates a Storefront API cart flow, buyer identity modes, Customer Account API, checkout presentation, protocol events, and configurable Shop Pay and Apple Pay accelerated checkout buttons.

## Contributing

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import ShopifyAcceleratedCheckouts
import SwiftUI

struct AcceleratedCheckoutsConfiguredView<Content: View>: View {
let content: Content

@AppStorage(AppStorageKeys.requireEmail.rawValue)
private var requireEmail = true

@AppStorage(AppStorageKeys.requirePhone.rawValue)
private var requirePhone = true

@AppStorage(AppStorageKeys.locale.rawValue)
private var locale = "en"

@AppStorage(AppStorageKeys.email.rawValue)
private var email = ""

@AppStorage(AppStorageKeys.phone.rawValue)
private var phone = ""

@AppStorage(AppStorageKeys.supportedCountries.rawValue)
private var supportedCountriesString = ""

var body: some View {
if #available(iOS 16.0, *) {
content
.environment(
\.shopifyAcceleratedCheckoutsConfiguration,
ShopifyAcceleratedCheckouts.Configuration(
storefrontDomain: InfoDictionary.shared.domain,
storefrontAccessToken: InfoDictionary.shared.accessToken,
customer: customer
)
)
.environment(
\.shopifyApplePayConfiguration,
ShopifyAcceleratedCheckouts.ApplePayConfiguration(
merchantIdentifier: InfoDictionary.shared.merchantIdentifier,
contactFields: contactFields,
supportedShippingCountries: supportedCountries
)
)
.environment(\.locale, Locale(identifier: locale))
} else {
content
}
}

@available(iOS 16.0, *)
private var customer: ShopifyAcceleratedCheckouts.Customer? {
guard !email.isEmpty || !phone.isEmpty else { return nil }

return ShopifyAcceleratedCheckouts.Customer(
email: email.isEmpty ? nil : email,
phoneNumber: phone.isEmpty ? nil : phone
)
}

@available(iOS 16.0, *)
private var contactFields: [ShopifyAcceleratedCheckouts.RequiredContactFields] {
var fields: [ShopifyAcceleratedCheckouts.RequiredContactFields] = []

if requireEmail {
fields.append(.email)
}
if requirePhone {
fields.append(.phone)
}

return fields
}

@available(iOS 16.0, *)
private var supportedCountries: Set<String>? {
let countries = Set(
supportedCountriesString
.split(separator: ",")
.map(String.init)
.filter { !$0.isEmpty }
)
return countries.isEmpty ? nil : countries
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ShopifyAcceleratedCheckouts
import ShopifyCheckoutKit
import UIKit

Expand All @@ -21,6 +22,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
let checkoutKitLogLevel: LogLevel = getLogLevel(
key: AppStorageKeys.checkoutKitLogLevel.rawValue
)
let acceleratedCheckoutsLogLevel: LogLevel = getLogLevel(
key: AppStorageKeys.acceleratedCheckoutsLogLevel.rawValue
)
let checkoutPreloadingEnabled = UserDefaults.standard.object(
forKey: AppStorageKeys.checkoutPreloadingEnabled.rawValue
) as? Bool ?? true
Expand All @@ -32,8 +36,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
$0.logLevel = checkoutKitLogLevel
$0.preloading.enabled = checkoutPreloadingEnabled
}
ShopifyAcceleratedCheckouts.logLevel = acceleratedCheckoutsLogLevel

print("[CheckoutKitSwiftDemo] CheckoutKit Log level set to \(checkoutKitLogLevel)")
print(
"[CheckoutKitSwiftDemo] Accelerated Checkouts Log level set to \(acceleratedCheckoutsLogLevel)"
)

UIBarButtonItem.appearance().tintColor = ColorPalette.primaryColor

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var cancellables: Set<AnyCancellable> = []

let uiKitCartController = CartViewController()
let swiftUICartController = UIHostingController(rootView: CartView())
let productGridController = UIHostingController(rootView: ProductGridView())
let productGalleryController = UIHostingController(rootView: ProductGalleryView())
let swiftUICartController = UIHostingController(
rootView: AcceleratedCheckoutsConfiguredView(content: CartView())
)
let productGridController = UIHostingController(
rootView: AcceleratedCheckoutsConfiguredView(content: ProductGridView())
)
let productGalleryController = UIHostingController(
rootView: AcceleratedCheckoutsConfiguredView(content: ProductGalleryView())
)
let accountController = UIHostingController(rootView: AccountView())
let settingsController = UIHostingController(rootView: SettingsView())

Expand Down
Loading
Loading