Project Icon

Chat

SwiftUI聊天UI框架 自定义消息和内置媒体选择

Chat是一个基于SwiftUI的开源聊天UI框架,提供可自定义消息单元和内置媒体选择器。主要功能包括分页显示消息、发送新消息、自定义视图、多媒体选择和全屏消息菜单等。目前支持文本、照片、视频和音频消息,计划扩展到位置、文档和链接预览。框架设计灵活,支持多种聊天类型和回复模式,可用于开发各类聊天应用。

     

聊天媒体语音消息附加功能

聊天

一个SwiftUI聊天UI框架,具有完全可自定义的消息单元格和内置的媒体选择器

SPM Compatible Cocoapods Compatible Carthage Compatible License: MIT

功能

  • 显示您的消息并支持分页,允许您创建和"发送"新消息(发送意味着调用闭包,因为用户将提供实际的API调用)
  • 允许您为消息和输入视图传递自定义视图构建器
  • 内置照片和视频库/相机选择器,支持多媒体资产选择
  • 可以在长按消息单元格时显示全屏菜单(自动为长消息显示滚动)
  • 通过消息菜单或闭包支持"回复消息"。删除和编辑功能即将推出
  • 该库允许在消息中以任意组合发送以下内容:
    • 带/不带markdown的文本
    • 照片/视频
    • 音频录音 即将推出:
    • 用户位置
    • 文档
    • 带预览的链接

使用方法

像这样创建一个聊天视图:

@State var messages: [Message] = []

var body: some View {
    ChatView(messages: messages) { draft in
        yourViewModel.send(draft: draft)
    }
}

其中:
messages - 要显示的消息列表
didSendMessage - 用户按下发送按钮时调用的闭包

MessageChat用于内部实现的类型。在上面的代码中,它期望用户提供一个Message结构体列表,并在didSendMessage闭包中返回一个DraftMessage。您可以将其双向映射到您的API期望的自己的Message模型,或者按原样使用。

可用的聊天类型

聊天类型 - 决定消息的顺序和新消息动画的方向。可用选项:

  • conversation - 最新消息在底部,新消息从底部出现
  • comments - 最新消息在顶部,新消息从顶部出现

回复模式 - 决定回复消息的显示方式。可用选项:

  • quote - 当回复消息A时,新消息将作为最新消息出现,在其正文中引用消息A
  • answer - 当回复消息A时,新消息将直接出现在消息A下方作为单独的单元格,而不在其正文中重复消息A

要指定这些选项,可以通过init传递:

ChatView(messages: viewModel.messages, chatType: .comments, replyMode: .answer) { draft in
    yourViewModel.send(draft: draft)
}

自定义UI

您可以这样自定义消息单元格:

ChatView(messages: viewModel.messages) { draft in
    viewModel.send(draft: draft)
} messageBuilder: { message, positionInUserGroup, positionInCommentsGroup, showContextMenuClosure, messageActionClosure, showAttachmentClosure in
    VStack {
        Text(message.text)
        if !message.attachments.isEmpty {
            ForEach(message.attachments, id: \.id) { at in
                AsyncImage(url: at.thumbnail)
            }
        }
    }
}

messageBuilder的参数:

  • message - 包含用户信息、附件等的消息
  • positionInUserGroup - 消息在同一用户连续消息集合中的位置
  • positionInCommentsGroup - 消息在其连续评论组中的位置(仅适用于.answer回复模式,.quote模式下为nil)
  • showContextMenuClosure - 显示消息上下文菜单的闭包
  • messageActionClosure - 传递用户交互的闭包,例如.reply
  • showAttachmentClosure - 您可以将附件传递给此闭包以使用ChatView的全屏媒体查看器

您可以这样自定义输入视图(底部带按钮的文本字段):

ChatView(messages: viewModel.messages) { draft in
    viewModel.send(draft: draft)
} inputViewBuilder: { textBinding, attachments, inputViewState, inputViewStyle, inputViewActionClosure, dismissKeyboardClosure in
    Group {
        switch inputViewStyle {
        case .message: // 聊天屏幕上的输入视图
            VStack {
                HStack {
                    Button("发送") { inputViewActionClosure(.send) }
                    Button("附加") { inputViewActionClosure(.photo) }
                }
                TextField("输入您的消息", text: textBinding)
            }
        case .signature: // 照片选择屏幕上的输入视图
            VStack {
                HStack {
                    Button("发送") { inputViewActionClosure(.send) }
                }
                TextField("为照片添加说明", text: textBinding)
                    .background(Color.green)
            }
        }
    }
}

inputViewBuilder的参数:

  • textBinding 用于绑定您自己的TextField
  • attachments 是一个包含照片、视频、录音和您正在回复的消息的结构体
  • inputViewState - 输入视图的状态,如果可能,由库自动控制,或通过您调用inputViewActionClosure来控制
  • inputViewStyle - .message.signature(聊天屏幕或照片选择屏幕)
  • inputViewActionClosure 用于在点击您的自定义按钮时调用。例如,如果您想用自己的按钮发送消息,可以调用inputViewActionClosure(.send),然后库会重置文本和附件并调用didSendMessage发送闭包
  • dismissKeyboardClosure - 调用此闭包以关闭键盘

自定义消息菜单

长按消息将显示该消息的菜单(可以关闭,请参见修饰符)。要定义自定义消息菜单操作,请声明一个符合MessageMenuAction的枚举。然后,如果您将枚举的名称传递给它,库将在长按消息时显示您的自定义菜单选项,而不是默认选项(请参见代码示例)。一旦选择了操作,将调用特殊回调。这里是一个简单的例子:

enum Action: MessageMenuAction {
    case reply, edit

    func title() -> String {
        switch self {
        case .reply:
            "回复"
        case .edit:
            "编辑"
        }
    }
    
    func icon() -> Image {
        switch self {
        case .reply:
            Image(systemName: "arrowshape.turn.up.left")
        case .edit:
            Image(systemName: "square.and.pencil")
        }
    }
}
ChatView(messages: viewModel.messages) { draft in
    viewModel.send(draft: draft)
} messageMenuAction: { (action: Action, defaultActionClosure, message) in // <-- 在这里:指定你的 `MessageMenuAction` 枚举的名称
    switch action {
    case .reply:
        defaultActionClosure(message, .reply)
    case .edit:
        defaultActionClosure(message, .edit { editedText in
            // 在你的后端更新这条消息的文本
            print(editedText)
        })
    }
}

messageMenuAction 的参数:

  • selectedMenuAction - 用户从菜单中选择的操作。注意:声明这个变量时,需要明确指定其类型(你自定义的 MessageMenuAction 的子类)
  • defaultActionClosure - 一个闭包,接受 MessageMenuAction 默认实现的案例,提供简单的操作处理器;如果你需要默认操作,可以调用这个闭包,传入选中的消息并选择一个默认操作(.reply, .edit);或者你可以为所有操作编写自定义实现,在这种情况下只需忽略这个闭包
  • message - 显示菜单的消息

在实现你自己的 MessageMenuActionClosure 时,编写一个 switch 语句遍历你的 MessageMenuAction 的所有情况,在每个 case 中编写你自己的操作处理器,或者调用默认的处理器。注意:并非所有默认操作都能开箱即用 - 例如,对于 .edit,你仍需提供一个闭包来在后端保存编辑后的文本。请参考 ChatExample 项目中的 CommentsExampleView 以了解 MessageMenuActionClosure 的使用示例。

小型视图构建器:

这些使用 AnyView,所以请尽量保持简单

  • betweenListAndInputViewBuilder - 在聊天列表视图和输入视图之间显示的内容
  • mainHeaderBuilder - 整个聊天的头部,会随所有消息和头部一起滚动
  • headerBuilder - 日期分节头部构建器

修饰符

isListAboveInputView - 消息表格是否在输入字段视图上方 showDateHeaders - 是否在不同日期之间显示带日期的分节头部,默认为 true isScrollEnabled - 禁止消息 UITableView 的滚动 showMessageMenuOnLongPress - 开启/关闭长按显示菜单 showNetworkConnectionProblem - 开启/关闭网络错误显示 assetsPickerLimit - 设置库内置 MediaPicker 的限制 setMediaPickerSelectionParameters - 一个结构体,持有 MediaPicker 的选择参数(assetsPickerLimit 和其他如 mediaType, selectionStyle 等) orientationHandler - 处理屏幕旋转

enableLoadMore(offset: Int, handler: @escaping ChatPaginationClosure) - 当用户滚动到距离末尾第 offset 条消息时,调用处理函数,以便用户加载更多消息 chatNavigation(title: String, status: String? = nil, cover: URL? = nil) - 传递聊天导航栏的信息

仅适用于内置消息视图

avatarSize - 默认头像是一个圆形,你可以在这里指定其直径 tapAvatarClosure - 点击头像时调用的闭包 messageUseMarkdown - 是否使用 markdown(例如用 ** 使文字加粗) showMessageTimeView - 在消息角落显示时间戳 setMessageFont - 传递自定义字体用于消息

仅适用于内置输入视图

setAvailableInput - 在默认 InputView 中隐藏一些按钮。可用选项有: - .full - 媒体 + 文本 + 音频 - .textAndMedia - .textAndAudio - .textOnly

示例

有两个示例项目:

  • 一个是简单的机器人,每2秒发送随机文本/媒体消息。它没有后端和本地存储。每次启动都是全新的。
  • 另一个与 Firestore 数据库集成。它具有所有必要的后端支持,包括存储媒体和音频消息、未读消息计数器等。你需要创建自己的 Firestore 应用和数据库。还需用你自己的替换 GoogleService-Info。之后你可以在多个模拟器/设备上进行测试。

创建你的 firestore 应用 https://console.firebase.google.com/ 创建 firesote 数据库(用于轻量级文本数据) https://firebase.google.com/docs/firestore/manage-data/add-data 创建云 firestore 数据库(用于图片和语音录音) https://firebase.google.com/docs/storage/web/start

示例

要尝试 Chat 示例:

  • 克隆仓库 git clone git@github.com:exyte/Chat.git
  • 打开终端并运行 cd <ChatRepo>/Example
  • 等待 SPM 下载完成包
  • 运行它!

安装

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/exyte/Chat.git")
]

CocoaPods

pod 'ExyteChat'

Carthage

github "Exyte/Chat"

要求

  • iOS 16+
  • Xcode 14+

我们的其他开源 SwiftUI 库

PopupView - 吐司和弹出窗口库 Grid - 最强大的网格容器 ScalingHeaderScrollView - 带有随滚动缩小的粘性头部的滚动视图 AnimatedTabBar - 带有多种预设动画的标签栏 MediaPicker - 可自定义的媒体选择器 OpenAI OpenAI REST API 的包装库 AnimatedGradient - 动画线性渐变 ConcentricOnboarding - 动画引导流程 FloatingButton - 浮动按钮菜单 ActivityIndicatorView - 多种动画加载指示器 ProgressIndicatorView - 多种动画进度指示器 FlagAndCountryCode - 每个国家的电话区号和国旗 SVGView - SVG 解析器 LiquidSwipe - 液体导航动画

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

问小白

问小白是一个基于 DeepSeek R1 模型的智能对话平台,专为用户提供高效、贴心的对话体验。实时在线,支持深度思考和联网搜索。免费不限次数,帮用户写作、创作、分析和规划,各种任务随时完成!

Project Cover

白日梦AI

白日梦AI提供专注于AI视频生成的多样化功能,包括文生视频、动态画面和形象生成等,帮助用户快速上手,创造专业级内容。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

讯飞绘镜

讯飞绘镜是一个支持从创意到完整视频创作的智能平台,用户可以快速生成视频素材并创作独特的音乐视频和故事。平台提供多样化的主题和精选作品,帮助用户探索创意灵感。

Project Cover

讯飞文书

讯飞文书依托讯飞星火大模型,为文书写作者提供从素材筹备到稿件撰写及审稿的全程支持。通过录音智记和以稿写稿等功能,满足事务性工作的高频需求,帮助撰稿人节省精力,提高效率,优化工作与生活。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

Trae

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号