diff --git a/BrazeKit.podspec b/BrazeKit.podspec index bc3d7123e7..e350aed395 100644 --- a/BrazeKit.podspec +++ b/BrazeKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeKit' - s.version = '5.13.0' + s.version = '5.14.0' s.summary = 'Braze Main SDK library providing support for analytics and 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/5.13.0/BrazeKit.zip', - :sha256 => 'b63d2e6ecc4200b77769c38ddc04b4afb732833cb946c1799e59bb7e6c449ec0' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazeKit.zip', + :sha256 => '43c0aff33a6d89d5ee8182c19726b75c8c29335fc95dd579e57a959a763ba001' } s.swift_version = '5.0' diff --git a/BrazeKitCompat.podspec b/BrazeKitCompat.podspec index 1ccaf044fd..44001891cd 100644 --- a/BrazeKitCompat.podspec +++ b/BrazeKitCompat.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeKitCompat' - s.version = '5.13.0' + s.version = '5.14.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 => '5.13.0' } + s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.14.0' } s.swift_version = '5.0' s.ios.deployment_target = '11.0' @@ -18,8 +18,8 @@ Pod::Spec.new do |s| s.source_files = 'Sources/BrazeKitCompat/**/*.{h,m}' s.public_header_files = 'Sources/BrazeKitCompat/include/*.h' - s.dependency 'BrazeKit', '5.13.0' - s.dependency 'BrazeLocation', '5.13.0' + s.dependency 'BrazeKit', '5.14.0' + s.dependency 'BrazeLocation', '5.14.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } end diff --git a/BrazeLocation.podspec b/BrazeLocation.podspec index b8f662adee..9130fabdd7 100644 --- a/BrazeLocation.podspec +++ b/BrazeLocation.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeLocation' - s.version = '5.13.0' + s.version = '5.14.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/5.13.0/BrazeLocation.zip', - :sha256 => 'f7e62e3685dca2028454cbf4e9d1738dd172780455a4f6b12c8affc60e137086' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazeLocation.zip', + :sha256 => '9a1fec33eeb9b29baeb9156340a127bf64c99311a3e4d447f270c56d64ef222c' } s.swift_version = '5.0' @@ -21,7 +21,7 @@ Pod::Spec.new do |s| # Depends on BrazeKit because BrazeKit includes the internal _BrazeLocationClient symbols required # for linking against BrazeLocation. - s.dependency 'BrazeKit', '5.13.0' + s.dependency 'BrazeKit', '5.14.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } end diff --git a/BrazeNotificationService.podspec b/BrazeNotificationService.podspec index 931ededbed..83136dbeb4 100644 --- a/BrazeNotificationService.podspec +++ b/BrazeNotificationService.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeNotificationService' - s.version = '5.13.0' + s.version = '5.14.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/5.13.0/BrazeNotificationService.zip', - :sha256 => '231e81dca0315ddaad4935bdb5e79752b6cf050c0a9aec9f9523e766a3a5e5a0' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazeNotificationService.zip', + :sha256 => 'b0f60f74760d63ff3dc3a16dd11e5c711d4c0ed7fdee3681ffe451803542aa5b' } s.swift_version = '5.0' diff --git a/BrazePushStory.podspec b/BrazePushStory.podspec index 0d2953cf00..85ca3f62a8 100644 --- a/BrazePushStory.podspec +++ b/BrazePushStory.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazePushStory' - s.version = '5.13.0' + s.version = '5.14.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/5.13.0/BrazePushStory.zip', - :sha256 => 'ad7bf6bfe70c54e0e00f9dcd828eabe71d06c435efaccee0d2c4112b596f85ff' + :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazePushStory.zip', + :sha256 => '2d6e53a749ff54cd0d6ca898b761696c828a8172eafa2522c245706324e1d0c6' } s.swift_version = '5.0' diff --git a/BrazeUI.podspec b/BrazeUI.podspec index a618540ac2..65a45d6fa6 100644 --- a/BrazeUI.podspec +++ b/BrazeUI.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeUI' - s.version = '5.13.0' + s.version = '5.14.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 => '5.13.0' } + s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.14.0' } s.swift_version = '5.0' s.ios.deployment_target = '11.0' @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.source_files = 'Sources/BrazeUI/**/*.swift' s.resource_bundles = { 'BrazeUI' => ['Sources/BrazeUI/Resources/**/*'] } - s.dependency 'BrazeKit', '5.13.0' + s.dependency 'BrazeKit', '5.14.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } end diff --git a/BrazeUICompat.podspec b/BrazeUICompat.podspec index 3f63198c44..c7930007ed 100644 --- a/BrazeUICompat.podspec +++ b/BrazeUICompat.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'BrazeUICompat' - s.version = '5.13.0' + s.version = '5.14.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 => '5.13.0' } + s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.14.0' } s.swift_version = '5.0' s.ios.deployment_target = '11.0' @@ -18,7 +18,7 @@ Pod::Spec.new do |s| s.public_header_files = 'Sources/BrazeUICompat/ABK*/**/*.h' s.resource_bundles = { 'BrazeUICompat' => 'Sources/BrazeUICompat/*/Resources/**/*.*' } - s.dependency 'BrazeKitCompat', '5.13.0' + s.dependency 'BrazeKitCompat', '5.14.0' s.dependency 'SDWebImage', '>= 5.8.2', '< 6' s.user_target_xcconfig = { 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES' } diff --git a/CHANGELOG.md b/CHANGELOG.md index 570b85844d..3ea9356341 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## 5.14.0 + +##### Fixed +- VoiceOver now correctly focuses on in-app message views when they are presented. +- Fixes an issue causing in-app messages with re-eligibility disabled to display multiple times under certain conditions. +- Fixes an issue where modal and full in-app message headers were truncated on devices running iOS versions lower than 16 when displaying non-ASCII characters. +- The dynamic variant of `BrazeUI.framework` in the release artifact `braze-swift-sdk-prebuilt.zip` is now an actual dynamic framework. Previously, this specific framework was mistakenly distributed as a static framework. + +##### Added +- Adds the `BrazeSDKAuthDelegate` protocol as a separate protocol from `BrazeDelegate`, allowing for more flexible integrations. + - Apps implementing `BrazeDelegate.braze(_:sdkAuthenticationFailedWithError:)` should migrate to use `BrazeSDKAuthDelegate` and remove the old implementation. The `BrazeDelegate` method will be removed in a future major release. + ## 5.13.0 ##### Fixed diff --git a/Examples/ObjC/Sources/ContentCards/Info.plist b/Examples/ObjC/Sources/ContentCards/Info.plist new file mode 100644 index 0000000000..0c015f1468 --- /dev/null +++ b/Examples/ObjC/Sources/ContentCards/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ContentCards + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/ObjC/Sources/InAppMessages/Info.plist b/Examples/ObjC/Sources/InAppMessages/Info.plist new file mode 100644 index 0000000000..4f97542122 --- /dev/null +++ b/Examples/ObjC/Sources/InAppMessages/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + InAppMessages + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/ObjC/manual-integration-setup.sh b/Examples/ObjC/manual-integration-setup.sh index 326cf26b83..6bb00123cf 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/5.13.0/braze-swift-sdk-prebuilt.zip" +url="https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/braze-swift-sdk-prebuilt.zip" echo "→" "Cleaning up" rm -rf braze-swift-sdk-prebuilt diff --git a/Examples/Swift/Sources/ContentCards/Info.plist b/Examples/Swift/Sources/ContentCards/Info.plist new file mode 100644 index 0000000000..0c015f1468 --- /dev/null +++ b/Examples/Swift/Sources/ContentCards/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ContentCards + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/Swift/Sources/InAppMessages/Info.plist b/Examples/Swift/Sources/InAppMessages/Info.plist new file mode 100644 index 0000000000..4f97542122 --- /dev/null +++ b/Examples/Swift/Sources/InAppMessages/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + InAppMessages + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/Examples/Swift/manual-integration-setup.sh b/Examples/Swift/manual-integration-setup.sh index 326cf26b83..6bb00123cf 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/5.13.0/braze-swift-sdk-prebuilt.zip" +url="https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/braze-swift-sdk-prebuilt.zip" echo "→" "Cleaning up" rm -rf braze-swift-sdk-prebuilt diff --git a/Package.swift b/Package.swift index 690c943c9f..aca8261494 100644 --- a/Package.swift +++ b/Package.swift @@ -47,8 +47,8 @@ let package = Package( targets: [ .binaryTarget( name: "BrazeKit", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.13.0/BrazeKit.zip", - checksum: "b63d2e6ecc4200b77769c38ddc04b4afb732833cb946c1799e59bb7e6c449ec0" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazeKit.zip", + checksum: "43c0aff33a6d89d5ee8182c19726b75c8c29335fc95dd579e57a959a763ba001" ), .target( name: "BrazeKitResources", @@ -65,18 +65,18 @@ let package = Package( ), .binaryTarget( name: "BrazeLocation", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.13.0/BrazeLocation.zip", - checksum: "f7e62e3685dca2028454cbf4e9d1738dd172780455a4f6b12c8affc60e137086" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazeLocation.zip", + checksum: "9a1fec33eeb9b29baeb9156340a127bf64c99311a3e4d447f270c56d64ef222c" ), .binaryTarget( name: "BrazeNotificationService", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.13.0/BrazeNotificationService.zip", - checksum: "231e81dca0315ddaad4935bdb5e79752b6cf050c0a9aec9f9523e766a3a5e5a0" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazeNotificationService.zip", + checksum: "b0f60f74760d63ff3dc3a16dd11e5c711d4c0ed7fdee3681ffe451803542aa5b" ), .binaryTarget( name: "BrazePushStory", - url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.13.0/BrazePushStory.zip", - checksum: "ad7bf6bfe70c54e0e00f9dcd828eabe71d06c435efaccee0d2c4112b596f85ff" + url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.14.0/BrazePushStory.zip", + checksum: "2d6e53a749ff54cd0d6ca898b761696c828a8172eafa2522c245706324e1d0c6" ), .target( name: "BrazeKitCompat", diff --git a/README.md b/README.md index 44da1828d5..027a0bcc11 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

- Version: 5.13.0 + Version: 5.14.0

+# ⚠️ Xcode 14.3 RC (14E222a) support + +The XCFrameworks distributed by this repository are not supported by Xcode 14.3 Release Candidate (14E222a). Please use our alternative repository [`braze-swift-sdk-xcode-14-3-preview`](https://github.com/braze-inc/braze-swift-sdk-xcode-14-3-preview) to build and distribute your application using Xcode 14.3 Release Candidate (14E222a). + +Follow this [issue](https://github.com/braze-inc/braze-swift-sdk/issues/52) for updates. + # Braze Swift SDK - [Braze User Guide](https://www.braze.com/docs/user_guide/introduction/ "Braze User Guide") diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift index 7168626b49..974e691c0a 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageMocks.swift @@ -173,6 +173,17 @@ import Foundation ] ) + public static let mockTallCharacters = Self( + data: .mock, + graphic: .icon(""), + header: "헤더입니다", + message: + """ + 제1항의 탄핵소추는 국회재적의원 3분의 1 이상의 발의가 있어야 하며, 그 의결은 국회재적의원 과반수의 찬성이 있어야 한다. 다만, 대통령에 대한 탄핵소추는 국회재적의원 과반수의 발의와 국회재적의원 3분의 2 이상의 찬성이 있어야 한다. + 국가는 건전한 소비행위를 계도하고 생산품의 품질향상을 촉구하기 위한 소비자보호운동을 법률이 정하는 바에 의하여 보장한다. 모든 국민은 능력에 따라 균등하게 교육을 받을 권리를 가진다. + """ + ) + public static let mockThemed = Self( data: .mock, graphic: .icon(""), @@ -351,6 +362,17 @@ import Foundation ] ) + public static let mockTallCharacters = Self( + data: .mock, + imageURL: .mockImage(width: 1200, height: 1000), + header: "헤더입니다", + message: + """ + 제1항의 탄핵소추는 국회재적의원 3분의 1 이상의 발의가 있어야 하며, 그 의결은 국회재적의원 과반수의 찬성이 있어야 한다. 다만, 대통령에 대한 탄핵소추는 국회재적의원 과반수의 발의와 국회재적의원 3분의 2 이상의 찬성이 있어야 한다. + 국가는 건전한 소비행위를 계도하고 생산품의 품질향상을 촉구하기 위한 소비자보호운동을 법률이 정하는 바에 의하여 보장한다. 모든 국민은 능력에 따라 균등하게 교육을 받을 권리를 가진다. + """ + ) + public static let mockThemed = Self( data: .mock, imageURL: .mockImage(width: 1200, height: 1000), diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift index 304cf68e3e..a367e423ce 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUI.swift @@ -158,6 +158,7 @@ open class BrazeInAppMessageUI: } else { window = Window(frame: UIScreen.main.bounds) } + window.accessibilityViewIsModal = true window.windowLevel = context.windowLevel window.rootViewController = viewController self.window = window diff --git a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift index a32e88a8f3..dd1f01aca8 100644 --- a/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift +++ b/Sources/BrazeUI/InAppMessageUI/InAppMessageUIViewController.swift @@ -57,6 +57,11 @@ extension BrazeInAppMessageUI { didSet { setNeedsStatusBarAppearanceUpdate() } } + /// The message view initial accessibility element. + /// + /// If assigned, VoiceOver will focus on this element when the message view is presented. + var messageViewInitialAccessibilityElement: Any? + // MARK: - Initialization /// Creates an in-app message view controller. diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift index 0b34af4ad6..bd7356e2b7 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIFullView.swift @@ -339,6 +339,11 @@ extension BrazeInAppMessageUI { .preview() .frame(maxHeight: 500) .previewDisplayName("Var. Full | Long (constrained)") + + FullView(message: .mockTallCharacters, presented: true) + .preview() + .frame(maxHeight: 800) + .previewDisplayName("Var. Full | Tall Characters") } @ViewBuilder @@ -393,6 +398,12 @@ extension BrazeInAppMessageUI { .frame(width: 540, height: 500) .environment(\.horizontalSizeClass, .regular) .previewDisplayName("Var. Modal | Long (constrained)") + + FullView(message: .mockTallCharacters, presented: true) + .preview() + .frame(width: 540, height: 820) + .environment(\.horizontalSizeClass, .regular) + .previewDisplayName("Var. Modal | Tall Characters") } @ViewBuilder diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift index d728693c0e..3dae261925 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIHtmlView.swift @@ -199,6 +199,7 @@ extension BrazeInAppMessageUI { public func present(completion: (() -> Void)? = nil) { prefersStatusBarHidden = true + addVoiceOverHook() setupWebView() installPresentationConstraintsIfNeeded() @@ -429,6 +430,19 @@ extension BrazeInAppMessageUI.HtmlView: WKUIDelegate { // MARK: - Misc. +extension BrazeInAppMessageUI.HtmlView { + + fileprivate func addVoiceOverHook() { + // This view helps the accessibility engine focus on the message view. Without it, the + // accessibility engine will fail to properly focus on an accessible element within the web + // view. + let voiceOverHook = UIView() + insertSubview(voiceOverHook, at: 0) + initialAccessibilityElement = voiceOverHook + } + +} + extension WKWebView { fileprivate func disableDragAndDrop() { diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift index 8cfad91d4f..b4054e021c 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift @@ -126,9 +126,9 @@ extension BrazeInAppMessageUI { right: 0 ) textContainer.layoutMargins = .init( - top: TextViewLayoutConstants.textContainerLayoutMargins.top, + top: 0, left: padding.left, - bottom: TextViewLayoutConstants.textContainerLayoutMargins.bottom, + bottom: 0, right: padding.right ) buttonsContainer?.stack.layoutMargins = .init( @@ -555,20 +555,21 @@ extension BrazeInAppMessageUI { textView.attributedText = textViewText } - } - private enum TextViewLayoutConstants { - // Manually-tuned values to get us close to our previous StackView+Label appearance. - - // Soak up some vertical space that UITextView leaves above and below its text: - static let textContainerLayoutMargins = UIEdgeInsets(top: -8, left: 0, bottom: -8, right: 0) - // Scale factors for label → textview line spacing: - static let headerLineSpacingScaleFactor = 0.78 - static let messageLineSpacingScaleFactor = 0.47 - // Subtraction offset between header and message: - // (textview/TextKit renders a tiny bit of extra ascender+descender space that we want to eat up) - static let headerMessageSpacingOffset: Double = 1.0 + private enum TextViewLayoutConstants { + // Manually-tuned values to get us close to our previous StackView+Label appearance. + + // Soak up some vertical space that UITextView leaves above and below its text: + static let textContainerLayoutMargins = UIEdgeInsets(top: -8, left: 0, bottom: -8, right: 0) + // Scale factors for label → textview line spacing: + static let headerLineSpacingScaleFactor = 0.78 + static let messageLineSpacingScaleFactor = 0.47 + // Subtraction offset between header and message: + // (textview/TextKit renders a tiny bit of extra ascender+descender space that we want to eat up) + static let headerMessageSpacingOffset: Double = 1.0 + } } + } // MARK: - Previews @@ -630,6 +631,11 @@ extension BrazeInAppMessageUI { .preview(center: .required) .frame(maxHeight: 375) .previewDisplayName("Var. | Long (constrained)") + + ModalView(message: .mockTallCharacters, presented: true) + .preview(center: .required) + .frame(maxHeight: 500) + .previewDisplayName("Var. | Tall Characters") } @ViewBuilder diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift index 43dda0cb09..cb77e336c5 100644 --- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift +++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageView.swift @@ -52,6 +52,14 @@ public protocol InAppMessageView: UIView { extension InAppMessageView { + /// The initial accessibility element. + /// + /// If assigned, VoiceOver will focus on this element when the message view is presented. + public var initialAccessibilityElement: Any? { + get { controller?.messageViewInitialAccessibilityElement } + set { controller?.messageViewInitialAccessibilityElement = newValue } + } + /// The preferred status bar hidden state. /// /// Setting this value may have no effect depending of upstream customizations. @@ -76,6 +84,10 @@ extension InAppMessageView { return } + // Ensure that VoiceOver moves to initial accessibility element + let accessibilityElement = initialAccessibilityElement ?? self + UIAccessibility.post(notification: .screenChanged, argument: accessibilityElement) + ui.delegate?.inAppMessage(ui, didPresent: controller.message, view: self) }