Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entry widget and secure conversations v2 #1036

Draft
wants to merge 74 commits into
base: development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
34fc21a
Update dependencies declared in `Podfile` and `Package.swift`
Nov 11, 2024
8eb8444
Add EntryWidget UI
rasmustautsglia Sep 23, 2024
93afead
Add Engagement Launcher interface and getter from Glia
ykyivskyi-gl Sep 25, 2024
5c2d22d
Add EntryWidget embedded view
rasmustautsglia Sep 26, 2024
db3e355
Implement EngagementLauncher logic
ykyivskyi-gl Sep 30, 2024
6a52c27
Add Unified Customization to EntryWidget
rasmustautsglia Oct 3, 2024
5bd0fda
Update Entry Widget media types texts
rasmustautsglia Oct 8, 2024
7abf3cd
Implement QueuesMonitor to observe queues' engagement type updates
ykyivskyi-gl Oct 8, 2024
77fe018
Add remote configuration for secure conversations
igorkravchenko Oct 11, 2024
59aff6e
Integrate queues monitor and engagement launcher into EntryWidget
ykyivskyi-gl Oct 13, 2024
68010a5
Add new localization keys and update existing for local strings for SC
igorkravchenko Oct 14, 2024
6b5ed3b
Make entry widget height dynamic
rasmustautsglia Oct 16, 2024
0c62041
Update 'Check Messages' button and margins on SC Welcome screen
igorkravchenko Oct 15, 2024
9e1e4cf
Add new public interfaces to the Entry Widget
rasmustautsglia Oct 18, 2024
fcd1213
Cover QueuesMonitor with unit tests
ykyivskyi-gl Oct 18, 2024
db032c8
Add new localizations for the Entry Widget.
AndriiHorishniiMOC Oct 16, 2024
a2b3df2
Add Entry Widget Loading view design
rasmustautsglia Oct 21, 2024
2e3c1c2
Introduce SC bottom banner UI on chat screen
igorkravchenko Oct 21, 2024
af16a01
Implement unified customization for SC bottom banner
igorkravchenko Oct 23, 2024
7c8de73
Make passed getEngagementLauncher queuesId paramater non-nullable
ykyivskyi-gl Oct 24, 2024
feea833
Leave Current Conversation dialog UI
Oct 25, 2024
5d02ccd
Remote config for Leave Current Conversation dialog
Oct 25, 2024
854c22c
Hide the "Secure Messaging" if visitor is not authenticated
rasmustautsglia Oct 24, 2024
34e7833
Snapshot tests for Leave Current Conversation dialog
Oct 25, 2024
cfb1cbc
Add accessibility modifiers to the Entry Widget
AndriiHorishniiMOC Oct 22, 2024
1eb6ae8
Add new send message unavailability banner
igorkravchenko Oct 24, 2024
40aefc5
Add unified customization for new SC unavailability indicator for chat
igorkravchenko Oct 26, 2024
d7d8252
Make EntryWidget sheet landscape adaptable
rasmustautsglia Oct 28, 2024
49aa424
Replace unavailability dialog with banner view on Transcript screen
igorkravchenko Oct 28, 2024
3a5569a
Toggle SC bottom banner visibility based on view model
igorkravchenko Oct 29, 2024
8155cd3
Use queues from QueuesMonitor to determine Secure Conversations avail…
ykyivskyi-gl Oct 30, 2024
265105f
Improve the Entry Widget Style structures
AndriiHorishniiMOC Oct 28, 2024
b89d0a6
Hide EntryWidget sheet before engagement
rasmustautsglia Nov 4, 2024
3f738ab
Add snapshot tests to EntryWidget
rasmustautsglia Nov 1, 2024
d9bbf22
Remove rebasing issue
rasmustautsglia Nov 5, 2024
fdd95d4
Optimize using of strings for the Entry Widget
AndriiHorishniiMOC Nov 4, 2024
89974ea
Introduce disabled state for ChatMessageEntry style
igorkravchenko Nov 2, 2024
ecfc23a
Bump up deployment target from iOS 13 to 14
AndriiHorishniiMOC Nov 6, 2024
2affe9e
Introduce disabled state for file upload list
igorkravchenko Nov 7, 2024
68560d3
Update dependencies declared in `Podfile` and `Package.swift`
Nov 12, 2024
d9e5420
Disable send message and pick media buttons instead of hiding them
igorkravchenko Nov 11, 2024
7c5a60a
Chat to Secure Conversation transfer
Nov 8, 2024
e5a3d43
Add SC unread message badge on Entry Widget
ykyivskyi-gl Nov 11, 2024
fdf5d87
Add logs and telemetry for Entry Widget
rasmustautsglia Nov 12, 2024
5fd5a3b
Update default global colors according to color palette
igorkravchenko Oct 22, 2024
5a52b54
Remove deprecated and existing startEngagement methods
ykyivskyi-gl Nov 14, 2024
5efb1c8
Fix remote configuration not being applied to Entry Widget
rasmustautsglia Nov 15, 2024
dc927a2
Change Chat Button label in EntryWidget
rasmustautsglia Nov 13, 2024
9ea2333
SecureConversation business logic
Nov 18, 2024
8049031
Add disabled unified customization for disabled state for chat messag…
AndriiHorishniiMOC Nov 15, 2024
f8943d7
Add snapshot tests for bottom banner
igorkravchenko Nov 19, 2024
1ed5665
Add entry point for EntryWidget for Secure Conversation
ykyivskyi-gl Nov 20, 2024
84b5137
ViewController refactoring
Nov 20, 2024
892a2d9
Add pending secure messaging logic to EntryWidget
Nov 19, 2024
9ef8591
Apply Unified UI for the SC
AndriiHorishniiMOC Nov 20, 2024
8ba7c71
Change subheadline color In EntryWidget
rasmustautsglia Nov 20, 2024
92ed9b3
Extend SCv2 logic with unreadMessageCount
Nov 25, 2024
2881222
Add accessibility identifiers to Entry Widget items
AndriiHorishniiMOC Nov 25, 2024
46b401c
Bump up Core SDK version to 2.0.2 and update SC interface
igorkravchenko Nov 27, 2024
0382f24
Show Entry Widget on SC top banner click
ykyivskyi-gl Nov 26, 2024
e58aee8
Add Unit and Snapshot tests for top banner on Secure Conversations
ykyivskyi-gl Nov 28, 2024
f307f55
Fix memory leak in Chat module
Nov 28, 2024
d6e9a3c
Apply unified UI for SC's top banner on ChatView
ykyivskyi-gl Nov 29, 2024
0cafd2c
Isolate pending interaction logic in separate model
igorkravchenko Nov 29, 2024
f59d414
Fix strict version in Podfile.lock
Dec 6, 2024
cde6e59
Improve mark as read SC messages
ykyivskyi-gl Dec 5, 2024
c2dbc0e
Address unavailability banner showing up for SC flow
igorkravchenko Dec 5, 2024
ef35aef
Update SC availability taking into account 'transferring' state
igorkravchenko Dec 5, 2024
3f50686
Create PendingInteraction model after configuration
igorkravchenko Dec 11, 2024
15c0b41
Update dependencies declared in `Podfile` and `Package.swift`
Dec 13, 2024
e2ee5e6
Handle ongoing engagement in EntryWidget
rasmustautsglia Dec 6, 2024
3b18dad
Create interface for resuming call visualizer
rasmustautsglia Dec 17, 2024
59069f2
Add a state property to determine resume behavior
rasmustautsglia Dec 19, 2024
db2b9a3
Fill area under message entry with same bg color as message entry
igorkravchenko Dec 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions GliaWidgets.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Pod::Spec.new do |s|
s.source = { :git => 'https://github.com/salemove/ios-sdk-widgets.git', :tag => s.version.to_s }

s.module_name = 'GliaWidgets'
s.ios.deployment_target = '13.0'
s.ios.deployment_target = '14.0'
s.source_files = 'GliaWidgets/**/*.swift'
s.swift_version = '5.3'

Expand All @@ -19,5 +19,5 @@ Pod::Spec.new do |s|
}
s.exclude_files = ['GliaWidgets/Window/**']

s.dependency 'GliaCoreSDK', '1.5.8'
s.dependency 'GliaCoreSDK', '2.0.4'
end
470 changes: 438 additions & 32 deletions GliaWidgets.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions GliaWidgets/Asset.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ public enum Asset {
public static let uploadRemove = ImageAsset(name: "uploadRemove")
public static let chatPickMedia = ImageAsset(name: "chatPickMedia")
public static let chatSend = ImageAsset(name: "chatSend")
public static let sendMessageUnavailableInfo = ImageAsset(name: "send-message-unavailable-info")
public static let unreadMessageIndicator = ImageAsset(name: "unreadMessageIndicator")
public static let back = ImageAsset(name: "back")
public static let close = ImageAsset(name: "close")
public static let browseIcon = ImageAsset(name: "browseIcon")
public static let cameraIcon = ImageAsset(name: "cameraIcon")
public static let chevronDownIcon = ImageAsset(name: "chevronDownIcon")
public static let photoLibraryIcon = ImageAsset(name: "photoLibraryIcon")
public static let gliaLogo = ImageAsset(name: "gliaLogo")
public static let startScreenShare = ImageAsset(name: "startScreenShare")
Expand Down Expand Up @@ -109,11 +111,13 @@ public enum Asset {
uploadRemove,
chatPickMedia,
chatSend,
sendMessageUnavailableInfo,
unreadMessageIndicator,
back,
close,
browseIcon,
cameraIcon,
chevronDownIcon,
photoLibraryIcon,
gliaLogo,
startScreenShare,
Expand Down
10 changes: 5 additions & 5 deletions GliaWidgets/Color.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import UIKit

enum Color {
static let primary = UIColor(hex: 0x0F6BFF) // blue
static let secondary = UIColor(hex: 0x00B233) // green
static let secondary = UIColor(hex: 0x18901C) // green
static let baseLight = UIColor(hex: 0xFFFFFF) // white
static let systemNegative = UIColor(hex: 0xD11149) // red
static let baseNormal = UIColor(hex: 0x6C7683) // grey
static let baseShade = UIColor(hex: 0x6C7683, alpha: 0.5)
static let systemNegative = UIColor(hex: 0xBC0F42) // red
static let baseNormal = UIColor(hex: 0x616A75) // gray
static let baseShade = UIColor(hex: 0xB6BBC1) // mid-gray
static let baseDark = UIColor(hex: 0x2C0735) // purple
static let baseNeutral = UIColor(hex: 0xF3F3F3) // light gray
static let baseNeutral = UIColor(hex: 0xF7F7F7) // light gray
}
142 changes: 130 additions & 12 deletions GliaWidgets/Localization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -432,14 +432,106 @@ internal enum Localization {
internal static var message: String { Localization.tr("Localizable", "engagement.queue_wait.message", fallback: "You can continue browsing and we will connect you automatically.") }
}
internal enum SecureMessaging {
/// Messaging
internal static var title: String { Localization.tr("Localizable", "engagement.secure_messaging.title", fallback: "Messaging") }
/// Secure Messaging
internal static var title: String { Localization.tr("Localizable", "engagement.secure_messaging.title", fallback: "Secure Messaging") }
}
internal enum Video {
/// Video
internal static var title: String { Localization.tr("Localizable", "engagement.video.title", fallback: "Video") }
}
}
internal enum EntryWidget {
internal enum Audio {
internal enum Button {
/// Speak through your device
internal static var description: String { Localization.tr("Localizable", "entry_widget.audio.button.description", fallback: "Speak through your device") }
/// Audio
internal static var label: String { Localization.tr("Localizable", "entry_widget.audio.button.label", fallback: "Audio") }
internal enum Accessibility {
/// Starts a call
internal static var hint: String { Localization.tr("Localizable", "entry_widget.audio.button.accessibility.hint", fallback: "Starts a call") }
}
}
}
internal enum CallVisualizer {
/// Screen sharing in progress
internal static var desciption: String { Localization.tr("Localizable", "entry_widget.call_visualizer.desciption", fallback: "Screen sharing in progress") }
internal enum Button {
/// Call Visualizer
internal static var label: String { Localization.tr("Localizable", "entry_widget.call_visualizer.button.label", fallback: "Call Visualizer") }
}
}
internal enum EmptyState {
/// We are here to assist you during our business hours.
internal static var description: String { Localization.tr("Localizable", "entry_widget.empty_state.description", fallback: "We are here to assist you during our business hours.") }
/// Support team is currently offline
internal static var title: String { Localization.tr("Localizable", "entry_widget.empty_state.title", fallback: "Support team is currently offline") }
}
internal enum ErrorState {
/// We could not load the contacts at this time. This may be due to a temporary syncing issue or network problem.
internal static var description: String { Localization.tr("Localizable", "entry_widget.error_state.description", fallback: "We could not load the contacts at this time. This may be due to a temporary syncing issue or network problem.") }
/// Could not load the contacts
internal static var title: String { Localization.tr("Localizable", "entry_widget.error_state.title", fallback: "Could not load the contacts") }
internal enum TryAgain {
internal enum Button {
/// Try again
internal static var label: String { Localization.tr("Localizable", "entry_widget.error_state.try_again.button.label", fallback: "Try again") }
}
}
}
internal enum LiveChat {
internal enum Button {
/// For the texter in all of us
internal static var description: String { Localization.tr("Localizable", "entry_widget.live_chat.button.description", fallback: "For the texter in all of us") }
/// Chat
internal static var label: String { Localization.tr("Localizable", "entry_widget.live_chat.button.label", fallback: "Chat") }
internal enum Accessibility {
/// Starts a chat
internal static var hint: String { Localization.tr("Localizable", "entry_widget.live_chat.button.accessibility.hint", fallback: "Starts a chat") }
}
}
}
internal enum Loading {
internal enum Accessibility {
/// Loading indicator. Waiting for available options.
internal static var label: String { Localization.tr("Localizable", "entry_widget.loading.accessibility.label", fallback: "Loading indicator. Waiting for available options.") }
}
}
internal enum OngoingEngagement {
/// Ongoing • Tap to return
internal static var description: String { Localization.tr("Localizable", "entry_widget.ongoing_engagement.description", fallback: "Ongoing • Tap to return") }
internal enum Button {
internal enum Accessibility {
/// Returns to ongoing engagement
internal static var hint: String { Localization.tr("Localizable", "entry_widget.ongoing_engagement.button.accessibility.hint", fallback: "Returns to ongoing engagement") }
}
}
}
internal enum SecureMessaging {
internal enum Button {
/// Start a conversation, we’ll get back to you
internal static var description: String { Localization.tr("Localizable", "entry_widget.secure_messaging.button.description", fallback: "Start a conversation, we’ll get back to you") }
/// Secure Messaging
internal static var label: String { Localization.tr("Localizable", "entry_widget.secure_messaging.button.label", fallback: "Secure Messaging") }
internal enum Accessibility {
/// Starts messaging with us
internal static var hint: String { Localization.tr("Localizable", "entry_widget.secure_messaging.button.accessibility.hint", fallback: "Starts messaging with us") }
}
}
}
internal enum Video {
internal enum Button {
/// Face-to-face, just like in person
internal static var description: String { Localization.tr("Localizable", "entry_widget.video.button.description", fallback: "Face-to-face, just like in person") }
/// Video
internal static var label: String { Localization.tr("Localizable", "entry_widget.video.button.label", fallback: "Video") }
internal enum Accessibility {
/// Starts a video call
internal static var hint: String { Localization.tr("Localizable", "entry_widget.video.button.accessibility.hint", fallback: "Starts a video call") }
}
}
}
}
internal enum Error {
/// Something went wrong.
internal static var general: String { Localization.tr("Localizable", "error.general", fallback: "Something went wrong.") }
Expand Down Expand Up @@ -563,11 +655,11 @@ internal enum Localization {
}
}
internal enum MessageCenter {
/// Messaging
internal static var header: String { Localization.tr("Localizable", "message_center.header", fallback: "Messaging") }
/// Secure Messaging
internal static var header: String { Localization.tr("Localizable", "message_center.header", fallback: "Secure Messaging") }
internal enum Confirmation {
/// Your message has been sent. We will get back to you within 48 hours.
internal static var subtitle: String { Localization.tr("Localizable", "message_center.confirmation.subtitle", fallback: "Your message has been sent. We will get back to you within 48 hours.") }
/// Your message has been sent. We will get back to you within 1 business day.
internal static var subtitle: String { Localization.tr("Localizable", "message_center.confirmation.subtitle", fallback: "Your message has been sent. We will get back to you within 1 business day.") }
internal enum CheckMessages {
internal enum Accessibility {
/// Navigates you to the chat transcript.
Expand All @@ -592,10 +684,10 @@ internal enum Localization {
internal static var checkMessages: String { Localization.tr("Localizable", "message_center.welcome.check_messages", fallback: "Check messages") }
/// Your message
internal static var messageTitle: String { Localization.tr("Localizable", "message_center.welcome.message_title", fallback: "Your message") }
/// Send a message and we will get back to you within 48 hours.
internal static var subtitle: String { Localization.tr("Localizable", "message_center.welcome.subtitle", fallback: "Send a message and we will get back to you within 48 hours.") }
/// Welcome to Message Center
internal static var title: String { Localization.tr("Localizable", "message_center.welcome.title", fallback: "Welcome to Message Center") }
/// Send a message and we will get back to you within 1 business day.
internal static var subtitle: String { Localization.tr("Localizable", "message_center.welcome.subtitle", fallback: "Send a message and we will get back to you within 1 business day.") }
/// Welcome to Secure Messaging
internal static var title: String { Localization.tr("Localizable", "message_center.welcome.title", fallback: "Welcome to Secure Messaging") }
internal enum CheckMessages {
internal enum Accessibility {
/// Navigates you to the chat transcript.
Expand All @@ -611,8 +703,8 @@ internal enum Localization {
}
}
internal enum MessageInput {
/// Enter your message
internal static var placeholder: String { Localization.tr("Localizable", "message_center.welcome.message_input.placeholder", fallback: "Enter your message") }
/// Enter message
internal static var placeholder: String { Localization.tr("Localizable", "message_center.welcome.message_input.placeholder", fallback: "Enter message") }
}
internal enum MessageLength {
/// The message cannot exceed 10,000 characters.
Expand Down Expand Up @@ -644,6 +736,32 @@ internal enum Localization {
}
}
}
internal enum SecureMessaging {
internal enum Chat {
internal enum Banner {
/// Secure messaging has an expected response time of 1 business day.
internal static var bottom: String { Localization.tr("Localizable", "secure_messaging.chat.banner.bottom", fallback: "Secure messaging has an expected response time of 1 business day.") }
/// Need live support?
internal static var top: String { Localization.tr("Localizable", "secure_messaging.chat.banner.top", fallback: "Need live support?") }
}
internal enum LeaveCurrentConversation {
/// You have an ongoing conversation. Starting a new conversation before ongoing ones are resolved may lead to our agents overlooking your current query.
internal static var message: String { Localization.tr("Localizable", "secure_messaging.chat.leave_current_conversation.message", fallback: "You have an ongoing conversation. Starting a new conversation before ongoing ones are resolved may lead to our agents overlooking your current query.") }
/// Leave Current Conversation?
internal static var title: String { Localization.tr("Localizable", "secure_messaging.chat.leave_current_conversation.title", fallback: "Leave Current Conversation?") }
internal enum Button {
/// Leave
internal static var negative: String { Localization.tr("Localizable", "secure_messaging.chat.leave_current_conversation.button.negative", fallback: "Leave") }
/// Stay
internal static var positive: String { Localization.tr("Localizable", "secure_messaging.chat.leave_current_conversation.button.positive", fallback: "Stay") }
}
}
internal enum Unavailable {
/// Sending messages is currently not available.
internal static var message: String { Localization.tr("Localizable", "secure_messaging.chat.unavailable.message", fallback: "Sending messages is currently not available.") }
}
}
}
internal enum Survey {
internal enum Action {
/// Please provide an answer.
Expand Down
26 changes: 26 additions & 0 deletions GliaWidgets/Public/Glia/Glia+EngagementLauncher.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

extension Glia {
/// Retrieves an instance of `EngagementLauncher`.
///
/// - Parameters:
/// - queueIds: A list of queue IDs to be used for the engagement launcher. When nil, the default queues will be used.
///
/// - Returns:
/// - `EngagementLauncher` instance.
public func getEngagementLauncher(queueIds: [String]) throws -> EngagementLauncher {
let parameters = try getEngagementParameters(in: queueIds)
loggerPhase.logger.info("Returning an Engagement Launcher")
return try EngagementLauncher { [weak self] engagementKind, sceneProvider in
try self?.resolveEngagementState(
engagementKind: engagementKind,
sceneProvider: sceneProvider,
configuration: parameters.configuration,
interactor: parameters.interactor,
features: parameters.features,
viewFactory: parameters.viewFactory,
ongoingEngagementMediaStreams: parameters.ongoingEngagementMediaStreams
)
}
}
}
Loading
Loading