Skip to content

Commit

Permalink
Introduce disabled state for ChatMessageEntry style
Browse files Browse the repository at this point in the history
Introduce disabled state for ChatMessageEntry style for SC 2.0.

MOB-3748
  • Loading branch information
igorkravchenko committed Nov 4, 2024
1 parent 14d76ce commit 000092a
Show file tree
Hide file tree
Showing 23 changed files with 446 additions and 226 deletions.
48 changes: 36 additions & 12 deletions GliaWidgets.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extension SecureConversations.TranscriptModel.Environment {
createFileUploadListModel: environment.createFileUploadListModel,
uuid: environment.uuid,
secureUploadFile: environment.secureUploadFile,
fileUploadListStyle: viewFactory.theme.chatStyle.messageEntry.uploadList,
fileUploadListStyle: viewFactory.theme.chatStyle.messageEntry.enabled.uploadList,
fetchSiteConfigurations: environment.fetchSiteConfigurations,
getSecureUnreadMessageCount: environment.getSecureUnreadMessageCount,
messagesWithUnreadCountLoaderScheduler: environment.messagesWithUnreadCountLoaderScheduler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ extension SecureConversations.FileUploadView.Props {
}

extension FileUploadStyle {
static let initial = Theme().chat.messageEntry.uploadList.item
static let initial = Theme().chat.messageEntry.enabled.uploadList.item
}

extension SecureConversations.FileUploadView {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

extension MessageButton {
typealias StateStyle = StatefulStyle<MessageButtonStateStyle>
}
28 changes: 21 additions & 7 deletions GliaWidgets/Sources/Component/Button/Message/MessageButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,25 @@ class MessageButton: UIButton {
override var isEnabled: Bool {
didSet {
super.isEnabled = isEnabled
alpha = isEnabled ? 1.0 : 0.6
style = isEnabled ? .enabled(styleStates.enabled)
: .disabled(styleStates.disabled)
}
}

private let style: MessageButtonStyle
private let styleStates: MessageButtonStyle
private var style: StateStyle {
didSet {
renderStyle()
}
}
private let width: CGFloat = 30

init(with style: MessageButtonStyle, tap: (() -> Void)? = nil) {
self.style = style
init(
with styleStates: MessageButtonStyle,
tap: (() -> Void)? = nil
) {
self.styleStates = styleStates
self.style = .enabled(styleStates.enabled)
self.tap = tap
super.init(frame: .zero)
setup()
Expand All @@ -27,10 +37,8 @@ class MessageButton: UIButton {
}

private func setup() {
tintColor = style.color
setImage(style.image, for: .normal)
setImage(style.image, for: .highlighted)
addTarget(self, action: #selector(tapped), for: .touchUpInside)
renderStyle()
}

private func layout() {
Expand All @@ -40,4 +48,10 @@ class MessageButton: UIButton {
@objc private func tapped() {
tap?()
}

private func renderStyle() {
tintColor = style.color
setImage(style.image, for: .normal)
setImage(style.image, for: .highlighted)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
extension MessageButtonStyle {
extension MessageButtonStateStyle {
/// Accessibility properties of MessageButtonStyle.
public struct Accessibility: Equatable {
/// Accessibility label of the button.
Expand All @@ -13,7 +13,7 @@ extension MessageButtonStyle {
}
}

extension MessageButtonStyle.Accessibility {
extension MessageButtonStateStyle.Accessibility {
/// Accessibility is not supported intentionally.
public static let unsupported = Self(accessibilityLabel: "")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import UIKit

/// Style for state of the button shown to the right of the message input area.
/// Used for "Send message" and "Pick attachment" buttons.
public struct MessageButtonStateStyle {
/// Image of the button.
public var image: UIImage

/// Color of the button's image.
public var color: UIColor

/// Accessibility related properties.
public var accessibility: Accessibility

/// - Parameters:
/// - image: Image of the button.
/// - color: Color of the button's image.
/// - accessibility: Accessibility related properties.
///
public init(
image: UIImage,
color: UIColor,
accessibility: Accessibility = .unsupported
) {
self.image = image
self.color = color
self.accessibility = accessibility
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
import UIKit
import Foundation

/// Style of a button shown to the right of the message input area.
/// Used for "Send message" and "Pick attachment" buttons.
/// Style for the button shown to the right of the message input area.
public struct MessageButtonStyle {
/// Image of the button.
public var image: UIImage

/// Color of the button's image.
public var color: UIColor

/// Accessibility related properties.
public var accessibility: Accessibility
/// Style for enabled state of the button.
public var enabled: MessageButtonStateStyle
/// Style for disabled state of the button.
public var disabled: MessageButtonStateStyle

/// - Parameters:
/// - image: Image of the button.
/// - color: Color of the button's image.
/// - accessibility: Accessibility related properties.
///
/// - enabled: Style for enabled state of the button.
/// - disabled: Style for disabled state of the button.
public init(
image: UIImage,
color: UIColor,
accessibility: Accessibility = .unsupported
enabled: MessageButtonStateStyle,
disabled: MessageButtonStateStyle
) {
self.image = image
self.color = color
self.accessibility = accessibility
self.enabled = enabled
self.disabled = disabled
}
}
31 changes: 31 additions & 0 deletions GliaWidgets/Sources/StatefulStyle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// Stateful style to represent enabled and disabled states of the component.
/// Simplifies access to underlying properties of the generic `State` type.
@dynamicMemberLookup
enum StatefulStyle<State> {
/// Enabled state.
case enabled(State)
/// Disabled state.
case disabled(State)

subscript<T>(dynamicMember keyPath: WritableKeyPath<State, T>) -> T {
get {
switch self {
case let .enabled(style):
return style[keyPath: keyPath]
case let .disabled(style):
return style[keyPath: keyPath]
}
}

set (newValue) {
switch self {
case var .enabled(style):
style[keyPath: keyPath] = newValue
self = .enabled(style)
case var .disabled(style):
style[keyPath: keyPath] = newValue
self = .disabled(style)
}
}
}
}
50 changes: 47 additions & 3 deletions GliaWidgets/Sources/Theme/Theme+Chat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -293,17 +293,37 @@ extension Theme {
choiceOption: choiceCardOption,
accessibility: .init(imageLabel: Localization.Chat.ChoiceCard.Image.Accessibility.label)
)
let mediaButton = MessageButtonStyle(
let mediaButtonEnabled = MessageButtonStateStyle(
image: Asset.chatPickMedia.image,
color: color.baseNormal,
accessibility: .init(accessibilityLabel: Localization.Chat.attachFiles)
)
let sendButton = MessageButtonStyle(
let mediaButtonDisabled = MessageButtonStateStyle(
image: Asset.chatPickMedia.image,
color: color.baseShade,
accessibility: .init(accessibilityLabel: Localization.Chat.attachFiles)
)
let mediaButton = MessageButtonStyle(
enabled: mediaButtonEnabled,
disabled: mediaButtonDisabled
)
let sendButtonEnabled = MessageButtonStateStyle(
image: Asset.chatSend.image,
color: color.primary,
accessibility: .init(accessibilityLabel: Localization.General.send)
)
let messageEntry = ChatMessageEntryStyle(

let sendButtonDisabled = MessageButtonStateStyle(
image: Asset.chatSend.image,
color: color.baseShade,
accessibility: .init(accessibilityLabel: Localization.General.send)
)

let sendButton = MessageButtonStyle(
enabled: sendButtonEnabled,
disabled: sendButtonDisabled
)
let messageEntryEnabled = ChatMessageEntryStateStyle(
messageFont: font.bodyText,
messageColor: color.baseDark,
enterMessagePlaceholder: Localization.Chat.Input.placeholder,
Expand All @@ -321,6 +341,30 @@ extension Theme {
isFontScalingEnabled: true
)
)
let messageEntryDisabled = ChatMessageEntryStateStyle(
messageFont: font.bodyText,
messageColor: color.baseDark,
enterMessagePlaceholder: Localization.Chat.Input.placeholder,
startEngagementPlaceholder: Localization.Chat.Message.startEngagementPlaceholder,
choiceCardPlaceholder: Localization.Chat.ChoiceCard.placeholderMessage,
placeholderFont: font.bodyText,
placeholderColor: color.baseShade,
separatorColor: color.baseShade,
backgroundColor: color.baseLight,
mediaButton: mediaButton,
sendButton: sendButton,
uploadList: uploadListStyle,
accessibility: .init(
messageInputAccessibilityLabel: Localization.General.message,
isFontScalingEnabled: true
)
)

let messageEntry = ChatMessageEntryStyle(
enabled: messageEntryEnabled,
disabled: messageEntryDisabled
)

let audioUpgrade = ChatCallUpgradeStyle(
icon: Asset.upgradeAudio.image,
iconColor: color.primary,
Expand Down
2 changes: 2 additions & 0 deletions GliaWidgets/Sources/View/Chat/ChatStyle.RemoteConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ extension ChatStyle {
)
messageEntry.apply(
configuration: configuration?.input,
// TODO: Add Unified customization (MOB-3762)
disabledConfiguration: configuration?.input,
assetsBuilder: assetsBuilder
)
choiceCardStyle.apply(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
extension ChatMessageEntryStyle {
/// Accessibility properties for ChatMessageEntryStyle.
extension ChatMessageEntryStateStyle {
/// Accessibility properties for ChatMessageEntryStateStyle.
public struct Accessibility: Equatable {
/// Accessibility label for message text view.
public var messageInputAccessibilityLabel: String

/// Flag that provides font dynamic type by setting `adjustsFontForContentSizeCategory`
/// Flag that provides font dynamic type by setting `adjustsFontForContentSizeCategory`
/// for component that supports it.
public var isFontScalingEnabled: Bool

/// - Parameters:
/// - messageInputAccessibilityLabel: Accessibility label for message text view.
/// - isFontScalingEnabled: Flag that provides font dynamic type by setting
/// - isFontScalingEnabled: Flag that provides font dynamic type by setting
/// `adjustsFontForContentSizeCategory` for component that supports it.
///
public init(
Expand All @@ -23,7 +23,7 @@ extension ChatMessageEntryStyle {
}
}

extension ChatMessageEntryStyle.Accessibility {
extension ChatMessageEntryStateStyle.Accessibility {
/// Accessibility is not supported intentionally.
public static let unsupported = Self(
messageInputAccessibilityLabel: "",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import UIKit

extension ChatMessageEntryStateStyle {
mutating func apply(
configuration: RemoteConfiguration.Input?,
assetsBuilder: RemoteConfiguration.AssetsBuilder
) {
configuration?.background?.color?.value
.map { UIColor(hex: $0) }
.first
.unwrap { backgroundColor = $0 }

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

UIFont.convertToFont(
uiFont: assetsBuilder.fontBuilder(configuration?.text?.font),
textStyle: messageTextStyle
).unwrap { messageFont = $0 }

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

UIFont.convertToFont(
uiFont: assetsBuilder.fontBuilder(configuration?.placeholder?.font),
textStyle: placeholderTextStyle
).unwrap { placeholderFont = $0 }

configuration?.separator?.value
.map { UIColor(hex: $0) }
.first
.unwrap { separatorColor = $0 }
// TODO: Add Unified customization (MOB-3762)
configuration?.mediaButton?.tintColor?.value
.map { UIColor(hex: $0) }
.first
.unwrap { mediaButton.enabled.color = $0 }
// TODO: Add Unified customization (MOB-3762)
configuration?.sendButton?.tintColor?.value
.map { UIColor(hex: $0) }
.first
.unwrap { sendButton.enabled.color = $0 }

uploadList.apply(
configuration: configuration?.fileUploadBar,
assetsBuilder: assetsBuilder
)
}
}
Loading

0 comments on commit 000092a

Please sign in to comment.