From 62a2a13c0d2475c588786e096c564090f68a6abc Mon Sep 17 00:00:00 2001 From: Yevhen Kyivskyi Date: Fri, 29 Nov 2024 16:58:42 +0100 Subject: [PATCH] Apply unified UI for SC's top banner on ChatView --- GliaWidgets.xcodeproj/project.pbxproj | 42 +++++++++++++-- ...rsations.TranscriptModel.Environment.swift | 11 ++-- .../SecureConversations.TranscriptModel.swift | 3 +- .../EntryWidget.Configuration.swift | 4 +- .../EntryWidget/EntryWidgetViewModel.swift | 10 +++- .../MediaTypeItemStyle.Accessibility.swift | 0 ...aTypeItemStyle.Loading.Accessibility.swift | 0 .../MediaTypeItemStyle.Loading.swift | 2 +- .../MediaTypeItemStyle.Mock.swift | 53 +++++++++++++++++++ .../MediaTypeItemStyle.RemoteConfig.swift | 0 .../MediaTypeItemStyle.swift | 2 +- .../MediaTypeItemsStyle.Mock.swift | 15 ++++++ .../MediaTypeItemsStyle.RemoteConfig.swift | 15 ++++++ .../MediaTypeItems/MediaTypeItemsStyle.swift | 22 ++++++++ GliaWidgets/Sources/Theme/Theme+Chat.swift | 8 ++- .../View/Chat/ChatStyle.Deprecated.swift | 6 ++- .../View/Chat/ChatStyle.RemoteConfig.swift | 8 +++ GliaWidgets/Sources/View/Chat/ChatStyle.swift | 7 ++- .../TranscriptModel.Environment.Failing.swift | 3 +- .../Sources/ChatView/ChatStyle.Mock.swift | 6 ++- .../EntryWidget/EntryWidget.Mock.swift | 6 ++- .../EntryWidgetViewModelTests.swift | 45 ++++++++++++++++ 22 files changed, 246 insertions(+), 22 deletions(-) rename GliaWidgets/Sources/EntryWidget/{ => MediaTypeItem}/MediaTypeItemStyle.Accessibility.swift (100%) rename GliaWidgets/Sources/EntryWidget/{ => MediaTypeItem}/MediaTypeItemStyle.Loading.Accessibility.swift (100%) rename GliaWidgets/Sources/EntryWidget/{ => MediaTypeItem}/MediaTypeItemStyle.Loading.swift (94%) create mode 100644 GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Mock.swift rename GliaWidgets/Sources/EntryWidget/{ => MediaTypeItem}/MediaTypeItemStyle.RemoteConfig.swift (100%) rename GliaWidgets/Sources/EntryWidget/{ => MediaTypeItem}/MediaTypeItemStyle.swift (99%) create mode 100644 GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.Mock.swift create mode 100644 GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.RemoteConfig.swift create mode 100644 GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.swift diff --git a/GliaWidgets.xcodeproj/project.pbxproj b/GliaWidgets.xcodeproj/project.pbxproj index 62b2625f8..96f4cf2f8 100644 --- a/GliaWidgets.xcodeproj/project.pbxproj +++ b/GliaWidgets.xcodeproj/project.pbxproj @@ -182,6 +182,10 @@ 216D31092CF5DC080019CA9E /* OverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216D31082CF5DC080019CA9E /* OverlayView.swift */; }; 216D310B2CF790980019CA9E /* EntryWidget.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216D310A2CF790980019CA9E /* EntryWidget.Mock.swift */; }; 216D310D2CF795380019CA9E /* EntryWidgetViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216D310C2CF795380019CA9E /* EntryWidgetViewModelTests.swift */; }; + 216D31172CFE25510019CA9E /* MediaTypeItemsStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216D31162CFE25510019CA9E /* MediaTypeItemsStyle.swift */; }; + 216D311B2CFE25A20019CA9E /* MediaTypeItemsStyle.RemoteConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216D311A2CFE25A20019CA9E /* MediaTypeItemsStyle.RemoteConfig.swift */; }; + 216D311D2CFE2ED10019CA9E /* MediaTypeItemsStyle.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216D311C2CFE2ED10019CA9E /* MediaTypeItemsStyle.Mock.swift */; }; + 216D311F2CFE2F050019CA9E /* MediaTypeItemStyle.Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 216D311E2CFE2F050019CA9E /* MediaTypeItemStyle.Mock.swift */; }; 2188DED22CECC3D400FA3BEF /* SecureMessagingTopBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2188DED12CECC3D400FA3BEF /* SecureMessagingTopBannerView.swift */; }; 2188DED42CECE15800FA3BEF /* SecureMessagingTopBannerViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2188DED32CECE15800FA3BEF /* SecureMessagingTopBannerViewStyle.swift */; }; 2188DEDD2CEE2C3F00FA3BEF /* SecureMessagingBottomBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2188DED92CEE2C3F00FA3BEF /* SecureMessagingBottomBannerView.swift */; }; @@ -1268,6 +1272,10 @@ 216D31082CF5DC080019CA9E /* OverlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlayView.swift; sourceTree = ""; }; 216D310A2CF790980019CA9E /* EntryWidget.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryWidget.Mock.swift; sourceTree = ""; }; 216D310C2CF795380019CA9E /* EntryWidgetViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryWidgetViewModelTests.swift; sourceTree = ""; }; + 216D31162CFE25510019CA9E /* MediaTypeItemsStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTypeItemsStyle.swift; sourceTree = ""; }; + 216D311A2CFE25A20019CA9E /* MediaTypeItemsStyle.RemoteConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTypeItemsStyle.RemoteConfig.swift; sourceTree = ""; }; + 216D311C2CFE2ED10019CA9E /* MediaTypeItemsStyle.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTypeItemsStyle.Mock.swift; sourceTree = ""; }; + 216D311E2CFE2F050019CA9E /* MediaTypeItemStyle.Mock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaTypeItemStyle.Mock.swift; sourceTree = ""; }; 2188DED12CECC3D400FA3BEF /* SecureMessagingTopBannerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecureMessagingTopBannerView.swift; sourceTree = ""; }; 2188DED32CECE15800FA3BEF /* SecureMessagingTopBannerViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureMessagingTopBannerViewStyle.swift; sourceTree = ""; }; 2188DED92CEE2C3F00FA3BEF /* SecureMessagingBottomBannerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecureMessagingBottomBannerView.swift; sourceTree = ""; }; @@ -3350,6 +3358,29 @@ path = EngagementLauncher; sourceTree = ""; }; + 216D31182CFE25570019CA9E /* MediaTypeItem */ = { + isa = PBXGroup; + children = ( + C0C5BB762CAD4259001B2025 /* MediaTypeItemStyle.swift */, + AFA7A8A62CD9482E00861322 /* MediaTypeItemStyle.Accessibility.swift */, + 216D311E2CFE2F050019CA9E /* MediaTypeItemStyle.Mock.swift */, + C0C5BB782CAD42FD001B2025 /* MediaTypeItemStyle.RemoteConfig.swift */, + AFB6A0782CCBF3B700A1ED9A /* MediaTypeItemStyle.Loading.swift */, + AFB6A07A2CCBF53800A1ED9A /* MediaTypeItemStyle.Loading.Accessibility.swift */, + ); + path = MediaTypeItem; + sourceTree = ""; + }; + 216D31192CFE25630019CA9E /* MediaTypeItems */ = { + isa = PBXGroup; + children = ( + 216D31162CFE25510019CA9E /* MediaTypeItemsStyle.swift */, + 216D311C2CFE2ED10019CA9E /* MediaTypeItemsStyle.Mock.swift */, + 216D311A2CFE25A20019CA9E /* MediaTypeItemsStyle.RemoteConfig.swift */, + ); + path = MediaTypeItems; + sourceTree = ""; + }; 2188DED52CECE18C00FA3BEF /* SecureMessaging */ = { isa = PBXGroup; children = ( @@ -5213,6 +5244,8 @@ C0F3DE352C69F4A700DE6D7B /* EntryWidget */ = { isa = PBXGroup; children = ( + 216D31192CFE25630019CA9E /* MediaTypeItems */, + 216D31182CFE25570019CA9E /* MediaTypeItem */, C0F7EA372CA1D6D40038019C /* CustomPresentationController.swift */, 216D31022CEF83A90019CA9E /* EntryWidget.Builder.swift */, C0F3DE362C69F51D00DE6D7B /* EntryWidget.swift */, @@ -5224,11 +5257,6 @@ C034EEEC2CAAB525002650B8 /* EntryWidgetStyle.RemoteConfig.swift */, C0F3DE3A2C6E0DD900DE6D7B /* EntryWidgetView.swift */, C0F3DE3C2C6E170600DE6D7B /* EntryWidgetViewModel.swift */, - C0C5BB762CAD4259001B2025 /* MediaTypeItemStyle.swift */, - AFA7A8A62CD9482E00861322 /* MediaTypeItemStyle.Accessibility.swift */, - C0C5BB782CAD42FD001B2025 /* MediaTypeItemStyle.RemoteConfig.swift */, - AFB6A0782CCBF3B700A1ED9A /* MediaTypeItemStyle.Loading.swift */, - AFB6A07A2CCBF53800A1ED9A /* MediaTypeItemStyle.Loading.Accessibility.swift */, ); path = EntryWidget; sourceTree = ""; @@ -6036,6 +6064,7 @@ C0D6CA092C18451800D4709B /* CallViewController.Environment.swift in Sources */, 84D5B9622A14F33400807F92 /* QuickLookBased.Live.swift in Sources */, C09047152B7E18E7003C437C /* Theme.Text.Accessibility.swift in Sources */, + 216D311F2CFE2F050019CA9E /* MediaTypeItemStyle.Mock.swift in Sources */, AF6291112B0813B000D3D76B /* SwiftBased.Live.swift in Sources */, 75940953298D3832008B173A /* Command.swift in Sources */, 75C1143429A3F58E0004E5F7 /* RemoteConfiguration+SecureConversationsWelcomeScreen.swift in Sources */, @@ -6095,6 +6124,7 @@ AFF4412D2CD572AE0088B1C5 /* ChatMessageEntryView.StateStyle.swift in Sources */, 1A0452F025DBE268000DA0C1 /* MessageButtonStateStyle.swift in Sources */, 216D31052CF4D3590019CA9E /* ChatView.DefineLayout.swift in Sources */, + 216D311B2CFE25A20019CA9E /* MediaTypeItemsStyle.RemoteConfig.swift in Sources */, EB2CBB1227D89F7D004F178E /* OnHoldOverlayStyle.swift in Sources */, C09047482B7E20B0003C437C /* FileUploadStateStyle.Mock.swift in Sources */, 75940983298D38C2008B173A /* VisitorCodeViewModel+Delegate.swift in Sources */, @@ -6189,6 +6219,7 @@ 1A60B0192567FC8A00E53F53 /* ButtonKind.swift in Sources */, AFA5E96229F2CF9400F13DB7 /* SecureConversations.TranscriptModel.DividedChatItemsForUnreadCount.swift in Sources */, C42463742673ABE10082C135 /* ScreenShareHandler.Interface.swift in Sources */, + 216D311D2CFE2ED10019CA9E /* MediaTypeItemsStyle.Mock.swift in Sources */, 3100EEFD293F757E00D57F71 /* SecureConversations.WelcomeStyle.swift in Sources */, C09046F02B7E0F78003C437C /* Theme.OperatorChatMessageStyle.RemoteConfig.swift in Sources */, 755D187729A6A6D70009F5E8 /* WelcomeStyle.MessageWarningStyle.swift in Sources */, @@ -6500,6 +6531,7 @@ AF7753102B19EB9500E523A2 /* Logger.Interface.swift in Sources */, 1A1E309625F8CA4400850E68 /* FileDownload.swift in Sources */, EB2CBB1527D8DB95004F178E /* OnHoldOverlayVisualEffectView.swift in Sources */, + 216D31172CFE25510019CA9E /* MediaTypeItemsStyle.swift in Sources */, AFEF5C7129929601005C3D8D /* SecureConversations.FilePreviewView.swift in Sources */, C090475C2B7E2254003C437C /* FileUploadListStyle.Mock.swift in Sources */, 1A4AD3AF256D283700468BFB /* ChatMessageView.swift in Sources */, diff --git a/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.Environment.swift b/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.Environment.swift index 883d01fdf..1a6865fdb 100644 --- a/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.Environment.swift +++ b/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.Environment.swift @@ -35,6 +35,7 @@ extension SecureConversations.TranscriptModel { var leaveCurrentSecureConversation: Cmd var createEntryWidget: EntryWidgetBuilder var switchToEngagement: Command + var topBannerItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle } } @@ -77,7 +78,8 @@ extension SecureConversations.TranscriptModel.Environment { shouldShowLeaveSecureConversationDialog: environment.shouldShowLeaveSecureConversationDialog, leaveCurrentSecureConversation: environment.leaveCurrentSecureConversation, createEntryWidget: environment.createEntryWidget, - switchToEngagement: environment.switchToEngagement + switchToEngagement: environment.switchToEngagement, + topBannerItemsStyle: viewFactory.theme.chat.secureMessagingExpandedTopBannerItemsStyle ) } } @@ -117,7 +119,9 @@ extension SecureConversations.TranscriptModel.Environment { shouldShowLeaveSecureConversationDialog: Bool = false, leaveCurrentSecureConversation: Cmd = .nop, createEntryWidget: @escaping EntryWidgetBuilder = { _ in .mock() }, - switchToEngagement: Command = .nop + switchToEngagement: Command = .nop, + // swiftlint:disable:next line_length + secureMessagingExpandedTopBannerItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle = Theme().chatStyle.secureMessagingExpandedTopBannerItemsStyle ) -> Self { Self( fetchFile: fetchFile, @@ -152,7 +156,8 @@ extension SecureConversations.TranscriptModel.Environment { shouldShowLeaveSecureConversationDialog: shouldShowLeaveSecureConversationDialog, leaveCurrentSecureConversation: leaveCurrentSecureConversation, createEntryWidget: createEntryWidget, - switchToEngagement: switchToEngagement + switchToEngagement: switchToEngagement, + topBannerItemsStyle: secureMessagingExpandedTopBannerItemsStyle ) } } diff --git a/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.swift b/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.swift index 19fd259b0..7b8e42317 100644 --- a/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.swift +++ b/GliaWidgets/SecureConversations/ChatTranscript/SecureConversations.TranscriptModel.swift @@ -760,7 +760,8 @@ extension SecureConversations.TranscriptModel { ), showPoweredBy: false, filterSecureConversation: true, - mediaTypeSelected: .init(closure: entryWidgetMediaTypeSelected) + mediaTypeSelected: .init(closure: entryWidgetMediaTypeSelected), + mediaTypeItemsStyle: environment.topBannerItemsStyle ) } diff --git a/GliaWidgets/Sources/EntryWidget/EntryWidget.Configuration.swift b/GliaWidgets/Sources/EntryWidget/EntryWidget.Configuration.swift index 838f9526a..c23ed1856 100644 --- a/GliaWidgets/Sources/EntryWidget/EntryWidget.Configuration.swift +++ b/GliaWidgets/Sources/EntryWidget/EntryWidget.Configuration.swift @@ -20,6 +20,7 @@ extension EntryWidget { let showPoweredBy: Bool let filterSecureConversation: Bool let mediaTypeSelected: Command? + let mediaTypeItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle? } } @@ -37,6 +38,7 @@ extension EntryWidget.Configuration { ), showPoweredBy: true, filterSecureConversation: false, - mediaTypeSelected: nil + mediaTypeSelected: nil, + mediaTypeItemsStyle: nil ) } diff --git a/GliaWidgets/Sources/EntryWidget/EntryWidgetViewModel.swift b/GliaWidgets/Sources/EntryWidget/EntryWidgetViewModel.swift index f5b4f0915..74a17cb56 100644 --- a/GliaWidgets/Sources/EntryWidget/EntryWidgetViewModel.swift +++ b/GliaWidgets/Sources/EntryWidget/EntryWidgetViewModel.swift @@ -8,8 +8,16 @@ extension EntryWidgetView { let configuration: EntryWidget.Configuration let showHeader: Bool var retryMonitoring: (() -> Void)? + var style: EntryWidgetStyle { - theme.entryWidget + if let mediaTypeItemsStyle = configuration.mediaTypeItemsStyle { + var widgetStyle = theme.entryWidgetStyle + widgetStyle.mediaTypeItem = mediaTypeItemsStyle.mediaItemStyle + widgetStyle.dividerColor = mediaTypeItemsStyle.dividerColor + return widgetStyle + } else { + return theme.entryWidgetStyle + } } var showPoweredBy: Bool { diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.Accessibility.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Accessibility.swift similarity index 100% rename from GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.Accessibility.swift rename to GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Accessibility.swift diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.Loading.Accessibility.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Loading.Accessibility.swift similarity index 100% rename from GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.Loading.Accessibility.swift rename to GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Loading.Accessibility.swift diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.Loading.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Loading.swift similarity index 94% rename from GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.Loading.swift rename to GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Loading.swift index d0430a485..9d651eccc 100644 --- a/GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.Loading.swift +++ b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Loading.swift @@ -2,7 +2,7 @@ import Foundation extension EntryWidgetStyle.MediaTypeItemStyle { /// The style of a media type item when it is loading. - public struct LoadingStyle { + public struct LoadingStyle: Equatable { /// The color of the placeholders during the loading state. public var loadingTintColor: ColorType diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Mock.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Mock.swift new file mode 100644 index 000000000..8b0a4fa7b --- /dev/null +++ b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.Mock.swift @@ -0,0 +1,53 @@ +#if DEBUG +import UIKit + +extension EntryWidgetStyle.MediaTypeItemStyle { + static func mock( + chatTitle: String = "Chat", + audioTitle: String = "Audio", + videoTitle: String = "Video", + secureMessagingTitle: String = "Secure messaging", + titleFont: UIFont = .systemFont(ofSize: 16), + titleColor: UIColor = .black, + titleTextStyle: UIFont.TextStyle = .body, + chatMessage: String = "Chat message", + audioMessage: String = "Audio message", + videoMessage: String = "Video message", + secureMessagingMessage: String = "Secure messaging message", + messageFont: UIFont = .systemFont(ofSize: 16), + messageColor: UIColor = .black, + unreadMessagesCounterFont: UIFont = .systemFont(ofSize: 16), + unreadMessagesCounterColor: UIColor = .white, + unreadMessagesCounterBackgroundColor: ColorType = .fill(color: .blue), + messageTextStyle: UIFont.TextStyle = .footnote, + iconColor: ColorType = .fill(color: .blue), + backgroundColor: ColorType = .fill(color: .white), + loading: LoadingStyle = .init(loadingTintColor: .fill(color: .gray)), + accessibility: Accessibility = .unsupported + ) -> Self { + Self( + chatTitle: chatTitle, + audioTitle: audioTitle, + videoTitle: videoTitle, + secureMessagingTitle: secureMessagingTitle, + titleFont: titleFont, + titleColor: titleColor, + titleTextStyle: titleTextStyle, + chatMessage: chatMessage, + audioMessage: audioMessage, + videoMessage: videoMessage, + secureMessagingMessage: secureMessagingMessage, + messageFont: messageFont, + messageColor: messageColor, + unreadMessagesCounterFont: unreadMessagesCounterFont, + unreadMessagesCounterColor: unreadMessagesCounterColor, + unreadMessagesCounterBackgroundColor: unreadMessagesCounterBackgroundColor, + messageTextStyle: messageTextStyle, + iconColor: iconColor, + backgroundColor: backgroundColor, + loading: loading, + accessibility: accessibility + ) + } +} +#endif diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.RemoteConfig.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.RemoteConfig.swift similarity index 100% rename from GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.RemoteConfig.swift rename to GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.RemoteConfig.swift diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.swift similarity index 99% rename from GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.swift rename to GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.swift index b74d41a8f..881ebb5f7 100644 --- a/GliaWidgets/Sources/EntryWidget/MediaTypeItemStyle.swift +++ b/GliaWidgets/Sources/EntryWidget/MediaTypeItem/MediaTypeItemStyle.swift @@ -1,7 +1,7 @@ import UIKit extension EntryWidgetStyle { - public struct MediaTypeItemStyle { + public struct MediaTypeItemStyle: Equatable { /// The title for chat media type. public var chatTitle: String diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.Mock.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.Mock.swift new file mode 100644 index 000000000..f4476f799 --- /dev/null +++ b/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.Mock.swift @@ -0,0 +1,15 @@ +#if DEBUG +import UIKit + +extension EntryWidgetStyle.MediaTypeItemsStyle { + static func mock( + mediaItemStyle: EntryWidgetStyle.MediaTypeItemStyle = .mock(), + dividerColor: UIColor = .gray + ) -> Self { + Self( + mediaItemStyle: mediaItemStyle, + dividerColor: dividerColor + ) + } +} +#endif diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.RemoteConfig.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.RemoteConfig.swift new file mode 100644 index 000000000..761c344d6 --- /dev/null +++ b/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.RemoteConfig.swift @@ -0,0 +1,15 @@ +import UIKit + +extension EntryWidgetStyle.MediaTypeItemsStyle { + mutating func apply( + configuration: RemoteConfiguration.MediaTypeItems?, + assetBuilder: RemoteConfiguration.AssetsBuilder + ) { + mediaItemStyle.apply(configuration: configuration?.mediaTypeItem, assetsBuilder: assetBuilder) + + configuration?.dividerColor?.value + .map { UIColor(hex: $0) } + .first + .unwrap { dividerColor = $0 } + } +} diff --git a/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.swift b/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.swift new file mode 100644 index 000000000..07cb6bd2a --- /dev/null +++ b/GliaWidgets/Sources/EntryWidget/MediaTypeItems/MediaTypeItemsStyle.swift @@ -0,0 +1,22 @@ +import UIKit + +extension EntryWidgetStyle { + public struct MediaTypeItemsStyle: Equatable { + /// The style of media type item. + public var mediaItemStyle: EntryWidgetStyle.MediaTypeItemStyle + + /// The color of the divider. + public var dividerColor: UIColor + + /// - Parameters: + /// - mediaItemStyle: Style of media type item.. + /// - dividerColor: Color of the banner divider. + public init( + mediaItemStyle: EntryWidgetStyle.MediaTypeItemStyle, + dividerColor: UIColor + ) { + self.mediaItemStyle = mediaItemStyle + self.dividerColor = dividerColor + } + } +} diff --git a/GliaWidgets/Sources/Theme/Theme+Chat.swift b/GliaWidgets/Sources/Theme/Theme+Chat.swift index 561e29a5a..c38392400 100644 --- a/GliaWidgets/Sources/Theme/Theme+Chat.swift +++ b/GliaWidgets/Sources/Theme/Theme+Chat.swift @@ -470,6 +470,11 @@ extension Theme { iconColor: color.baseLight ) + let secureMessagingExpandedTopBannerItemsStyle = EntryWidgetStyle.MediaTypeItemsStyle( + mediaItemStyle: entryWidgetStyle.mediaTypeItem, + dividerColor: entryWidgetStyle.dividerColor + ) + return ChatStyle( header: header, connect: connect, @@ -498,7 +503,8 @@ extension Theme { gliaVirtualAssistant: gliaVirtualAssistantStyle, secureMessagingTopBannerStyle: secureMessagingTopBannerStyle, secureMessagingBottomBannerStyle: secureMessagingBottomBannerStyle, - sendingMessageUnavailableBannerViewStyle: sendingMessageUnavailableBannerViewStyle + sendingMessageUnavailableBannerViewStyle: sendingMessageUnavailableBannerViewStyle, + secureMessagingExpandedTopBannerItemsStyle: secureMessagingExpandedTopBannerItemsStyle ) } diff --git a/GliaWidgets/Sources/View/Chat/ChatStyle.Deprecated.swift b/GliaWidgets/Sources/View/Chat/ChatStyle.Deprecated.swift index bc6ddf65f..f05c9123a 100644 --- a/GliaWidgets/Sources/View/Chat/ChatStyle.Deprecated.swift +++ b/GliaWidgets/Sources/View/Chat/ChatStyle.Deprecated.swift @@ -91,7 +91,8 @@ extension ChatStyle { gliaVirtualAssistant: GliaVirtualAssistantStyle, secureMessagingTopBannerStyle: SecureMessagingTopBannerViewStyle, secureMessagingBottomBannerStyle: SecureMessagingBottomBannerViewStyle, - sendingMessageUnavailableBannerViewStyle: SendingMessageUnavailableBannerViewStyle + sendingMessageUnavailableBannerViewStyle: SendingMessageUnavailableBannerViewStyle, + secureMessagingExpandedTopBannerItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle ) { self.init( header: header, @@ -117,7 +118,8 @@ extension ChatStyle { gliaVirtualAssistant: gliaVirtualAssistant, secureMessagingTopBannerStyle: secureMessagingTopBannerStyle, secureMessagingBottomBannerStyle: secureMessagingBottomBannerStyle, - sendingMessageUnavailableBannerViewStyle: sendingMessageUnavailableBannerViewStyle + sendingMessageUnavailableBannerViewStyle: sendingMessageUnavailableBannerViewStyle, + secureMessagingExpandedTopBannerItemsStyle: secureMessagingExpandedTopBannerItemsStyle ) } } diff --git a/GliaWidgets/Sources/View/Chat/ChatStyle.RemoteConfig.swift b/GliaWidgets/Sources/View/Chat/ChatStyle.RemoteConfig.swift index 99fccbeff..c7d5a127d 100644 --- a/GliaWidgets/Sources/View/Chat/ChatStyle.RemoteConfig.swift +++ b/GliaWidgets/Sources/View/Chat/ChatStyle.RemoteConfig.swift @@ -78,6 +78,14 @@ extension ChatStyle { configuration: configuration?.gva, assetBuilder: assetsBuilder ) + secureMessagingTopBannerStyle.apply( + configuration: configuration?.secureMessaging, + assetBuilder: assetsBuilder + ) + secureMessagingExpandedTopBannerItemsStyle.apply( + configuration: configuration?.secureMessaging?.mediaTypeItems, + assetBuilder: assetsBuilder + ) secureMessagingBottomBannerStyle.apply( configuration: configuration?.secureMessaging, assetBuilder: assetsBuilder diff --git a/GliaWidgets/Sources/View/Chat/ChatStyle.swift b/GliaWidgets/Sources/View/Chat/ChatStyle.swift index 08db4175f..932b71e46 100644 --- a/GliaWidgets/Sources/View/Chat/ChatStyle.swift +++ b/GliaWidgets/Sources/View/Chat/ChatStyle.swift @@ -59,6 +59,9 @@ public class ChatStyle: EngagementStyle { /// Style of the secure messaging bottom banner view. public var secureMessagingBottomBannerStyle: SecureMessagingBottomBannerViewStyle + /// Style of the secure messaging expanded top banner view. + public var secureMessagingExpandedTopBannerItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle + /// Style for unavailability to send messages banner view. public var sendingMessageUnavailableBannerViewStyle: SendingMessageUnavailableBannerViewStyle @@ -110,7 +113,8 @@ public class ChatStyle: EngagementStyle { gliaVirtualAssistant: GliaVirtualAssistantStyle, secureMessagingTopBannerStyle: SecureMessagingTopBannerViewStyle, secureMessagingBottomBannerStyle: SecureMessagingBottomBannerViewStyle, - sendingMessageUnavailableBannerViewStyle: SendingMessageUnavailableBannerViewStyle + sendingMessageUnavailableBannerViewStyle: SendingMessageUnavailableBannerViewStyle, + secureMessagingExpandedTopBannerItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle ) { self.title = title self.visitorMessageStyle = visitorMessageStyle @@ -132,6 +136,7 @@ public class ChatStyle: EngagementStyle { self.secureMessagingTopBannerStyle = secureMessagingTopBannerStyle self.secureMessagingBottomBannerStyle = secureMessagingBottomBannerStyle self.sendingMessageUnavailableBannerViewStyle = sendingMessageUnavailableBannerViewStyle + self.secureMessagingExpandedTopBannerItemsStyle = secureMessagingExpandedTopBannerItemsStyle super.init( header: header, diff --git a/GliaWidgetsTests/SecureConversations/ChatTranscript/TranscriptModel.Environment.Failing.swift b/GliaWidgetsTests/SecureConversations/ChatTranscript/TranscriptModel.Environment.Failing.swift index 48821d20e..fff298163 100644 --- a/GliaWidgetsTests/SecureConversations/ChatTranscript/TranscriptModel.Environment.Failing.swift +++ b/GliaWidgetsTests/SecureConversations/ChatTranscript/TranscriptModel.Environment.Failing.swift @@ -87,6 +87,7 @@ extension SecureConversations.TranscriptModel.Environment { }, switchToEngagement: .init { _ in fail("\(Self.self).switchToEngagement") - } + }, + topBannerItemsStyle: .mock() ) } diff --git a/GliaWidgetsTests/Sources/ChatView/ChatStyle.Mock.swift b/GliaWidgetsTests/Sources/ChatView/ChatStyle.Mock.swift index 856015731..adba7c4e9 100644 --- a/GliaWidgetsTests/Sources/ChatView/ChatStyle.Mock.swift +++ b/GliaWidgetsTests/Sources/ChatView/ChatStyle.Mock.swift @@ -26,7 +26,8 @@ extension ChatStyle { gliaVirtualAssistant: GliaVirtualAssistantStyle = .mock(), secureMessagingBottomBannerStyle: SecureMessagingBottomBannerViewStyle = .mock(), secureMessagingTopBannerStyle: SecureMessagingTopBannerViewStyle = .mock(), - sendingMessageUnavailableBannerViewStyle: SendingMessageUnavailableBannerViewStyle = .mock() + sendingMessageUnavailableBannerViewStyle: SendingMessageUnavailableBannerViewStyle = .mock(), + secureMessagingExpandedTopBannerItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle = .mock() ) -> ChatStyle { ChatStyle.init( header: header, @@ -51,7 +52,8 @@ extension ChatStyle { gliaVirtualAssistant: gliaVirtualAssistant, secureMessagingTopBannerStyle: secureMessagingTopBannerStyle, secureMessagingBottomBannerStyle: secureMessagingBottomBannerStyle, - sendingMessageUnavailableBannerViewStyle: sendingMessageUnavailableBannerViewStyle + sendingMessageUnavailableBannerViewStyle: sendingMessageUnavailableBannerViewStyle, + secureMessagingExpandedTopBannerItemsStyle: secureMessagingExpandedTopBannerItemsStyle ) } } diff --git a/GliaWidgetsTests/Sources/EntryWidget/EntryWidget.Mock.swift b/GliaWidgetsTests/Sources/EntryWidget/EntryWidget.Mock.swift index a8fac5277..1df0cdec8 100644 --- a/GliaWidgetsTests/Sources/EntryWidget/EntryWidget.Mock.swift +++ b/GliaWidgetsTests/Sources/EntryWidget/EntryWidget.Mock.swift @@ -5,7 +5,8 @@ extension EntryWidget.Configuration { sizeConstraint: EntryWidget.SizeConstraints? = nil, showPoweredBy: Bool? = nil, filterSecureConversation: Bool? = nil, - mediaTypeSelected: Command? = nil + mediaTypeSelected: Command? = nil, + mediaTypeItemsStyle: EntryWidgetStyle.MediaTypeItemsStyle? = nil ) -> Self { Self( sizeConstraints: sizeConstraint ?? .init( @@ -20,7 +21,8 @@ extension EntryWidget.Configuration { ), showPoweredBy: showPoweredBy ?? true, filterSecureConversation: filterSecureConversation ?? false, - mediaTypeSelected: mediaTypeSelected + mediaTypeSelected: mediaTypeSelected, + mediaTypeItemsStyle: mediaTypeItemsStyle ) } } diff --git a/GliaWidgetsTests/Sources/EntryWidget/EntryWidgetViewModelTests.swift b/GliaWidgetsTests/Sources/EntryWidget/EntryWidgetViewModelTests.swift index b56247c89..300976a22 100644 --- a/GliaWidgetsTests/Sources/EntryWidget/EntryWidgetViewModelTests.swift +++ b/GliaWidgetsTests/Sources/EntryWidget/EntryWidgetViewModelTests.swift @@ -46,4 +46,49 @@ class EntryWidgetViewModelTests: XCTestCase { XCTAssertFalse(viewModel.showPoweredBy) } + + func test_viewModelUsesDefaultStyleFromTheme() { + let entryWidget = EntryWidget.mock() + let theme = Theme.mock() + let viewModel = EntryWidgetView.Model( + theme: theme, + showHeader: true, + configuration: .mock(showPoweredBy: true), + viewStatePublisher: entryWidget.$viewState, + mediaTypeSelected: { _ in } + ) + + XCTAssertEqual( + viewModel.style.mediaTypeItem, + theme.chatStyle.secureMessagingExpandedTopBannerItemsStyle.mediaItemStyle + ) + XCTAssertEqual( + viewModel.style.dividerColor, + theme.chatStyle.secureMessagingExpandedTopBannerItemsStyle.dividerColor + ) + } + + func test_viewModelUsesConfiguredMediaTypeItemsStyle() { + let entryWidget = EntryWidget.mock() + let theme = Theme.mock() + let mockStyle = EntryWidgetStyle.MediaTypeItemsStyle.mock() + let viewModel = EntryWidgetView.Model( + theme: theme, + showHeader: true, + configuration: .mock(showPoweredBy: true, mediaTypeItemsStyle: mockStyle), + viewStatePublisher: entryWidget.$viewState, + mediaTypeSelected: { _ in } + ) + + XCTAssertEqual(viewModel.style.mediaTypeItem, mockStyle.mediaItemStyle) + XCTAssertEqual(viewModel.style.dividerColor, mockStyle.dividerColor) + XCTAssertNotEqual( + viewModel.style.mediaTypeItem, + theme.chatStyle.secureMessagingExpandedTopBannerItemsStyle.mediaItemStyle + ) + XCTAssertNotEqual( + viewModel.style.dividerColor, + theme.chatStyle.secureMessagingExpandedTopBannerItemsStyle.dividerColor + ) + } }