A SwiftUI Chat UI framework with fully customizable message cells and a built-in media picker
We are a development agency building
phenomenal apps.
Features
Displays your messages with pagination and allows you to create and “send” new messages (sending means calling a closure since user will be the one providing actual API calls)
Allows you to pass a custom view builder for messages and input views
Has a built-in photo and video library/camera picker for multiple media asset selection
Can display a fullscreen menu on long press a message cell (automatically shows scroll for big messages)
Supports “reply to message” via message menu. Remove and edit are coming soon
Supports voice recording, video/photo and text. More content types are coming soon
Usage
Create a chat view like this:
@State var messages: [Message] = []
var body: some View {
ChatView(messages: messages) { draft in
yourViewModel.send(draft: draft)
}
}
where: messages - list of messages to display didSendMessage - a closure which is called when the user presses the send button
Message is a type that Chat uses for the internal implementation. In the code above it expects the user to provide a list of Message structs, and it returns a DraftMessage in the didSendMessage closure. You can map it both ways to your own Message model that your API expects.
Customization
You may customize message cells like this:
ChatView(messages: viewModel.messages) { draft in
viewModel.send(draft: draft)
} messageBuilder: { message, positionInGroup, showAttachmentClosure in
VStack {
Text(message.text)
if !message.attachments.isEmpty {
ForEach(message.attachments, id: \.id) { at in
AsyncImage(url: at.thumbnail)
}
}
}
}
messageBuilder‘s parameters:
message - the message containing user info, attachments, etc.
positionInGroup - the position of the message in its continuous collection of messages from the same user
showAttachmentClosure - you can pass an attachment to this closure to use ChatView’s fullscreen media viewer
You may customize the input view (a text field with buttons at the bottom) like this:
ChatView(messages: viewModel.messages) { draft in
viewModel.send(draft: draft)
} inputViewBuilder: { textBinding, attachments, state, style, actionClosure in
Group {
switch style {
case .message: // input view on chat screen
VStack {
HStack {
Button("Send") { actionClosure(.send) }
Button("Attach") { actionClosure(.photo) }
}
TextField("Write your message", text: textBinding)
}
case .signature: // input view on photo selection screen
VStack {
HStack {
Button("Send") { actionClosure(.send) }
}
TextField("Compose a signature for photo", text: textBinding)
.background(Color.green)
}
}
}
}
inputViewBuilder‘s parameters:
textBinding to bind your own TextField
attachments is a struct containing photos, videos, recordings and a message you are replying to
state - the state of the input view that is controled by the library automatically if possible or through your calls of actionClosure
style - .message or .signature (the chat screen or the photo selection screen)
actionClosure is called on taps on your custom buttons. For example, call actionClosure(.send) if you want to send your message, then the library will reset the text and attachments and call the didSendMessage sending closure
Supported content types
This library allows to send the following content in messages in any combination:
Text with/without markdown
Photo/video
Audio recording
Coming soon:
User’s location
Documents
Modifiers
If you are not using your own messageBuilder: avatarSize - the default avatar is a circle, you can specify its diameter here messageUseMarkdown - whether the default message cell uses markdown assetsPickerLimit - the maximum media count that the user can select in the media picker enableLoadMore(offset: Int, handler: @escaping ChatPaginationClosure) - when user scrolls to offset-th message from the end, call the handler function, so the user can load more messages chatNavigation(title: String, status: String? = nil, cover: URL? = nil) - pass the info for the Chat’s navigation bar
Example
To try out the Chat examples:
Clone the repo git clone git@github.com:exyte/Chat.git
Chat
A SwiftUI Chat UI framework with fully customizable message cells and a built-in media picker
We are a development agency building phenomenal apps.
Features
Usage
Create a chat view like this:
where:
messages
- list of messages to displaydidSendMessage
- a closure which is called when the user presses the send buttonMessage
is a type thatChat
uses for the internal implementation. In the code above it expects the user to provide a list ofMessage
structs, and it returns aDraftMessage
in thedidSendMessage
closure. You can map it both ways to your ownMessage
model that your API expects.Customization
You may customize message cells like this:
messageBuilder
‘s parameters:message
- the message containing user info, attachments, etc.positionInGroup
- the position of the message in its continuous collection of messages from the same usershowAttachmentClosure
- you can pass an attachment to this closure to use ChatView’s fullscreen media viewerYou may customize the input view (a text field with buttons at the bottom) like this:
inputViewBuilder
‘s parameters:textBinding
to bind your own TextFieldattachments
is a struct containing photos, videos, recordings and a message you are replying tostate
- the state of the input view that is controled by the library automatically if possible or through your calls ofactionClosure
style
-.message
or.signature
(the chat screen or the photo selection screen)actionClosure
is called on taps on your custom buttons. For example, callactionClosure(.send)
if you want to send your message, then the library will reset the text and attachments and call thedidSendMessage
sending closureSupported content types
This library allows to send the following content in messages in any combination:
Coming soon:
Modifiers
If you are not using your own
messageBuilder
:avatarSize
- the default avatar is a circle, you can specify its diameter heremessageUseMarkdown
- whether the default message cell uses markdownassetsPickerLimit
- the maximum media count that the user can select in the media pickerenableLoadMore(offset: Int, handler: @escaping ChatPaginationClosure)
- when user scrolls tooffset
-th message from the end, call the handler function, so the user can load more messageschatNavigation(title: String, status: String? = nil, cover: URL? = nil)
- pass the info for the Chat’s navigation barExample
To try out the Chat examples:
git clone git@github.com:exyte/Chat.git
cd <ChatRepo>/Example
Installation
Swift Package Manager
CocoaPods
Carthage
Requirements
Our other open source SwiftUI libraries
PopupView - Toasts and popups library
Grid - The most powerful Grid container
ScalingHeaderScrollView - A scroll view with a sticky header which shrinks as you scroll
AnimatedTabBar - A tabbar with number of preset animations
MediaPicker - Customizable media picker
ConcentricOnboarding - Animated onboarding flow
FloatingButton - Floating button menu
ActivityIndicatorView - A number of animated loading indicators
ProgressIndicatorView - A number of animated progress indicators
SVGView - SVG parser
LiquidSwipe - Liquid navigation animation