From 4183918f7eb88ffb5c2b55c47fd759c9a802ec6a Mon Sep 17 00:00:00 2001 From: Louis Bur Date: Thu, 7 Mar 2024 10:43:43 -0400 Subject: [PATCH] Version 8.1.0 --- .github/assets/logo-dark.png | Bin 5947 -> 16236 bytes .github/assets/logo-light.png | Bin 5947 -> 16531 bytes BrazeKit.podspec | 6 +- BrazeKitCompat.podspec | 8 +- BrazeLocation.podspec | 8 +- BrazeNotificationService.podspec | 6 +- BrazePushStory.podspec | 6 +- BrazeUI.podspec | 6 +- BrazeUICompat.podspec | 8 +- CHANGELOG.md | 23 ++++ .../project.pbxproj | 2 +- Examples/ObjC/Podfile | 68 +++++------ Examples/ObjC/manual-integration-setup.sh | 2 +- .../project.pbxproj | 2 +- Examples/Swift/Podfile | 68 +++++------ .../InAppMessages-Custom-UI/Extensions.swift | 8 +- Examples/Swift/manual-integration-setup.sh | 2 +- LICENSE | 2 +- Package.swift | 18 +-- README.md | 2 +- .../BrazeKitResources/Resources/braze.license | 2 +- .../Cells/ContentCardUICell.swift | 2 +- .../Cells/ContentCardUITextStack.swift | 7 +- .../ContentCardUIViewController.swift | 11 -- .../BrazeUI/Dependencies/AsyncImageView.swift | 2 +- Sources/BrazeUI/Dependencies/Localize.swift | 3 +- Sources/BrazeUI/Deprecations.swift | 10 ++ .../InAppMessageUI/InAppMessageExt.swift | 8 -- .../InAppMessageUIViewController.swift | 2 - .../Views/InAppMessageUIHtmlView.swift | 25 ++-- .../Views/InAppMessageUIModalImageView.swift | 7 +- .../Views/InAppMessageUISlideupView.swift | 2 +- .../InAppMessageUI/Views/Misc/IconView.swift | 3 +- Sources/BrazeUI/Resources.swift | 113 +++++++++++------- 34 files changed, 225 insertions(+), 217 deletions(-) diff --git a/.github/assets/logo-dark.png b/.github/assets/logo-dark.png index b1aa7416a258fecd667895a041429045b9ca0f8e..2c01e0b933f4184b65b73cdd6d46cec46d43855e 100644 GIT binary patch literal 16236 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 NkQ9{@sTDE^{6A6-?V|ty literal 5947 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 V50%A;|HauD5U`d~wSran{{YHzi0l9W diff --git a/.github/assets/logo-light.png b/.github/assets/logo-light.png index 14b1b02e8d682423df6e4b1d4dba4c9fad4b6195..dabfeecfcddc63f9058e14c073274617458480a6 100644 GIT binary patch literal 16531 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

wO^D64o@8` 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 literal 5947 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 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazeKit.zip', - :sha256 => '8ba73f7f193f4ea52d8673535b12c224cfb16bfcc1683e52a0c267addce2beb7' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazeKit.zip', + :sha256 => 'd33cb483bb4ed954baaf61621efcb3aab48e41af21d11a4c04ac41575c22c567' } s.swift_version = '5.0' diff --git a/BrazeKitCompat.podspec b/BrazeKitCompat.podspec index bb875d9ca4..706c97a3bb 100644 --- a/BrazeKitCompat.podspec +++ b/BrazeKitCompat.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeKitCompat' - s.version = '8.0.1' + s.version = '8.1.0' s.summary = 'Compatibility library for users migrating from AppboyKit.' s.homepage = 'https://braze.com' @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.license = { :type => 'Commercial' } s.authors = 'Braze, Inc.' - s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '8.0.1' } + s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '8.1.0' } s.swift_version = '5.0' s.ios.deployment_target = '12.0' @@ -18,8 +18,8 @@ Pod::Spec.new do |s| s.public_header_files = 'Sources/BrazeKitCompat/include/*.h' s.static_framework = true - s.dependency 'BrazeKit', '8.0.1' - s.dependency 'BrazeLocation', '8.0.1' + s.dependency 'BrazeKit', '8.1.0' + s.dependency 'BrazeLocation', '8.1.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } end diff --git a/BrazeLocation.podspec b/BrazeLocation.podspec index 47cfa2d9cd..ccae4bbb69 100644 --- a/BrazeLocation.podspec +++ b/BrazeLocation.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeLocation' - s.version = '8.0.1' + s.version = '8.1.0' s.summary = 'Braze location library providing support for location analytics and geofence monitoring.' s.homepage = 'https://braze.com' @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.authors = 'Braze, Inc.' s.source = { - :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazeLocation.zip', - :sha256 => '22753521e3cebbd1ec0b0986339b10b03f00a3258ecf4c209066de575b98d630' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazeLocation.zip', + :sha256 => '63b18e6ff1c579b0d8687181c6b6b82f2861cd4824a7f1d7df8e632a1e0fbb42' } s.swift_version = '5.0' @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.vendored_framework = 'BrazeLocation.xcframework' s.resource_bundles = { 'BrazeLocation' => ['Sources/BrazeLocationResources/Resources/**/*'] } - s.dependency 'BrazeKit', '8.0.1' + s.dependency 'BrazeKit', '8.1.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } end diff --git a/BrazeNotificationService.podspec b/BrazeNotificationService.podspec index b3e258bffe..a70e714c34 100644 --- a/BrazeNotificationService.podspec +++ b/BrazeNotificationService.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeNotificationService' - s.version = '8.0.1' + s.version = '8.1.0' s.summary = 'Braze notification service extension library providing support for Rich Push notifications.' s.homepage = 'https://braze.com' @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.authors = 'Braze, Inc.' s.source = { - :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazeNotificationService.zip', - :sha256 => '5c17a259982cea0aaa06ee59ef64f52f0fb0325bdd973d7ccfe954babd9179e2' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazeNotificationService.zip', + :sha256 => 'fac7499f1baa938e4ea19fe18f5b13d3ab92369294bdf96c4738115bbcc09341' } s.swift_version = '5.0' diff --git a/BrazePushStory.podspec b/BrazePushStory.podspec index 20ddc96439..7b7611a0ee 100644 --- a/BrazePushStory.podspec +++ b/BrazePushStory.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazePushStory' - s.version = '8.0.1' + s.version = '8.1.0' s.summary = 'Braze notification content extension library providing support for Push Stories.' s.homepage = 'https://braze.com' @@ -9,8 +9,8 @@ Pod::Spec.new do |s| s.authors = 'Braze, Inc.' s.source = { - :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazePushStory.zip', - :sha256 => 'ce056068074e29b218eda70c1dbf60d942905e48183384c530b408b9dbe2aee2' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazePushStory.zip', + :sha256 => '19332ac17475d6cd7394f48e3f8c6a4d3ad111c0f49c333e704dc22ab1b4f8d3' } s.swift_version = '5.0' diff --git a/BrazeUI.podspec b/BrazeUI.podspec index e405dab1c5..e6e912322f 100644 --- a/BrazeUI.podspec +++ b/BrazeUI.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeUI' - s.version = '8.0.1' + s.version = '8.1.0' s.summary = 'Braze-provided user interface library for In-App Messages and Content Cards.' s.homepage = 'https://braze.com' @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.license = { :type => 'Commercial' } s.authors = 'Braze, Inc.' - s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '8.0.1' } + s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '8.1.0' } s.swift_version = '5.0' s.ios.deployment_target = '12.0' @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.resource_bundles = { 'BrazeUI' => ['Sources/BrazeUI/Resources/**/*'] } s.static_framework = true - s.dependency 'BrazeKit', '8.0.1' + s.dependency 'BrazeKit', '8.1.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } end diff --git a/BrazeUICompat.podspec b/BrazeUICompat.podspec index 9a481ceadd..da52de556b 100644 --- a/BrazeUICompat.podspec +++ b/BrazeUICompat.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeUICompat' - s.version = '8.0.1' + s.version = '8.1.0' s.summary = 'Compatibility UI library for users migrating from AppboyUI.' s.homepage = 'https://braze.com' @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.license = { :type => 'Commercial' } s.authors = 'Braze, Inc.' - s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '8.0.1' } + s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '8.1.0' } s.swift_version = '5.0' s.ios.deployment_target = '12.0' @@ -18,8 +18,8 @@ Pod::Spec.new do |s| s.resource_bundles = { 'BrazeUICompat' => 'Sources/BrazeUICompat/*/Resources/**/*.*' } s.static_framework = true - s.dependency 'BrazeKitCompat', '8.0.1' - s.dependency 'SDWebImage', '>= 5.18.7', '< 6' + s.dependency 'BrazeKitCompat', '8.1.0' + s.dependency 'SDWebImage', '>= 5.19.0', '< 6' s.user_target_xcconfig = { 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES' } s.pod_target_xcconfig = { diff --git a/CHANGELOG.md b/CHANGELOG.md index 80ee945e00..5401987222 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +## 8.1.0 + +##### Added +- Adds the `is_test_send` boolean value in the in-app message JSON representation. +- Adds the [`Braze.subscribeToSessionUpdates(_:)`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/subscribetosessionupdates(_:)) method and [`Braze.sessionUpdatesStream`](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/sessionupdatesstream) property to subscribe to the session updates events generated by the SDK. +- Adds public APIs to access `BrazeKit`, `BrazeLocation` and `BrazeUI` resources bundles: + - `Braze.Resources.bundle` + - `BrazeLocationResources.bundle` + - `BrazeUIResources.bundle` +- `BrazeKit.overrideResourceBundle` and `BrazeUI.overrideResourceBundle` have been deprecated in favor of `BrazeKit.overrideResourcesBundle` and `BrazeUI.overrideResourcesBundle`. +- Re-enables visionOS sample apps requiring SDWebImage in `Examples-CocoaPods.xcworkspace`. SDWebImage for visionOS is now supported when using CocoaPods. +- Updated SDWebImage dependency in `BrazeUICompat` to `5.19.0+`. + +##### Fixed +- Fixes multiple issues on visionOS: + - Sessions now properly start as expected. + - The click behavior _Open Web URL Inside App_ now properly opens the URL in a modal web view. Previously, the URL would always be opened using the default web browser. + - [Braze.Notifications.Payload.targetScene](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/notifications-swift.class/payload/targetscene) is now defined. + - [Braze.URLContext.targetScene](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/urlcontext/targetscene) is now properly set by the SDK for in-app messages click actions. + - [Braze.WebViewBridge.ScriptMessageHandler.init(logClick:logError:showNewsFeed:closeMessage:braze:)](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/braze/webviewbridge/scriptmessagehandler/init(logclick:logerror:shownewsfeed:closemessage:braze:)-p2ki) is now defined. + - [BrazeDelegate.braze(_:willPresentModalWithContext:)](https://braze-inc.github.io/braze-swift-sdk/documentation/brazekit/brazedelegate/braze(_:willpresentmodalwithcontext:)-1fj41) now have a default implementation. + - Handling network requests and persisting data properly extend the lifetime of the application for processing. + ## 8.0.1 ##### Fixed diff --git a/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj index 3e0bfabaf3..65420c051a 100644 --- a/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj +++ b/Examples/ObjC/Examples-SwiftPM.xcodeproj/project.pbxproj @@ -1880,7 +1880,7 @@ repositoryURL = "https://github.com/SDWebImage/SDWebImage"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 5.18.7; + minimumVersion = 5.19.0; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Examples/ObjC/Podfile b/Examples/ObjC/Podfile index f58cd950b7..cd9f88bb0e 100644 --- a/Examples/ObjC/Podfile +++ b/Examples/ObjC/Podfile @@ -26,15 +26,14 @@ target 'InAppMessageUI-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'InAppMessageUI-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'InAppMessageUI-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'InAppMessageUI-Customization-iOS' do platform :ios, '11.0' @@ -45,15 +44,14 @@ target 'InAppMessageUI-Customization-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'InAppMessageUI-Customization-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'InAppMessageUI-Customization-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'InAppMessages-Custom-UI-iOS' do platform :ios, '11.0' @@ -79,15 +77,14 @@ target 'ContentCardUI-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'ContentCardUI-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'ContentCardUI-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'ContentCardUI-Customization-iOS' do platform :ios, '11.0' @@ -98,15 +95,14 @@ target 'ContentCardUI-Customization-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'ContentCardUI-Customization-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'ContentCardUI-Customization-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'ContentCards-Custom-UI-iOS' do platform :ios, '11.0' diff --git a/Examples/ObjC/manual-integration-setup.sh b/Examples/ObjC/manual-integration-setup.sh index 65ff7ca775..f433253238 100755 --- a/Examples/ObjC/manual-integration-setup.sh +++ b/Examples/ObjC/manual-integration-setup.sh @@ -20,7 +20,7 @@ if [ ! -f "manual-integration-setup.sh" ]; then fi # Constants -url="https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/braze-swift-sdk-prebuilt.zip" +url="https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/braze-swift-sdk-prebuilt.zip" echo "→" "Cleaning up" rm -rf braze-swift-sdk-prebuilt diff --git a/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj index cfb197ec93..83d4232e80 100644 --- a/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj +++ b/Examples/Swift/Examples-SwiftPM.xcodeproj/project.pbxproj @@ -1872,7 +1872,7 @@ repositoryURL = "https://github.com/SDWebImage/SDWebImage"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 5.18.7; + minimumVersion = 5.19.0; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Examples/Swift/Podfile b/Examples/Swift/Podfile index f58cd950b7..cd9f88bb0e 100644 --- a/Examples/Swift/Podfile +++ b/Examples/Swift/Podfile @@ -26,15 +26,14 @@ target 'InAppMessageUI-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'InAppMessageUI-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'InAppMessageUI-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'InAppMessageUI-Customization-iOS' do platform :ios, '11.0' @@ -45,15 +44,14 @@ target 'InAppMessageUI-Customization-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'InAppMessageUI-Customization-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'InAppMessageUI-Customization-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'InAppMessages-Custom-UI-iOS' do platform :ios, '11.0' @@ -79,15 +77,14 @@ target 'ContentCardUI-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'ContentCardUI-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'ContentCardUI-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'ContentCardUI-Customization-iOS' do platform :ios, '11.0' @@ -98,15 +95,14 @@ target 'ContentCardUI-Customization-iOS' do pod 'SDWebImage', :modular_headers => true end -# Disabled until SDWebImage supports visionOS via CocoaPods -# target 'ContentCardUI-Customization-visionOS' do -# platform :visionos, '1.0' -# pod 'BrazeKit' -# pod 'BrazeUI' -# # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. -# # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations -# pod 'SDWebImage', :modular_headers => true -# end +target 'ContentCardUI-Customization-visionOS' do + platform :visionos, '1.0' + pod 'BrazeKit' + pod 'BrazeUI' + # SDWebImage is optional. BrazeUI requires a third party library to display GIF images. + # See https://braze-inc.github.io/braze-swift-sdk/documentation/braze/gif-support-integrations + pod 'SDWebImage', :modular_headers => true +end target 'ContentCards-Custom-UI-iOS' do platform :ios, '11.0' diff --git a/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift b/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift index 2d9c717aa2..c6d65f6064 100644 --- a/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift +++ b/Examples/Swift/Sources/InAppMessages-Custom-UI/Extensions.swift @@ -19,9 +19,7 @@ extension Encodable { func prettyPrint() -> String { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted - if #available(iOS 11.0, tvOS 11.0, *) { - encoder.outputFormatting.insert(.sortedKeys) - } + encoder.outputFormatting.insert(.sortedKeys) if #available(iOS 13.0, tvOS 13.0, *) { encoder.outputFormatting.insert(.withoutEscapingSlashes) } @@ -41,9 +39,7 @@ extension Dictionary where Key == String, Value == Any { func prettyPrint() -> String { var options: JSONSerialization.WritingOptions = .prettyPrinted - if #available(iOS 11.0, tvOS 11.0, *) { - options.insert(.sortedKeys) - } + options.insert(.sortedKeys) if #available(iOS 13.0, tvOS 13.0, *) { options.insert(.withoutEscapingSlashes) } diff --git a/Examples/Swift/manual-integration-setup.sh b/Examples/Swift/manual-integration-setup.sh index 65ff7ca775..f433253238 100755 --- a/Examples/Swift/manual-integration-setup.sh +++ b/Examples/Swift/manual-integration-setup.sh @@ -20,7 +20,7 @@ if [ ! -f "manual-integration-setup.sh" ]; then fi # Constants -url="https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/braze-swift-sdk-prebuilt.zip" +url="https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/braze-swift-sdk-prebuilt.zip" echo "→" "Cleaning up" rm -rf braze-swift-sdk-prebuilt diff --git a/LICENSE b/LICENSE index 466b967fcc..540aa60b25 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2022 Braze, Inc. +Copyright (c) 2024 Braze, Inc. All rights reserved. * Use of source code or binaries contained within Braze’s SDKs is permitted only to enable use of the Braze platform by customers of Braze. diff --git a/Package.swift b/Package.swift index f88efb3f2f..c459640cef 100644 --- a/Package.swift +++ b/Package.swift @@ -42,15 +42,15 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.18.7"), + .package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.19.0"), /* ${dependencies-start} */ /* ${dependencies-end} */ ], targets: [ .binaryTarget( name: "BrazeKit", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazeKit.zip", - checksum: "8ba73f7f193f4ea52d8673535b12c224cfb16bfcc1683e52a0c267addce2beb7" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazeKit.zip", + checksum: "d33cb483bb4ed954baaf61621efcb3aab48e41af21d11a4c04ac41575c22c567" ), .target( name: "BrazeKitResources", @@ -67,8 +67,8 @@ let package = Package( ), .binaryTarget( name: "BrazeLocation", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazeLocation.zip", - checksum: "22753521e3cebbd1ec0b0986339b10b03f00a3258ecf4c209066de575b98d630" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazeLocation.zip", + checksum: "63b18e6ff1c579b0d8687181c6b6b82f2861cd4824a7f1d7df8e632a1e0fbb42" ), .target( name: "BrazeLocationResources", @@ -78,13 +78,13 @@ let package = Package( ), .binaryTarget( name: "BrazeNotificationService", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazeNotificationService.zip", - checksum: "5c17a259982cea0aaa06ee59ef64f52f0fb0325bdd973d7ccfe954babd9179e2" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazeNotificationService.zip", + checksum: "fac7499f1baa938e4ea19fe18f5b13d3ab92369294bdf96c4738115bbcc09341" ), .binaryTarget( name: "BrazePushStory", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.0.1/BrazePushStory.zip", - checksum: "ce056068074e29b218eda70c1dbf60d942905e48183384c530b408b9dbe2aee2" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/8.1.0/BrazePushStory.zip", + checksum: "19332ac17475d6cd7394f48e3f8c6a4d3ad111c0f49c333e704dc22ab1b4f8d3" ), .target( name: "BrazeKitCompat", diff --git a/README.md b/README.md index 3e9ecac22a..93ba56fa45 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

- Version: 8.0.1 + Version: 8.1.0 String { return override } - return resourcesBundle?.localizedString(forKey: key, value: nil, table: localizationSet.rawValue) + return BrazeUIResources.bundle?.localizedString( + forKey: key, value: nil, table: localizationSet.rawValue) ?? key } diff --git a/Sources/BrazeUI/Deprecations.swift b/Sources/BrazeUI/Deprecations.swift index 94c098d757..c98f57b21a 100644 --- a/Sources/BrazeUI/Deprecations.swift +++ b/Sources/BrazeUI/Deprecations.swift @@ -1,3 +1,5 @@ +import Foundation + // MARK: - Pre feature-parity // MARK: 08/25/2022 @@ -18,3 +20,11 @@ extension GIFViewProvider { public static let `default`: GIFViewProvider = .nonAnimating } + +// MARK: 02/23/2024 + +/// See ``overrideResourcesBundle``. +public var overrideResourceBundle: Bundle? { + get { overrideResourcesBundle } + set { overrideResourcesBundle = newValue } +} diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift index 77f1a42c66..2944f76365 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageExt.swift @@ -10,10 +10,6 @@ extension BrazeInAppMessageThemeable { /// /// [Dark Mode]: https://apple.co/2WBiaQ7 public func theme(for traits: UITraitCollection) -> Braze.InAppMessage.Theme { - guard #available(iOS 12.0, *) else { - return themes.light - } - switch traits.userInterfaceStyle { case .light, .unspecified: return themes.light @@ -35,10 +31,6 @@ extension Braze.InAppMessage.Button { /// /// [Dark Mode]: https://apple.co/2WBiaQ7 public func theme(for traits: UITraitCollection) -> Braze.InAppMessage.ButtonTheme { - guard #available(iOS 12.0, *) else { - return themes.light - } - switch traits.userInterfaceStyle { case .light, .unspecified: return themes.light diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift index 163566d1f6..b4c7fe1328 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift @@ -203,12 +203,10 @@ extension BrazeInAppMessageUI { #endif } - @available(iOS 11.0, *) open override var prefersHomeIndicatorAutoHidden: Bool { preferencesProxy?.prefersHomeIndicatorAutoHidden ?? false } - @available(iOS 11.0, *) open override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge { preferencesProxy?.preferredScreenEdgesDeferringSystemGestures ?? [] } diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift index a5956ed369..0050354819 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift @@ -309,12 +309,10 @@ extension BrazeInAppMessageUI { // Disable this optimization for mac catalyst (force webview in window bounds) #if !targetEnvironment(macCatalyst) - if #available(iOS 11.0, *) { - // Make web view ignore the safe area allowing proper handling in html / css. See the usage - // section at https://developer.mozilla.org/en-US/docs/Web/CSS/env() (archived version: - // https://archive.is/EBSJD) for instructions. - webView.scrollView.contentInsetAdjustmentBehavior = .never - } + // Make web view ignore the safe area allowing proper handling in html / css. See the usage + // section at https://developer.mozilla.org/en-US/docs/Web/CSS/env() (archived version: + // https://archive.is/EBSJD) for instructions. + webView.scrollView.contentInsetAdjustmentBehavior = .never #endif webView.alpha = attributes.animation.initialAlpha(legacy: message.legacy) addSubview(webView) @@ -532,15 +530,12 @@ extension BrazeInAppMessageUI.HtmlView { extension WKWebView { fileprivate func disableDragAndDrop() { - if #available(iOS 11.0, *) { - self - .bfsSubviews - .lazy - .first { $0.interactions.contains(where: { $0 is UIDragInteraction }) }? - .interactions - .filter { $0 is UIDragInteraction } - .forEach { $0.view?.removeInteraction($0) } - } + bfsSubviews + .lazy + .first { $0.interactions.contains(where: { $0 is UIDragInteraction }) }? + .interactions + .filter { $0 is UIDragInteraction } + .forEach { $0.view?.removeInteraction($0) } } fileprivate func disableSelection() { diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift index fbc468f5f2..b375c8bed8 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalImageView.swift @@ -153,12 +153,7 @@ extension BrazeInAppMessageUI { public lazy var imageContainerView: UIScrollView = { let view = UIScrollView() view.addSubview(imageView) - if #available(iOS 11, *) { - view.contentInsetAdjustmentBehavior = .never - } else { - // No need for iOS 10 support. - // No devices supporting iOS 10 has a need for safe-area handling. - } + view.contentInsetAdjustmentBehavior = .never return view }() diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift index 4e8a1dc7b9..82d5ce02ff 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUISlideupView.swift @@ -234,7 +234,7 @@ extension BrazeInAppMessageUI { open lazy var chevronView: UIImageView = { let image = UIImage( named: "InAppMessage/chevron", - in: resourcesBundle, + in: BrazeUIResources.bundle, compatibleWith: traitCollection )? .withRenderingMode(.alwaysTemplate) diff --git a/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift b/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift index 99210ba53b..15b9ac64a8 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/Misc/IconView.swift @@ -141,7 +141,8 @@ extension BrazeInAppMessageUI { guard UIFont(name: "FontAwesome", size: 30) == nil else { return true } - guard let url = resourcesBundle?.url(forResource: "FontAwesome", withExtension: "otf"), + guard + let url = BrazeUIResources.bundle?.url(forResource: "FontAwesome", withExtension: "otf"), let data = try? Data(contentsOf: url), let dataProvider = CGDataProvider(data: data as CFData), let font = CGFont(dataProvider) diff --git a/Sources/BrazeUI/Resources.swift b/Sources/BrazeUI/Resources.swift index 57b8c72778..98b6b4c0c7 100644 --- a/Sources/BrazeUI/Resources.swift +++ b/Sources/BrazeUI/Resources.swift @@ -6,54 +6,75 @@ import Foundation /// automatically include the resources (e.g. Tuist setup) /// /// - Important: This property needs to be set before the SDK initialization. -public var overrideResourceBundle: Bundle? +public var overrideResourcesBundle: Bundle? private class BundleFinder {} -/// UI resources bundle. -var resourcesBundle: Bundle? = { - // Use overriden resource bundle - if let overrideResourceBundle = overrideResourceBundle { - return overrideResourceBundle - } - - let bundleNames = [ - // SwiftPM source target resources - "braze-swift-sdk_BrazeUI", - // SwiftPM binary target resources - "braze-swift-sdk_BrazeUIResources", - // Cocoapods or prebuilt resources - "BrazeUI", - ] - - let candidates = [ - // Bundle should be present here when the package is linked into an App. - Bundle.main.resourceURL, - // Bundle should be present here when the package is linked into a framework. - Bundle(for: BundleFinder.self).resourceURL, - // For command-line tools. - Bundle.main.bundleURL, - ] - - for bundleName in bundleNames { - for candidate in candidates { - let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle") - if let bundle = bundlePath.flatMap(Bundle.init(url:)) { - return bundle +/// Resources related utilities. +@objc(BRZUIResources) +public class BrazeUIResources: NSObject { + + /// The resources bundle. + @objc + public static let bundle: Bundle? = { + // Use overriden resources bundle + if let overrideResourcesBundle = overrideResourcesBundle { + return overrideResourcesBundle + } + + let bundleNames = [ + // SwiftPM source target resources + "braze-swift-sdk_BrazeUI", + // SwiftPM binary target resources + "braze-swift-sdk_BrazeUIResources", + // Cocoapods or prebuilt resources + "BrazeUI", + ] + + let candidates = [ + // Bundle should be present here when the package is linked into an App. + Bundle.main.resourceURL, + // Bundle should be present here when the package is linked into a framework. + Bundle(for: BundleFinder.self).resourceURL, + // For command-line tools. + Bundle.main.bundleURL, + ] + + for bundleName in bundleNames { + for candidate in candidates { + let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle") + if let bundle = bundlePath.flatMap(Bundle.init(url:)) { + return bundle + } } } - } - - // Returns the framework bundle if available - let frameworkBundle = Bundle(for: BundleFinder.self) - if let name = frameworkBundle.infoDictionary?["CFBundleName"] as? String, - name.hasPrefix("BrazeUI") - { - return frameworkBundle - } - - print( - "[braze] Error: Unable to find UI resources bundle, cannot load localizations and acknowledgments" - ) - return nil -}() + + // Returns the framework bundle if available + let frameworkBundle = Bundle(for: BundleFinder.self) + if let name = frameworkBundle.infoDictionary?["CFBundleName"] as? String, + name.hasPrefix("BrazeUI") + { + return frameworkBundle + } + + print( + "[braze] Error: Unable to find UI resources bundle, cannot load localizations and acknowledgments" + ) + return nil + }() + + /// Acknowledgments for third-party open-source libraries used by BrazeUI. + /// + /// The dictionary maps the library name to the path to the license on the file system. + @objc + public static let acknowledgments: [String: URL] = { + var acknowledgments: [String: URL] = [:] + + if let align = bundle?.url(forResource: "align", withExtension: "license") { + acknowledgments["align"] = align + } + + return acknowledgments + }() + +}