diff --git a/BrazeKit.podspec b/BrazeKit.podspec
index 5620c93a10..e38f730899 100644
--- a/BrazeKit.podspec
+++ b/BrazeKit.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeKit'
- s.version = '5.9.1'
+ s.version = '5.10.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.9.1/BrazeKit.zip',
- :sha256 => '4a1e89795467329b8e30f069d9df34acd4a95d179527c41dffe2f1d336533728'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazeKit.zip',
+ :sha256 => 'ab2660fa83c6aba270d205dae8a298be642059cd64e1a0bbfa8a1a06fe02107d'
}
s.swift_version = '5.0'
diff --git a/BrazeKitCompat.podspec b/BrazeKitCompat.podspec
index 2b08f5dc5d..742c2fa97f 100644
--- a/BrazeKitCompat.podspec
+++ b/BrazeKitCompat.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeKitCompat'
- s.version = '5.9.1'
+ s.version = '5.10.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.9.1' }
+ s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.10.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.9.1'
- s.dependency 'BrazeLocation', '5.9.1'
+ s.dependency 'BrazeKit', '5.10.0'
+ s.dependency 'BrazeLocation', '5.10.0'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
end
diff --git a/BrazeLocation.podspec b/BrazeLocation.podspec
index d67869857a..aba67bcb5c 100644
--- a/BrazeLocation.podspec
+++ b/BrazeLocation.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeLocation'
- s.version = '5.9.1'
+ s.version = '5.10.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.9.1/BrazeLocation.zip',
- :sha256 => 'f2b52b2db62cc3d2675a3b831692cba482d20d3b7d3002a335b15266e7ae1cc9'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazeLocation.zip',
+ :sha256 => '7e0ff737566c98b9293ea3f9dec6d3589c70822f6caf98c21f361585cc83a202'
}
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.9.1'
+ s.dependency 'BrazeKit', '5.10.0'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
end
diff --git a/BrazeNotificationService.podspec b/BrazeNotificationService.podspec
index 12a6ffb801..d18a02d35f 100644
--- a/BrazeNotificationService.podspec
+++ b/BrazeNotificationService.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeNotificationService'
- s.version = '5.9.1'
+ s.version = '5.10.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.9.1/BrazeNotificationService.zip',
- :sha256 => '5227b1321b27505a106809e71f60390671f35d292fb1accf29c2f1869c7b28af'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazeNotificationService.zip',
+ :sha256 => 'a068c73678861acdf6378cad866ab1a53372fbdc3c70d0780d54f96f0baff8f2'
}
s.swift_version = '5.0'
diff --git a/BrazePushStory.podspec b/BrazePushStory.podspec
index 05f4afd2bf..df8d3e9afa 100644
--- a/BrazePushStory.podspec
+++ b/BrazePushStory.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazePushStory'
- s.version = '5.9.1'
+ s.version = '5.10.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.9.1/BrazePushStory.zip',
- :sha256 => 'af2a93ca9a00be0d3840f91290bb7cdf1fb75798d7b7017b881b2f7606a6824d'
+ :http => 'https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazePushStory.zip',
+ :sha256 => '81e13d3247a5ad6af899a5e77336ebeee759735c188caad2f52c40e33f4ddc54'
}
s.swift_version = '5.0'
diff --git a/BrazeUI.podspec b/BrazeUI.podspec
index 720fb6c153..b68f315d3b 100644
--- a/BrazeUI.podspec
+++ b/BrazeUI.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeUI'
- s.version = '5.9.1'
+ s.version = '5.10.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.9.1' }
+ s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.10.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.9.1'
+ s.dependency 'BrazeKit', '5.10.0'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
end
diff --git a/BrazeUICompat.podspec b/BrazeUICompat.podspec
index ba337afcb0..61a8a52066 100644
--- a/BrazeUICompat.podspec
+++ b/BrazeUICompat.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'BrazeUICompat'
- s.version = '5.9.1'
+ s.version = '5.10.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.9.1' }
+ s.source = { :git => 'https://github.com/braze-inc/braze-swift-sdk.git', :tag => '5.10.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.9.1'
+ s.dependency 'BrazeKitCompat', '5.10.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 0762334b3f..7807538642 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 5.10.0
+
+##### Fixed
+- Fixes an issue where test content cards were removed before their expiration date.
+- Fixes an issue in `BrazeUICompat` where the status bar appearance wasn't restored to its original state after dismissing a full in-app message.
+- Fixes an issue when decoding notification payloads where some valid boolean values weren't correctly parsed.
+
+##### Changed
+- In-app modal and full-screen messages are now rendered with `UITextView`, which better supports large amounts of text and extended UTF code points.
+
## 5.9.1
##### Fixed
diff --git a/Examples/ObjC/Sources/ContentCards/Info.plist b/Examples/ObjC/Sources/ContentCards/Info.plist
deleted file mode 100644
index 0c015f1468..0000000000
--- a/Examples/ObjC/Sources/ContentCards/Info.plist
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- 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
deleted file mode 100644
index 4f97542122..0000000000
--- a/Examples/ObjC/Sources/InAppMessages/Info.plist
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- 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 d676523bd6..c75f2a1beb 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.9.1/braze-swift-sdk-prebuilt.zip"
+url="https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.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
deleted file mode 100644
index 0c015f1468..0000000000
--- a/Examples/Swift/Sources/ContentCards/Info.plist
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- 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
deleted file mode 100644
index 4f97542122..0000000000
--- a/Examples/Swift/Sources/InAppMessages/Info.plist
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- 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 d676523bd6..c75f2a1beb 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.9.1/braze-swift-sdk-prebuilt.zip"
+url="https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/braze-swift-sdk-prebuilt.zip"
echo "→" "Cleaning up"
rm -rf braze-swift-sdk-prebuilt
diff --git a/Package.swift b/Package.swift
index 704ec2af96..2d24daeae7 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.9.1/BrazeKit.zip",
- checksum: "4a1e89795467329b8e30f069d9df34acd4a95d179527c41dffe2f1d336533728"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazeKit.zip",
+ checksum: "ab2660fa83c6aba270d205dae8a298be642059cd64e1a0bbfa8a1a06fe02107d"
),
.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.9.1/BrazeLocation.zip",
- checksum: "f2b52b2db62cc3d2675a3b831692cba482d20d3b7d3002a335b15266e7ae1cc9"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazeLocation.zip",
+ checksum: "7e0ff737566c98b9293ea3f9dec6d3589c70822f6caf98c21f361585cc83a202"
),
.binaryTarget(
name: "BrazeNotificationService",
- url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.9.1/BrazeNotificationService.zip",
- checksum: "5227b1321b27505a106809e71f60390671f35d292fb1accf29c2f1869c7b28af"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazeNotificationService.zip",
+ checksum: "a068c73678861acdf6378cad866ab1a53372fbdc3c70d0780d54f96f0baff8f2"
),
.binaryTarget(
name: "BrazePushStory",
- url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.9.1/BrazePushStory.zip",
- checksum: "af2a93ca9a00be0d3840f91290bb7cdf1fb75798d7b7017b881b2f7606a6824d"
+ url: "https://github.com/braze-inc/braze-swift-sdk/releases/download/5.10.0/BrazePushStory.zip",
+ checksum: "81e13d3247a5ad6af899a5e77336ebeee759735c188caad2f52c40e33f4ddc54"
),
.target(
name: "BrazeKitCompat",
diff --git a/README.md b/README.md
index bcfa899286..199a0414e6 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
-
+
{ Anchor(base, .leading) }
var trailing: Anchor { Anchor(base, .trailing) }
+ var topMargin: Anchor { Anchor(base, .topMargin) }
+ var bottomMargin: Anchor { Anchor(base, .bottomMargin) }
+ var leftMargin: Anchor { Anchor(base, .leftMargin) }
+ var rightMargin: Anchor { Anchor(base, .rightMargin) }
+ var leadingMargin: Anchor { Anchor(base, .leadingMargin) }
+ var trailingMargin: Anchor { Anchor(base, .trailingMargin) }
+
var centerX: Anchor { Anchor(base, .centerX) }
var centerY: Anchor { Anchor(base, .centerY) }
diff --git a/Sources/BrazeUI/Dependencies/UIKitExt.swift b/Sources/BrazeUI/Dependencies/UIKitExt.swift
index e8a6256cbc..7cc246bc74 100644
--- a/Sources/BrazeUI/Dependencies/UIKitExt.swift
+++ b/Sources/BrazeUI/Dependencies/UIKitExt.swift
@@ -87,8 +87,11 @@ extension UIResponder {
extension String {
- func attributed(_ setup: (NSMutableParagraphStyle) -> Void) -> NSAttributedString {
- let attributedText = NSMutableAttributedString(string: self)
+ func attributed(
+ with attributes: [NSAttributedString.Key: Any]? = nil,
+ _ setup: (NSMutableParagraphStyle) -> Void
+ ) -> NSAttributedString {
+ let attributedText = NSMutableAttributedString(string: self, attributes: attributes)
let style = NSMutableParagraphStyle()
setup(style)
attributedText.addAttribute(
diff --git a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift
index c1b2bd92eb..8cfad91d4f 100644
--- a/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift
+++ b/Sources/BrazeUI/InAppMessageUI/Views/InAppMessageUIModalView.swift
@@ -1,6 +1,17 @@
import BrazeKit
import UIKit
+struct TextStyle: Equatable {
+ var color: UIColor
+ var font: UIFont
+}
+
+struct TextViewStyle: Equatable {
+ var header: TextStyle
+ var message: TextStyle
+ var headerMessageSpacing: Double
+}
+
extension BrazeInAppMessageUI {
/// The view for modal in-app messages.
@@ -114,10 +125,10 @@ extension BrazeInAppMessageUI {
bottom: padding.bottom,
right: 0
)
- textStack.layoutMargins = .init(
- top: 0,
+ textContainer.layoutMargins = .init(
+ top: TextViewLayoutConstants.textContainerLayoutMargins.top,
left: padding.left,
- bottom: 0,
+ bottom: TextViewLayoutConstants.textContainerLayoutMargins.bottom,
right: padding.right
)
buttonsContainer?.stack.layoutMargins = .init(
@@ -128,12 +139,12 @@ extension BrazeInAppMessageUI {
)
// Spacings
- textStack.spacing = attributes.labelsSpacing
+ textViewStyle.headerMessageSpacing = attributes.labelsSpacing
contentView.stack.spacing = attributes.spacing
// Fonts
- headerLabel.font = attributes.headerFont
- messageLabel.font = attributes.messageFont
+ textViewStyle.header.font = attributes.headerFont
+ textViewStyle.message.font = attributes.messageFont
// Corner radius
shadowView.layer.cornerRadius = attributes.cornerRadius
@@ -187,42 +198,30 @@ extension BrazeInAppMessageUI {
}
}()
- public lazy var headerLabel: UILabel = {
- let label = UILabel()
- label.numberOfLines = 0
- label.adjustsFontForContentSizeCategory = true
- label.attributedText = message.header.attributed {
- $0.lineSpacing = 2
- $0.alignment = message.headerTextAlignment.nsTextAlignment(forTraits: traitCollection)
- }
- label.setContentCompressionResistancePriority(.required, for: .vertical)
- label.setContentHuggingPriority(.required, for: .vertical)
- return label
- }()
-
- public lazy var messageLabel: UILabel = {
- let label = UILabel()
- label.numberOfLines = 0
- label.adjustsFontForContentSizeCategory = true
- label.attributedText = message.message.attributed {
- $0.lineSpacing = 4
- $0.alignment = message.messageTextAlignment.nsTextAlignment(forTraits: traitCollection)
- }
- label.setContentCompressionResistancePriority(.required, for: .vertical)
- label.setContentHuggingPriority(.required, for: .vertical)
- return label
- }()
-
- public lazy var textStack: UIStackView = {
- let stack = UIStackView(arrangedSubviews: [headerLabel, messageLabel])
- stack.axis = .vertical
- stack.isLayoutMarginsRelativeArrangement = true
- return stack
+ public lazy var textView: UITextView = {
+ let textView = UITextView()
+ // Config defaults:
+ textView.backgroundColor = .clear
+ textView.isEditable = false
+ textView.isSelectable = false
+ textView.adjustsFontForContentSizeCategory = true
+
+ // Don't allow scrolling; the textview's parent (a scrollview) will control that.
+ // This will force the textView to render its full content height,
+ // and the textViewContainer can then take that as its content and scroll it for us.
+ // (This hot tip brought to you by https://archive.is/fMUR7 and many other results.)
+ textView.isScrollEnabled = false
+
+ // Layout defaults:
+ textView.setContentCompressionResistancePriority(.required, for: .vertical)
+ textView.setContentHuggingPriority(.required, for: .vertical)
+
+ return textView
}()
public lazy var textContainer: UIScrollView = {
let container = UIScrollView()
- container.addSubview(textStack)
+ container.addSubview(textView)
return container
}()
@@ -295,6 +294,18 @@ extension BrazeInAppMessageUI {
self.gifViewProvider = gifViewProvider
self.presented = presented
+ self.textViewStyle = TextViewStyle(
+ header: .init(
+ color: .clear,
+ font: attributes.headerFont
+ ),
+ message: .init(
+ color: .clear,
+ font: attributes.messageFont
+ ),
+ headerMessageSpacing: attributes.labelsSpacing
+ )
+
super.init(frame: .zero)
addSubview(shadowView)
@@ -320,8 +331,8 @@ extension BrazeInAppMessageUI {
public var theme: Braze.InAppMessage.Theme { message.theme(for: traitCollection) }
open func applyTheme() {
- headerLabel.textColor = theme.headerTextColor.uiColor
- messageLabel.textColor = theme.textColor.uiColor
+ textViewStyle.header.color = theme.headerTextColor.uiColor
+ textViewStyle.message.color = theme.textColor.uiColor
closeButton.setTitleColor(theme.closeButtonColor.uiColor, for: .normal)
contentView.backgroundColor = theme.backgroundColor.uiColor
backgroundColor = theme.frameColor.uiColor
@@ -372,14 +383,18 @@ extension BrazeInAppMessageUI {
break
}
- // Text
- textStack.anchors.edges.pin()
- textStack.anchors.width.equal(textContainer.anchors.width)
- // - not required priority to allow the text container scrollview to shrink
- textStack.anchors.height.lessThanOrEqual(textContainer.anchors.height).priority =
+ // Anchor the text view's layout using margins from its parent container:
+ textView.anchors.leading.equal(textContainer.anchors.leadingMargin)
+ textView.anchors.trailing.equal(textContainer.anchors.trailingMargin)
+ textView.anchors.top.equal(textContainer.anchors.topMargin)
+ textView.anchors.bottom.equal(textContainer.anchors.bottomMargin)
+ textView.anchors.width.equal(textContainer.layoutMarginsGuide.anchors.width)
+ // Add a not-required priority to allow the text container scrollview to shrink
+ textView.anchors.height.lessThanOrEqual(textContainer.layoutMarginsGuide.anchors.height)
+ .priority =
.defaultHigh
- let textStackHeightConstraint = textStack.anchors.height.equal(textContainer.anchors.height)
- textStackHeightConstraint.priority = .defaultHigh - 1
+ let textViewHeightConstraint = textView.anchors.height.equal(textContainer.anchors.height)
+ textViewHeightConstraint.priority = .defaultHigh - 1
// Close button
closeButton.anchors.height.equal(closeButton.anchors.width)
@@ -492,8 +507,68 @@ extension BrazeInAppMessageUI {
}
dismiss()
}
+
+ // MARK: - Text view style
+
+ private var textViewStyle: TextViewStyle {
+ didSet {
+ if oldValue != textViewStyle {
+ self.updateTextViewContent()
+ }
+ }
+ }
+
+ private func updateTextViewContent() {
+ let textViewText = NSMutableAttributedString()
+
+ textViewText.append(
+ message.header.attributed(
+ with: [
+ NSAttributedString.Key.font: textViewStyle.header.font,
+ NSAttributedString.Key.foregroundColor: textViewStyle.header.color,
+ ],
+ {
+ $0.lineSpacing = 2 * TextViewLayoutConstants.headerLineSpacingScaleFactor
+ $0.alignment = message.headerTextAlignment.nsTextAlignment(forTraits: traitCollection)
+ $0.paragraphSpacing = max(
+ 0.0,
+ textViewStyle.headerMessageSpacing
+ - TextViewLayoutConstants.headerMessageSpacingOffset)
+ })
+ )
+ // Users don't add newlines to the end of their header text
+ // Insert a newline between header and message, but not with the possible extra styling of the header (e.g. font size, etc.)
+ // The paragraph spacing set above will occur between the header text and this linebreak.
+ textViewText.append(NSAttributedString(string: "\n"))
+
+ textViewText.append(
+ message.message.attributed(
+ with: [
+ NSAttributedString.Key.font: textViewStyle.message.font,
+ NSAttributedString.Key.foregroundColor: textViewStyle.message.color,
+ ],
+ {
+ $0.lineSpacing = 4 * TextViewLayoutConstants.messageLineSpacingScaleFactor
+ $0.alignment = message.messageTextAlignment.nsTextAlignment(forTraits: traitCollection)
+ })
+ )
+
+ 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
+ }
}
// MARK: - Previews
diff --git a/Sources/BrazeUICompat/ABKInAppMessage/ViewControllers/ABKInAppMessageViewController.m b/Sources/BrazeUICompat/ABKInAppMessage/ViewControllers/ABKInAppMessageViewController.m
index 85b014d790..eb4991c055 100644
--- a/Sources/BrazeUICompat/ABKInAppMessage/ViewControllers/ABKInAppMessageViewController.m
+++ b/Sources/BrazeUICompat/ABKInAppMessage/ViewControllers/ABKInAppMessageViewController.m
@@ -56,6 +56,7 @@ - (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
nil);
+ [[ABKUIUtils activeApplicationViewController] setNeedsStatusBarAppearanceUpdate];
}
- (BOOL)prefersStatusBarHidden {