Skip to content

Commit

Permalink
Add Unified Customization to EntryWidget
Browse files Browse the repository at this point in the history
Add Unified Customization to EntryWidget, as well as add missing UI
elements to accompany the customization options

MOB-3592
  • Loading branch information
rasmustautsglia committed Oct 4, 2024
1 parent 996e729 commit e86aa46
Show file tree
Hide file tree
Showing 15 changed files with 537 additions and 78 deletions.
20 changes: 16 additions & 4 deletions GliaWidgets.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@
C0175A2C2A67E2E9001FACDE /* Theme+Gva.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0175A2B2A67E2E9001FACDE /* Theme+Gva.swift */; };
C02248A72AD53DDA00CC4930 /* LiveObservationConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C02248A62AD53DDA00CC4930 /* LiveObservationConfirmation.swift */; };
C02248AA2AD53E6100CC4930 /* LiveObservation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C02248A92AD53E6100CC4930 /* LiveObservation.swift */; };
C034EEED2CAAB525002650B8 /* EntryWidgetStyle.RemoteConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C034EEEC2CAAB525002650B8 /* EntryWidgetStyle.RemoteConfig.swift */; };
C039FA7F2B19EB6E00DFD0E0 /* MediaPickerLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C039FA7E2B19EB6E00DFD0E0 /* MediaPickerLayoutTests.swift */; };
C039FA812B19ECBA00DFD0E0 /* MediaPickerDynamicFontTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C039FA802B19ECBA00DFD0E0 /* MediaPickerDynamicFontTests.swift */; };
C039FA832B19ED7D00DFD0E0 /* MediaPickerVoiceOverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C039FA822B19ED7D00DFD0E0 /* MediaPickerVoiceOverTests.swift */; };
Expand Down Expand Up @@ -846,6 +847,8 @@
C090478C2B7E5C8F003C437C /* FilePreviewStyle.Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C090478B2B7E5C8F003C437C /* FilePreviewStyle.Equatable.swift */; };
C096B40B297EBDE400F0C552 /* VisitorCodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C096B40A297EBDE400F0C552 /* VisitorCodeTests.swift */; };
C0B325E72AC5A8FA006BC430 /* AlertViewController+LiveObservationConfirmation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0B325E62AC5A8FA006BC430 /* AlertViewController+LiveObservationConfirmation.swift */; };
C0C5BB772CAD4278001B2025 /* MediaTypeItemStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0C5BB762CAD4259001B2025 /* MediaTypeItemStyle.swift */; };
C0C5BB792CAD42FD001B2025 /* MediaTypeItemStyle.RemoteConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0C5BB782CAD42FD001B2025 /* MediaTypeItemStyle.RemoteConfig.swift */; };
C0D2F02C2991219100803B47 /* VideoCallCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0D2F02B2991219100803B47 /* VideoCallCoordinator.swift */; };
C0D2F02E2991221900803B47 /* VideoCallCoordinator.DelegateEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0D2F02D2991221900803B47 /* VideoCallCoordinator.DelegateEvent.swift */; };
C0D2F0302991229F00803B47 /* VideoCallCoordinator.Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0D2F02F2991229F00803B47 /* VideoCallCoordinator.Environment.swift */; };
Expand Down Expand Up @@ -1706,6 +1709,7 @@
C0175A2B2A67E2E9001FACDE /* Theme+Gva.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Theme+Gva.swift"; sourceTree = "<group>"; };
C02248A62AD53DDA00CC4930 /* LiveObservationConfirmation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveObservationConfirmation.swift; sourceTree = "<group>"; };
C02248A92AD53E6100CC4930 /* LiveObservation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveObservation.swift; sourceTree = "<group>"; };
C034EEEC2CAAB525002650B8 /* EntryWidgetStyle.RemoteConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryWidgetStyle.RemoteConfig.swift; sourceTree = "<group>"; };
C039FA7E2B19EB6E00DFD0E0 /* MediaPickerLayoutTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPickerLayoutTests.swift; sourceTree = "<group>"; };
C039FA802B19ECBA00DFD0E0 /* MediaPickerDynamicFontTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPickerDynamicFontTests.swift; sourceTree = "<group>"; };
C039FA822B19ED7D00DFD0E0 /* MediaPickerVoiceOverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPickerVoiceOverTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1877,6 +1881,8 @@
C090478B2B7E5C8F003C437C /* FilePreviewStyle.Equatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilePreviewStyle.Equatable.swift; sourceTree = "<group>"; };
C096B40A297EBDE400F0C552 /* VisitorCodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VisitorCodeTests.swift; sourceTree = "<group>"; };
C0B325E62AC5A8FA006BC430 /* AlertViewController+LiveObservationConfirmation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AlertViewController+LiveObservationConfirmation.swift"; sourceTree = "<group>"; };
C0C5BB762CAD4259001B2025 /* MediaTypeItemStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTypeItemStyle.swift; sourceTree = "<group>"; };
C0C5BB782CAD42FD001B2025 /* MediaTypeItemStyle.RemoteConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTypeItemStyle.RemoteConfig.swift; sourceTree = "<group>"; };
C0D2F02B2991219100803B47 /* VideoCallCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCallCoordinator.swift; sourceTree = "<group>"; };
C0D2F02D2991221900803B47 /* VideoCallCoordinator.DelegateEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCallCoordinator.DelegateEvent.swift; sourceTree = "<group>"; };
C0D2F02F2991229F00803B47 /* VideoCallCoordinator.Environment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoCallCoordinator.Environment.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4985,14 +4991,17 @@
C0F3DE352C69F4A700DE6D7B /* EntryWidget */ = {
isa = PBXGroup;
children = (
C0F7EA372CA1D6D40038019C /* CustomPresentationController.swift */,
C0F3DE362C69F51D00DE6D7B /* EntryWidget.swift */,
C0F7EA392CA1D7050038019C /* EntryWidget.SizeConstraints.swift */,
C0F3DE382C69FC2100DE6D7B /* EntryWidget.Presentation.swift */,
C0F3DE3E2C6E176A00DE6D7B /* EntryWidget.Channel.swift */,
C0F3DE382C69FC2100DE6D7B /* EntryWidget.Presentation.swift */,
C0F7EA392CA1D7050038019C /* EntryWidget.SizeConstraints.swift */,
C0F3DE442C6E3D7C00DE6D7B /* EntryWidgetStyle.swift */,
C034EEEC2CAAB525002650B8 /* EntryWidgetStyle.RemoteConfig.swift */,
C0F3DE3A2C6E0DD900DE6D7B /* EntryWidgetView.swift */,
C0F3DE3C2C6E170600DE6D7B /* EntryWidgetViewModel.swift */,
C0F3DE442C6E3D7C00DE6D7B /* EntryWidgetStyle.swift */,
C0F7EA372CA1D6D40038019C /* CustomPresentationController.swift */,
C0C5BB762CAD4259001B2025 /* MediaTypeItemStyle.swift */,
C0C5BB782CAD42FD001B2025 /* MediaTypeItemStyle.RemoteConfig.swift */,
);
path = EntryWidget;
sourceTree = "<group>";
Expand Down Expand Up @@ -5632,6 +5641,7 @@
9AE9E4B727E1E30500BFE239 /* MockHelpers.swift in Sources */,
C0EC58CE2B02775100E78C70 /* SnackBar+View+Mock.swift in Sources */,
8464297D2A459E7D00943BD6 /* UIViewController+Replaceble.swift in Sources */,
C0C5BB772CAD4278001B2025 /* MediaTypeItemStyle.swift in Sources */,
C09046EA2B7E0F06003C437C /* Theme.VIsitorChatMessageStyle.RemoteConfig.swift in Sources */,
C09046A82B7D08CD003C437C /* WelcomeStyle.SendButton.LoadingStyle.RemoteConfig.swift in Sources */,
1A2DA72625EF892600032611 /* FilePickerController.swift in Sources */,
Expand Down Expand Up @@ -5799,6 +5809,7 @@
84265E64298D7B2900D65842 /* ScreenSharingViewStyle.Accessibility.swift in Sources */,
756B8B202996EFA2001D2BB2 /* Header.Props.swift in Sources */,
AFA2FDFC289082F500428E6D /* OnHoldOverlayStyle.Mock.swift in Sources */,
C034EEED2CAAB525002650B8 /* EntryWidgetStyle.RemoteConfig.swift in Sources */,
C0F3DE432C6E3D2400DE6D7B /* Theme.EntryWidget.swift in Sources */,
C090476E2B7E2546003C437C /* UnreadMessageDividerStyle.Equatable.swift in Sources */,
C09047602B7E2320003C437C /* ChatFileDownloadStyle.RemoteConfig.swift in Sources */,
Expand Down Expand Up @@ -5961,6 +5972,7 @@
3100D92D296E946600DEC9CE /* SecureConversations.ConfirmationViewModel.swift in Sources */,
75D987FC2AF2D9F90016A702 /* SnackBar.Live.swift in Sources */,
3100EEFB293F363100D57F71 /* SecureConversations.WelcomeView.swift in Sources */,
C0C5BB792CAD42FD001B2025 /* MediaTypeItemStyle.RemoteConfig.swift in Sources */,
1A475BBC25DFA10100296D55 /* UnreadMessagesHandler.swift in Sources */,
C09046752B7CFFCB003C437C /* ConfirmationStyle.CheckMessageButtonStyle.Accessibility.swift in Sources */,
845E2F85283FA90200C04D56 /* Theme.Survey.ValidationError.Accessibility.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import UIKit

final class CustomPresentationController: UIPresentationController {
private let height: CGFloat

private let cornerRadius: CGFloat
private let dimmingView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.black.withAlphaComponent(0.13)
Expand All @@ -12,9 +12,11 @@ final class CustomPresentationController: UIPresentationController {
init(
presentedViewController: UIViewController,
presenting presentingViewController: UIViewController?,
height: CGFloat
height: CGFloat,
cornerRadius: CGFloat
) {
self.height = height
self.cornerRadius = cornerRadius
super.init(
presentedViewController: presentedViewController,
presenting: presentingViewController
Expand Down Expand Up @@ -46,7 +48,7 @@ final class CustomPresentationController: UIPresentationController {

override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedView?.layer.cornerRadius = 24
presentedView?.layer.cornerRadius = cornerRadius
presentedView?.layer.masksToBounds = true
presentedView?.frame = frameOfPresentedViewInContainerView
}
Expand Down
15 changes: 12 additions & 3 deletions GliaWidgets/Sources/EntryWidget/EntryWidget.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,15 @@ private extension EntryWidget {
let view = makeView(model: model)
let hostingController = UIHostingController(rootView: view)

hostingController.view.backgroundColor = UIColor.white
switch theme.entryWidget.backgroundColor {
case .fill(let color):
hostingController.view.backgroundColor = color
case .gradient(let colors):
hostingController.view.makeGradientBackground(
colors: colors,
cornerRadius: theme.entryWidget.cornerRadius
)
}

// Due to the more modern sheet presenting approach being
// available starting from iOS 16, we need to handle cases
Expand All @@ -105,7 +113,7 @@ private extension EntryWidget {
}
sheet.detents = [smallDetent]
sheet.prefersScrollingExpandsWhenScrolledToEdge = true
sheet.preferredCornerRadius = 24
sheet.preferredCornerRadius = theme.entryWidget.cornerRadius
} else {
hostingController.modalPresentationStyle = .custom
hostingController.transitioningDelegate = self
Expand Down Expand Up @@ -163,7 +171,8 @@ extension EntryWidget: UIViewControllerTransitioningDelegate {
return CustomPresentationController(
presentedViewController: presented,
presenting: presenting,
height: height
height: height,
cornerRadius: theme.entryWidget.cornerRadius
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import UIKit

extension EntryWidgetStyle {
mutating func apply(
configuration: RemoteConfiguration.EntryWidget?,
assetsBuilder: RemoteConfiguration.AssetsBuilder
) {
applyBackground(configuration: configuration?.background)
applyDivider(configuration: configuration?.mediaTypeItems?.dividerColor)
applyErrorTitle(
configuration: configuration?.errorTitle,
assetsBuilder: assetsBuilder
)
applyErrorMessage(
configuration: configuration?.errorMessage,
assetsBuilder: assetsBuilder
)
errorButton.apply(
configuration: configuration?.errorButton,
assetsBuilder: assetsBuilder
)
mediaTypeItem.apply(
configuration: configuration?.mediaTypeItems?.mediaTypeItem,
assetsBuilder: assetsBuilder
)
}
}

private extension EntryWidgetStyle {
mutating func applyBackground(configuration: RemoteConfiguration.Layer?) {
configuration?.color.unwrap {
switch $0.type {
case .fill:
$0.value
.map { UIColor(hex: $0) }
.first
.unwrap { backgroundColor = .fill(color: $0) }
case .gradient:
let colors = $0.value.convertToCgColors()
backgroundColor = .gradient(colors: colors)
}
}
configuration?.cornerRadius.unwrap {
cornerRadius = $0
}
}

mutating func applyErrorMessage(
configuration: RemoteConfiguration.Text?,
assetsBuilder: RemoteConfiguration.AssetsBuilder
) {
configuration.unwrap {
UIFont.convertToFont(
uiFont: assetsBuilder.fontBuilder($0.font),
textStyle: errorMessageStyle
).unwrap { errorMessageFont = $0 }

$0.foreground?.value
.map { UIColor(hex: $0) }
.first
.unwrap { errorMessageColor = $0 }
}
}

mutating func applyErrorTitle(
configuration: RemoteConfiguration.Text?,
assetsBuilder: RemoteConfiguration.AssetsBuilder
) {
configuration.unwrap {
UIFont.convertToFont(
uiFont: assetsBuilder.fontBuilder($0.font),
textStyle: errorTitleStyle
).unwrap { errorTitleFont = $0 }

$0.foreground?.value
.map { UIColor(hex: $0) }
.first
.unwrap { errorTitleColor = $0 }
}
}

mutating func applyDivider(configuration: RemoteConfiguration.Color?) {
configuration?.value
.map { UIColor(hex: $0) }
.first
.unwrap { dividerColor = $0 }
}
}
113 changes: 61 additions & 52 deletions GliaWidgets/Sources/EntryWidget/EntryWidgetStyle.swift
Original file line number Diff line number Diff line change
@@ -1,71 +1,80 @@
import UIKit

public struct EntryWidgetStyle {
/// Engagement channel style.
public var channel: EntryWidgetChannelStyle
/// The style of a media type item.
public var mediaTypeItem: MediaTypeItemStyle

/// Background color of the view.
public var backgroundColor: UIColor
/// The background color of the view.
public var backgroundColor: ColorType

/// Style of 'powered by' view.
/// The corner radius of the view.
public var cornerRadius: CGFloat

/// The style of 'powered by' view.
public var poweredBy: PoweredByStyle

/// The color of the dragger
public var draggerColor: UIColor
/// The color of the divider.
public var dividerColor: UIColor

/// - Parameters:
/// - channel: Engagement channel style.
/// - backgroundColor: Background color of the view.
/// - poweredBy: Style of 'powered by' view.
/// - draggerColor: The color of the dragger
///
public init(
channel: EntryWidgetChannelStyle,
backgroundColor: UIColor,
poweredBy: PoweredByStyle,
draggerColor: UIColor
) {
self.channel = channel
self.backgroundColor = backgroundColor
self.poweredBy = poweredBy
self.draggerColor = draggerColor
}
}
/// The font for the title of the error message.
public var errorTitleFont: UIFont

/// The text style for the title of the error message.
public var errorTitleStyle: UIFont.TextStyle

public struct EntryWidgetChannelStyle {
/// Font of the headline text.
public var headlineFont: UIFont
/// The color for the title of the error message.
public var errorTitleColor: UIColor

/// Color of the headline text.
public var headlineColor: UIColor
/// The error message string.
public var errorMessageFont: UIFont

/// Font of the subheadline text.
public var subheadlineFont: UIFont
/// The text style for the error message.
public var errorMessageStyle: UIFont.TextStyle

/// Color of the subheadline text.
public var subheadlineColor: UIColor
/// The color for the error message.
public var errorMessageColor: UIColor

/// Color of the icon.
public var iconColor: UIColor
/// The style of the error button.
public var errorButton: ActionButtonStyle

/// - Parameters:
/// - headlineFont: Font of the headline text.
/// - headlineColor: Color of the headline text.
/// - subheadlineFont: Font of the subheadline text.
/// - subheadlineColor: Color of the subheadline text.
/// - iconColor: Color of the icon.
///
/// - mediaTypeItem: The style of a media type item.
/// - backgroundColor: The background color of the view.
/// - cornerRadius: The corner radius of the view.
/// - poweredBy: The style of the 'powered by' view.
/// - dividerColor: The color of the divider.
/// - errorTitleFont: The font for the title of the error message.
/// - errorTitleStyle: The text style for the title of the error message.
/// - errorTitleColor: The color for the title of the error message.
/// - errorMessage: The error message string.
/// - errorMessageStyle: The text style for the error message.
/// - errorMessageColor: The color for the error message.
/// - errorButton: The style of the error button.
public init(
headlineFont: UIFont,
headlineColor: UIColor,
subheadlineFont: UIFont,
subheadlineColor: UIColor,
iconColor: UIColor
mediaTypeItem: MediaTypeItemStyle,
backgroundColor: ColorType,
cornerRadius: CGFloat,
poweredBy: PoweredByStyle,
dividerColor: UIColor,
errorTitleFont: UIFont,
errorTitleStyle: UIFont.TextStyle,
errorTitleColor: UIColor,
errorMessageFont: UIFont,
errorMessageStyle: UIFont.TextStyle,
errorMessageColor: UIColor,
errorButton: ActionButtonStyle
) {
self.headlineFont = headlineFont
self.headlineColor = headlineColor
self.subheadlineFont = subheadlineFont
self.subheadlineColor = subheadlineColor
self.iconColor = iconColor
self.mediaTypeItem = mediaTypeItem
self.backgroundColor = backgroundColor
self.cornerRadius = cornerRadius
self.poweredBy = poweredBy
self.dividerColor = dividerColor
self.errorTitleFont = errorTitleFont
self.errorTitleStyle = errorTitleStyle
self.errorTitleColor = errorTitleColor
self.errorMessageFont = errorMessageFont
self.errorMessageStyle = errorMessageStyle
self.errorMessageColor = errorMessageColor
self.errorButton = errorButton
}
}
Loading

0 comments on commit e86aa46

Please sign in to comment.