diff --git a/.github/workflows/blank.yml b/.github/workflows/blank.yml index cecf5aaf6..916d29971 100644 --- a/.github/workflows/blank.yml +++ b/.github/workflows/blank.yml @@ -64,10 +64,18 @@ jobs: REMOTE_USER: ${{ secrets.SERVER_USER_NAME }} TARGET: /data/apps/data/docs-im-beta/ # 服务器目标路径 - - name: CDN Refresh + - name: CDN Refresh HTTPS uses: visionwx/ali-cdn-refresh@main with: accessKeyId: ${{ secrets.ALIYUN_CDN_ACCESS_KEY_ID }} accessKeySecret: ${{ secrets.ALIYUN_CDN_ACCESS_KEY_SECRET }} type: Directory - path: https://docs-im-beta.easemob.com/\r\nhttp://docs-im-beta.easemob.com/ + path: https://doc.easemob.com/ + + - name: CDN Refresh HTTP + uses: visionwx/ali-cdn-refresh@main + with: + accessKeyId: ${{ secrets.ALIYUN_CDN_ACCESS_KEY_ID }} + accessKeySecret: ${{ secrets.ALIYUN_CDN_ACCESS_KEY_SECRET }} + type: Directory + path: http://doc.easemob.com/ diff --git a/docs/.vuepress/components/HomePage.vue b/docs/.vuepress/components/HomePage.vue index 1d6571771..aa45efe05 100644 --- a/docs/.vuepress/components/HomePage.vue +++ b/docs/.vuepress/components/HomePage.vue @@ -1,11 +1,112 @@ + diff --git a/docs/.vuepress/components/PlatformSwitch.vue b/docs/.vuepress/components/PlatformSwitch.vue index c932ff404..1f0d85828 100644 --- a/docs/.vuepress/components/PlatformSwitch.vue +++ b/docs/.vuepress/components/PlatformSwitch.vue @@ -40,6 +40,14 @@ const PLATFORM_ICON_MAP = { icon : '/icon-platform.svg', activeIcon: '/icon-platform-hover.svg', }, + electron: { + icon : '/icon-Electron.svg', + activeIcon: '/icon-Electron-hover.svg', + }, + linux: { + icon : '/icon-linux.svg', + activeIcon: '/icon-linux-hover.svg', + }, } const platform = ref('android') @@ -88,6 +96,10 @@ const options = [ value: 'windows', label: 'Windows', }, + { + value: 'linux', + label: 'Linux', + }, ], }, { @@ -109,6 +121,10 @@ const options = [ value: 'applet', label: '小程序', }, + { + value: 'electron', + label: 'Electron', + }, ], }, { diff --git a/docs/.vuepress/components/UIKitSwitch.vue b/docs/.vuepress/components/UIKitSwitch.vue index 0e4aa2919..f3c4ee4e4 100644 --- a/docs/.vuepress/components/UIKitSwitch.vue +++ b/docs/.vuepress/components/UIKitSwitch.vue @@ -42,32 +42,6 @@ const PLATFORM_ICON_MAP = { }, } -const platform = ref('android') -const platformIcon = computed(() => PLATFORM_ICON_MAP[platform.value]?.activeIcon) -const route = useRoute() -const router = useRouter() -watch(()=>route.path, ()=> { - if (route.path.indexOf('/uikit') == 0) { - platform.value = route.path.split('/')[2] - } -}, {immediate:true}) - - -// 切换平台,如果有相同路径的route就直接跳转 -const onChange = (platform) => { - const nextPlatformDocRouters = router.options.routes.filter(item=>item.hasOwnProperty('name') && item?.path.indexOf('/uikit/'+platform) == 0).map(item=>item.path) - - let newPath = route.path.split('/') - newPath[2] = platform - const nextPathPath = newPath.join('/') - - if (nextPlatformDocRouters.indexOf(nextPathPath) > -1) { - router.push(nextPathPath) - } else { - router.push('/uikit/'+platform+'/overview.html') - } -} - const options = [ { label: '平台', @@ -80,14 +54,10 @@ const options = [ value: 'ios', label: 'iOS', }, - // { - // value: 'web', - // label: 'Web', - // }, - // { - // value: 'windows', - // label: 'Windows', - // }, + { + value: 'web', + label: 'Web', + }, ], }, { @@ -101,17 +71,44 @@ const options = [ value: 'flutter', label: 'Flutter', }, - // { - // value: 'unity', - // label: 'Unity', - // }, - // { - // value: 'applet', - // label: '小程序', - // }, ], }, ] + +const platform = ref('android') +const kitType = ref('chatuikit') +const platformIcon = computed(() => PLATFORM_ICON_MAP[platform.value]?.activeIcon) +const route = useRoute() +const router = useRouter() +watch(()=>route.path, ()=> { + if (route.path.indexOf('/uikit') == 0) { + const splitRoute = route.path.split('/') + kitType.value = splitRoute[2] + platform.value = splitRoute[3] + } +}, {immediate:true}) + + +// 切换平台,如果有相同路径的route就直接跳转 +const onChange = (platform) => { + const nextPlatformDocRouters = router.options.routes.filter(item=>item.hasOwnProperty('name') && + item?.path.indexOf(`/uikit/${kitType.value}/${platform}`) == 0).map(item=>item.path) + + let newPath = route.path.split('/') + newPath[3] = platform + const nextPathPath = newPath.join('/') + + if (nextPlatformDocRouters.indexOf(nextPathPath) > -1) { + router.push(nextPathPath) + } else { + if (kitType.value == 'chatuikit') { + router.push(`/uikit/${kitType.value}/${platform}/overview.html`) + } + if (kitType.value == 'chatroomuikit') { + router.push(`/uikit/${kitType.value}/${platform}/roomuikit_overview.html`) + } + } +} diff --git a/docs/.vuepress/navbar/index.ts b/docs/.vuepress/navbar/index.ts index f494f0c2f..26bf6180e 100644 --- a/docs/.vuepress/navbar/index.ts +++ b/docs/.vuepress/navbar/index.ts @@ -1,220 +1,249 @@ import { navbar } from "vuepress-theme-hope"; export const zhNavbar = navbar([ - { text: '产品简介', link: '/product/introduction.html' }, + { text: "产品简介", link: "/product/introduction.html" }, { - text: 'SDK/REST 集成', - children: [ + text: "SDK/REST 集成", + children: [ { - text: '平台', + text: "平台", children: [ { - text: 'Android', - icon: '/icon-Android.svg', - link: '/document/android/quickstart.html' + text: "Android", + icon: "/icon-Android.svg", + link: "/document/android/quickstart.html", + }, + { + text: "iOS", + icon: "/icon-iOS.svg", + link: "/document/ios/quickstart.html", }, { - text: 'iOS', - icon: '/icon-iOS.svg', - link: '/document/ios/quickstart.html' + text: "Web", + icon: "/icon-web.svg", + link: "/document/web/quickstart.html", }, { - text: 'Web', - icon: '/icon-web.svg', - link: '/document/web/quickstart.html' + text: "Windows", + icon: "/icon-windows.svg", + link: "/document/windows/quickstart.html", }, { - text: 'Windows', - icon: '/icon-windows.svg', - link: '/document/windows/quickstart.html' - } - ] + text: "Linux", + icon: "/icon-linux.svg", + link: "/document/linux/overview.html", + }, + ], }, { - text: '框架', + text: "框架", children: [ { - text: 'React Native', - icon: '/icon-ReactNative.svg', - link: '/document/react-native/quickstart.html' + text: "React Native", + icon: "/icon-ReactNative.svg", + link: "/document/react-native/quickstart.html", }, { - text: 'Flutter', - icon: '/icon-flutter.svg', - link: '/document/flutter/quickstart.html' + text: "Flutter", + icon: "/icon-flutter.svg", + link: "/document/flutter/quickstart.html", }, { - text: 'Unity', - icon: '/icon-unity.svg', - link: '/document/unity/quickstart.html' + text: "Unity", + icon: "/icon-unity.svg", + link: "/document/unity/quickstart.html", }, { - text: '小程序', - icon: '/icon-mini-program.svg', - link: '/document/applet/overview.html' + text: "小程序", + icon: "/icon-mini-program.svg", + link: "/document/applet/overview.html", }, { - text: 'uni-app', - icon: '/icon-uni-app.svg', - link: '/document/applet/uniapp.html' + text: "uni-app", + icon: "/icon-uni-app.svg", + link: "/document/applet/uniapp.html", }, - ] + { + text: "Electron", + icon: "/icon-Electron.svg", + link: "/document/electron/overview.html", + }, + ], }, { - text: '服务端', + text: "服务端", children: [ { - text: 'REST API', - icon: '/icon-platform.svg', - link: '/document/server-side/overview.html' - } - ] - }, - ] - }, + text: "REST API", + icon: "/icon-platform.svg", + link: "/document/server-side/overview.html", + }, + { + text: "Java", + icon: "/icon-platform.svg", + link: "/document/server-side/java_server_sdk.html", + }, + { + text: "PHP", + icon: "/icon-platform.svg", + link: "/document/server-side/php_server_sdk.html", + }, + ], + }, + ], + }, { - text: 'UIKit', + text: "UIKit", children: [ - { - text: '平台', - children: [ - { - text: 'Android', - icon: '/icon-Android.svg', - link: '/uikit/android/overview.html' - }, - { - text: 'iOS', - icon: '/icon-iOS.svg', - link: '/uikit/ios/overview.html' - }, - // { - // text: 'Web', - // icon: '/icon-web.svg', - // link: '/uikit/web/overview.html' - // }, - // { - // text: 'Windows', - // icon: '/icon-windows.svg', - // link: '/uikit/windows/overview.html' - // } - ] - }, - { - text: '框架', - children: [ - { - text: 'React Native', - icon: '/icon-ReactNative.svg', - link: '/uikit/react-native/overview.html' - }, - { - text: 'Flutter', - icon: '/icon-flutter.svg', - link: '/uikit/flutter/overview.html' - }, - // { - // text: 'Unity', - // icon: '/icon-unity.svg', - // link: '/uikit/unity/overview.html' - // }, - // { - // text: '小程序', - // icon: '/icon-mini-program.svg', - // link: '/uikit/applet/overview.html' - // }, - // { - // text: 'uni-app', - // icon: '/icon-uni-app.svg', - // link: '/uikit/applet/uniapp.html' - // }, - ] - }, - ] - }, - { - text: 'API 参考', - children: [ { - text: '平台', + text: "单群聊 UIKit", children: [ { - text: 'Android', - icon: '/icon-Android.svg', - link: 'https://sdkdocs.easemob.com/apidoc/android/chat3.0/annotated.html' + text: "Android", + icon: "/icon-Android.svg", + link: "/uikit/chatuikit/android/chatuikit_overview.html", + }, + { + text: "iOS", + icon: "/icon-iOS.svg", + link: "/uikit/chatuikit/ios/chatuikit_overview.html", }, { - text: 'iOS', - icon: '/icon-iOS.svg', - link: 'https://sdkdocs.easemob.com/apidoc/ios/chat3.0/annotated.html' + text: "Web", + icon: "/icon-web.svg", + link: "/uikit/chatuikit/web/chatuikit_overview.html", }, { - text: 'Web/小程序', - icon: '/icon-web.svg', - link: 'https://docs-im-beta.easemob.com/jsdoc/index.html' + text: "React Native", + icon: "/icon-ReactNative.svg", + link: "/uikit/chatuikit/react-native/chatuikit_overview.html", }, { - text: 'Windows', - icon: '/icon-windows.svg', - link: 'https://sdkdocs.easemob.com/apidoc/unity/annotated.html' - } - ] + text: "Flutter", + icon: "/icon-flutter.svg", + link: "/uikit/chatuikit/flutter/chatuikit_overview.html", + }, + ], }, { - text: '框架', + text: "聊天室 UIKit", children: [ { - text: 'React Native', - icon: '/icon-ReactNative.svg', - link: 'https://sdkdocs.easemob.com/apidoc/rn/modules.html' + text: "Android", + icon: "/icon-Android.svg", + link: "/uikit/chatroomuikit/android/roomuikit_overview.html", }, { - text: 'Flutter', - icon: '/icon-flutter.svg', - link: 'https://sdkdocs.easemob.com/apidoc/flutter/index.html' + text: "iOS", + icon: "/icon-iOS.svg", + link: "/uikit/chatroomuikit/ios/roomuikit_overview.html", }, { - text: 'Unity', - icon: '/icon-unity.svg', - link: 'https://sdkdocs.easemob.com/apidoc/unity/annotated.html' - } - ] - }, - { - text: '服务端', - children: [ + text: "Web", + icon: "/icon-web.svg", + link: "/uikit/chatroomuikit/web/roomuikit_overview.html", + }, { - text: 'Java', - icon: '/icon-platform.svg', - link: 'https://easemob.github.io/easemob-im-server-sdk/' + text: "React Native", + icon: "/icon-ReactNative.svg", + link: "/uikit/chatroomuikit/react-native/roomuikit_overview.html", }, { - text: 'PHP', - icon: '/icon-platform.svg', - link: 'https://easemob.github.io/im-php-server-sdk/annotated.html' - } - ] + text: "Flutter", + icon: "/icon-flutter.svg", + link: "/uikit/chatroomuikit/flutter/roomuikit_overview.html", + }, + ], }, - ] - }, - { - text: '即时推送', - link: '/push/push_overview.html' + ], }, { - text: '私有部署', + text: "API 参考", children: [ + { + text: "平台", + children: [ { - text: '即时通讯', - link: '/private/im/uc_deploy.html' + text: "Android", + icon: "/icon-Android.svg", + link: "https://sdkdocs.easemob.com/apidoc/android/chat3.0/annotated.html", }, { - text: '音视频', - link: '/private/media/common_introduction.html' - } - ] - + text: "iOS", + icon: "/icon-iOS.svg", + link: "https://sdkdocs.easemob.com/apidoc/ios/chat3.0/annotated.html", + }, + { + text: "Web/小程序", + icon: "/icon-web.svg", + link: "https://doc.easemob.com/jsdoc/index.html", + }, + { + text: "Windows", + icon: "/icon-windows.svg", + link: "https://sdkdocs.easemob.com/apidoc/unity/annotated.html", + }, + ], + }, + { + text: "框架", + children: [ + { + text: "React Native", + icon: "/icon-ReactNative.svg", + link: "https://sdkdocs.easemob.com/apidoc/rn/modules.html", + }, + { + text: "Flutter", + icon: "/icon-flutter.svg", + link: "https://sdkdocs.easemob.com/apidoc/flutter/index.html", + }, + { + text: "Unity", + icon: "/icon-unity.svg", + link: "https://sdkdocs.easemob.com/apidoc/unity/annotated.html", + }, + { + text: "Electron", + icon: "/icon-Electron.svg", + link: "https://downloads.easemob.com/doc/desktop/apidoc/index.html", + }, + ], + }, + { + text: "服务端", + children: [ + { + text: "Java", + icon: "/icon-platform.svg", + link: "https://easemob.github.io/easemob-im-server-sdk/", + }, + { + text: "PHP", + icon: "/icon-platform.svg", + link: "https://easemob.github.io/im-php-server-sdk/annotated.html", + }, + ], + }, + ], + }, + { + text: "即时推送", + link: "/push/push_overview.html", }, - { text: '历史版本', link: 'https://docs-im.easemob.com/ccim/intro' }, - { text: '文档“捉虫”活动', link: 'https://www.imgeek.org/article/825360944' }, + // { + // text: "私有部署", + // children: [ + // { + // text: "即时通讯", + // link: "/private/im/uc_deploy.html", + // }, + // { + // text: "音视频", + // link: "/private/media/common_introduction.html", + // }, + // ], + // }, + { text: "历史版本", link: "https://docs-im.easemob.com/ccim/intro" }, + { text: "文档“捉虫”活动", link: "https://www.imgeek.org/article/825360944" }, ]); diff --git a/docs/.vuepress/public/icon-linux-hover.svg b/docs/.vuepress/public/icon-linux-hover.svg new file mode 100644 index 000000000..5e0be5bd8 --- /dev/null +++ b/docs/.vuepress/public/icon-linux-hover.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/icon-linux.svg b/docs/.vuepress/public/icon-linux.svg new file mode 100644 index 000000000..5f5df5045 --- /dev/null +++ b/docs/.vuepress/public/icon-linux.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/sidebar/document.ts b/docs/.vuepress/sidebar/document.ts index 597ced12f..7822599e8 100644 --- a/docs/.vuepress/sidebar/document.ts +++ b/docs/.vuepress/sidebar/document.ts @@ -27,7 +27,7 @@ const documentSidebar = [ { text: '快速开始', link: 'quickstart.html', only: ['windows', 'react-native', 'flutter', 'unity'] }, { text: 'SDK 集成概述', link: 'overview.html', only: ['android', 'ios', 'web', 'flutter'] }, { text: 'SDK 集成概述', link: 'overview.html', only: ['windows', 'react-native', 'unity'] }, - { text: '私有云 SDK 集成配置', link: 'privatecloud.html', except: ['windows', 'server-side', 'react-native', 'flutter', 'unity'] }, + // { text: '私有云 SDK 集成配置', link: 'privatecloud.html', except: ['windows', 'server-side', 'react-native', 'flutter', 'unity'] }, { text: 'SDK 更新日志', link: 'releasenote.html', except: ['server-side']}, /*{ text: 'API reference', link: 'apireference.html', only: ['android', 'ios', 'web', 'windows', 'react-native', 'flutter', 'unity']},*/ { text: '开通和配置服务 console', link: 'enable_and_configure_IM.html', only: ['server-side'] }, @@ -36,23 +36,41 @@ const documentSidebar = [ { text: 'IM 产品使用限制', link: 'limitation.html', only: ['server-side'] }, { text: '接口频率限制', link: 'limitationapi.html', only: ['server-side'] }, ], - except: ['applet'] + except: ['applet', 'electron','linux'] }, { text: '基础功能', children: [ + { + text: '会话管理', + collapsible: true, + children: [ + { text: '会话介绍', link: 'conversation_overview.html' }, + { text: '会话列表', link: 'conversation_list.html' }, + { text: '本地会话', link: 'conversation_local.html', only: ['web'] }, + { text: '会话未读数', link: 'conversation_unread.html', except: ['web'] }, + { text: '置顶会话', link: 'conversation_pin.html' }, + { text: '会话标记', link: 'conversation_mark.html', except: ['windows', 'react-native', 'flutter', 'unity'] }, + { text: '删除会话', link: 'conversation_delete.html' }, + ] + }, { text: '消息管理', collapsible: true, children: [ { text: '消息概述', link: 'message_overview.html' }, { text: '发送和接收消息', link: 'message_send_receive.html' }, - { text: '管理本地会话和消息', link: 'message_manage.html', except: ['react-native'] }, - { text: '管理会话和消息', link: 'message_manage.html', only: ['react-native'] }, - { text: '管理服务端消息', link: 'message_retrieve.html', except: ['react-native'] }, - { text: '管理消息回执', link: 'message_receipt.html' }, - { text: '修改消息', link: 'message_modify.html' }, - { text: '翻译', link: 'message_translation.html' }, + { text: '获取历史消息', link: 'message_retrieve.html' }, + { text: '撤回消息', link: 'message_recall.html' }, + { text: '搜索消息', link: 'message_search.html', except: ['web']}, + { text: '修改消息', link: 'message_modify.html'}, + { text: '导入和插入消息', link: 'message_import_insert.html', except: ['web']}, + { text: '更新消息', link: 'message_update.html', except: ['web']}, + { text: '删除消息', link: 'message_delete.html' }, + { text: '实现消息回执', link: 'message_receipt.html'}, + { text: '翻译消息', link: 'message_translation.html' }, + { text: '只投在线用户', link: 'message_deliver_only_online.html'}, + { text: '获取消息流量统计', link: 'message_traffic_statis.html', only: ['android', 'ios'] }, ] }, { text: '管理用户属性', link: 'userprofile.html' }, @@ -78,7 +96,7 @@ const documentSidebar = [ ] }, ], - except: ['applet', 'server-side'] + except: ['applet', 'server-side', 'electron','linux'] }, { text: '进阶功能', @@ -97,7 +115,7 @@ const documentSidebar = [ }, { text: '消息审核(举报)', link: 'moderation.html'}, ], - except: ['applet','server-side'] + except: ['applet','server-side','electron','linux'] }, { text: '其他', @@ -106,7 +124,15 @@ const documentSidebar = [ //{ text: 'EaseIMKit 使用指南', link: 'easeimkit.html', except: ['web', 'windows', 'react-native', 'flutter', 'unity'] }, { text: 'EaseCallKit 使用指南', link: 'easecallkit.html', except: ['web', 'windows', 'react-native', 'flutter', 'unity'] }, ], - except: ['applet', 'server-side'] + except: ['applet', 'server-side','electron','linux'] + + }, + { + text: '精简版 SDK', + children: [ + { text: '精简版 SDK 使用说明', link: 'elite_sdk.html' }, + ], + only: ['android', 'ios'] }, { text: '产品介绍', @@ -133,16 +159,32 @@ const documentSidebar = [ text: '基本功能', children: [ { text: '初始化及登录', link: 'initialization.html' }, + { + text: '会话管理', + collapsible: true, + children: [ + { text: '会话介绍', link: 'conversation_overview.html' }, + { text: '会话列表', link: 'conversation_list.html' }, + { text: '本地会话', link: 'conversation_local.html' }, + { text: '会话未读数', link: 'conversation_unread.html' }, + { text: '置顶会话', link: 'conversation_pin.html' }, + { text: '会话标记', link: 'conversation_mark.html'}, + { text: '删除会话', link: 'conversation_delete.html'}, + ] + }, { text: '消息管理', collapsible: true, children: [ { text: '消息概述', link: 'message_overview.html' }, { text: '发送和接收消息', link: 'message_send_receive.html' }, - { text: '管理服务端消息', link: 'message_retrieve.html' }, - { text: '管理消息回执', link: 'message_receipt.html' }, + { text: '获取历史消息', link: 'message_retrieve.html' }, + { text: '撤回消息', link: 'message_recall.html' }, { text: '修改消息', link: 'message_modify.html' }, - { text: '翻译', link: 'message_translation.html' }, + { text: '删除消息', link: 'message_delete.html' }, + { text: '实现消息回执', link: 'message_receipt.html' }, + { text: '只投在线用户', link: 'message_deliver_only_online.html'}, + { text: '翻译消息', link: 'message_translation.html' }, ] }, { text: '用户属性', link: 'userprofile.html' }, @@ -198,6 +240,45 @@ const documentSidebar = [ ], only: ['applet'] }, + { + text: 'SDK 集成介绍', + children: [ + { text: '集成说明', link: 'overview.html' }, + { text: 'SDK 基础功能', link: 'sdk_basic_function.html' }, + { text: 'Demo 下载体验', link: 'demo_download.html' }, + { text: '桌面 SDK API 文档', link: 'sdk_api.html' }, + ], + only: ['electron'] + }, + { + text: 'IM 基本功能', + children: [ + { text: '消息', link: 'message.html' }, + { text: '会话管理', link: 'conversation.html' }, + { text: '好友管理', link: 'contact.html' }, + { text: '群组', link: 'group.html' }, + { text: '聊天室管理', link: 'chatroom.html' }, + { text: '多设备监听', link: 'multi_device.html' }, + { text: '附录', link: 'annex.html' }, + ], + only: ['electron'] + }, + { + text: '更新日志', + children: [ + { text: 'SDK 更新日志', link: 'releasenote.html' }, + ], + only: ['electron'] + }, + { + text: 'Linux SDK 集成介绍', + children: [ + { text: 'Linux SDK 集成说明', link: 'overview.html' }, + { text: '技术参数', link: 'technical_parameter.html' }, + { text: 'Linux SDK 更新日志', link: 'releasenote.html' }, + ], + only: ['linux'] + }, { text: '服务端 REST API', children: [ @@ -213,6 +294,7 @@ const documentSidebar = [ { text: '上传和下载文件', link: 'message_download.html' }, { text: '获取历史消息记录', link: 'message_historical.html' }, { text: '撤回消息和单向删除会话', link: 'message_recall.html' }, + { text: '修改文本或自定义消息', link: 'message_modify_text_custom.html' }, { text: '导入消息', link: 'message_import.html' } ] }, diff --git a/docs/.vuepress/sidebar/index.ts b/docs/.vuepress/sidebar/index.ts index c7f5d299c..371c8447e 100644 --- a/docs/.vuepress/sidebar/index.ts +++ b/docs/.vuepress/sidebar/index.ts @@ -1,12 +1,11 @@ import { sidebar } from "vuepress-theme-hope"; -import { DOC_SIDEBAR } from "./document" -import { UIKIT_SIDEBAR } from "./uikit" -import { PRIVATE_IM_SIDEBAR, PRIVATE_MEDIA_SIDEBAR } from './private' -import { PUSH_SIDEBAR } from './push' +import { DOC_SIDEBAR } from "./document"; +import { CHAT_UIKIT_SIDEBAR, CHATROOM_UIKIT_SIDEBAR } from "./uikit"; +import { PRIVATE_IM_SIDEBAR, PRIVATE_MEDIA_SIDEBAR } from "./private"; +import { PUSH_SIDEBAR } from "./push"; export const zhSidebar = sidebar({ - - '/product/': [ + "/product/": [ { /* text: 分组标题 @@ -17,140 +16,263 @@ export const zhSidebar = sidebar({ collapsible: 子菜单是否允许展开/收起,true: 允许; false: 不允许。请参考「子菜单示例」 children: 子菜单。请参考「子菜单示例」 */ - text: '产品简介', + text: "产品简介", children: [ - { text: '产品概述', link: 'introduction.html' }, - { text: '产品动态', link: 'product_dynamics.html' }, - { text: 'IM 产品使用限制', link: 'limitation.html' }, - { text: '接口频率限制', link: 'limitationapi.html' }, - { text: '产品价格', link: 'pricing.html' }, - { text: '术语表', link: 'glossary.html' } - ] + { text: "产品概述", link: "introduction.html" }, + { text: "产品动态", link: "product_dynamics.html" }, + { text: "IM 产品使用限制", link: "limitation.html" }, + { text: "接口频率限制", link: "limitationapi.html" }, + { text: "产品价格", link: "pricing.html" }, + { text: "术语表", link: "glossary.html" }, + ], }, { - text: '快速开始', + text: "快速开始", children: [ - { text: '使用环信 App Token 鉴权', link: 'easemob_app_token.html' }, - { text: '使用环信 User Token 鉴权', link: 'easemob_user_token.html' }, - { text: '快速开始 Android', link: '/document/android/quickstart.html' }, - { text: '快速开始 iOS', link: '/document/ios/quickstart.html' }, - { text: '快速开始 Web', link: '/document/web/quickstart.html' } - ] + { text: "使用环信 App Token 鉴权", link: "easemob_app_token.html" }, + { text: "使用环信 User Token 鉴权", link: "easemob_user_token.html" }, + { text: "快速开始 Android", link: "/document/android/quickstart.html" }, + { text: "快速开始 iOS", link: "/document/ios/quickstart.html" }, + { text: "快速开始 Web", link: "/document/web/quickstart.html" }, + ], }, { - text: '内容审核', + text: "内容审核", children: [ - { text: '产品简介', collapsible: true, children: [ - { text: '产品概述', link: 'moderation/moderation_overview.html' }, - ]}, - { text: '产品定价', collapsible: true, children: [ - { text: '国内计费说明', link: 'moderation/moderation_billing_domestic.html' }, - { text: '海外计费说明', link: 'moderation/moderation_billing_overseas.html' }, - ]}, - { text: '快速开始', collapsible: true, children: [ - { text: '开通审核服务', link: 'moderation/moderation_enable.html' }, - { text: '规则配置', link: 'moderation/moderation_rule_config.html' }, - { text: '规则测试', link: 'moderation/moderation_rule_test.html' }, - { text: '历史记录', link: 'moderation/moderation_history.html' }, - { text: '关键词审核', link: 'moderation/keyword_review.html' }, - { text: '消息审核机制', link: 'moderation/moderation_mechanism.html' }, - ]}, - { text: '进阶功能', collapsible: true, children: [ - { text: '审核记录回调', link: 'moderation/moderation_record_callback.html' }, - { text: '消息人工审核', link: 'moderation/moderation_manual_review.html' }, - { text: '用户管理', link: 'moderation/moderation_usermgmt.html' }, - ]}, - { text: '常见问题', collapsible: true, children: [ - { text: '如何开始使用内容审核服务?', link: 'moderation/moderation_use_console.html' }, - { text: '如何新增自定义词?', link: 'moderation/moderation_add_word.html' }, - { text: '为什么处置方式选择了替换***,但实际被拦截了没有发出来?', link: 'moderation/moderation_replace_refuse.html' }, - ]}, - ] + { + text: "产品简介", + collapsible: true, + children: [ + { text: "产品概述", link: "moderation/moderation_overview.html" }, + ], + }, + { + text: "产品定价", + collapsible: true, + children: [ + { + text: "国内计费说明", + link: "moderation/moderation_billing_domestic.html", + }, + { + text: "海外计费说明", + link: "moderation/moderation_billing_overseas.html", + }, + ], + }, + { + text: "快速开始", + collapsible: true, + children: [ + { text: "开通审核服务", link: "moderation/moderation_enable.html" }, + { + text: "规则配置", + link: "moderation/moderation_rule_config.html", + }, + { text: "规则测试", link: "moderation/moderation_rule_test.html" }, + { text: "历史记录", link: "moderation/moderation_history.html" }, + { text: "关键词审核", link: "moderation/keyword_review.html" }, + { + text: "消息审核机制", + link: "moderation/moderation_mechanism.html", + }, + ], + }, + { + text: "进阶功能", + collapsible: true, + children: [ + { + text: "审核记录回调", + link: "moderation/moderation_record_callback.html", + }, + { + text: "消息人工审核", + link: "moderation/moderation_manual_review.html", + }, + { text: "用户管理", link: "moderation/moderation_usermgmt.html" }, + ], + }, + { + text: "常见问题", + collapsible: true, + children: [ + { + text: "如何开始使用内容审核服务?", + link: "moderation/moderation_use_console.html", + }, + { + text: "如何新增自定义词?", + link: "moderation/moderation_add_word.html", + }, + { + text: "为什么处置方式选择了替换***,但实际被拦截了没有发出来?", + link: "moderation/moderation_replace_refuse.html", + }, + ], + }, + ], }, { - text: '场景方案', + text: "场景方案", children: [ - { text: '超级社区', collapsible: true, children: [ - { text: '产品概述', link: 'circle/circle_overview.html' }, - { text: '快速开始', collapsible: false, children: [ - { text: 'Android 快速开始', link: 'circle/circle_quickstart_android.html' }, - { text: 'iOS 快速开始', link: 'circle/circle_quickstart_ios.html' }, - { text: 'Web 快速开始', link: 'circle/circle_quickstart_web.html' }, - ] - }, - { text: '集成说明', collapsible: false, children: [ - { text: 'Android 社区管理', link: 'circle/server_mgmt_android.html' }, - { text: 'Android 频道管理', link: 'circle/channel_mgmt_android.html' }, - { text: 'Android 频道分组管理', link: 'circle/category_mgmt_android.html' }, - { text: 'iOS 社区管理', link: 'circle/server_mgmt_ios.html' }, - { text: 'iOS 频道管理', link: 'circle/channel_mgmt_ios.html' }, - { text: 'iOS 频道分组管理', link: 'circle/category_mgmt_ios.html' }, - { text: 'Web 社区管理', link: 'circle/server_mgmt_web.html' }, - { text: 'Web 频道管理', link: 'circle/channel_mgmt_web.html' }, - { text: 'Web 频道分组管理', link: 'circle/category_mgmt_web.html' }, - ] - }, - { text: 'API 参考', collapsible: false, children: [ - { text: 'REST 社区管理', link: 'circle/server_mgmt_rest.html' }, - { text: 'REST 频道管理', link: 'circle/channel_mgmt_rest.html' }, - { text: 'REST 频道分组管理', link: 'circle/category_mgmt_rest.html' }, - { text: 'Android API 参考', link: 'circle/api_reference_android.html' }, - { text: 'iOS API 参考', link: 'circle/api_reference_ios.html' }, - { text: 'Web API 参考', link: 'circle/api_reference_web.html' }, - ] - }, - ] - }, - { text: '语聊房', collapsible: true, children: [ - { text: '场景概览', collapsible: false, children: [ - { text: '场景介绍', link: 'voiceroom/demo_scenario_introduction.html' }, - { text: 'Demo 体验(Android/iOS)', link: 'voiceroom/demo_experience.html' }, - ] - }, - { text: '快速开始', collapsible: false, children: [ - { text: '跑通示例项目(Android)', link: 'voiceroom/run_through_demo_android.html' }, - { text: '跑通示例项目(iOS)', link: 'voiceroom/run_through_demo_ios.html' }, - ] - }, - { text: '实现流程', collapsible: false, children: [ - { text: '客户端实现(Android)', link: 'voiceroom/client_implementation_android.html' }, - { text: '客户端实现(iOS)', link: 'voiceroom/client_implementation_ios.html' }, - ] - }, - ]}, - ]}, + { + text: "超级社区", + collapsible: true, + children: [ + { text: "产品概述", link: "circle/circle_overview.html" }, + { + text: "快速开始", + collapsible: false, + children: [ + { + text: "Android 快速开始", + link: "circle/circle_quickstart_android.html", + }, + { + text: "iOS 快速开始", + link: "circle/circle_quickstart_ios.html", + }, + { + text: "Web 快速开始", + link: "circle/circle_quickstart_web.html", + }, + ], + }, + { + text: "集成说明", + collapsible: false, + children: [ + { + text: "Android 社区管理", + link: "circle/server_mgmt_android.html", + }, + { + text: "Android 频道管理", + link: "circle/channel_mgmt_android.html", + }, + { + text: "Android 频道分组管理", + link: "circle/category_mgmt_android.html", + }, + { text: "iOS 社区管理", link: "circle/server_mgmt_ios.html" }, + { text: "iOS 频道管理", link: "circle/channel_mgmt_ios.html" }, + { + text: "iOS 频道分组管理", + link: "circle/category_mgmt_ios.html", + }, + { text: "Web 社区管理", link: "circle/server_mgmt_web.html" }, + { text: "Web 频道管理", link: "circle/channel_mgmt_web.html" }, + { + text: "Web 频道分组管理", + link: "circle/category_mgmt_web.html", + }, + ], + }, + { + text: "API 参考", + collapsible: false, + children: [ + { text: "REST 社区管理", link: "circle/server_mgmt_rest.html" }, + { + text: "REST 频道管理", + link: "circle/channel_mgmt_rest.html", + }, + { + text: "REST 频道分组管理", + link: "circle/category_mgmt_rest.html", + }, + { + text: "Android API 参考", + link: "circle/api_reference_android.html", + }, + { text: "iOS API 参考", link: "circle/api_reference_ios.html" }, + { text: "Web API 参考", link: "circle/api_reference_web.html" }, + ], + }, + ], + }, + { + text: "语聊房", + collapsible: true, + children: [ + { + text: "场景概览", + collapsible: false, + children: [ + { + text: "场景介绍", + link: "voiceroom/demo_scenario_introduction.html", + }, + { + text: "Demo 体验(Android/iOS)", + link: "voiceroom/demo_experience.html", + }, + ], + }, + { + text: "快速开始", + collapsible: false, + children: [ + { + text: "跑通示例项目(Android)", + link: "voiceroom/run_through_demo_android.html", + }, + { + text: "跑通示例项目(iOS)", + link: "voiceroom/run_through_demo_ios.html", + }, + ], + }, + { + text: "实现流程", + collapsible: false, + children: [ + { + text: "客户端实现(Android)", + link: "voiceroom/client_implementation_android.html", + }, + { + text: "客户端实现(iOS)", + link: "voiceroom/client_implementation_ios.html", + }, + ], + }, + ], + }, + ], + }, { - text: '常见方案', - children: [ - { text: '迁移到环信', link: 'migrate_to_easemob.html' }, - ] + text: "常见方案", + children: [{ text: "迁移到环信", link: "migrate_to_easemob.html" }], }, { - text: 'FAQ', + text: "FAQ", children: [ - { text: 'FAQ 质量', link: 'faq_quality_issues.html' }, - { text: 'FAQ 集成', link: 'faq_integration_issues.html' }, - { text: '帮助中心', link: 'help.html' }, - ] + { text: "FAQ 质量", link: "faq_quality_issues.html" }, + { text: "FAQ 集成", link: "faq_integration_issues.html" }, + { text: "帮助中心", link: "help.html" }, + ], }, { - text: '安全', + text: "安全", children: [ - { text: '安全最佳实践', link: 'security_best_practices.html' }, - { text: 'GDPR 安全合规', link: 'GDPR.html' }, - ] + { text: "安全最佳实践", link: "security_best_practices.html" }, + { text: "GDPR 安全合规", link: "GDPR.html" }, + ], }, { - text: 'Console 指南', + text: "Console 指南", children: [ - { text: '开通和配置服务', link: 'enable_and_configure_IM.html' }, - { text: '请求质量概览', link: 'request_quality_overview.html' }, - ] + { text: "开通和配置服务", link: "enable_and_configure_IM.html" }, + { text: "请求质量概览", link: "request_quality_overview.html" }, + ], }, ], ...DOC_SIDEBAR, - ...UIKIT_SIDEBAR, - '/private/im/': PRIVATE_IM_SIDEBAR, - '/private/media/': PRIVATE_MEDIA_SIDEBAR, - '/push': PUSH_SIDEBAR + ...CHAT_UIKIT_SIDEBAR, + ...CHATROOM_UIKIT_SIDEBAR, + "/private/im/": PRIVATE_IM_SIDEBAR, + "/private/media/": PRIVATE_MEDIA_SIDEBAR, + "/push": PUSH_SIDEBAR, }); diff --git a/docs/.vuepress/sidebar/push.ts b/docs/.vuepress/sidebar/push.ts index 0c0d424d3..ee54ed929 100644 --- a/docs/.vuepress/sidebar/push.ts +++ b/docs/.vuepress/sidebar/push.ts @@ -9,6 +9,7 @@ export const PUSH_SIDEBAR = [ { text: 'iOS SDK 发布动态', link: 'push_dynamics_ios.html' }, ]}, { text: '全球化部署', link: 'push_global_deployment.html' }, + { text: '接口频率限制', link: 'push_api_call_limitation.html' }, ] }, { diff --git a/docs/.vuepress/sidebar/uikit.ts b/docs/.vuepress/sidebar/uikit.ts index 80fb32ec4..6275cdb5e 100644 --- a/docs/.vuepress/sidebar/uikit.ts +++ b/docs/.vuepress/sidebar/uikit.ts @@ -1,11 +1,16 @@ -import path from "node:path" -import fs from "node:fs" +import path from "node:path"; +import fs from "node:fs"; -const getSubDirectories = (dir) => fs.readdirSync(dir).filter(item => fs.statSync(path.join(dir, item)).isDirectory()) -const DOC_PATH = path.resolve(__dirname, '../../uikit') -const platformList = getSubDirectories(DOC_PATH) +const getSubDirectories = (dir) => + fs + .readdirSync(dir) + .filter((item) => fs.statSync(path.join(dir, item)).isDirectory()); +const CHAT_DOC_PATH = path.resolve(__dirname, "../../uikit/chatuikit"); +const CHATROOM_DOC_PATH = path.resolve(__dirname, "../../uikit/chatroomuikit"); +const chatPlatformList = getSubDirectories(CHAT_DOC_PATH); +const chatroomPlatformList = getSubDirectories(CHATROOM_DOC_PATH); -const uikitSidebar = [ +const chatUikitSidebar = [ { /* text: 分组标题 @@ -18,35 +23,205 @@ const uikitSidebar = [ collapsible: 子菜单是否允许展开/收起,true: 允许; false: 不允许。请参考「子菜单示例」 children: 子菜单。请参考「子菜单示例」 */ - text: 'UIKit 介绍', link: 'overview.html', - except: ['android', 'ios'] + text: '产品介绍', + children: [ + { text: '概述', link: 'chatuikit_overview.html' }, + { text: '特性', + children: [ + { text: '通用', link: 'chatfeature_common.html' }, + { text: '会话', link: 'chatfeature_conversation.html' }, + { text: '消息', link: 'chatfeature_message.html' }, + ], + }, + ], + only: ['ios'] }, { - text: '快速开始', link: 'quickstart.html', + text: '快速开始', + children: [ + { text: '跑通示例项目', link: 'chatuikit_run.html' }, + { text: '集成单群聊 UIKit', link: 'chatuikit_integrated.html' }, + { text: '快速开始', link: 'chatuikit_quickstart.html' }, + ], + only: ['ios'] }, { - text: '集成聊天页面', link: 'key_function_chat_page.html', - except: ['android', 'ios'] - }, + text: '集成文档', + children: [ + { text: '进阶用法', link: 'chatuikit_advancedusage.html' }, + { text: '可配项', link: 'chatuikit_config_item.html' }, + { text: '主题', link: 'chatuikit_theme.html' }, + { text: '自定义', link: 'chatuikit_customize.html' }, + { text: '事件监听', link: 'chatuikit_listener.html' }, + { text: '拦截主要页面点击跳转事件', link: 'chatuikit_customize_clickjump.html' }, + ], + only: ['ios'] + }, { - text: '集成会话列表页面', link: 'key_function_conversation_list.html', - except: ['android', 'ios'] + text: '设计文档', + children: [ + { text: '设计指南', link: 'chatuikit_design_guide.html' }, + ], + only: ['ios'] + }, + { + text: '产品介绍', + children: [ + { text: '概述', link: 'chatuikit_overview.html' }, + { text: '特性', + children: [ + { text: '通用', link: 'chatfeature_common.html' }, + { text: '会话', link: 'chatfeature_conversation.html' }, + { text: '消息', link: 'chatfeature_message.html' }, + ], + }, + ], + only: ['web'] + }, + { + text: '快速开始', + children: [ + { text: '快速开始', link: 'chatuikit_quickstart.html' }, + ], + only: ['web'] + }, + { + text: '集成文档', + children: [ + { text: '集成单群聊 UIKit', link: 'chatuikit_integrated.html' }, + { text: '用户信息提供', link: 'chatuikit_provider.html' }, + { text: '全局上下文', link: 'chatuikit_context.html' }, + { text: '登录', link: 'chatuikit_login.html' }, + { text: '事件监听器', link: 'chatuikit_listener.html' }, + { text: '会话列表', link: 'chatuikit_conversation.html' }, + { text: '消息', link: 'chatuikit_chat.html' }, + { text: '通讯录', link: 'chatuikit_contactlist.html' }, + { text: '音视频通话', link: 'chatuikit_video.html' }, + { text: '主题', link: 'chatuikit_theme.html' }, + ], + only: ['web'] + }, + { + text: '组件文档', + children: [ + { text: '组件文档', link: 'chatuikit_storybook.html' }, + ], + only: ['web'] + }, + { + text: '设计文档', + children: [ + { text: '设计指南', link: 'chatuikit_design_guide.html' }, + ], + only: ['web'] + }, + { + text: '产品介绍', + children: [ + { text: '概述', link: 'chatuikit_overview.html' }, + { text: '特性', + children: [ + { text: '通用', link: 'chatfeature_common.html' }, + { text: '会话', link: 'chatfeature_conversation.html' }, + { text: '消息', link: 'chatfeature_message.html' }, + ], + }, + ], + only: ['android', 'react-native', 'flutter'] + }, + { + text: '快速开始', + children: [ + { text: '跑通示例项目', link: 'chatuikit_run.html', except: ['android'] }, + { text: '快速开始', link: 'chatuikit_quickstart.html' }, + ], + only: ['android', 'react-native', 'flutter'] + }, + { + text: '集成文档', + children: [ + { text: '集成单群聊 UIKit', link: 'chatuikit_integrated.html' }, + { text: '进阶用法', link: 'chatuikit_advancedusage.html' }, + { text: '用户信息提供', link: 'chatuikit_userinfo.html' }, + { text: '会话列表', link: 'chatuikit_conversation.html' }, + { text: '消息', link: 'chatuikit_chat.html' }, + { text: '通讯录', link: 'chatuikit_contactlist.html' }, + { text: '主题', link: 'chatuikit_theme.html' }, + { text: '国际化', link: 'chatuikit_internationalization.html', except: ['android'] }, + ], + only: ['android', 'react-native', 'flutter'] + }, + { + text: '设计文档', + children: [ + { text: '设计指南', link: 'chatuikit_design_guide.html' }, + ], + only: ['android', 'react-native', 'flutter'] + }, + { + text: '历史文档', + children: [ + { text: '历史文档', link: 'ui_historic.html', only: ['android','ios']}, + { text: 'UIKit 介绍', link: 'ui_overview.html', except: ['android','ios'] }, + { text: '快速开始', link: 'ui_quickstart.html', except: ['android','ios'] }, + { text: '集成聊天页面', link: 'ui_chat.html', except: ['android','ios'] }, + { text: '集成会话列表页面', link: 'ui_conversation.html', except: ['android','ios'] }, + ], + only: ['android', 'react-native', 'flutter', 'ios'] } ] +const chatroomUikitSidebar = [ + { text: "概述", link: "roomuikit_overview.html" }, + { + text: "特性", + collapsible: true, + children: [ + { text: "通用", link: "roomfeature_common.html" }, + { text: "消息扩展", link: "roomfeature_message.html" }, + { text: "成员管理", link: "roomfeature_member.html" }, + ], + }, + { text: "跑通示例项目", link: "roomuikit_run.html" }, + { text: "集成 ChatroomUIKit", link: "roomuikit_integrated.html"}, + { text: "快速开始", link: "roomuikit_quickstart.html" }, + { text: "最佳实践", link: "roomuikit_best_practice.html" }, + { text: "可配置项", link: "roomuikit_config_item.html" }, + { text: "主题", link: "roomuikit_theme.html" }, + { text: "自定义", link: "roomuikit_customize.html" }, + { text: "组件文档", link: "roomuikit_storybook.html", only: ['web'] }, + { text: "更新日志", link: "roomuikit_releasenote.html" }, + { text: "设计指南", link: "design_guide.html" }, +]; -function buildDocSidebar() { - const result = {} - platformList.forEach(platform => { - const key = `/uikit/${platform}/` - result[key] = uikitSidebar.map(sidebar => handleSidebarItem(platform, sidebar)).filter(s => s) +function buildChatUikitSidebar() { + const result = {}; + chatPlatformList.forEach((platform) => { + const key = `/uikit/chatuikit/${platform}/`; + result[key] = chatUikitSidebar + .map((sidebar) => + handleSidebarItem(platform, sidebar, CHAT_DOC_PATH, "chatuikit") + ) + .filter((s) => s); }); - return result + return result; } +function buildChatroomUikitSidebar() { + const result = {}; + chatroomPlatformList.forEach((platform) => { + const key = `/uikit/chatroomuikit/${platform}/`; + result[key] = chatroomUikitSidebar + .map((sidebar) => + handleSidebarItem(platform, sidebar, CHATROOM_DOC_PATH, "chatroomuikit") + ) + .filter((s) => s); + }); + return result; +} -function linkExists(platform: string, link: string): boolean { +function linkExists(platform: string, link: string, docPath: string): boolean { try { - const filePath = `${DOC_PATH}/${platform}/${link.replace(/.html$/, '.md')}`; + const filePath = `${docPath}/${platform}/${link.replace(/.html$/, ".md")}`; return fs.existsSync(filePath); } catch (e) { console.error(`Error checking file existence: ${e}`); @@ -54,36 +229,39 @@ function linkExists(platform: string, link: string): boolean { } } +function handleSidebarItem(platform, sidebar, docPath, kitType) { + const hasChildren = + sidebar.hasOwnProperty("children") && sidebar.children.length > 0; + const hasOnly = sidebar.hasOwnProperty("only") && sidebar.only.length > 0; + const hasExcept = + sidebar.hasOwnProperty("except") && sidebar.except.length > 0; -function handleSidebarItem(platform, sidebar) { - const hasChildren = sidebar.hasOwnProperty('children') && sidebar.children.length >0 - const hasOnly = sidebar.hasOwnProperty('only') && sidebar.only.length >0 - const hasExcept = sidebar.hasOwnProperty('except') && sidebar.except.length >0 - - let needThisPlatform = true + let needThisPlatform = true; if (hasOnly) { - needThisPlatform = sidebar.only.indexOf(platform) > -1 + needThisPlatform = sidebar.only.indexOf(platform) > -1; } if (hasExcept) { - needThisPlatform = sidebar.except.indexOf(platform) == -1 + needThisPlatform = sidebar.except.indexOf(platform) == -1; } if (!needThisPlatform) { - return null + return null; } if (hasChildren) { - let newchildren = sidebar.children.map(s => handleSidebarItem(platform, s)).filter(s=>s) + let newchildren = sidebar.children + .map((s) => handleSidebarItem(platform, s, docPath, kitType)) + .filter((s) => s); if (newchildren.length > 0) { - return {...sidebar, children: newchildren } + return { ...sidebar, children: newchildren }; } } else { - if (linkExists(platform, sidebar.link)) { - const newLink = `/uikit/${platform}/${sidebar.link}` - return {...sidebar, link:newLink} + if (linkExists(platform, sidebar.link, docPath)) { + const newLink = `/uikit/${kitType}/${platform}/${sidebar.link}`; + return { ...sidebar, link: newLink }; } } } -export const UIKIT_SIDEBAR = buildDocSidebar() - +export const CHAT_UIKIT_SIDEBAR = buildChatUikitSidebar(); +export const CHATROOM_UIKIT_SIDEBAR = buildChatroomUikitSidebar(); diff --git a/docs/.vuepress/templates/index.build.html b/docs/.vuepress/templates/index.build.html index 66a7bfc63..008d8f152 100644 --- a/docs/.vuepress/templates/index.build.html +++ b/docs/.vuepress/templates/index.build.html @@ -33,19 +33,19 @@ - + + - +
diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts index 226a8f546..82401946f 100644 --- a/docs/.vuepress/theme.ts +++ b/docs/.vuepress/theme.ts @@ -3,18 +3,18 @@ import { zhNavbar } from "./navbar/index.js"; import { zhSidebar } from "./sidebar/index.js"; interface CustomConfig { - extra_nav ?: any[] + extra_nav?: any[]; } export default hopeTheme({ hostname: "https://docs-im-beta2-private.easemob.com/", - home: '/product/introduction', + home: "/", iconAssets: "iconfont", - logo: '/logo.png', + logo: "/logo.png", repo: "easemob/easemob-doc", - docsBranch: 'doc-v2', + docsBranch: "doc-v2", docsDir: "docs", - darkmode: 'disable', + darkmode: "disable", pure: true, contributors: false, // navbar @@ -26,8 +26,16 @@ export default hopeTheme({ headerDepth: 2, extra_nav: [ // { text: '提交工单', link: 'https://console.easemob.com/ticket', type: 'info' }, - { text: '登录', link: 'https://console.easemob.com/user/login', type: 'success' }, - { text: '注册', link: 'https://console.easemob.com/user/register', type: 'primary' } + { + text: "登录", + link: "https://console.easemob.com/user/login", + type: "success", + }, + { + text: "注册", + link: "https://console.easemob.com/user/register", + type: "primary", + }, ], // page meta metaLocales: { @@ -35,7 +43,8 @@ export default hopeTheme({ }, plugins: { mdEnhance: { - container: true + container: true, + imgSize: true, }, }, }); diff --git a/docs/README.md b/docs/README.md index ed71d371f..e9822864c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,208 @@ --- home: true ---- +title: 主页 +# heroImage: https://www.easemob.com/statics/product/im/images/banner-pic.png +# heroText: 环信IM文档 +# tagline: 12小时快速集成、二进制私有协议、亿级高并发、消息及时到达、全球互联互通三大范德萨发生发大水范德萨三大法师法as的撒发的 +heroText: false +tagline: false +products: + - title: 产品介绍 + links: + - link: # + text: 产品概述 + - link: # + text: 产品动态 + - link: # + text: 产品价格 + + - title: 使用限制 + links: + - link: # + text: 使用限制 + - link: # + text: REST API调用策略 + + - title: 隐私与合规 + links: + - link: # + text: 隐私协议 + - link: # + text: 合规要求 + - link: # + text: 最佳实践 + + - title: 回调 + links: + - link: # + text: 设置回调 + - link: # + text: 回调事件 + - link: # + text: 产品价格 -Easemob Docs + - title: 错误码 + links: + - link: # + text: Android + - link: # + text: iOS + - link: # + text: Web + - link: # + text: Unity/Windows + - link: # + text: RESTful + - title: 最新发版 + links: + - link: # + icon: /icon-Android-hover.svg + - link: # + icon: /icon-iOS-hover.svg + - link: # + icon: /icon-web-hover.png + - link: # + icon: /icon-windows-hover.svg + - link: # + icon: /icon-linux-hover.svg + - link: # + icon: /icon-ReactNative-hover.svg + - link: # + icon: /icon-flutter-hover.png + - link: # + icon: /icon-unity-hover.svg + - link: # + icon: /icon-mini-program-hover.svg + - link: # + icon: /icon-Electron-hover.svg + - link: # + icon: /icon-platform-hover.svg + - title: 超级社区 + links: + - link: # + text: 社区管理 + - link: # + text: 频道管理 + - link: # + text: 频道分组管理 + - title: 语聊房 + links: + - link: # + text: 跑通示例项目 + - link: # + text: 客户端实现 + +projects: + - title: SDK快速开始 + desc: 快速集成IM SDK,实现即时通讯功能 + info: + - links: + - link: # + icon: /icon-Android-hover.svg + - link: # + icon: /icon-iOS-hover.svg + - link: # + icon: /icon-web-hover.png + - link: # + icon: /icon-windows-hover.svg + - link: # + icon: /icon-linux-hover.svg + - link: # + icon: /icon-ReactNative-hover.svg + - link: # + icon: /icon-flutter-hover.png + - link: # + icon: /icon-unity-hover.svg + + - title: 主要功能 + info: + - name: SDK(无UIKIT) + links: + - link: # + text: 会话 + - link: # + text: 消息 + - link: # + text: 群组 + - link: # + text: 聊天室 + - link: # + text: 用户属性 + - link: # + text: 用户关系 + - link: # + text: 在线状态订阅 + - link: # + text: 消息表情恢复 + - link: # + text: 子区 + - link: # + text: 离线推送 + - link: # + text: 内容审核 + - name: 单群聊 UIKIT + links: + - link: # + text: 会话 + - link: # + text: 消息 + - link: # + text: 群组 + - link: # + text: 联系人 + - name: 聊天室 UIKIT + links: + - link: # + text: 聊天室管理 + - link: # + text: 弹幕和打赏 + - link: # + text: 禁言 + - link: # + text: 全局广播 + - link: # + text: 消息管理 + - link: # + text: 成员管理 + + - title: API参考 + info: + - name: IM客户端API + links: + - link: # + icon: /icon-Android-hover.svg + - link: # + icon: /icon-iOS-hover.svg + - link: # + icon: /icon-web-hover.png + - link: # + icon: /icon-windows-hover.svg + - link: # + icon: /icon-linux-hover.svg + - link: # + icon: /icon-ReactNative-hover.svg + - link: # + icon: /icon-flutter-hover.png + - link: # + icon: /icon-unity-hover.svg + - link: # + icon: /icon-mini-program-hover.svg + - link: # + icon: /icon-Electron-hover.svg + - link: # + icon: /icon-platform-hover.svg + - name: IM服务端API + links: + - link: # + text: Java + - link: # + text: PHP + - name: 超级社区 + links: + - link: # + text: Android + - link: # + text: iOS + - link: # + text: Web +--- diff --git a/docs/document/android/conversation_delete.md b/docs/document/android/conversation_delete.md new file mode 100644 index 000000000..fdf4efd2d --- /dev/null +++ b/docs/document/android/conversation_delete.md @@ -0,0 +1,62 @@ +# 删除会话 + + + +删除好友或退出群组后,SDK 不会自动删除对应的单聊或群聊会话。你可以调用相应的接口从服务器和本地删除单个会话及其历史消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地删除单个会话及其历史消息,主要方法如下: + +- `deleteConversationFromServer`:单向删除服务端的单个会话及其历史消息。 +- `deleteConversation`:删除本地单个会话及其历史消息。 + +## 实现方法 + +### 单向删除服务端会话及其历史消息 + +你可以调用 `deleteConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 + +调用该方法之前,需调用 `getConversation` 方法获取会话 ID。 + +示例代码如下: + +```java +//获取指定的会话 ID。 +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); + +// 删除指定会话。如果需要保留历史消息,`isDeleteServerMessages` 传 `false`。 +EMClient.getInstance().chatManager().deleteConversationFromServer(conversationId, conversationType, isDeleteServerMessages, new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String error) { + + } +}); +``` + +### 删除本地会话及历史消息 + +你可以删除本地会话和历史消息,示例代码如下: + +```java +// 删除指定用户的会话,如果需要保留历史消息,传 `false`。 +EMClient.getInstance().chatManager().deleteConversation(username, true); +``` + +```java +// 删除指定会话中指定的一条历史消息。 +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); +conversation.removeMessage(deleteMsg.msgId); +``` diff --git a/docs/document/android/conversation_list.md b/docs/document/android/conversation_list.md new file mode 100644 index 000000000..3075d0347 --- /dev/null +++ b/docs/document/android/conversation_list.md @@ -0,0 +1,76 @@ +# 会话列表 + + + +对于单聊、群组聊天和聊天室会话,用户发消息时 SDK 会自动创建会话并将会话添加至用户的会话列表。 + +环信服务器和本地均存储会话,你可以获取会话列表。**服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地获取会话列表,主要方法如下: + +- `asyncFetchConversationsFromServer`:从服务器获取会话列表。 +- `getAllConversationsBySort`:获取本地所有会话。 + +## 实现方法 + +### 从服务器分页获取会话列表 + +你可以调用 `asyncFetchConversationsFromServer` 方法从服务端分页获取会话列表,包含单聊和群组聊天会话,不包含聊天室会话。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)、会话标记以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 + +:::tip +1. **若使用该功能,需在环信控制台开通,并将 SDK 升级至 4.0.3。而且,只有开通该功能,你才能使用置顶会话和会话标记功能。** +2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `getAllConversationsBySort` 或 `getAllConversations` 方法获取本地所有会话即可。 +3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +::: + +示例代码如下: + +```java +// limit: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新活跃的会话开始获取。 +int limit = 10; +String cursor = ""; +EMClient.getInstance().chatManager().asyncFetchConversationsFromServer(limit, cursor, new EMValueCallBack>() { + @Override + public void onSuccess(EMCursorResult result) { + // 获取到的会话列表 + List conversations = result.getData(); + // 下一次请求的 cursor + String nextCursor = result.getCursor(); + } + + @Override + public void onError(int error, String errorMsg) { + + } +}); +``` + +### 获取本地所有会话 + +你可以调用 `getAllConversationsBySort` 方法一次性获取本地所有会话。SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 + +本地会话列表包含单聊和群组聊天会话,至于是否包含聊天室会话,取决于在 SDK 初始化时 `com.hyphenate.chat.EMOptions#setDeleteMessagesAsExitChatRoom` 参数的设置。若设置为 `true`,即离开聊天室时删除该聊天室的所有本地消息,则本地会话列表中不包含聊天室会话。若设置为 `false`,即保留该聊天室的所有本地消息,则本地会话列表中包含聊天室会话。 + +若在初始化时,将 `EMOptions#setLoadEmptyConversations` 设置为 `true` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 + +:::tip +若使用该功能,需将 SDK 升级至 4.0.3。 +::: + +示例代码如下: + +```java +List conversations = EMClient.getInstance().chatManager().getAllConversationsBySort(); +``` + +你也可以调用 `getAllConversations` 方法返回 `Map ` 结构的会话。 \ No newline at end of file diff --git a/docs/document/android/conversation_mark.md b/docs/document/android/conversation_mark.md new file mode 100644 index 000000000..da11694eb --- /dev/null +++ b/docs/document/android/conversation_mark.md @@ -0,0 +1,163 @@ +# 会话标记 + + + +某些情况下,你可能需要对会话添加标记,例如会话标星或将会话标为已读或未读。即时通讯云 IM 支持对单聊和群聊会话添加标记,最大支持 20 个标记,所以一个会话最多可添加 20 个标记。 + +**如果要使用会话标记功能,你需要确保开通了[会话列表服务](conversation_list.html#从服务器分页获取会话列表)并将 SDK 版本升级至 4.3.0 或以上版本。** + +你需要自行维护会话标记与具体业务含义(比如 `MARK_0` 为重要会话)之间的映射关系。例如: + +```java +Map mapping=new HashMap<>(); +mapping.put(EMConversation.EMMarkType.MARK_0,"important"); +mapping.put(EMConversation.EMMarkType.MARK_1,"normal"); +mapping.put(EMConversation.EMMarkType.MARK_2,"unimportant"); +mapping.put(EMConversation.EMMarkType.MARK_3,"boys"); +mapping.put(EMConversation.EMMarkType.MARK_4,"girls"); +…… +``` + +## 技术原理 + +环信即时通讯 IM 支持会话标记功能,主要方法如下: + +- `EMChatManager#asyncAddConversationMark`:标记会话。 +- `EMChatManager#asyncRemoveConversationMark`:取消标记会话。 +- `EMChatManager#asyncGetConversationsFromServerWithCursor`:根据会话标记从服务器分页查询会话列表。 +- 根据会话标记从本地查询会话列表:调用 `getAllConversations` 方法获取本地所有会话后自己进行会话过滤。 +- `EMConversation#marks`:获取本地单个会话的所有标记。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 实现方法 + +### 标记会话 + +你可以调用 `asyncAddConversationMark` 方法标记会话。每次最多可为 20 个会话添加标记。调用该方法会同时为本地和服务器端的会话添加标记。 + +添加会话标记后,若调用 `asyncFetchConversationsFromServer` 接口从服务器分页获取会话列表,返回的会话对象中包含会话标记,你需要通过 `EMConversation#marks` 方法获取。若你已经达到了服务端会话列表长度限制(默认 100 个会话),服务端会根据会话的活跃度删除不活跃会话,这些会话的会话标记也随之删除。 + +:::tip +对会话添加标记,例如会话标星,并不影响会话的其他逻辑,例如会话的未读消息数。 +::: + +```java +String conversationId = "huanhuan"; +List ids=new ArrayList<>(); +ids.add(conversationId); +EMClient.getInstance().chatManager().asyncAddConversationMark(ids, EMConversation.EMMarkType.MARK_0, new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String error) { + + } +}); +``` + +### 取消标记会话 + +你可以调用 `asyncRemoveConversationMark` 方法删除会话标记。每次最多可移除 20 个会话的标记。 + +调用该方法会同时移除本地和服务器端会话的标记。 + +```java +String conversationId = "huanhuan"; +List ids=new ArrayList<>(); +ids.add(conversationId); +EMClient.getInstance().chatManager().asyncRemoveConversationMark(ids, EMConversation.EMMarkType.MARK_0,new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String error) { + + } +}); +``` + +### 根据会话标记从服务器分页查询会话列表 + +你可以调用 `asyncGetConversationsFromServerWithCursor` 方法根据会话标记从服务器分页获取会话列表。SDK 会按会话标记的时间的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 0)、会话标记以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 + +```java +// 最终的查询结果全部放入 result 中。 +List result=new ArrayList<>(); +// cursor:查询的开始位置。若传入空字符串,SDK 从最新标记操作的会话开始获取。 +String cursor=""; +// filter:会话查询选项,包括会话标记和每页获取的会话条数(最多可获取 10 条)。下面的代码以查询服务端所有标记了 `EMConversation.EMMarkType.MARK_0` 的会话为例。 +EMConversationFilter filter=new EMConversationFilter(EMConversation.EMMarkType.MARK_0,10); +doAsyncGetConversationsFromServerWithCursor(result,cursor,filter); + +private void doAsyncGetConversationsFromServerWithCursor(List result, @NonNull String cursor, @NonNull EMConversationFilter filter) { + EMClient.getInstance().chatManager().asyncGetConversationsFromServerWithCursor(cursor, filter, new EMValueCallBack>() { + @Override + public void onSuccess(EMCursorResult value) { + List datas=value.getData(); + if(!CollectionUtils.isEmpty(datas)){ + result.addAll(datas); + } + String cursor_ = value.getCursor(); + if(!TextUtils.isEmpty(cursor_)){ + doAsyncGetConversationsFromServerWithCursor(result,cursor_,filter); + } + } + + @Override + public void onError(int error, String errorMsg) { + + } + }); + } +``` + +### 根据会话标记从本地查询会话列表 + +对于本地会话,你可以调用 `getAllConversations` 方法获取本地所有会话后自己进行会话过滤。下面以查询标记了 `EMConversation.EMMarkType.MARK_0` 的所有本地会话为例。 + +```java +//最终的查询结果全部放入 result 中。 +List result=new ArrayList<>(); +Map localConversations = EMClient.getInstance().chatManager().getAllConversations(); +if(localConversations!=null&&!localConversations.isEmpty()){ + for(EMConversation conversation:localConversations.values()){ + Set marks = conversation.marks(); + if(marks!=null&&!marks.isEmpty()){ + for(EMConversation.EMMarkType mark:marks){ + if(mark==EMConversation.EMMarkType.MARK_0){ + result.add(conversation); + } + } + } + } +} +``` + +### 获取本地单个会话的所有标记 + +你可以调用 `EMConversation#marks` 方法获取本地单个会话的所有标记,示例代码如下: + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation("conversationId"); +Set marks = conversation.marks(); +``` + + + + + + + + diff --git a/docs/document/android/conversation_overview.md b/docs/document/android/conversation_overview.md new file mode 100644 index 000000000..75a7c9bac --- /dev/null +++ b/docs/document/android/conversation_overview.md @@ -0,0 +1,74 @@ +# 会话介绍 + + + +会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息、查看或清空历史消息等操作。 + +环信即时通讯 IM SDK 提供 `EMChatManager` 和 `EMConversation` 类以会话为单位对消息数据进行管理,如获取会话列表、置顶会话、添加会话标记、删除会话和管理未读消息等。 + +## 会话类 + +环信即时通讯 IM 提供会话类 `EMConversation`。该类定义了以下内容: + +| 类/方法 | 描述 | +| :--------- | :------- | +| EMConversationType | 会话类型枚举。
- `Chat`:单聊会话;
- `GroupChat`:群聊会话;
- `ChatRoom`:聊天室会话。 | +| EMSearchDirection | 消息搜索方向枚举。
- UP:按照消息中的 Unix 时间戳的逆序搜索。
- DOWN:按照消息中的时间戳的正序搜索。 | +| EMMarkType | 会话标记枚举类型:MARK_0,MARK_1,MARK_2,MARK_3,
MARK_4,MARK_5,MARK_6,MARK_7,MARK_8,
MARK_9,MARK_10,MARK_11,MARK_12,
MARK_13,MARK_14,MARK_15,
MARK_16,MARK_17,MARK_18,MARK_19。 | +| marks | 获取会话的所有标记。 | +| conversationId | 会话 ID,取决于会话类型。
- 单聊:会话 ID 为对方的用户 ID;
- 群聊:会话 ID 为群组 ID;
- 聊天室:会话 ID 为聊天室的 ID。| +| getType | 获取会话类型。 | +| getUnreadMsgCount | 获取会话中未读的消息数量。 | +| markAllMessagesAsRead | 将所有未读消息设置为已读。 | +| markMessageAsRead | 设置指定消息为已读。 | +| getAllMsgCount | 获取 SDK 本地数据库中会话的全部消息数。 | +| loadMoreMsgFromDB(String startMsgId, int pageSize) | 从 SDK 本地数据库中分页加载消息。加载的消息会基于消息中的时间戳放入当前会话的缓存中,调用 `getAllMessages` 时会返回所有加载的消息。 | +| loadMoreMsgFromDB(String startMsgId, int pageSize, EMSearchDirection direction) | 从指定消息 ID 开始分页加载数据库中的消息。加载到的消息会加入到当前会话的消息中。 | +| searchMsgFromDB(long timeStamp, int maxCount, EMSearchDirection direction) | 基于 Unix 时间戳搜索本地数据库中的消息。 | +| searchMsgFromDB(EMMessage.Type type, long timeStamp, int maxCount, String from, EMSearchDirection direction) | 从本地数据库获取指定会话的一定数量的特定类型的消息。 | +| searchMsgFromDB(String keywords, long timeStamp, int maxCount, String from, EMSearchDirection direction) | 从本地数据库获取会话中的指定用户发送的包含特定关键词的消息。 | +| searchMsgFromDB(long startTimeStamp, long endTimeStamp, int maxCount) | 从本地数据库中搜索指定时间段内发送或接收的一定数量的消息。 | +| searchCustomMsgFromDB(String keywords, long timeStamp, int maxCount, String from, EMSearchDirection direction) | 从本地数据库获取会话中的指定用户发送的包含特定关键词的自定义消息。 | +| getMessage | 根据消息 ID 获取已读的消息。 | +| getAllMessages | 获取该会话当前内存中的所有消息。 | +| removeMessage | 删除本地数据库中的一条指定消息。 | +| getLastMessage | 获取会话中的最新一条消息。 | +| getLatestMessageFromOthers | 获取会话中收到的最新一条消息。 | +| clear | 清除会话中的所有消息。只清除内存的,不清除本地数据库的消息。 | +| clearAllMessages | 清除内存和数据库中指定会话中的消息。 | +| setExtField | 设置会话的扩展字段。 | +| getExtField | 获取会话的扩展字段。 | +| isPinned | 获取会话的置顶状态。 | +| getPinnedTime | 获取会话置顶时间。会话置顶的 UNIX 时间戳,单位为毫秒。未置顶时值为 `0`。 | +| insertMessage | 在本地数据库的会话中插入一条消息。消息的会话 ID 应与会话的 ID 一致。消息会根据消息里的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 | +| updateMessage | 更新本地数据库的指定消息。消息更新后,消息 ID 不会修改,SDK 会自动更新会话的 `latestMessage` 等属性。 | +| `removeMessagesFromServer(List, EMCallBack)` | 根据消息 ID 单向删除漫游消息。 | +| removeMessagesFromServer(long, EMCallBack) | 根据时间单向删除漫游消息。 | +| removeMessages | 从本地数据库中删除指定时间段内的消息。 | + + +## 会话事件 + +`EMConversationListener` 中提供会话事件的监听接口。开发者可以通过设置此监听,获取会话事件,并做出相应处理。如果不再使用该监听,需要移除,防止出现内存泄漏。 + +示例代码如下: + +```java +EMConversationListener listener=new EMConversationListener() { + // 收到会话已读的事件。该事件在以下场景中触发: + // 1. 当消息接收方调用 `ackConversationRead()` 方法,SDK 会执行此回调, + // 会将本地数据库中该会话中消息的 `isAcked` 属性置为 `true`。 + // 2. 多端多设备登录时,若一端发送会话已读回执(conversation ack), + // 服务器端会将会话的未读消息数置为 0, + // 同时其他端会回调此方法,并将本地数据库中该会话中消息的 `isRead` 属性置为 `true`。 + @Override + public void onConversationRead(String from, String to) { + } + }; +``` + + + + + + diff --git a/docs/document/android/conversation_pin.md b/docs/document/android/conversation_pin.md new file mode 100644 index 000000000..efbbef083 --- /dev/null +++ b/docs/document/android/conversation_pin.md @@ -0,0 +1,78 @@ +# 会话置顶 + + + +会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 + +**若使用会话置顶功能,需将 SDK 升级至 4.0.3,并[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 技术原理 + +环信即时通讯 IM 支持会话置顶,主要方法如下: + +- `asyncPinConversation`:置顶会话。 +- `asyncFetchPinnedConversationsFromServer`:获取服务端置顶会话列表。 + +## 实现方法 + +### 置顶会话 + +你可以调用 `asyncPinConversation` 方法设置是否置顶会话。置顶状态会存储在服务器上,多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他登录设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。 + +你最多可以置顶 50 个会话。 + +示例代码如下: + +```java +EMClient.getInstance().chatManager().asyncPinConversation(conversationId, isPinned, new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String error) { + + } +}); +``` + +你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 + +### 获取服务端的置顶会话列表 + +你可以调用 `asyncFetchPinnedConversationsFromServer` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 + +你最多可以拉取 50 个置顶会话。 + +示例代码如下: + +```java +// limit: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新置顶的会话开始查询。 +int limit = 10; +String cursor = ""; +EMClient.getInstance().chatManager().asyncFetchPinnedConversationsFromServer(limit, cursor, new EMValueCallBack>() { + @Override + public void onSuccess(EMCursorResult result) { + // 获取到的会话列表 + List conversations = result.getData(); + // 下一次请求的 cursor + String nextCursor = result.getCursor(); + } + + @Override + public void onError(int error, String errorMsg) { + + } +}); +``` + diff --git a/docs/document/android/conversation_unread.md b/docs/document/android/conversation_unread.md new file mode 100644 index 000000000..2d86b8ef3 --- /dev/null +++ b/docs/document/android/conversation_unread.md @@ -0,0 +1,67 @@ +# 会话未读数 + + + +你可以查看本地所有会话或指定会话的未读消息数,并针对会话的未读消息数清零。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM Android SDK 通过 `EMChatManager` 和 `EMConversation` 类实现对本地会话的未读消息数的管理,其中核心方法如下: + +- `EMChatManager#getUnreadMessageCount`:获取本地所有会话的未读消息数。 +- `EMConversation#getUnreadMsgCount`:获取本地指定会话的未读消息数。 +- `EMChatManager#markAllConversationsAsRead`:将本地所有会话的未读消息数清零。 +- `EMChatManager#markAllMessagesAsRead`:对于本地指定会话的未读消息数清零。 +- `EMConversation#markMessageAsRead`:将指定会话的单条未读消息置为已读。 + +## 实现方法 + +### 获取所有会话的未读消息数 + +你可以调用 `getUnreadMessageCount` 方法获取本地所有会话的未读消息数量,示例代码如下: + +```java +EMClient.getInstance().chatManager().getUnreadMessageCount(); +``` + +### 获取指定会话的未读消息数 + +你可以调用 `getUnreadMsgCount` 获取本地指定会话的未读消息数,示例代码如下: + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); +conversation.getUnreadMsgCount(); +``` + +### 将所有会话的未读消息数清零 + +你可以调用 `markAllConversationsAsRead` 方法将本地所有会话的未读消息数清零,示例代码如下: + +```java +EMClient.getInstance().chatManager().markAllConversationsAsRead(); +``` + +### 指定会话的未读消息数清零 + +你可以调用 `markAllMessagesAsRead` 方法对指定会话的未读消息数清零,示例代码如下: + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); +conversation.markAllMessagesAsRead(); +``` + +### 将指定会话的单条未读消息置为已读 + +你可以调用 `markMessageAsRead` 方法将指定会话的单条未读消息置为已读。 + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); +conversation.markMessageAsRead(messageId); +``` diff --git a/docs/document/android/elite_sdk.md b/docs/document/android/elite_sdk.md new file mode 100644 index 000000000..a4a4b4837 --- /dev/null +++ b/docs/document/android/elite_sdk.md @@ -0,0 +1,385 @@ +# 精简版 SDK + +精简版 SDK 4.2.0 支持 Android 和 iOS 平台,包含基础的单聊和聊天室功能,适用于 SDK 包体积尽量小、仅需基础收发消息功能、而无需离线推送通知等功能的情况。 + +精简版 SDK 对应用的体积增量不大,android 为 1.11 MB,iOS 为 1.09 MB。 + +要下载 Android 端精简版 SDK,点击[这里](https://download-sdk.oss-cn-beijing.aliyuncs.com/downloads/SDK-mini/easemob-sdk-4.2.0-lite.zip)。 + +:::tip +精简版 SDK 无本地存储,可以升级为标准版 SDK,但标准版不能降级为精简版。 +::: + +## 功能列表 + +精简版 SDK 的功能如下表所示: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能模块功能功能细分/描述 接口文档 精简版 SDK标准版 SDK
消息管理发送和接收消息发送和接收消息

发送和接收消息

接收消息
发送和接收附件类型的消息
发送和接收位置消息
发送和接收透传消息
发送自定义类型消息
发送和接收合并消息
发送和接收定向消息
使用消息的扩展字段
管理本地消息管理本地消息

获取本地历史消息

+

搜索消息

+

导入和插入消息

+

更新消息

+

删除消息

管理服务端消息管理服务端消息

从服务器分页获取指定会话的历史消息

+

单向删除服务端的历史消息

管理消息回执消息送达回执

消息送达回执

消息已读回执

消息已读回执

撤回消息

撤回消息

+

设置消息撤回监听

 
修改消息单聊会话中已经发送成功的文本消息进行修改

修改消息

获取消息流量统计获取消息流量统计获取消息流量统计  
翻译消息翻译

消息翻译

会话管理会话列表获取本地所有会话 获取本地所有会话
从服务器分页获取会话列表

从服务器分页获取会话列表

会话未读数获取或清零本地会话的未读数

 

+

会话未读数

置顶会话置顶会话置顶会话
删除会话单向删除服务端会话及其历史消息单向删除服务端会话及其历史消息
删除本地会话及历史消息删除本地会话及历史消息
管理用户属性设置和获取用户属性用户属性指实时消息互动用户的信息,如用户昵称、头像、邮箱、电话、性别、签名、生日等管理用户属性
管理用户关系好友列表管理和黑名单管理

添加、删除好友;

+

设置和获取好友备注;

+

从服务器获取好友列表;

+

将用户添加到或移除黑名单

+

从服务器获取黑名单列表

管理用户关系
群组管理群组为多人聊天,有稳定的成员关系。

创建、管理群组;

+

管理群成员;

+

管理群成员属性

群组管理
聊天室管理聊天室为多人聊天,没有固定的成员关系。

聊天室概述

聊天室概述  
创建和管理聊天室创建聊天室创建和管理聊天室
加入聊天室
获取聊天室详情
退出聊天室
解散聊天室
监听聊天室事件
管理聊天室成员获取聊天室成员列表管理聊天室成员
将成员移出聊天室
管理聊天室黑名单
管理聊天室白名单
管理聊天室禁言列表
开启和关闭聊天室全员禁言
管理聊天室所有者和管理员
管理聊天室基本属性获取聊天室公告管理聊天室基本属性
更新聊天室公告
修改聊天室名称
修改聊天室描述
管理聊天室自定义属性管理聊天室自定义属性管理聊天室自定义属性
进阶功能离线推送集成第三方消息推送服务离线推送
登录多个设备支持同一账号在多个设备上登录并接收消息 
多设备管理多设备登录
管理在线状态订阅管理在线状态订阅在线状态订阅
消息表情回复 Reaction对单聊和群聊中的消息通过表情回复消息表情回复
子区管理子区是群组成员的子集子区管理
消息举报开发者可以在客户端调用该接口举报违规消息消息举报
+ +## 错误码 + +[Android 错误码](error.html) + + + + + + + + + + + + + + + + + diff --git a/docs/document/android/group_attributes.md b/docs/document/android/group_attributes.md index ec13e6e4a..01f48504c 100644 --- a/docs/document/android/group_attributes.md +++ b/docs/document/android/group_attributes.md @@ -77,7 +77,7 @@ EMClient.getInstance().groupManager().fetchGroupAnnouncement(groupId); #### 上传共享文件 -所有群组成员均可以调用 `uploadGroupSharedFile` 方法上传共享文件至群组,群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `EMGroupChangeListener#OnSharedFileAddedFromGroup` 回调。 +所有群组成员均可以调用 `uploadGroupSharedFile` 方法上传共享文件至群组,单个群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `EMGroupChangeListener#OnSharedFileAddedFromGroup` 回调。 示例代码如下: diff --git a/docs/document/android/group_manage.md b/docs/document/android/group_manage.md index c262f70ab..63a621b7d 100644 --- a/docs/document/android/group_manage.md +++ b/docs/document/android/group_manage.md @@ -109,6 +109,10 @@ EMClient.getInstance().groupManager().destroyGroup(groupId); 群成员也可以调用 `getGroupFromServer(String groupId, boolean fetchMembers)` 方法从服务器获取群组详情。返回的结果包括群组 ID、群组名称、群组描述、群组基本属性、群主、群组管理员列表、是否已屏蔽群组消息以及群组是否禁用等信息。另外,若将该方法的 `fetchMembers` 参数设置为 `true`,可获取群成员列表,默认最多包括 200 个成员。 +:::tip +对于公有群,用户即使不加入群也能获取群组详情,而对于私有群,用户只有加入了群组才能获取群详情。 +::: + 示例代码如下: ```java @@ -211,7 +215,7 @@ String cursor = result.getCursor(); ### 查询当前用户已加入的群组数量 -你可以调用 `EMGroupManager#asyncGetJoinedGroupsCountFromServer` 方法从服务器获取当前用户已加入的群组数量。单个用户可加入群组数量的上限取决于订阅的即时通讯的套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +自 4.2.1 版本开始,你可以调用 `EMGroupManager#asyncGetJoinedGroupsCountFromServer` 方法从服务器获取当前用户已加入的群组数量。单个用户可加入群组数量的上限取决于订阅的即时通讯的套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。 ```java EMClient.getInstance().groupManager().asyncGetJoinedGroupsCountFromServer(new EMValueCallBack() { diff --git a/docs/document/android/group_members.md b/docs/document/android/group_members.md index bef5716fb..4225fe775 100644 --- a/docs/document/android/group_members.md +++ b/docs/document/android/group_members.md @@ -148,9 +148,9 @@ EMClient.getInstance().groupManager().leaveGroup(groupId); #### 群成员被移出群组 -仅群主和群管理员可以调用 `removeUserFromGroup` 方法将指定成员移出群组。被踢出群组后,被踢成员将会收到群组事件回调 `EMGroupChangeListener#onUserRemoved`,其他成员将会收到回调 `EMGroupChangeListener#onMemberExited`。被移出群组后,该用户还可以再次加入群组。 +仅群主和群管理员可以调用 `removeUserFromGroup` 或 `asyncRemoveUsersFromGroup` 方法将单个或多个成员移出群组。被踢出群组后,被踢成员将会收到群组事件回调 `EMGroupChangeListener#onUserRemoved`,其他成员将会收到回调 `EMGroupChangeListener#onMemberExited`。被移出群组后,用户还可以再次加入群组。 -示例代码如下: +- 移出单个群成员,示例代码如下: ```java // 同步方法,会阻塞当前线程。 @@ -158,6 +158,23 @@ EMClient.getInstance().groupManager().leaveGroup(groupId); EMClient.getInstance().groupManager().removeUserFromGroup(groupId, username); ``` +- 批量移出群成员,示例代码如下: + +```java +// 异步方法。 +EMClient.getInstance().groupManager().asyncRemoveUsersFromGroup("GroupId", userList, new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String error) { + + } + }); +``` + ### 管理群成员的自定义属性 群成员可设置自定义属性(key-value),例如在群组中的昵称和头像等。 @@ -384,7 +401,7 @@ EMClient.getInstance().groupManager().getBlockedUsers(groupId); ```java // 同步方法,会阻塞当前线程。 // 异步方法为 asyncMuteGroupMembers(String, List, long, EMValueCallBack)。 -// 若对 `duration` 传 -1,表示永久禁言。 +// `duration`:禁言时间。传 -1 表示永久禁言。 EMClient.getInstance().groupManager().muteGroupMembers(groupId, muteMembers, duration); ``` @@ -414,10 +431,12 @@ EMClient.getInstance().groupManager().fetchGroupMuteList(String groupId, int pag #### 开启群组全员禁言 -仅群主和群管理员可以调用 `muteAllMembers` 方法开启全员禁言。 +仅群主和群管理员可以调用 `muteAllMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `unmuteAllMembers` 方法解除全员禁言。 -群主和群管理员开启群组全员禁言后,除了在白名单中的群成员,其他成员将不能发言。开启群组全员禁言后,群成员将会收到群组事件回调 `EMGroupChangeListener#onAllMemberMuteStateChanged`。 +开启群组全员禁言后,除了在白名单中的群成员,其他成员将不能发言。开启群组全员禁言后,群成员将会收到群组事件回调 `EMGroupChangeListener#onAllMemberMuteStateChanged`。 +群组全员禁言状态(`isAllMemberMuted` 的返回值)存储在本地数据库中,下次登录时可以直接从本地获取到。 + 示例代码如下: ```java diff --git a/docs/document/android/group_overview.md b/docs/document/android/group_overview.md index 4ba6e8af2..45dfc2985 100644 --- a/docs/document/android/group_overview.md +++ b/docs/document/android/group_overview.md @@ -23,9 +23,8 @@ | 创建方式 | 所有 app 用户都可以创建群组。 | 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 有权限创建聊天室。 | | 类型 | 分为公开群和私有群,创建群组时可设置入群是否需获得群主和群管理员的同意,支持不同使用场景。 | 没有公开和私有之分,所有用户均可自由加入或退出。 | | 最大成员数 | 成员数支持取决于所选择的版本,最高版本支持 8,000 人。 | 成员数支持取决于所选择的版本,最高版本支持 10,000 人。如需提升该上限,请联系商务。 | -| 离线推送消息 | 离线时,会收到推送消息。 | 离线时,不会收到推送消息;成员(除聊天室白名单中的成员)离线超过 2 分钟会自动退出聊天室。 | -| 离线消息存储 | 支持离线消息存储,每个会话存储 200 条消息。
用户上线时,会收到离线消息。 | 不支持离线消息存储。如果需要用户新加入聊天室时服务器推送最近的历史消息,可以联系商务开通聊天室历史消息推送,每个会话默认支持 10 条消息,最多可调整至 200 条。 | -| 漫游消息存储 | 支持漫游消息存储。你可以从服务器获取指定会话的消息。 | 不支持漫游消息存储。 | +| 离线消息存储 | 支持离线消息存储。用户离线时,服务器会先保存发送给这些用户的消息,等待这些用户上线时发送。对于单个终端用户来说,服务器最多可保存 200 条离线消息。 | 不支持离线消息存储。离线时,不会收到推送消息;成员(除聊天室白名单中的成员)离线超过 2 分钟会自动退出聊天室。 | +| 漫游消息/历史消息记录存储 | 支持漫游消息存储。服务器存储漫游消息和历史消息记录的时间取决于你订阅的 IM 套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。你可以[调用 REST API 接口从服务端获取历史消息记录 JSON 文件](/server-side/message_historical.html#获取历史消息记录)。此外,你还可以[调用客户端接口从服务端获取指定会话的漫游消息](message_retrieve.html#从服务器获取指定会话的消息),在多设备间同步。 | 不支持漫游消息存储,支持历史消息记录存储。你可以[调用 REST API 接口从服务端获取历史消息记录 JSON 文件](/server-side/message_historical.html#获取历史消息记录),但无法调用客户端接口获取指定会话的漫游消息。服务器存储历史消息记录的时间取决于你订阅的 IM 套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。
如果需要用户新加入聊天室时服务器推送最近的漫游消息,可以联系商务开通,每个会话默认支持 10 条消息,最多可调整至 200 条。 | | 消息可靠性 | 群组中发送的所有消息,用户都会收到。 | 当消息量大时,聊天室中超过阈值的消息会被丢弃。消息开始丢弃的阈值为每秒 100 条消息,可以根据需求进行调整。 | ### 群组成员角色 @@ -36,12 +35,18 @@ | 群管理员 | 由群主指定,协助群主进行管理,拥有一定的管理权限。 | 管理员可以更改群组名称和描述信息、对群成员进行管理。 | | 群主 | 群组的创建者,在群中拥有最高权限。 | 群主可以指定管理员、解散群组、将群主权限转移给他人、更改群组名称和描述信息和对群成员进行管理。 | -### 群组类型 +### 群组分类 -| 群组类型 | 介绍 | -| :------- | :----------------------------------------------------------- | -| 公开群 | 公开群可以被搜索到,用户只能申请加入群或者被管理员和群主邀请入群。 | -| 私有群 | 私有群不能被搜索到,用户需要被邀请才能入群。 | +- 群组按照是否对用户公开,可以分为公开群和私有群。 + +| 群组分类 | 加群方式 | 获取群组信息 | +| :------- | :---------- | :---------- | +| 公开群 | 任何用户可以搜索到该群,可申请加入群或者被管理员和群主邀请入群。任何用户均可申请入群,是否需要群主和群管理员审批,取决于群组的设置,例如 Android 为 `EMGroupStyle` 参数。 | - 对于群组详情和公开群列表,用户即使不加入群也能获取。
- 对于群公告和群共享文件列表,用户只有加入群时才能获取。 | +| 私有群 | 群外用户不能搜索到此类群组,需要被邀请才能入群。除了群主和群管理员,群成员是否也能邀请其他用户进群取决于群组的设置,例如 Android 为 `EMGroupStyle` 参数。 | 用户只有加入群后才能获取群详情、群公告、群共享文件列表、和群成员列表等群组信息。 | + +- 群组按照规模,可以分为普通群和大型群: + - 普通群:群成员总数不超过 3000 人。 + - 大型群:群成员总数超过 3000 人。大型群不支持离线推送。如需默认创建大型群,请联系环信商务。 ### 群组功能 @@ -81,4 +86,4 @@ ### 群组人数限制 -群成员的数量根据不同的套餐版本而不同,免费版 100 人/群,专业版 300 人/群, 旗舰版 3,000 人/群,尊享版 8,000 人/群。 +群成员的数量根据不同的套餐版本而不同,详见[产品价格](/product/pricing.html#套餐包功能详情)。 diff --git a/docs/document/android/message_delete.md b/docs/document/android/message_delete.md new file mode 100644 index 000000000..01e336a86 --- /dev/null +++ b/docs/document/android/message_delete.md @@ -0,0 +1,120 @@ +# 删除消息 + + + +本文介绍用户如何单向删除服务端以及本地的历史消息。 + +## 技术原理 + +使用环信即时通讯 IM Android SDK 可以通过 `EMConversation` 和 `EMChatManager` 类从服务器单向删除历史消息,主要方法如下: + +- `EMChatManager#asyncDeleteAllMsgsAndConversations`:清空当前用户的聊天记录,包括消息和会话,同时可以选择是否单向清除服务端的聊天记录。 +- `EMConversation#removeMessagesFromServer`:按消息时间或消息 ID 单向删除服务端的历史消息。 +- `EMChatManager#clearAllMessages`:删除本地指定会话的所有消息。 +- `EMChatManager#removeMessages(startTime, endTime)`:删除指定时间段的本地消息。 +- `EMChatManager#removeMessage(targetMessageId)`:删除本地单个会话的指定消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +### 清空聊天记录 + +你可以调用 `EMChatManager#asyncDeleteAllMsgsAndConversations` 方法清空当前用户的聊天记录,包括消息和会话。同时你也可以选择是否清除服务端的聊天记录。若你清除了服务端的聊天记录,当前用户无法从服务端拉取到该消息。其他用户不受该操作影响。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.4.0 或以上版本。 +::: + +```java + EMClient.getInstance().chatManager().asyncDeleteAllMsgsAndConversations(true, new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String error) { + + } + }); +``` + +### 单向删除服务端的历史消息 + +你可以调用 `removeMessagesFromServer` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。删除后,消息自动从设备本地移除且该用户无法从服务端拉取到该消息。其他用户不受该操作影响。 + +登录该账号的其他设备会收到 `EMMultiDeviceListener` 中的 `onMessageRemoved` 回调,已删除的消息自动从设备本地移除。 + +:::tip +若使用该功能,需将 SDK 升级至 V3.9.8 或以上版本并联系商务开通。 +::: + +示例代码如下: + +```java +// 按时间删除消息 +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); +conversation.removeMessagesFromServer(time, new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String desc) { + + } + }); + +// 按消息 ID 删除消息 + conversation.removeMessagesFromServer(msgIdList, new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String desc) { + + } + }); +``` + +### 删除本地指定会话的所有消息 + +你可以删除本地指定会话的所有消息,示例代码如下: + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +if(conversation != null) { + conversation.clearAllMessages(); +} +``` + +### 删除指定时间段的本地消息 + +你可以删除本地指定会话在一段时间内的本地消息,示例代码如下: + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +if(conversation != null) { + conversation.removeMessages(startTime, endTime); +} +``` + +### 删除本地单个会话的指定消息 + +你可以删除本地单个会话的指定消息,示例代码如下: + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +if(conversation != null) { + conversation.removeMessage(messageId); +} +``` + + diff --git a/docs/document/android/message_deliver_only_online.md b/docs/document/android/message_deliver_only_online.md new file mode 100644 index 000000000..d96fde7db --- /dev/null +++ b/docs/document/android/message_deliver_only_online.md @@ -0,0 +1,41 @@ +# 消息仅投递在线用户 + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。 该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **支持本地存储**:消息成功发送后,写入数据库。 +3. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 技术原理 + +环信即时通讯 IM 通过 `EMMessage` 类支持只将消息投递给在线用户: + +- `deliverOnlineOnly`:设置消息是否只投递给在线用户。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +要将消息只投递给在线用户,你需要在发送消息时将 `EMMessage#deliverOnlineOnly` 设置为 `true`。 + +下面以发送文本消息为例进行说明: + +```java +// 创建一条文本消息,`content` 为消息文字内容。 +// `conversationId` 为消息接收方,单聊时为对端用户 ID、群聊时为群组 ID。 +EMMessage message = EMMessage.createTextSendMessage(content, conversationId); +// 消息是否只投递在线用户。(默认)`false`:不论用户是否在线均投递;`true`:只投递给在线用户。若用户离线,消息不投递。 +message.deliverOnlineOnly(true); +// 会话类型:单聊为 EMMessage.ChatType.Chat,群聊为 EMMessage.ChatType.GroupChat,默认为单聊。 +message.setChatType(EMMessage.ChatType.Chat); +// 发送消息。 +EMClient.getInstance().chatManager().sendMessage(message); +``` + diff --git a/docs/document/android/message_import_insert.md b/docs/document/android/message_import_insert.md new file mode 100644 index 000000000..dbf1d102d --- /dev/null +++ b/docs/document/android/message_import_insert.md @@ -0,0 +1,54 @@ +# 导入和插入消息 + + + +本文介绍环信即时通讯 IM Android SDK 如何在本地导入和插入消息。 + +## 技术原理 + +环信即时通讯 IM Android SDK 支持提供 `EMChatManager` 类支持在本地导入和插入消息,其中包含如下主要方法: + +- `EMChatManager#importMessages`:批量导入消息到数据库; +- `EMChatManager#insertMessage`:在本地指定会话中插入一条消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 批量导入消息到数据库 + +如果你需要使用批量导入方式在本地会话中插入消息,可以调用 `importMessages` 方法,构造 `EMMessage` 对象,将消息导入本地数据库。 + +当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 + +推荐一次导入 1,000 条以内的数据。 + +示例代码如下: + +```java +EMClient.getInstance().chatManager().importMessages(msgs); +``` + +### 插入消息 + +如果你需要在本地会话中加入一条消息,比如收到某些通知消息时,可以构造一条消息写入会话。 + +例如插入一条无需发送但有需要显示给用户看的内容,类似 “XXX 撤回一条消息”、“XXX 入群”、“对方正在输入” 等。 + +消息会根据消息中的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 + +示例代码如下: + +```java +// 将消息插入到指定会话中。 +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); +conversation.insertMessage(message); +// 直接插入消息。 +EMClient.getInstance().chatManager().saveMessage(message); +``` + diff --git a/docs/document/android/message_manage.md b/docs/document/android/message_manage.md deleted file mode 100644 index 3c957fee1..000000000 --- a/docs/document/android/message_manage.md +++ /dev/null @@ -1,249 +0,0 @@ -# 管理本地会话和消息 - - - -本文介绍环信即时通讯 IM SDK 如何管理本地会话和消息。SDK 内部使用 SQLite 保存本地消息,方便消息处理。 - -除了发送和接收消息外,环信即时通讯 IM SDK 还支持以会话为单位对本地的消息数据进行管理,如获取与管理未读消息、搜索和删除历史消息以及统计消息流量等。其中,会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息、查看或清空历史消息等操作。 - -## 技术原理 - -环信即时通讯 IM Android SDK 支持管理用户设备上存储的消息会话数据,其中包含如下主要方法: - -- `EMChatManager.getAllConversationsBySort` 获取本地所有会话; -- `EMConversation.getAllMessages/loadMoreMsgFromDB` 从本地读取指定会话的消息; -- `EMConversation.getUnreadMsgCount` 获取指定会话的未读消息数; -- `EMChatManager.getUnreadMessageCount` 获取所有会话的未读消息数; -- `EMChatManager.markAllConversationsAsRead` 指定会话的未读消息数清零; -- `EMChatManager.deleteConversation` 删除会话及历史消息; -- `EMConversation.getUnreadMsgCount` 获取指定会话的未读消息数; -- `EMChatManager.getMessage` 根据消息 ID 获取消息; -- `EMChatManager.searchMsgFromDB(Type type, long timeStamp, int maxCount, String from, EMConversation.EMSearchDirection direction)` 获取指定会话中特定类型的消息; -- `EMChatManager.searchMsgFromDB(long startTimeStamp, long endTimeStamp, int maxCount)` 获取指定时间段内发送或接收的消息; -- `searchMsgFromDB(string keywords, long timeStamp, int maxCount, string from, EMSearchDirection direction)` 根据关键字搜索本地会话消息; -- `EMChatManager.importMessages` 批量导入消息到数据库; -- `EMChatManager.insertMessage` 在指定会话中插入消息; -- `EMConversation.updateMessage` 更新消息到本地数据库; -- `EMStatisticsManager.getMessageStatistics` 根据消息 ID 获取消息流量统计信息; -- `EMStatisticsManager.getMessageCount` 获取一定时间段内发送和/或接收的指定或全部类型的消息条数; -- `EMStatisticsManager.getMessageSize` 获取一定时间段内发送和/或接收的指定或全部类型的消息的总流量。 - -## 前提条件 - -开始前,请确保满足以下条件: - -- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 -- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 - -## 实现方法 - -### 获取本地所有会话 - -你可以调用 `getAllConversationsBySort` 方法一次性获取本地所有会话。若在初始化时,将 `EMOptions#setLoadEmptyConversations` 设置为 `true` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 - -SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 - -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 -::: - -示例代码如下: - -```java -List conversations = EMClient.getInstance().chatManager().getAllConversationsBySort(); -``` - -你也可以调用 `getAllConversations` 方法返回 `Map ` 结构的会话。 - -### 从本地读取指定会话的消息 - -你可以调用 `getAllMessages` 方法获取指定会话在内存中的所有消息。如果内存中为空,SDK 再从本地数据库中加载最近一条消息。 - -你也可以调用 `loadMoreMsgFromDB` 方法从本地数据库中分页加载消息,加载的消息会基于消息中的时间戳放入当前会话的内存中。 - -```java -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); -List messages = conversation.getAllMessages(); -// startMsgId:查询的起始消息 ID。SDK 从该消息 ID 开始按消息时间戳的逆序加载。如果传入消息的 ID 为空,SDK 从最新消息开始按消息时间戳的逆序获取。 -// pageSize:每页期望加载的消息数。取值范围为 [1,400]。 -List messages = conversation.loadMoreMsgFromDB(startMsgId, pagesize); -``` - -### 获取指定会话的未读消息数 - -你可以调用接口获取特定会话的未读消息数,示例代码如下: - -```java -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); -conversation.getUnreadMsgCount(); -``` - -### 获取所有会话的未读消息数 - -你可以通过接口获取所有会话的未读消息数量,示例代码如下: - -```java -EMClient.getInstance().chatManager().getUnreadMessageCount(); -``` - -### 指定会话的未读消息数清零 - -你可以调用接口对特定会话的未读消息数清零,示例代码如下: - -```java -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); -// 指定会话的未读消息数清零。 -conversation.markAllMessagesAsRead(); -// 将一条消息置为已读。 -conversation.markMessageAsRead(messageId); -// 将所有未读消息数清零。 -EMClient.getInstance().chatManager().markAllConversationsAsRead(); -``` - -### 删除会话及历史消息 - -你可以删除本地会话和历史消息,示例代码如下: - -```java -// 删除和特定用户的会话,如果需要保留历史消息,传 `false`。 -EMClient.getInstance().chatManager().deleteConversation(username, true); -``` - -```java -// 删除指定会话中指定的一条历史消息。 -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); -conversation.removeMessage(deleteMsg.msgId); -``` - -删除服务端的会话及其历史消息,详见 [删除服务端会话及其历史消息](message_retrieve.html#单向删除服务端会话及其历史消息)。 - -### 根据消息 ID 获取消息 - -你可以调用 `getMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 - -```java -// msgId:要获取消息的消息 ID。 -EMMessage msg = EMClient.getInstance().chatManager().getMessage(msgId); -``` - -### 获取指定会话中特定类型的消息 - -你可以调用 `searchMsgFromDB(Type type, long timeStamp, int maxCount, String from, EMConversation.EMSearchDirection direction)` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 - -```java -//conversationId:会话 ID -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); -// Type:消息类型;timeStamp:消息搜索的起始时间戳,单位为毫秒。该参数设置后,SDK 从指定的时间戳的消息开始,按照搜索方向对消息进行搜索。若设置为负数,SDK 从当前时间开始,按消息时间戳的逆序搜索。 -// maxCount:每次获取的消息数量,取值范围为 [1,400];direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -List emMessages = conversation.searchMsgFromDB(EMMessage.Type.TXT, System.currentTimeMillis(), maxCount, from, EMConversation.EMSearchDirection.UP); -``` - -### 获取指定时间段内会话的消息 - -你可以调用 `searchMsgFromDB(long startTimeStamp, long endTimeStamp, int maxCount)` 方法从本地存储中搜索一定时间段内指定会话中发送和接收的消息。每次最多可获取 400 条消息。 - -```java -//conversationId:会话 ID -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); -// startTimeStamp:搜索的起始时间戳;endTimeStamp:搜索的结束时间戳;maxCount:每次获取的消息数量,取值范围为 [1,400]。 -List messageList = conversation.searchMsgFromDB(startTimeStamp,endTimeStamp, maxCount); -``` - -### 根据关键字搜索会话消息 - -你可以调用 `searchMsgFromDB(string keywords, long timeStamp, int maxCount, string from, EMSearchDirection direction)` 方法从本地数据库获取会话中的指定用户发送的包含特定关键字的消息,示例代码如下: - -```java -//conversationId:会话 ID -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); -// keywords:搜索关键字;timeStamp:搜索的起始时间戳;maxCount:每次获取的消息数量,取值范围为 [1,400]。 -// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -List messages = conversation.searchMsgFromDB(keywords, timeStamp, maxCount, from, EMConversation.EMSearchDirection.UP); -``` - -### 批量导入消息到数据库 - -如果你需要使用批量导入方式在本地会话中插入消息,可以使用下面的接口,构造 `EMMessage` 对象,将消息导入本地数据库。 - -示例代码如下: - -```java -EMClient.getInstance().chatManager().importMessages(msgs); -``` - -### 插入消息 - -如果你需要在本地会话中加入一条消息,比如收到某些通知消息时,可以构造一条消息写入会话。 - -例如插入一条无需发送但有需要显示给用户看的内容,类似 “XXX 撤回一条消息”、“XXX 入群”、“对方正在输入” 等。 - -示例代码如下: - -```java -// 将消息插入到指定会话中。 -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); -conversation.insertMessage(message); -// 直接插入消息。 -EMClient.getInstance().chatManager().saveMessage(message); -``` - -### 更新消息到 SDK 本地数据库 - -如果需要更新消息可以选用以下方法的任意一种: - -```java -// 简洁方式:直接通过 `EMChatManager` 更新 SDK 本地数据库消息 -EMClient.getInstance().chatManager().updateMessage(message); - -// 正在使用 `EMConversation` 类时:先获取会话,再更新 SDK 本地数据库会话中的消息 -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); -conversation.updateMessage(message); -``` - -### 获取本地消息的流量统计信息 - -本地消息的流量统计功能默认关闭。若要使用该功能,需在 SDK 初始化前设置 `EMOptions#setEnableStatistics(boolean)` 开启。 - -SDK 只支持统计该功能开启后最近 30 天内发送和接收的消息。各类消息的流量计算方法如下: - -- 对于文本、透传、位置消息,消息流量为消息体的流量; -- 对于图片和视频消息,消息流量为消息体、图片或视频文件以及缩略图的流量之和; -- 对于文件和语音消息,消息流量为消息体和附件的流量。 - -:::notice - 1. 统计时间段的开始时间和结束时间均为服务器接收消息的 Unix 时间戳。 - 2. 对于携带附件的消息,下载成功后 SDK 才统计附件的流量。若附件下载多次,则会对下载的流量进行累加。 - 3. 对于从服务器拉取的漫游消息,如果本地数据库中已经存在,则不进行统计。 -::: - -SDK 仅统计本地消息的流量,而非消息的实际流量。一般而言,该统计数据小于实际流量,原因如下: -- 未考虑发送消息时通用协议数据的流量; -- 对于接收到的消息,服务端会进行消息聚合,添加通用字段,而消息流量统计为各消息的流量,未考虑通用字段的流量消耗。 - -#### 根据消息 ID 获取消息流量统计信息 - -你可以根据消息 ID 获取指定消息的统计信息。该方法返回的消息流量统计信息包括消息 ID、消息的发送方和接收方、消息体类型、会话类型、消息方向、消息流量大小(单位为字节)以及服务器收到该消息的 Unix 时间戳。 - -示例代码如下: - -```java -EMMessageStatistics statistics = EMClient.getInstance().statisticsManager().getMessageStatistics(messageId); -``` - -#### 获取一定时间段内发送和/或接收的消息条数 - -你可以统计一定时间段内发送和/或接收的指定或全部类型的消息,示例代码如下: - -```java -int number = EMClient.getInstance().statisticsManager().getMessageCount(startTime, endTime, direct, style); -``` - -#### 获取一定时间段内发送和/或接收的消息的总流量 - -你可以统计一定时间段内发送和/或接收的指定或全部类型的消息的总流量,流量单位为字节。 - -示例代码如下: - -```java -long size = EMClient.getInstance().statisticsManager().getMessageSize(startTime, endTime, direct, style); -``` \ No newline at end of file diff --git a/docs/document/android/message_modify.md b/docs/document/android/message_modify.md index ec4acc2ee..e780a7b78 100644 --- a/docs/document/android/message_modify.md +++ b/docs/document/android/message_modify.md @@ -1,6 +1,15 @@ # 修改消息 -对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。消息内容修改流程如下: +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。 + +:::tip +1. 若使用该功能,需将 SDK 升级至 4.1.0 或以上版本。 +2. 聊天室会话不支持消息修改功能。 +::: + +## 技术原理 + +消息内容修改流程如下: 1. 用户调用 SDK 的 API 修改一条消息。 2. 服务端存储的该条消息,修改成功后回调给 SDK。 @@ -13,10 +22,8 @@ - 对于单聊会话,只有消息发送方才能对消息进行修改。 - 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -:::notice -1. 若使用该功能,需将 SDK 升级至 4.1.0 或以上版本。 -2. 聊天室会话不支持消息修改功能。 -::: + +## 实现方法 你可以调用 `com.hyphenate.chat.EMChatManager#asyncModifyMessage` 方法修改已经发送成功的消息。一条消息默认最多可修改 10 次,若要提升修改次数,需联系商务。 diff --git a/docs/document/android/message_overview.md b/docs/document/android/message_overview.md index 5cc7a54e2..692c799c0 100644 --- a/docs/document/android/message_overview.md +++ b/docs/document/android/message_overview.md @@ -4,73 +4,129 @@ 环信即时通讯 IM 支持多种消息类型,开发者可以方便地对本地会话、消息进行管理,可以从服务端获取历史会话和消息,提供送达回执和已读回执能力。 -消息:环信即时通讯 IM 中消息(Message)表示发送方给接收方发送的内容,消息包括多种类型,如:文本、图片、语音等。 +消息:环信即时通讯 IM 中消息表示发送方给接收方发送的内容,消息包括多种类型,如:文本、图片、语音等。 -会话:环信即时通讯 IM 中会话(Conversation)分为 3 种,单聊、群聊、聊天室会话。单聊是指 2 个用户建立的会话,双方可以在会话中收发消息。群聊会话是由群成员发送消息所组成的,群成员可以在群会话中收发消息。聊天室会话与群聊会话类似。 +会话:环信即时通讯 IM 中会话分为 3 种,单聊、群聊、聊天室会话。单聊是指 2 个用户建立的会话,双方可以在会话中收发消息。群聊会话是由群成员发送消息所组成的,群成员可以在群会话中收发消息。聊天室会话与群聊会话类似。 -### 消息类型 +## 消息类型 | 类型
| 描述 | | :------------- | :----------------------------------------------------------- | -| 文本消息 | 文本消息的内容是文本,包含超链接和表情符号等。表情消息基于文本消息实现。
文本消息大小限制为 3 KB。 | -| 图片消息 | 图片消息是附件消息,需要先将图片上传至消息服务器。接收方收到图片时自动下载图片缩略图。
图片不能超过 10 MB,图片消息大小限制为 3 KB。 | -| 语音消息 | 语音消息是附件消息,需要先将语音上传至消息服务器。接收方收到语音时自动下载语音。
音频文件不能超过 10 MB,音频消息大小限制为 3 KB。 | -| 视频消息 | 视频消息是附件消息,需要先将视频上传至消息服务器。接收方收到视频时自动下载视频缩略图,点击下载视频消息。对于 Web 端,视频消息没有缩略图。
视频文件不能超过 10 MB,视频消息大小限制为 3 KB。 | -| 文件消息 | 文件消息是附件消息,需要先将文件上传至消息服务器。
附件大小不能超过 10 MB,文件消息大小限制为 3 KB。 | +| 文本消息 | 文本消息的内容是文本,包含超链接和表情符号等。表情消息基于文本消息实现。
文本消息大小限制为 5 KB。 | +| 图片消息 | 图片消息是附件消息,需要先将图片上传至消息服务器。接收方收到图片时自动下载图片缩略图。
图片默认不能超过 10 MB,图片消息大小限制为 5 KB。 | +| 语音消息 | 语音消息是附件消息,需要先将语音上传至消息服务器。接收方收到语音时自动下载语音。
音频文件默认不能超过 10 MB,音频消息大小限制为 5 KB。 | +| 视频消息 | 视频消息是附件消息,需要先将视频上传至消息服务器。接收方收到视频时自动下载视频缩略图,点击下载视频消息。对于 Web 端,视频消息没有缩略图。
视频文件默认不能超过 10 MB,视频消息大小限制为 5 KB。 | +| 文件消息 | 文件消息是附件消息,需要先将文件上传至消息服务器。
附件大小不能超过 10 MB,文件消息大小限制为 5 KB。 | | 位置消息 | 位置消息需要第三方的地图服务提供经纬度信息。接收方接收到位置消息,通过经纬度信息可以在第三方的地图服务中显示位置。 | -| 透传消息 | 透传消息可视为命令消息。通过发送这条命令给对方,通知对方要执行的操作,对方收到消息后系统可以自定义处理。透传消息不会在 UI 上展示。
消息大小限制为 3 KB。
你可以使用透传消息更新头像和昵称以及进行状态同步等。
透传消息不会存入本地数据库。 | +| 透传消息 | 透传消息可视为命令消息。通过发送这条命令给对方,通知对方要执行的操作,对方收到消息后系统可以自定义处理。透传消息不会在 UI 上展示。
消息大小限制为 5 KB。
你可以使用透传消息更新头像和昵称以及进行状态同步等。
透传消息不会存入本地数据库。 | | 消息自定义扩展 | 当基础的消息类型不满足需求时,可以使用消息自定义扩展增强基础消息类型。
使用扩展后,消息大小不能超过原类型消息的大小。
典型的用例是发送引用较早文本或图像消息的消息。 | -| 自定义消息 | 开发者自定义的消息类型。自定义消息支持设置类型名称,开发者可以添加多种自定义消息。
自定义消息大小限制为 3 KB。
自定义消息的使用场景:红包消息、模板消息等。 | +| 自定义消息 | 开发者自定义的消息类型。自定义消息支持设置类型名称,开发者可以添加多种自定义消息。
自定义消息大小限制为 5 KB。
自定义消息的使用场景:红包消息、模板消息等。 | -### 消息功能 +:::tip +1. 默认情况下,消息附件,例如图片、音频、视频和其他文件不能超过 10 MB,可存储 7 天。若要提升其中一个上限,请联系商务。 +2. 消息附件的大小及存储时间限制与群组共享文件的相同。如果消息附件的其中一个限制进行了上调,群组共享文件的对应限制也会随之自动调整,反之亦然。 +::: + +## 消息功能 + +环信即时通讯 IM 在消息服务器保存历史消息,方便用户在新设备上获取历史消息。历史消息存储时间与套餐版本相关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + +SDK 内部使用 SQLite 保存本地消息,方便消息处理。 -#### 管理本地会话和消息 +下表为各平台/框架对消息功能的支持情况。 -使用环信即时通讯 IM 发送和接收到的消息会存储在本地数据库,消息以会话为单位进行管理。用户可基于会话获取、删除、导入和插入消息。 +| 消息功能 | Android | iOS | Web | 小程序 | Flutter | React Native | Unity | Windows | +| :---- | :------ |:------ |:------ |:------ |:------ |:------ |:------ |:------ | +| 发送和接收消息 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取服务端历史消息 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取本地历史消息 | ✓ | ✓ | — | — | ✓ | ✓ | ✓ | ✓ | +| 撤回消息 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 搜索消息 | ✓ | ✓ | — | — | ✓ | ✓ | ✓ | ✓ | +| 修改消息 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 导入和插入消息 | ✓ | ✓ | — | — | ✓ | ✓ | ✓ | ✓ | +| 更新消息 | ✓ | ✓ | — | — | ✓ | ✓ | ✓ | ✓ | +| 删除服务端历史消息 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 删除本地历史消息 | ✓ | ✓ | — | — | ✓ | ✓ | ✓ | ✓ | +| 实现消息回执 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 翻译消息 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| 获取消息流量统计 | ✓ | ✓ | — | — | — | — | — | — | + +:::tip + +1. Web 和小程序端无本地消息存储。 +2. 对于 Android、iOS 平台,用户可以获取本地消息的流量统计信息。 -:::notice -Web 和小程序端无本地消息存储。 ::: -| 功能 | 描述 | -| :--------------------------- | :----------------------------------------------------------- | -| 获取本地会话列表 | 获取本地所有的会话。本地存储的消息有已读和未读状态,获取时包含未读消息数。 | -| 从数据库中读取指定会话的消息 | 从本地数据库获取指定会话的消息,进入会话时,获取会话内容。 | -| 获取指定会话的未读消息数量 | 从本地数据库获取指定会话的未读消息数,显示指定会话的未读消息数。 | -| 获取所有会话的未读消息数量 | 从本地数据库获取所有会话的未读消息数,显示整个应用的未读消息数。 | -| 会话的未读消息数清零 | 查看未读消息后,未读消息数清零。可对指定会话和所有会话进行未读消息数清零。 | -| 删除会话及历史消息 | 删除本地会话,可选择是否删除会话里的历史消息。 | -| 根据消息 ID 搜索消息 | 根据消息 ID 搜索指定的消息。 | -| 获取指定会话中特定类型的消息 | 获取指定会话中特定类型的消息。 | -| 获取指定会话中一定时间段内的消息 | 获取指定会话中一定时间段内发送和接收的消息。 | -| 根据关键字搜索会话消息 | 根据关键字对会话里的消息内容进行搜索。 | -| 导入消息到数据库 | 将外部消息批量导入本地数据库。需构造消息对象。 | -| 插入消息 | 模拟收到某些消息通知,可以构造一条消息并写入会话。 | - -除此之外,对于 Android、iOS 和 Web 平台,用户可以获取本地消息的流量统计信息。 +### [发送和接收消息](message_send_receive.html) -| 功能 | 描述 | -| :--------------------------- | :----------------------------------------------------------- | -| 根据消息 ID 获取消息流量统计信息 | 你可以根据消息 ID 获取指定消息的统计信息。该方法返回的消息流量统计信息包括消息 ID、消息的发送方和接收方、消息体类型、会话类型、消息方向、消息流量大小(单位为字节)以及服务器收到该消息的 Unix 时间戳。 | -| 获取一定时间段内发送和/或接收的消息条数| 你可以统计一定时间段内发送和/或接收的指定或全部类型的消息。| -| 获取一定时间段内发送和/或接收的消息的总流量 | 你可以统计一定时间段内发送和/或接收的指定或全部类型的消息的总流量,流量单位为字节。 | +用户可以在单聊、群聊、聊天室中发送如下类型的消息: +- 文字消息,包含超链接和表情消息。 +- 附件消息,包含图片、语音、视频及文件消息。 +- 位置消息。 +- 透传消息。 +- 自定义消息。 +- 合并消息。 +- 定向消息(只适用于群组聊天和聊天室聊天)。 + +当目前消息类型不满足用户需求时,可以在扩展部分保存更多信息,例如消息中需要携带被回复的消息内容或者是图文消息等场景。 + +### [获取历史消息](message_retrieve.html) + +1. 从服务器获取指定会话的历史消息。 +2. 从本地获取历史消息: +- 从数据库中读取指定会话的消息; +- 根据消息 ID 获取本地消息; +- 获取本地指定会话中特定类型的消息; +- 获取指定时间段内本地单个会话的消息。 + +### [撤回消息](message_recall.html) + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的功能配置 > 功能配置总览 > 基础功能页面设置消息撤回时长,该时长不超过 7 天。 + +:::tip +除了透传消息,其他各类型的消息都支持撤回。 +::: + +### [搜索消息](message_search.html) + +搜索消息支持以下方式的搜索: + +- 根据关键字搜索本地数据库中单个会话中指定用户发送的消息。 +- 根据搜索范围搜索所有会话以及当前会话中的消息:除了设置关键字、消息时间戳、消息数量、发送方、搜索方向等条件搜索所有会话中的消息时,你还可以选择搜索范围,如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。 + +### [修改消息](message_modify.html) + +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。聊天室会话不支持消息修改功能。 -#### 从服务器获取消息 +对于修改后的消息,消息体中除了内容变化,还新增了修改者的用户 ID、修改时间和修改次数属性。除消息体外,该消息的其他信息(例如,消息发送方、接收方和扩展属性)均不会发生变化。 -环信即时通讯 IM 在消息服务器保存历史消息,方便用户在新设备上获取历史消息。 +- 对于单聊会话,只有消息发送方才能对消息进行修改。 +- 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -历史消息存储时间与套餐版本相关:专业版 7 天,旗舰版 90 天, 尊享版 180 天。 +### [导入和插入消息](message_import_insert.html) -| 功能 | 描述 | 适用的平台/框架| -| :---------- | :----------- |:----------------------------------- | -| 从服务端分页获取会话列表 | 从服务端分页获取会话列表。 | 所有平台/框架 | -| 分页获取指定会话的历史消息 | 从服务端分页获取会话的历史消息。 | 所有平台/框架 | -| 单向删除服务端的历史消息 | 当前用户单向删除服务端的历史消息。消息删除后,当前用户无法从服务端拉取到该消息,其他用户不受影响。 | 所有平台/框架 | -| 单向删除服务端会话及其历史消息 | 删除服务端会话及其历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息(Web 和小程序端不涉及本地会话和消息),其他用户不受影响。 | 所有平台/框架 | +你可以在本地会话中批量导入消息。当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 -#### 获取消息的已读回执和送达回执 +如果你需要在本地会话中加入一条消息,比如收到某些通知消息时,可以构造一条消息写入会话。消息会根据消息中的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 -环信即时通讯 IM 消息投递成功会返回送达回执,而且提供消息已读功能,接收方查看消息后会返回已读回执。 +### [更新消息](message_update.html) + +你可以更新本地数据库中的消息。 + +### [删除消息](message_delete.html) + +单向删除服务端的历史消息:删除后,消息自动从设备本地移除且该用户无法从服务端拉取到该消息。其他用户不受该操作影响。每次最多可删除 50 条消息。 + +登录该账号的其他设备会收到漫游消息删除回调。 + +### [实现消息回执](message_receipt.html) + +即时通讯 IM 消息投递成功会返回送达回执,而且提供消息已读功能,接收方查看消息后会返回已读回执。 | 功能 | 描述 | | :--------------- | :------------------------------------- | @@ -79,13 +135,52 @@ Web 和小程序端无本地消息存储。 | 单聊会话已读回执 | 接收方查看单聊会话后,返回会话已读回执。 | | 群组消息已读回执 | 提供群组消息已读回执能力。 | -#### 消息重发机制 +### [翻译消息](message_translation.html) + +环信即时通讯 IM SDK 集成了 Microsoft Azure Translation API,支持在发送或接收消息时对文本消息进行按需翻译或自动翻译: + +- 按需翻译:接收方在收到文本消息后,将消息内容翻译为目标语言。 +- 自动翻译:发送方发送消息时,SDK 根据发送方设置的目标语言自动翻译文本内容,然后将消息原文和译文一起发送给接收方。 + +### [只投在线用户](message_deliver_only_online.html) + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。 该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **支持本地存储**:消息成功发送后,写入数据库。 +3. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +### [获取消息流量统计](message_traffic_statis.html) + +对于 Android 和 iOS 平台,用户可以获取本地消息的流量统计信息。 + +| 功能 | 描述 | +| :--------------------------- | :----------------------------------------------------------- | +| 根据消息 ID 获取消息流量统计信息 | 你可以根据消息 ID 获取指定消息的统计信息。该方法返回的消息流量统计信息包括消息 ID、消息的发送方和接收方、消息体类型、会话类型、消息方向、消息流量大小(单位为字节)以及服务器收到该消息的 Unix 时间戳。 | +| 获取一定时间段内发送和/或接收的消息条数 | 你可以统计一定时间段内发送和/或接收的指定或全部类型的消息。| +| 获取一定时间段内发送和/或接收的消息的总流量 | 你可以统计一定时间段内发送和/或接收的指定或全部类型的消息的总流量,流量单位为字节。 | + +## 消息存储 + +消息存储分为本地存储和服务器存储: + +1. SDK 存储:SDK 内部使用 SQLite 保存本地消息,你可以获取本地消息。 + +2. 服务器存储:历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 + +**默认情况下,消息附件可在服务器存储 7 天。若要提升该限制,你需要联系商务。** + +各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 + +## 消息重发机制 -- 对于 Android、iOS 、Windows 端和三个跨平台框架 Unity、React Native 和 Flutter 来说,消息重发机制如下: +1. 对于 Android、iOS 、Windows 端和三个跨平台框架 Unity、React Native 和 Flutter 来说,消息重发机制如下: 客户端调用发送消息的方法后,会等待服务器返回响应,超时时间为 10 秒。若因响应超时导致发送失败,客户端会再次尝试发送消息,即通过长连接重连服务器,然后发送消息。如果再次失败,SDK 认为消息发送失败,返回服务器不可达的错误消息,即错误码 300,Android 为 `EMErrorServerNotReachable`,iOS 和 Windows 为 `SERVER_NOT_REACHABLE`。 -- 对于 Web 来说,消息重发机制如下: +2. 对于 Web 来说,消息重发机制如下: 发送消息时如果 WebSocket 已经断开正在进行重连时,重新连接后会重新发送消息;若 WebSocket 断开时发送消息,SDK 会提示网络断开连接导致消息发送失败的错误,即错误码 510 `MESSAGE_WEBSOCKET_DISCONNECTED`。 diff --git a/docs/document/android/message_recall.md b/docs/document/android/message_recall.md new file mode 100644 index 000000000..faa587366 --- /dev/null +++ b/docs/document/android/message_recall.md @@ -0,0 +1,70 @@ +# 撤回消息 + + + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能**页面设置消息撤回时长,该时长不超过 7 天。 + +:::tip +除了透传消息,其他各类型的消息都支持撤回。 +::: + +## 技术原理 + +环信即时通讯 IM 通过 `EMChatManager` 和 `EMMessage` 类支持你撤回一条发送成功的消息: + +- `recallMessage`:撤回一条发送成功的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 撤回消息 + +你可以调用 `recallMessage` 方法撤回一条发送成功的消息。 + +调用该方法后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `onMessageRecalled` 事件。 + +- 同步方法: + +```java +try { + EMClient.getInstance().chatManager().recallMessage(message); + EMLog.d("TAG", "撤回消息成功"); +} catch (EMException e) { + e.printStackTrace(); + EMLog.e("TAG", "撤回消息失败的原因: "+e.getDescription()); +} +``` + +- 异步方法: + +```java +EMClient.getInstance().chatManager().asyncRecallMessage(message, new CallBack() { + @Override + public void onSuccess() { + EMLog.d("TAG", "撤回消息成功"); + } + @Override + public void onError(int errorCode, String errorMessage) { + EMLog.e("TAG", "撤回消息失败的原因: "+errorMessage); + } + @Override + public void onProgress(int i, String s) { + } +}); +``` + +### 设置消息撤回监听 + +你可以设置消息撤回监听,通过 `onMessageRecalled` 事件监听发送方对已接收的消息的撤回。 + +```java +void onMessageRecalled(List messages); +``` \ No newline at end of file diff --git a/docs/document/android/message_receipt.md b/docs/document/android/message_receipt.md index 56038fd77..8932f176d 100644 --- a/docs/document/android/message_receipt.md +++ b/docs/document/android/message_receipt.md @@ -1,10 +1,10 @@ -# 获取消息的已读回执和送达回执 +# 实现消息回执 单聊会话支持消息送达回执、会话已读回执和消息已读回执,发送方发送消息后可及时了解接收方是否及时收到并阅读了信息,也可以了解整个会话是否已读。 -群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 本文介绍如何使用环信即时通讯 IM Android SDK 实现单聊和群聊的消息回执功能。 @@ -41,7 +41,7 @@ - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 -- 群消息已读回执功能仅在环信 IM 旗舰版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +- 群消息已读回执功能仅在环信 IM 专业版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 ## 实现方法 @@ -90,7 +90,6 @@ EMClient.getInstance().chatManager().removeMessageListener(msgListener); Options.setRequireAck = true; ``` - ##### 会话已读回执 参考以下步骤在单聊中实现会话已读回执。 @@ -125,6 +124,8 @@ EMClient.getInstance().chatManager().addConversationListener(new EMConversationL ##### 消息已读回执 +单聊消息的已读回执有效期与消息在服务端的存储时间一致,即在服务器存储消息期间均可发送已读回执。消息在服务端的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + 参考如下步骤在单聊中实现消息已读回执。 1. 接收方发送已读回执消息。 @@ -200,7 +201,9 @@ EMClient.getInstance().chatManager().addMessageListener(new EMMessageListener() 对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。 -仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊已读回执的有效期为 3 天,即群组中的消息发送时间超过 3 天,服务器不记录阅读该条消息的群组成员,也不会发送已读回执。 + +仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 1. 群主或群管理员发送消息时若需已读回执,需设置 `EMMessage` 的方法 `setIsNeedGroupAck()` 为 `YES`。 diff --git a/docs/document/android/message_retrieve.md b/docs/document/android/message_retrieve.md index 409c66231..fe4f1ea20 100644 --- a/docs/document/android/message_retrieve.md +++ b/docs/document/android/message_retrieve.md @@ -1,141 +1,47 @@ -# 管理服务端的会话和消息 +# 获取历史消息 -环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。本文介绍用户如何获取和删除服务端的会话和消息。 +本文介绍环信即时通讯 IM Android SDK 如何从服务器和本地获取历史消息。 -:::tip -本文介绍的功能均为增值服务,需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 -::: +- 环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 + +- SDK 内部使用 SQLite 保存本地消息,你可以获取本地消息。 ## 技术原理 -使用环信即时通讯 IM SDK 可以从服务器获取历史消息。 +环信即时通讯 IM Android SDK 提供 `EMChatManager` 和 `EMConversation` 类支持获取服务器和本地的消息,包含如下主要方法: -- `asyncFetchConversationsFromServer` 分页获取服务器保存的会话列表; -- `asyncFetchPinnedConversationsFromServer` 分页获取服务器保存的置顶会话列表; -- `asyncPinConversation` 置顶会话。 -- `asyncFetchHistoryMessage` 从服务端分页获取指定会话的历史消息; -- `removeMessagesFromServer` 单向删除服务端的历史消息; -- `deleteConversationFromServer` 删除服务端的会话及其历史消息。 +- `EMChatManager.asyncFetchHistoryMessage`:从服务端分页获取指定会话的历史消息; +- `EMConversation.getAllMessages/loadMoreMsgFromDB`:读取本地指定会话的消息; +- `EMChatManager.getMessage`:根据消息 ID 获取本地消息; +- `EMChatManager.searchMsgFromDB(Type type, long timeStamp, int maxCount, String from, EMConversation.EMSearchDirection direction)`:获取本地存储的指定会话中特定类型的消息; +- `EMChatManager.searchMsgFromDB(long startTimeStamp, long endTimeStamp, int maxCount)`:获取一定时间段内本地指定会话中发送和接收的消息; ## 前提条件 开始前,请确保满足以下条件: -- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 - 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 -### 从服务器分页获取会话列表 - -对于单聊或群聊,用户发消息时会自动将对方添加到用户的会话列表。 - -你可以调用 `asyncFetchConversationsFromServer` 方法从服务端分页获取会话列表。若在初始化时,将 `EMOptions#setLoadEmptyConversations` 设置为 `true` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 - -SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 - -服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。 - -:::notice -1. 若使用该功能,需将 SDK 升级至 4.0.3。 -2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `getAllConversationsBySort` 或 `getAllConversations` 方法获取本地所有会话即可。 -3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 -::: - -示例代码如下: - -```java -// limit: 每页返回的会话数。取值范围为 [1,50]。 -// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新活跃的会话开始获取。 -int limit = 10; -String cursor = ""; -EMClient.getInstance().chatManager().asyncFetchConversationsFromServer(limit, cursor, new EMValueCallBack>() { - @Override - public void onSuccess(EMCursorResult result) { - // 获取到的会话列表 - List conversations = result.getData(); - // 下一次请求的 cursor - String nextCursor = result.getCursor(); - } - - @Override - public void onError(int error, String errorMsg) { - - } -}); -``` - -## 获取服务端的置顶会话列表 - -你可以调用 `asyncFetchPinnedConversationsFromServer` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 - -你最多可以拉取 50 个置顶会话。 - -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 -::: - -示例代码如下: - -```java -// limit: 每页返回的会话数。取值范围为 [1,50]。 -// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新置顶的会话开始查询。 -int limit = 10; -String cursor = ""; -EMClient.getInstance().chatManager().asyncFetchPinnedConversationsFromServer(limit, cursor, new EMValueCallBack>() { - @Override - public void onSuccess(EMCursorResult result) { - // 获取到的会话列表 - List conversations = result.getData(); - // 下一次请求的 cursor - String nextCursor = result.getCursor(); - } - - @Override - public void onError(int error, String errorMsg) { - - } -}); -``` +### 从服务器获取指定会话的消息 -### 置顶会话 +对于单聊或群聊,用户发消息时,会自动将对方添加到用户的会话列表。 -会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 +你可以调用 `asyncFetchHistoryMessage` 方法从服务器分页获取指定会话的消息(消息漫游)。你可以指定消息查询方向,即明确按时间顺序或逆序获取。 -置顶状态会存储在服务器上,多设备登录情况下,更新置顶状态会同步到其他登录设备。你最多可以置顶 50 个会话。 +为确保数据可靠,我们建议你每次最多获取 50 条消息,可多次获取。拉取后,SDK 会自动将消息更新到本地数据库。 -你可以调用 `asyncPinConversation` 方法设置是否置顶会话。多设备登录情况下,会话置顶或取消置顶后,其他登录设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。 +若你在初始化时打开了 `EMOptions#setRegardImportedMsgAsRead` 开关,调用该接口获取的[通过服务端接口](/server-side/message_import.html)导入的消息为已读状态,会话中未读取的消息数量,即 `EMConversation#getUnreadMsgCount` 的返回值不发生变化。若该开关为关闭状态,`EMConversation#getUnreadMsgCount` 的返回值会增加。 -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 +:::tip +1. 历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +2. 各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 ::: -示例代码如下: - -```java -EMClient.getInstance().chatManager().asyncPinConversation(conversationId, isPinned, new EMCallBack() { - @Override - public void onSuccess() { - - } - - @Override - public void onError(int code, String error) { - - } -}); -``` - -你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 - -### 分页获取指定会话的历史消息 - -对于单聊或群聊,用户发消息时,会自动将对方添加到用户的会话列表。 - -你可以调用 `asyncFetchHistoryMessage` 方法从服务器获取指定会话的消息(消息漫游)。你可以指定消息查询方向,即明确按时间顺序或逆序获取。为确保数据可靠,我们建议你每次最多获取 50 条消息,可多次获取。拉取后,SDK 会自动将消息更新到本地数据库。 - ```java // 异步方法。同步方法为 fetchHistoryMessages(String, EMConversationType, int, String, EMConversation.EMSearchDirection)。 EMClient.getInstance().chatManager().asyncFetchHistoryMessage( @@ -158,66 +64,52 @@ EMClient.getInstance().chatManager().asyncFetchHistoryMessage( ); ``` -### 单向删除服务端的历史消息 - -你可以调用 `removeMessagesFromServer` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息。其他用户不受该操作影响。登录该账号的其他设备会收到 `EMMultiDeviceListener` 中的 `onMessageRemoved` 回调,已删除的消息自动从设备本地移除。 +### 从本地读取指定会话的消息 -:::tip -若使用该功能,需将 SDK 升级至 V3.9.8 或以上版本并联系商务开通。 -::: +你可以调用 `getAllMessages` 方法获取指定会话在内存中的所有消息。如果内存中为空,SDK 再从本地数据库中加载最近一条消息。 -示例代码如下: +你也可以调用 `loadMoreMsgFromDB` 方法从本地数据库中分页加载消息,加载的消息会基于消息中的时间戳放入当前会话的内存中。 -```java -// 按时间删除消息 +```java EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); -conversation.removeMessagesFromServer(time, new EMCallBack() { - @Override - public void onSuccess() { - - } - - @Override - public void onError(int code, String desc) { - - } - }); - -// 按消息 ID 删除消息 - conversation.removeMessagesFromServer(msgIdList, new EMCallBack() { - @Override - public void onSuccess() { - - } - - @Override - public void onError(int code, String desc) { - - } - }); -``` -### 单向删除服务端会话及其历史消息 - -你可以调用 `deleteConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 - -调用该方法之前,需调用 `getConversation` 方法获取会话 ID。 - -示例代码如下: +List messages = conversation.getAllMessages(); +// startMsgId:查询的起始消息 ID。SDK 从该消息 ID 开始按消息时间戳的逆序加载。如果传入消息的 ID 为空,SDK 从最新消息开始按消息时间戳的逆序获取。 +// pageSize:每页期望加载的消息数。取值范围为 [1,400]。 +List messages = conversation.loadMoreMsgFromDB(startMsgId, pagesize); +``` + +### 根据消息 ID 获取本地消息 + +你可以调用 `getMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 ```java -//获取指定的会话 ID。 -EMConversation conversation = EMClient.getInstance().chatManager().getConversation(username); +// msgId:要获取消息的消息 ID。 +EMMessage msg = EMClient.getInstance().chatManager().getMessage(msgId); +``` -// 删除指定会话。如果需要保留历史消息,`isDeleteServerMessages` 传 `false`。 -EMClient.getInstance().chatManager().deleteConversationFromServer(conversationId, conversationType, isDeleteServerMessages, new EMCallBack() { - @Override - public void onSuccess() { +### 获取本地会话中特定类型的消息 - } +你可以调用 `searchMsgFromDB(Type type, long timeStamp, int maxCount, String from, EMConversation.EMSearchDirection direction)` 方法从本地存储中获取指定会话中特定类型的消息。 - @Override - public void onError(int code, String error) { +每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 - } -}); -``` \ No newline at end of file +```java +//conversationId:会话 ID +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +// Type:消息类型;timeStamp:消息搜索的起始时间戳,单位为毫秒。该参数设置后,SDK 从指定的时间戳的消息开始,按照搜索方向对消息进行搜索。若设置为负数,SDK 从当前时间开始,按消息时间戳的逆序搜索。 +// maxCount:每次获取的消息数量,取值范围为 [1,400];direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +List emMessages = conversation.searchMsgFromDB(EMMessage.Type.TXT, System.currentTimeMillis(), maxCount, from, EMConversation.EMSearchDirection.UP); +``` + +### 获取一定时间内本地会话的消息 + +你可以调用 `searchMsgFromDB(long startTimeStamp, long endTimeStamp, int maxCount)` 方法从本地存储中搜索一定时间段内指定会话中发送和接收的消息。 + +每次最多可获取 400 条消息。 + +```java +//conversationId:会话 ID +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +// startTimeStamp:搜索的起始时间戳;endTimeStamp:搜索的结束时间戳;maxCount:每次获取的消息数量,取值范围为 [1,400]。 +List messageList = conversation.searchMsgFromDB(startTimeStamp,endTimeStamp, maxCount); +``` diff --git a/docs/document/android/message_search.md b/docs/document/android/message_search.md new file mode 100644 index 000000000..cda09d338 --- /dev/null +++ b/docs/document/android/message_search.md @@ -0,0 +1,65 @@ +# 搜索消息 + + + +本文介绍环信即时通讯 IM Android SDK 如何搜索本地消息。 + +## 技术原理 + +环信即时通讯 IM Android SDK 通过 `EMConversation` 类支持搜索用户设备上存储的消息数据,其中包含如下主要方法: + +- `EMConversation#searchMsgFromDB(string keywords, long timeStamp, int maxCount, string from, EMSearchDirection direction)`:根据关键字搜索本地数据库中单个会话中指定用户发送的消息。 +- `EMChatManager#searchMsgFromDB(java.lang.String, long, int, java.lang.String, com.hyphenate.chat.EMConversation.EMSearchDirection, com.hyphenate.chat.EMConversation.EMMessageSearchScope)`: 根据关键字搜索消息时,可以选择搜索范围在所有会话中进行消息搜索。 +- `EMConversation#searchMsgFromDB(java.lang.String, long, int, java.lang.String, com.hyphenate.chat.EMConversation.EMSearchDirection, com.hyphenate.chat.EMConversation.EMMessageSearchScope)`:根据关键字搜索消息时,可以选择搜索范围在当前会话中进行消息搜索。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 根据关键字搜索会话消息 + +你可以调用 `searchMsgFromDB(string keywords, long timeStamp, int maxCount, string from, EMSearchDirection direction)` 方法根据关键字搜索本地数据库中单个会话中指定用户发送的消息,示例代码如下: + +```java +//conversationId:会话 ID +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +// keywords:搜索关键字;timeStamp:搜索的起始时间戳;maxCount:每次获取的消息数量,取值范围为 [1,400]。 +// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +List messages = conversation.searchMsgFromDB(keywords, timeStamp, maxCount, from, EMConversation.EMSearchDirection.UP); +``` + +### 根据搜索范围搜索所有会话中的消息 + +你可以调用 `EMChatManager#searchMsgFromDB(java.lang.String, long, int, java.lang.String, com.hyphenate.chat.EMConversation.EMSearchDirection, com.hyphenate.chat.EMConversation.EMMessageSearchScope)` 方法,除了设置关键字、消息时间戳、消息数量、发送方、搜索方向等条件搜索所有会话中的消息时,你还可以选择搜索范围,如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.4.0 或以上版本。 +::: + +```java +String keyWord = "123"; +List messages = EMClient.getInstance().chatManager().searchMsgFromDB(keyWord, -1, 200, null, EMConversation.EMSearchDirection.UP, EMConversation.EMMessageSearchScope.ALL); + +``` + +### 根据搜索范围搜索当前会话中的消息 + +你可以调用 `com.hyphenate.chat.EMConversation#searchMsgFromDB(java.lang.String, long, int, java.lang.String, com.hyphenate.chat.EMConversation.EMSearchDirection, com.hyphenate.chat.EMConversation.EMMessageSearchScope)` 方法除了设置关键字、消息时间戳、消息数量、发送方、搜索方向等条件搜索当前会话中的消息,你还可以选择搜索范围,如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.4.0 或以上版本。 +::: + +```java +String keyWord = "123"; +String conversationId = "jack"; +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +List messages = conversation.searchMsgFromDB(keyWord, -1, 200, null, EMConversation.EMSearchDirection.UP, EMConversation.EMMessageSearchScope.ALL); + +``` + diff --git a/docs/document/android/message_send_receive.md b/docs/document/android/message_send_receive.md index cef95627c..459cc3cdc 100644 --- a/docs/document/android/message_send_receive.md +++ b/docs/document/android/message_send_receive.md @@ -20,14 +20,13 @@ ## 技术原理 -环信即时通讯 IM Android SDK 通过 `EMChatManager` 类和 `EMMessage` 类实现消息的发送、接收与撤回。 +环信即时通讯 IM Android SDK 通过 `EMChatManager` 类和 `EMMessage` 类实现消息的发送和接收。 其中,发送和接收消息的逻辑如下: 1. 发送方调用相应 Create 方法创建文本、文件、附件等类型的消息; -2. 发送方再调用 `SendMessage` 发送消息; -3. 发送方可通过 `recallMessage` 撤回自己发出的消息; -4. 通过 `addMessageListener` 添加消息接收的回调通知。 +2. 发送方调用 `SendMessage` 发送消息; +3. 通过 `addMessageListener` 添加消息接收的回调通知。 消息收发流程如下: @@ -97,13 +96,15 @@ message.setMessageStatusCallback(new EMCallBack() { EMClient.getInstance().chatManager().sendMessage(message); ``` +若初始化时打开了 `EMOptions#setUseReplacedMessageContents` 开关,发送文本消息时如果被内容审核(Moderation)进行了内容替换,发送方会收到替换后的内容。若该开关为关闭状态,则发送方不会收到替换后的内容。 + ### 接收消息 你可以用注册监听 `EMMessageListener` 接收消息。该 `EMMessageListener` 可以多次添加,请记得在不需要的时候移除 `listener`,如在 `activity` 的 `onDestroy()` 时。 -在新消息到来时,你会收到 `onMessageReceived` 的回调,消息接收时可能是一条,也可能是多条。你可以在该回调里遍历消息队列,解析并显示收到的消息。 +在新消息到来时,你会收到 `onMessageReceived` 的回调,消息接收时可能是一条,也可能是多条。你可以在该回调里遍历消息队列,解析并显示收到的消息。若在初始化时打开了 `EMOptions#setIncludeSendMessageInMessageListener` 开关,则该回调中会返回发送成功的消息。 -对于聊天室消息,你可以通过消息的 `EMMessage#isBroadcast` 属性判断通过该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 +对于聊天室消息,你可以通过消息的 `EMMessage#isBroadcast` 属性判断该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 ```java EMMessageListener msgListener = new EMMessageListener() { @@ -120,55 +121,6 @@ EMClient.getInstance().chatManager().addMessageListener(msgListener); EMClient.getInstance().chatManager().removeMessageListener(msgListener); ``` - - -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `onMessageRecalled` 事件。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 - -```java -try { - EMClient.getInstance().chatManager().recallMessage(message); - EMLog.d("TAG", "撤回消息成功"); -} catch (EMException e) { - e.printStackTrace(); - EMLog.e("TAG", "撤回消息失败的原因: "+e.getDescription()); -} -``` - -或者用异步方法: - -```java -EMClient.getInstance().chatManager().asyncRecallMessage(message, new CallBack() { - @Override - public void onSuccess() { - EMLog.d("TAG", "撤回消息成功"); - } - @Override - public void onError(int errorCode, String errorMessage) { - EMLog.e("TAG", "撤回消息失败的原因: "+errorMessage); - } - @Override - public void onProgress(int i, String s) { - } -}); -``` - -### 设置消息撤回监听 - -```java -/** - * \~chinese - * 接收到消息被撤回时触发此回调。 - * - * \~english - * Occurs when a received message is recalled. - */ -void onMessageRecalled(List messages); -``` - ### 发送和接收附件类型的消息 除文本消息外,SDK 还支持发送附件类型消息,包括语音、图片、视频和文件消息。 @@ -426,6 +378,10 @@ EMClient.getInstance().chatManager().sendMessage(message); 透传消息可视为命令消息,通过发送这条命令给对方,通知对方要进行的操作,收到消息可以自定义处理。(透传消息不会存入本地数据库中,所以在 UI 上不会显示)。具体功能可以根据自身业务需求自定义,例如实现头像、昵称的更新等。另外,以 “em_” 和 “easemob::” 开头的 action 为内部保留字段,注意不要使用。 +:::tip +透传消息发送后,不支持撤回。 +::: + ```java EMMessage cmdMsg = EMMessage.createSendMessage(EMMessage.Type.CMD); // 支持单聊、群聊和聊天室,默认为单聊。 @@ -475,10 +431,8 @@ EMMessageListener msgListener = new EMMessageListener(){ - 收到消息后,如果用户 B 与用户 A 的聊天页面处于打开状态,则显示用户 A 的输入指示器。 - 如果用户 B 在几秒后未收到用户 A 的输入,则自动取消输入指示器。 -:::notice - +:::tip 用户 A 可根据需要设置透传消息发送间隔。 - ::: 以下示例代码展示如何发送输入状态的透传消息。 @@ -599,7 +553,7 @@ EMClient.getInstance().chatManager().sendMessage(customMessage); | `messageIdList` | List | 合并消息的原始消息 ID 列表。该列表最多包含 300 个消息 ID。 | | `userId` | String | 消息接收方。该字段的设置取决于会话类型:
- 单聊:对方用户 ID;
- 群聊:群组 ID;
- 子区会话:子区 ID;
- 聊天室聊天:聊天室 ID。| -:::notice +:::tip 1. 合并转发支持嵌套,最多支持 10 层嵌套,每层最多 300 条消息。 2. 不论 `EMOptions#setAutoTransferMessageAttachments` 设置为 `false` 或 `true`,SDK 都会将合并消息附件上传到环信服务器。 3. 合并消息不支持搜索。 @@ -659,7 +613,7 @@ EMClient.getInstance().chatManager().downloadAndParseCombineMessage(combineMessa 该功能适用于文本消息、图片消息和音视频消息等全类型消息,最多可向群组或聊天室的 20 个成员发送定向消息。 -:::notice +:::tip 1. 仅 SDK 4.0.3 及以上版本支持。 2. 定向消息不写入服务端会话列表,不计入服务端会话的未读消息数。 3. 定向消息不支持消息漫游功能,因此从服务器拉取漫游消息时,不包含定向消息。 diff --git a/docs/document/android/message_traffic_statis.md b/docs/document/android/message_traffic_statis.md new file mode 100644 index 000000000..359efc644 --- /dev/null +++ b/docs/document/android/message_traffic_statis.md @@ -0,0 +1,66 @@ +# 获取本地消息的流量统计信息 + + + +即时通讯 IM 提供本地消息的流量统计功能。该功能默认关闭。若要使用该功能,需在 SDK 初始化前设置 `EMOptions#setEnableStatistics(boolean)` 开启。 + +SDK 只支持统计该功能开启后最近 30 天内发送和接收的消息。各类消息的流量计算方法如下: + +- 对于文本、透传、位置消息,消息流量为消息体的流量; +- 对于图片和视频消息,消息流量为消息体、图片或视频文件以及缩略图的流量之和; +- 对于文件和语音消息,消息流量为消息体和附件的流量。 + +:::tip + 1. 统计时间段的开始时间和结束时间均为服务器接收消息的 Unix 时间戳。 + 2. 对于携带附件的消息,下载成功后 SDK 才统计附件的流量。若附件下载多次,则会对下载的流量进行累加。 + 3. 对于从服务器拉取的漫游消息,如果本地数据库中已经存在,则不进行统计。 +::: + +SDK 仅统计本地消息的流量,而非消息的实际流量。一般而言,该统计数据小于实际流量,原因如下: +- 未考虑发送消息时通用协议数据的流量; +- 对于接收到的消息,服务端会进行消息聚合,添加通用字段,而消息流量统计为各消息的流量,未考虑通用字段的流量消耗。 + +## 技术原理 + +环信即时通讯 IM Android SDK 提供 `EMStatisticsManager` 类支持获取本地消息的流量统计信息,包含如下主要方法: + +- `EMStatisticsManager#getMessageStatistics`:根据消息 ID 获取消息流量统计信息; +- `EMStatisticsManager#getMessageCount`:获取一定时间段内发送和/或接收的指定或全部类型的消息条数; +- `EMStatisticsManager#getMessageSize`:获取一定时间段内发送和/或接收的指定或全部类型的消息的总流量。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 根据消息 ID 获取消息流量统计信息 + +你可以根据消息 ID 获取指定消息的统计信息。该方法返回的消息流量统计信息包括消息 ID、消息的发送方和接收方、消息体类型、会话类型、消息方向、消息流量大小(单位为字节)以及服务器收到该消息的 Unix 时间戳。 + +示例代码如下: + +```java +EMMessageStatistics statistics = EMClient.getInstance().statisticsManager().getMessageStatistics(messageId); +``` + +### 获取一定时间段内发送和/或接收的消息条数 + +你可以统计一定时间段内发送和/或接收的指定或全部类型的消息,示例代码如下: + +```java +int number = EMClient.getInstance().statisticsManager().getMessageCount(startTime, endTime, direct, style); +``` + +### 获取一定时间段内发送和/或接收的消息的总流量 + +你可以统计一定时间段内发送和/或接收的指定或全部类型的消息的总流量,流量单位为字节。 + +示例代码如下: + +```java +long size = EMClient.getInstance().statisticsManager().getMessageSize(startTime, endTime, direct, style); +``` \ No newline at end of file diff --git a/docs/document/android/message_translation.md b/docs/document/android/message_translation.md index 61c190787..91a3aa91f 100644 --- a/docs/document/android/message_translation.md +++ b/docs/document/android/message_translation.md @@ -7,10 +7,6 @@ - 按需翻译:接收方在收到文本消息后,将消息内容翻译为目标语言。 - 自动翻译:发送方发送消息时,SDK 根据发送方设置的目标语言自动翻译文本内容,然后将消息原文和译文一起发送给接收方。 -:::notice -私有化版本不支持消息翻译功能。 -::: - ## 前提条件 开始前,请确保满足以下条件: diff --git a/docs/document/android/message_update.md b/docs/document/android/message_update.md new file mode 100644 index 000000000..ca5812144 --- /dev/null +++ b/docs/document/android/message_update.md @@ -0,0 +1,38 @@ +# 更新消息 + + + +本文介绍环信即时通讯 IM Android SDK 如何更新本地消息。 + +## 技术原理 + +环信即时通讯 IM Android SDK 支持更新本地数据库中的消息,其中包含如下主要方法: + +- `EMConversation#updateMessage`:更新消息到本地数据库。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 更新消息到本地数据库 + +你可以通过以下方式更新本地数据库中的消息: + +- 直接调用 `EMChatManager#updateMessage` 方法更新 SDK 本地数据库中的消息。 + +```java +EMClient.getInstance().chatManager().updateMessage(message); +``` + +- 若正在使用 `EMConversation` 类,可以先获取会话,再调用 `EMConversation#updateMessage` 方法更新 SDK 本地数据库会话中的消息。 + +```java +EMConversation conversation = EMClient.getInstance().chatManager().getConversation(conversationId); +conversation.updateMessage(message); +``` + diff --git a/docs/document/android/moderation.md b/docs/document/android/moderation.md index c9a7e1677..c0b97b568 100644 --- a/docs/document/android/moderation.md +++ b/docs/document/android/moderation.md @@ -2,7 +2,14 @@ -即时通讯 IM SDK 提供消息举报接口。开发者可以在客户端调用该接口举报违规消息。当服务器端审核服务收到举报消息后,会将举报消息存储到数据库,并在 Console 展示。审核员可在 Console 查看举报记录,并进行相应处理。 +即时通讯 IM SDK 提供消息举报接口。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +:::tip +1. 使用前,你需要在[环信即时通讯云控制台](https://console.easemob.com/user/login) 开通该功能。 +2. 消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +关于如何开通消息举报和查看举报记录,详见[环信即时通讯云控制台文档说明](/product/enable_and_configure_IM.html#消息举报)。 ## 技术原理 @@ -13,7 +20,7 @@ 开始前,请确保满足以下条件: - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 已在 [环信即时通讯云控制台](https://console.easemob.com/user/login) 开通消息审核服务。 +- 已在 [环信即时通讯云控制台开通消息举报功能](/product/enable_and_configure_IM.html#消息举报)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 @@ -23,7 +30,7 @@ ```java // msgid:要举报的消息 ID。 // tag:非法消息的标签。你需要自定义标签,例如`涉政`或`广告`。该字段对应环信即时通讯云控制台的消息举报记录页面的`词条标记`字段。 -// reason:举报原因。你需要自行填写举报原因。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 +// reason:举报原因。你需要自行填写举报原因,最长不能超过 512 字节。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 EMClient.getInstance().chatManager().asyncReportMessage(msgid, tag, reason, new EMCallBack() { @Override public void onSuccess() { diff --git a/docs/document/android/multi_device.md b/docs/document/android/multi_device.md index d1cf34cd9..eaa515e63 100644 --- a/docs/document/android/multi_device.md +++ b/docs/document/android/multi_device.md @@ -73,9 +73,9 @@ Android SDK 初始化时会生成登录 ID 用于在多设备登录和消息推 ```java // 同步方法,会阻塞当前线程。异步方法为 asyncGetSelfIdsOnOtherPlatform(EMValueCallBack)。 List ids = EMClient.getInstance().contactManager().getSelfIdsOnOtherPlatform(); -// 选择一个登录 ID 作为消息发送方。 +// 选择一个登录 ID 作为消息接收方。 String toChatUsername = ids.get(0); -// 创建一条文本消息,content 为消息文字内容,toChatUsername 传入登录 ID 作为消息发送方。 +// 创建一条文本消息,content 为消息文字内容,toChatUsername 传入登录 ID 作为消息接收方。 EMMessage message = EMMessage.createTxtSendMessage(content, toChatUsername); // 发送消息。 EMClient.getInstance().chatManager().sendMessage(message); @@ -341,6 +341,9 @@ private class ChatEMMultiDeviceListener implements EMMultiDeviceListener { case CONVERSATION_DELETED: //当前用户在其他设备上删除了服务端的会话。 break; + case CONVERSATION_MARK_UPDATE: + //当前用户在其他设备上更新了会话标记,包括添加和移除会话标记。 + break; } } diff --git a/docs/document/android/overview.md b/docs/document/android/overview.md index 5d76db14d..e19aa5432 100644 --- a/docs/document/android/overview.md +++ b/docs/document/android/overview.md @@ -222,17 +222,25 @@ EMClient.getInstance().removeConnectionListener(connectionListener); ## 输出信息到日志文件 -开发者可以在开发阶段开启 `DEBUG` 模式,获取更多的调试信息。 +环信即时通讯 IM 日志记录 SDK 相关的信息和事件。环信技术支持团队帮你排查问题时可能会请你发送 SDK 日志。 + +默认情况下,SDK 最多可生成和保存三个文件,`easemob.log` 和两个 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件。这些文件为 UTF-8 编码,每个不超过 2 MB。SDK 会将最新的日志写入 `easemob.log` 文件,写满时则会将其重命名为对应时间点的 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件,若日志文件超过三个,则会删除最早的文件。 + +例如,SDK 在 2024 年 1 月 1 日上午 8:00:00 记录日志时会生成 `easemob.log` 文件,若在 8:30:00 将 `easemob.log` 文件写满则会将其重命名为 `easemob_2024-01-01_08-30-00.log` 文件,随后在 9:30:30 和 10:30:30 分别生成了 `easemob_2024-01-01_09-30-30.log` 和 `easemob_2024-01-01_10-30-30.log` 文件,则此时 `easemob_2024-01-01_08-30-00.log` 文件会被移除。 + +SDK 默认输出调试信息(所有日志,包括调试信息、警告和错误),如果只需输出错误日志,需要关闭调试模式。 ```java // 需要在 SDK 初始化后调用 -EMClient.getInstance().setDebugMode(true); +EMClient.getInstance().setDebugMode(false); ``` ### 获取本地日志 +打开以下目录,获取本地日志。 + ```shell -adb pull /sdcard/android/data/{应用包名}/{App Key}/core_log/easemob.log +adb pull /sdcard/android/data/{应用包名}/{App Key}/core_log ``` -获取本地日志,需要将 `{应用包名}` 替换为应用的包名,例如 `com.hyphenate.chatuidemo`;`{App Key}` 需要替换为应用设置的环信 App Key。 +获取本地日志,需要将 `{应用包名}` 替换为应用的包名,例如 `com.hyphenate.chatuidemo`;`{App Key}` 需要替换为应用的环信 App Key。 diff --git a/docs/document/android/push.md b/docs/document/android/push.md index 8347074f2..9f9f59b39 100644 --- a/docs/document/android/push.md +++ b/docs/document/android/push.md @@ -40,7 +40,7 @@ - 已开启环信即时通讯服务,详见 [开启和配置即时通讯服务](/product/enable_and_configure_IM.html)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 -- 你已在 [环信控制台](https://console.easemob.com/user/login)中激活推送高级功能。高级功能激活后,你可以设置推送通知方式、免打扰模式和自定义推送模板。如需关闭推送高级功能必须联系商务,因为该操作会删除所有相关配置。 +- 你已在 [环信控制台](https://console.easemob.com/user/login)的**即时通讯 > 功能配置 > 功能配置总览**页面激活推送高级功能。高级功能激活后,你可以设置推送通知方式、免打扰模式和自定义推送模板。如需关闭推送高级功能必须联系商务,因为该操作会删除所有相关配置。 各推送使用条件: @@ -61,7 +61,7 @@ SDK 内部会按照该顺序检测设备的推送支持情况。如果未设置 ### 上传到设备证书到环信即时通讯云控制台 -![image](@static/images/android/push/push_android_certificate_add.png) +![image](@static/images/android/push/fcm_certificate_v1.png) ## 在客户端实现推送 @@ -102,19 +102,79 @@ EMClient.getInstance().init(this, options); 详见 [FCM 的官网介绍](https://firebase.google.com/docs/android/setup?hl=zh-cn#console)。
-**步骤二:上传推送证书。** +**步骤二:获取 FCM V1 版本证书。** -注册完成后,在[环信即时通讯云控制台](https://console.easemob.com/user/login)上传推送证书,选择你的应用 > **即时通讯** > **功能配置** > **消息推送** > **证书配置**,点击 **添加推送证书**。即时通讯 IM 支持 FCM 的旧版证书和 v1 版证书。 +1. 登录 [FCM 控制台](https://console.firebase.google.com),选择你的项目。 -- 若 **证书类型** 选择 **旧版**,你需要将 **证书名称** 设置为 FCM 的发送者 ID,**推送秘钥** 设置为 FCM 的服务器密钥。你需在 [Firebase 控制台](https://console.firebase.google.com/?hl=zh-cn)的 **项目设置 > 云消息传递** 页面中,在 **Cloud Messaging API(旧版)** 区域中获取发送者 ID 和服务器密钥,如下图所示。配置完毕,设置 **铃声**、**推送优先级设置** 和 **推送消息类型** 参数。 +![image](@static/images/android/push/fcmproject.png) -![image](@static/images/android/push/fcm_old_version.png) +2. 选择该项目下的应用。 + +![image](@static/images/android/push/appsetting.png) + +3. 选择**服务账号**页签,点击**生成新的私钥**。 + +![image](@static/images/android/push/v1json.png) + +4. 下载证书,保存备用。 + +下载证书文件,例如 `myapplication-72d8c-firebase-adminsdk-yqa7z-4766fefcaf.json`。 + +```json +{ + "type": "service_account", + "project_id": "myapplication-72d8c", + "private_key_id": "xxx", + "private_key": "-----BEGIN PRIVATE KEY-----\xxx\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-yqa7z@myapplication-72d8c.iam.gserviceaccount.com", + "client_id": "xxx", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-yqa7z%40myapplication-72d8c.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} +``` + +**步骤三:上传推送证书。** + +1. 在[环信即时通讯云控制台](https://console.easemob.com/user/login)上传推送证书,选择你的应用 > **即时通讯** > **功能配置** > **消息推送** > **证书管理**。 -- 若 **证书类型** 选择 **V1**,你需要上传证书文件(.json 文件)并将 **证书名称** 设置为 FCM 的发送者 ID。你需要在[Firebase 控制台](https://console.firebase.google.com/?hl=zh-cn)的 **项目设置** > **服务账号** 页面,点击 **生成新的私钥**,下载推送证书文件(.json),然后在 **项目设置** > **云消息传递** 页面中,在 **Firebase Cloud Messaging API(V1)** 区域中获取 发送者 ID。配置完毕,设置 **铃声**、**推送优先级设置** 和 **推送消息类型** 参数。 +![image](@static/images/android/push/fcm_certificate_v1.png) + +2. 点击 **添加推送证书**。在默认打开的 **谷歌** 页签中,配置 FCM 推送: +- **证书类型** 选择 **V1**。 +- 点击 **上传证书** 上传获取的 FCM V1 版本证书文件(.json 文件)。 +- **证书名称** 设置为 FCM 的发送者 ID。你需要在[Firebase 控制台](https://console.firebase.google.com/?hl=zh-cn)的 **项目设置** > **云消息传递** 页面中,在 **Firebase Cloud Messaging API(V1)** 区域中获取发送者 ID,如下图所示。 +- 设置 **铃声**、**推送优先级设置** 和 **推送消息类型** 参数。 ![image](@static/images/android/push/fcm_v1.png) -**步骤三:FCM 推送集成。** +##### **旧版证书无缝切换至 V1 证书** + +若你仍使用旧版证书,即 **证书类型** 选择 **旧版**,你需要将 **证书名称** 设置为 FCM 的发送者 ID,**推送秘钥** 设置为 FCM 的服务器密钥。你需在 [Firebase 控制台](https://console.firebase.google.com/?hl=zh-cn)的 **项目设置 > 云消息传递** 页面中,在 **Cloud Messaging API(旧版)** 区域中获取发送者 ID 和服务器密钥,如下图所示。配置完毕,设置 **铃声**、**推送优先级设置** 和 **推送消息类型** 参数。 + +![image](@static/images/android/push/fcm_old_version.png) + +**旧版 HTTP 或 XMPP API 于 2024 年 6 月 20 日停用,请尽快迁移到最新的 FCM API(HTTP v1)版本证书。详见 [FCM 控制台](https://console.firebase.google.com)。请确保 V1 证书可用,因为执行转换证书后,旧证书会被删除,若此时新证书不可用,会导致推送失败。** + +你可以参考以下步骤从旧版证书无缝切换到 V1 新证书: + +1. 在 **证书管理** 页面的旧版证书的 **操作** 栏中点击 **编辑**。 + +![image](@static/images/android/push/hxconsoleedit.png) + +2. 在**编辑推送证书** 窗口的 **谷歌** 页签,将**证书类型**切换为 **V1**。 + +![fcmapp](@static/images/android/push/old2V1.png) + +3. 点击 **上传证书** 上传本地保存的 V1 证书文件(.json)。 + +![fcmapp](@static/images/android/push/v1Chosefile.png) + +4. 点击 **保存** 完成切换。 + +**步骤四:FCM 推送集成。** 1. 在项目根目录下的 `build.gradle` 中添加 FCM 服务插件。 @@ -262,7 +322,69 @@ public class EMFCMMSGService extends FirebaseMessagingService { ``` -3. [获取 Token 及 自动初始化](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/android-client-dev-0000001050042041)。 +3. [获取 Token 及自动初始化](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/android-client-dev-0000001050042041)。 + +打开应用,初始化环信 IM SDK 成功且成功登录后,获取一次华为推送 token,将 token 上传至环信服务器,与 IM 的登录账号绑定。 + +```java +/** + * 申请华为 Push Token: + * 1. getToken 接口只有在 AppGallery Connect 平台开通服务后申请 token 才会返回成功。 + * + * 2. EMUI 10.0 及以上版本的华为设备上,getToken 接口直接返回 token。如果当次调用失败 Push 会缓存申请,之后会自动重试申请,成功后则以onNewToken 接口返回。 + * + * 3. 低于 EMUI 10.0 的华为设备上,getToken 接口如果返回为空,确保 Push 服务开通的情况下,结果后续以 onNewToken 接口返回。 + * + * 4. 服务端识别 token 过期后刷新 token,以 onNewToken 接口返回。 + */ + public void getHMSToken(Activity activity){ + // 判断是否启用 FCM 推送 + if (EMClient.getInstance().isFCMAvailable()) { + return; + } + try { + if(Class.forName("com.huawei.hms.api.HuaweiApiClient") != null){ + Class classType = Class.forName("android.os.SystemProperties"); + Method getMethod = classType.getDeclaredMethod("get", new Class[] {String.class}); + String buildVersion = (String)getMethod.invoke(classType, new Object[]{"ro.build.version.emui"}); + //在某些手机上,invoke 方法不报错 + if(!TextUtils.isEmpty(buildVersion)){ + EMLog.d("HWHMSPush", "huawei hms push is available!"); + new Thread() { + @Override + public void run() { + try { + // read from agconnect-services.json +// String appId = AGConnectServicesConfig.fromContext(activity).getString("client/app_id"); + String appId = new AGConnectOptionsBuilder().build(activity).getString("client/app_id"); + EMLog.e("AGConnectOptionsBuilder","appId:"+appId); + // 申请华为推送 token + String token = HmsInstanceId.getInstance(activity).getToken(appId, "HCM"); + EMLog.d("HWHMSPush", "get huawei hms push token:" + token); + if(token != null && !token.equals("")){ + //没有失败回调,假定 token 失败时 token 为 null + EMLog.d("HWHMSPush", "register huawei hms push token success token:" + token); + // 上传华为推送 token + EMClient.getInstance().sendHMSPushTokenToServer(token); + }else{ + EMLog.e("HWHMSPush", "register huawei hms push token fail!"); + } + } catch (ApiException e) { + EMLog.e("HWHMSPush","get huawei hms push token failed, " + e); + } + } + }.start(); + }else{ + EMLog.d("HWHMSPush", "huawei hms push is unavailable!"); + } + }else{ + EMLog.d("HWHMSPush", "no huawei hms push sdk or mobile is not a huawei phone"); + } + } catch (Exception e) { + EMLog.d("HWHMSPush", "no huawei hms push sdk or mobile is not a huawei phone"); + } + } +``` 4. 在 SDK 初始化的时候,配置启用华为推送。 @@ -900,7 +1022,7 @@ OPPO 推送在 2.1.0 适配了 Android Q,在 Android Q 上接收 OPPO 推送 - 设置推送通知,包含设置推送通知方式和免打扰模式。 - 配置推送翻译和推送模板。 -其中,设置推送通知方式、免打扰模式和推送模板为推送的高级功能,使用前需要在[环信即时通讯云控制后台](https://console.easemob.com/user/login)上开通。 +其中,设置推送通知方式、免打扰模式和推送模板为推送的高级功能,使用前需要在 [环信控制台](https://console.easemob.com/user/login)的**即时通讯 > 功能配置 > 功能配置总览**页面激活推送高级功能。如需关闭推送高级功能必须联系商务,因为该操作会删除所有相关配置。 ![image](@static/images/android/push/push_android_enable_push.png) @@ -1153,37 +1275,107 @@ EMClient.getInstance().pushManager().setPreferredNotificationLanguage("en", new EMClient.getInstance().pushManager().getPreferredNotificationLanguage(new EMValueCallBack(){}); ``` -#### 4.4 设置推送模板 +#### 4.4 使用推送模板 + +你可以使用推送模板设置推送标题和内容。推送模板包括默认推送模板 `default` 和自定义推送模板,你可以通过以下两种方式设置: + +- [调用 REST API 配置](/document/server-side/push.html#使用推送模板)。 +- 在[环信即时通讯云控制台](https://console.easemob.com/user/login)设置推送模板,详见[控制台文档](/document/product/enable_and_configure_IM.html#配置推送模板)。 + +使用推送模板有以下优势: + +1. 自定义修改环信服务端默认推送内容。 + +2. 接收方可以决定使用哪个模板。 + +3. 按优先级选择模板使用方式。 + +**推送通知栏内容设置的使用优先级** + +通知栏中显示的推送标题和内容可通过以下方式设置,优先级为由低到高: + +1. 发送消息时使用默认的推送标题和内容:设置推送通知的展示方式 `DisplayStyle`。推送标题为“您有一条新消息”,推送内容为“请点击查看”。 +2. 发送消息时使用默认模板:若有默认模板 `default`,发消息时无需指定。 +3. 发送消息时使用扩展字段自定义要显示的推送标题和推送内容,即 `em_push_title` 和 `em_push_content`。 +4. 接收方设置了推送模板。 +5. 发送消息时通过消息扩展字段指定模板名称。 + +##### **发送消息时使用推送模板** + +创建模板后,你可以在发送消息时选择此推送模板,分为以下三种情况: + +:::tip +若使用默认模板 **default**,消息推送时自动使用默认模板,创建消息时无需传入模板名称。 +::: + +1. 使用固定内容的推送模板,通过 `ext` 扩展字段指定推送模板名称。 + +这种情况下,创建消息时无需传入 `titleArgs` 和 `contentArgs` 参数。 + +```java +// 下面以文本消息为例,其他类型的消息设置方法相同。 +EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT); +EMTextMessageBody txtBody = new EMTextMessageBody("消息内容"); +message.setTo("6006"); +// 设置推送模板。 +JSONObject pushObject = new JSONObject(); +try { + // 设置推送模板名称。设置前需在环信即时通讯云管理后台或调用 REST 接口创建推送模板。 + //若为默认模板 `default`,无需传入模板名称。 + //若为自定义模板,需传入模板名称。 + pushObject.put("name", "test7"); + +} catch (JSONException e) { + e.printStackTrace(); +} +// 将推送扩展设置到消息中。 +message.setAttribute("em_push_template", pushObject); +// 设置消息状态回调。 +message.setMessageStatusCallback(new EMCallBack() {...}); +// 发送消息。 +EMClient.getInstance().chatManager().sendMessage(message); +``` + +2. 使用自定义或者默认推送模板,模板中的推送标题和推送内容使用以下内置参数: +- `{$dynamicFrom}`:服务器按优先级从高到底的顺序填充备注、群昵称(仅限群消息)和推送昵称。 +- `{$fromNickname}`:推送昵称。 +- `{$msg}`:消息内容。 + +内置参数的介绍,详见[环信即时通讯控制台文档](/product/enable_and-configure_IM.html#使用默认推送模板)。 + +这种方式的示例代码与“使用固定内容的推送模板”的相同。 -环信 IM 支持自定义推送通知模板。使用前,你可参考以下步骤在环信即时通讯云管理后台上创建推送模板: +3. 使用自定义推送模板,而且推送标题和推送内容为自定义参数: -1. 登录环信 IM Console,进入首页。 -2. 在 **应用列表** 区域中,点击对应 app 的 **操作** 一栏中的 **查看** 按钮。 -3. 在环信 IM 配置页面的左侧导航栏,选择 **即时通讯 > 功能配置 > 消息推送 > 模板管理**,进入推送模板管理页面。 - ![image](@static/images/android/push/push_android_template_mgmt.png) -4. 点击 **添加推送模板**。弹出以下页面,进行参数配置。 - ![image](@static/images/android/push/push_android_template_add.png) +例如,推送模板的设置如下图所示: -在环信即时通讯云管理后台中完成模板创建后,用户可以在发送消息时选择此推送模板作为默认布局,如下代码示例所示: +![img](@static/images/android/push/push_template_custom.png) + +使用下面的示例代码后,通知栏中弹出的推送通知为: + +您收到了一条消息
+请及时查看 ```java // 下面以文本消息为例,其他类型的消息设置方法相同。 EMMessage message = EMMessage.createSendMessage(EMMessage.Type.TXT); EMTextMessageBody txtBody = new EMTextMessageBody("消息内容"); message.setTo("6006"); -// 设置推送模板。设置前需在环信即时通讯云管理后台上创建推送模板。 +// 设置推送模板。设置前需在环信即时通讯云管理后台或调用 REST 接口创建推送模板。 JSONObject pushObject = new JSONObject(); JSONArray titleArgs = new JSONArray(); JSONArray contentArgs = new JSONArray(); try { - // 设置推送模板名称。 - pushObject.put("name", "test7"); + // 设置推送模板名称。若不指定,设置默认推送模板的信息。 + pushObject.put("name", "push"); // 设置填写模板标题的 value 数组。 - titleArgs.put("value1"); + titleArgs.put("您"); + titleArgs.put("消息,"); //... pushObject.put("title_args", titleArgs); // 设置填写模板内容的 value 数组。 - contentArgs.put("value1"); + contentArgs.put("请"); + contentArgs.put("查看"); //... pushObject.put("content_args", contentArgs); } catch (JSONException e) { @@ -1197,6 +1389,28 @@ message.setMessageStatusCallback(new EMCallBack() {...}); EMClient.getInstance().chatManager().sendMessage(message); ``` +##### **消息接收方使用推送模板** + +消息接收方可以调用 `setPushTemplate` 方法传入推送模板名称,选择要使用的模板。 + +:::tip +若发送方在发送消息时使用了推送模板,则推送通知栏中的显示内容以发送方的推送模板为准。 +::: + +```java +EMClient.getInstance().pushManager().setPushTemplate("Template Name", new EMCallBack() { + @Override + public void onSuccess() { + + } + + @Override + public void onError(int code, String error) { + + } +}); +``` + ### 5. 解析收到的推送字段 #### 收到的推送字段解释 @@ -1315,6 +1529,64 @@ public class MyVivoMsgReceiver extends EMVivoMsgReceiver { 解析方式同华为。 +## 厂商通道限制及解决方案 + +### 华为 + +华为推送通道将根据应用类型对资讯营销类消息的每日推送数量进行上限管理。详情请参考[推送数量管理细则](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/message-restriction-description-0000001361648361)。 + +环信建议你做出以下调整: + +1. [申请华为消息自分类权益功能](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/message-classification-0000001149358835)。 + +2. 环信证书补充华为配置 category,如下图所示: + +![image](@static/images/android/push/huawei-notifier-category.png) + +### OPPO + +OPPO PUSH 推送服务将增加区分应用类型的推送频控限制,公信消息单用户限制 2~5 条,私信消息不受限。详情请登录OPPO PUSH 开发者账号,管理中心查阅《【OPPO PUSH】推送服务规则更新说明》。 + +环信建议您做出以下调整: + +1. [申请 OPPO PUSH 私信通道权限](https://open.oppomobile.com/new/developmentDoc/info?id=11227)。 + +2. [客户端创建私信通道](https://open.oppomobile.com/new/developmentDoc/info?id=11252)。 + +3. 环信推送证书补充 OPPO 配置 channelId,如下图所示: + +![image](@static/images/android/push/oppo-notifier-channelId.png) + +### 小米 + +小米推送通道将分为“私信消息”和“公信消息”两个类别,不同类别对应不同的权限,若应用选择不接入私信或公信,则会接入默认通道,单个应用单个设备单日 1 条消息。详情查看[小米推送消息限制说明](https://dev.mi.com/console/doc/detail?pId=2086)。 + +环信建议你做出以下调整: + +1. [申请小米公私信渠道id](https://dev.mi.com/console/doc/detail?pId=2422#_2)。 + +2. 环信推送证书补充小米配置 channelId,如下图所示: + +![image](@static/images/android/push/xiaomi-notifier-channelId.png) + +### vivo + +vivo 推送通道区分 “系统消息” 和”运营消息”,消息类别决定单日单用户推送量上限(环信服务端默认”系统消息”,即 classification = 1)。 + +[推送消息限制说明](https://dev.vivo.com.cn/documentCenter/doc/695#w1-53292792),在此基础上进行消息分类优化,新增 “二级分类”功能,根据推送内容界定不同推送分类。 + +环信建议你做出以下调整: + +1. [二级分类说明和申请](https://dev.vivo.com.cn/documentCenter/doc/359#_Toc64906673)。 + +2. 环信推送证书补充 vivo 配置 category,如下图所示: + +:::tip +vivo 提醒配置使用请确保 category 与**推送类型**为正确对应关系,否则推送失败。 +::: + +![image](@static/images/android/push/vivo-notifier-category.png) + ## 更多功能 ### 自定义字段 diff --git a/docs/document/android/reaction.md b/docs/document/android/reaction.md index a7d2f6d5d..65d1c81be 100644 --- a/docs/document/android/reaction.md +++ b/docs/document/android/reaction.md @@ -6,9 +6,8 @@ :::notice -1. 目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 -2. 私有化版本不支持 Reaction 功能。 - ::: +目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 +::: ## 技术原理 diff --git a/docs/document/android/releasenote.md b/docs/document/android/releasenote.md index 02048f9ab..6f8d4086b 100644 --- a/docs/document/android/releasenote.md +++ b/docs/document/android/releasenote.md @@ -2,11 +2,52 @@ -## 版本 V4.2.1 Dev 2023-11-17(开发版) +## 版本 V4.4.0 Dev 2024-01-30(开发版) ### 新增特性 -- [IM SDK] 新增[好友备注功能](user_relationship.html#设置好友备注)。 +- [IM SDK] 新增 [EMChatManager#asyncDeleteAllMsgsAndConversations](message_delete.html#清空聊天记录)方法,用于清空当前用户的聊天记录,包括消息和会话,同时可以选择是否清除服务端的聊天记录。 +- [IM SDK] 新增 [EMChatManager#searchMsgFromDB(java.lang.String, long, int, java.lang.String, com.hyphenate.chat.EMConversation.EMSearchDirection, com.hyphenate.chat.EMConversation.EMMessageSearchScope)](message_search.html#根据搜索范围搜索所有会话中的消息) 和 [EMConversation#searchMsgFromDB(java.lang.String, long, int, java.lang.String, com.hyphenate.chat.EMConversation.EMSearchDirection, com.hyphenate.chat.EMConversation.EMMessageSearchScope)](message_search.html#根据搜索范围搜索当前会话中的消息),可以在根据关键字搜索消息时,选择搜索范围,如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。 +- [IM SDK] 新增 [EMOptions#setUseReplacedMessageContents](message_send_receive.html#发送文本消息) 开关。开启后,发送消息时如果被内容审核进行了内容替换,发送方可以获取替换后的内容。 +- [IM SDK] 新增 [EMOptions#setIncludeSendMessageInMessageListener](message_send_receive.html#接收消息) 开关。开启后,在 `EMMessageListener#onMessageReceived` 回调里增加发送成功的消息。 +- [IM SDK] 新增 [EMOptions#setRegardImportedMsgAsRead](message_retrieve.html#从服务器获取指定会话的消息) 开关。开启后,[利用服务端接口](/document/server-side/message_import.html)导入的消息,客户端上通过[漫游拉取](message_retrieve.html#从服务器获取指定会话的消息)到后,这些消息为已读状态,会话中未读取的消息数量,即 `EMConversation#getUnreadMsgCount` 的返回值不发生变化。若该开关为关闭状态,`EMConversation#getUnreadMsgCount` 的返回值会增加。 + +### 优化 + +- [IM SDK] 群组全员禁言状态(`isAllMemberMuted` 的返回值)存储到本地数据库,下次登录时可以直接从本地获取到。 +- [IM SDK] 转发合并消息时导致的附件重复上传问题。 + +### 修复 + +- [IM SDK] 部分场景下群成员人数计算重复问题。 +- [IM SDK] 搜索消息的关键字中带有单引号 `‘` 引起的 SQL 语句报错问题。 +- [IM SDK] 修复数据上报模块偶现的崩溃问题。 + +## 版本 V4.3.0 Dev 2023-12-22(开发版) + +### 新增特性 + +[IM SDK] 支持[会话标记功能](conversation_mark.html)。 +- `EMChatManager#asyncAddConversationMark`:[标记会话](conversation_mark.html#标记会话)。 +- `EMChatManager#asyncRemoveConversationMark`:[取消标记会话](conversation_mark.html#取消标记会话)。 +- `EMChatManager#asyncGetConversationsFromServerWithCursor`:[根据会话标记从服务器分页查询会话列表](conversation_mark.html#根据会话标记从服务器分页查询会话列表)。 +- `EMConversation#marks`:[获取本地单个会话的所有标记](conversation_mark.html#获取本地单个会话的所有标记)。 +- `onChatThreadEvent#CONVERSATION_MARK_UPDATE`:[多设备场景下的会话标记事件](multi_device.html#获取其他设备上的操作)。当前用户在一台登录设备上更新了会话标记,包括添加和移除会话标记,其他登录设备会收到该事件。 + +### 优化 + +- [IM SDK] 移除 FPA 功能,重新编译 boringssl、cipherdb、libevent 库,减小 SDK 体积。 +- [IM SDK] 单个日志文件大小由 2 MB 提升到 5 MB。 +- [IM SDK] 优化附件类型消息发送时中的附件上传,支持分片上传。 + +## 版本 V4.2.1 Dev 2023-11-17 + +### 新增特性 + +- [IM SDK] 新增[设置好友备注功能](user_relationship.html#设置好友备注)。 +- [IM SDK] 新增 `asyncFetchAllContactsFromServer` 方法[从服务器一次性或分页获取好友列表](user_relationship.html#从服务端获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。 +- [IM SDK] 新增 `fetchContactFromLocal` 方法[从本地获取单个好友的用户 ID 和好友备注](user_relationship.html#从本地获取好友列表)。 +- [IM SDK] 新增 `asyncFetchAllContactsFromLocal` 方法[从本地分页获取好友列表](user_relationship.html#从本地获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。 - [IM SDK] 新增 `EMMessage#isBroadcast` 属性用于判断通过该消息是否为聊天室全局广播消息。可通过[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 - [IM SDK] 新增 `EMGroupManager#asyncGetJoinedGroupsCountFromServer` 方法用于[从服务器获取当前用户已加入的群组数量](group_manage.html#查询当前用户已加入的群组数量)。 - [IM SDK] 新增[错误码 706](error.html) `CHATROOM_OWNER_NOT_ALLOW_LEAVE`,表示聊天室所有者不允许离开聊天室。若初始化时,`EMOptions#allowChatroomOwnerLeave` 参数设置为 `false`,聊天室所有者调用 `leaveChatRoom` 方法离开聊天室时会提示该错误。 @@ -91,11 +132,11 @@ ### 新增特性 -- [IM SDK] 新增 `EMChatManager#asyncFetchConversationsFromServer` 方法实现[从服务器拉取会话](message_retrieve.html#从服务器分页获取会话列表),原接口标记为已废弃。 +- [IM SDK] 新增 `EMChatManager#asyncFetchConversationsFromServer` 方法实现[从服务器拉取会话](conversation_list.html#从服务器分页获取会话列表),原接口标记为已废弃。 - [IM SDK] 新增置顶服务器会话的功能: - - 新增 `EMChatManager#asyncPinConversation` 方法,实现[置顶或取消置顶服务器会话](message_retrieve.html#置顶会话): - - 新增 `EMChatManager#asyncFetchPinnedConversationsFromServer` 方法,实现[获取置顶的服务器会话](message_retrieve.html#获取服务端的置顶会话列表)。 -- [IM SDK] 新增 `EMChatManager#getAllConversationsBySort` 方法实现[从本地获取排序后的会话列表](message_manage.html#获取本地所有会话); + - 新增 `EMChatManager#asyncPinConversation` 方法,实现[置顶或取消置顶服务器会话](conversation_pin.html#置顶会话): + - 新增 `EMChatManager#asyncFetchPinnedConversationsFromServer` 方法,实现[获取置顶的服务器会话](conversation_pin.html#获取服务端的置顶会话列表)。 +- [IM SDK] 新增 `EMChatManager#getAllConversationsBySort` 方法实现[从本地获取排序后的会话列表](conversation_list.html#获取本地所有会话); - [IM SDK] 新增在群组或聊天室中[发送定向消息](message_send_receive.html#发送和接收定向消息)的功能; - [IM SDK] 新增[荣耀推送](push.html#荣耀推送集成)。 @@ -159,7 +200,7 @@ ### 新增特性 -[IM SDK] [新增 `EMChatManager#asyncFetchConversationsFromServer(int, int, EMValueCallBack)` 方法实现从服务端分页获取会话列表](message_retrieve.html#从服务器分页获取会话列表)。 +[IM SDK] [新增 `EMChatManager#asyncFetchConversationsFromServer(int, int, EMValueCallBack)` 方法实现从服务端分页获取会话列表](conversation_list.html#从服务器分页获取会话列表)。 ### 优化 @@ -177,7 +218,7 @@ ### 新增特性 -[IM SDK] 新增[消息流量统计功能](message_manage.html#获取本地消息的流量统计信息)。 +[IM SDK] 新增[消息流量统计功能](message_traffic_statis.html#获取本地消息的流量统计信息)。 ### 修复 diff --git a/docs/document/android/room_attributes.md b/docs/document/android/room_attributes.md index b520bc5c6..a6789d520 100644 --- a/docs/document/android/room_attributes.md +++ b/docs/document/android/room_attributes.md @@ -12,8 +12,8 @@ - 获取和更新聊天室基本属性; - 获取聊天室自定义属性; -- 设置聊天室自定义属性; -- 删除聊天室自定义属性。 +- 设置和强制设置聊天室自定义属性; +- 删除和强制删除聊天室自定义属性。 ## 前提条件 @@ -174,7 +174,9 @@ EMClient.getInstance().chatroomManager().asyncSetChatroomAttribute( }); ``` -若要覆盖其他聊天室成员设置的自定义属性,需调用 `asyncSetChatroomAttributeForced` 方法。设置后,其他聊天室成员收到 `onAttributesUpdate` 回调。 +#### 强制设置单个聊天室属性 + +如果除了设置自己的单个自定义属性还需覆盖其他聊天室成员设置的该属性,需调用 `asyncSetChatroomAttributeForced` 方法。设置后,其他聊天室成员收到 `onAttributesUpdate` 回调。 示例代码如下: @@ -239,7 +241,9 @@ EMClient.getInstance().chatroomManager().asyncSetChatroomAttributes( }); ``` -若要覆盖其他聊天室成员设置的自定义属性,需调用 `asyncSetChatroomAttributesForced` 方法。设置后,其他聊天室成员收到 `onAttributesUpdate` 回调。 +#### 强制设置多个聊天室属性 + +如果除了设置自己的多个自定义属性还需覆盖其他聊天室成员设置的这些属性,需调用 `asyncSetChatroomAttributesForced` 方法。设置后,其他聊天室成员收到 `onAttributesUpdate` 回调。 示例代码如下: @@ -294,7 +298,9 @@ EMClient.getInstance().chatroomManager().asyncRemoveChatRoomAttributeFromServer( }); ``` -若要删除其他聊天室成员设置的自定义属性,需调用 `asyncRemoveChatRoomAttributeFromServerForced` 方法。删除后,聊天室其他成员收到 `onAttributesRemoved` 回调。 +#### 强制删除单个聊天室自定义属性 + +如果除了删除自己设置的单个自定义属性还需删除其他聊天室成员设置的该属性,需调用 `asyncRemoveChatRoomAttributeFromServerForced` 方法。删除后,聊天室其他成员收到 `onAttributesRemoved` 回调。 示例代码如下: @@ -345,7 +351,9 @@ EMClient.getInstance().chatroomManager().asyncRemoveChatRoomAttributesFromServer }); ``` -若要删除其他聊天室成员设置的自定义属性,需调用 `asyncRemoveChatRoomAttributesFromServerForced` 方法。删除后,聊天室其他成员收到 `onAttributesRemoved` 回调。 +#### 强制删除多个聊天室自定义属性 + +如果除了删除自己设置的多个自定义属性还需删除其他聊天室成员设置的这些属性,需调用 `asyncRemoveChatRoomAttributesFromServerForced` 方法。删除后,聊天室其他成员收到 `onAttributesRemoved` 回调。 示例代码如下: diff --git a/docs/document/android/room_manage.md b/docs/document/android/room_manage.md index ef4501871..098999cad 100644 --- a/docs/document/android/room_manage.md +++ b/docs/document/android/room_manage.md @@ -38,7 +38,7 @@ 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 可以调用 `createChatRoom` 方法创建聊天室,并设置聊天室的名称、描述、最大成员数等信息。成功创建聊天室后,该超级管理员为该聊天室的所有者。 -你也可以直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 +建议直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 示例代码如下: @@ -107,7 +107,7 @@ EMOptions options = new EMOptions(); options.setDeleteMessagesAsExitChatRoom(false); ``` -与群主无法退出群组不同,聊天室所有者可以离开聊天室,例如,所有者从服务器下线则 2 分钟后自动离开聊天室。如果所有者重新进入聊天室仍是该聊天室的所有者。若 `EMOptions#allowChatroomOwnerLeave` 参数在初始化时设置为 `false`,聊天室所有者调用 `leaveChatRoom` 方法离开聊天室时会提示错误 706 `CHATROOM_OWNER_NOT_ALLOW_LEAVE`。 +与群主无法退出群组不同,聊天室所有者可以离开聊天室,重新进入聊天室仍是该聊天室的所有者。若 `EMOptions#allowChatroomOwnerLeave` 参数在初始化时设置为 `true` 时,聊天室所有者可以离开聊天室;若该参数设置为 `false`,聊天室所有者调用 `leaveChatRoom` 方法离开聊天室时会提示错误 706 `CHATROOM_OWNER_NOT_ALLOW_LEAVE`。 ### 解散聊天室 diff --git a/docs/document/android/room_members.md b/docs/document/android/room_members.md index 70609b77d..c28f657f4 100644 --- a/docs/document/android/room_members.md +++ b/docs/document/android/room_members.md @@ -42,7 +42,7 @@ public EMCursorResult fetchChatRoomMembers(String chatRoomId, String cur ### 将成员移出聊天室 -仅聊天室所有者和管理员可调用 `EMChatRoomManager#removeChatRoomMembers` 方法将指定成员移出聊天室。 +仅聊天室所有者和管理员可调用 `EMChatRoomManager#removeChatRoomMembers` 方法将单个或多个成员移出聊天室。 被移出后,该成员收到 `onRemovedFromChatRoom` 回调,其他成员收到 `EMChatRoomChangeListener#BE_KICKED` 回调。 @@ -186,6 +186,7 @@ EMClient.getInstance().chatroomManager().removeFromChatRoomWhiteList(chatRoomId, ```java // 同步方法,会阻塞当前线程。 // 异步方法为 asyncMuteChatRoomMembers(String, List, long, EMValueCallBack)。 +// `duration`:禁言时间。传 -1 表示永久禁言。 EMChatRoom chatRoom = EMClient.getInstance().chatroomManager().muteChatRoomMembers(chatRoomId, members, duration); ``` @@ -223,7 +224,9 @@ Map memberMap = EMClient.getInstance().chatroomManager().fetchCha #### 开启全员禁言 -仅聊天室所有者和管理员可以调用 `EMChatRoomManager#muteAllMembers` 方法开启全员禁言。全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `EMChatRoomChangeListener#onAllMemberMuteStateChanged` 回调。 +仅聊天室所有者和管理员可以调用 `EMChatRoomManager#muteAllMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `EMChatRoomManager#unmuteAllMembers` 方法解除禁言。 + +全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `EMChatRoomChangeListener#onAllMemberMuteStateChanged` 回调。 示例代码如下: diff --git a/docs/document/android/thread.md b/docs/document/android/thread.md index 1dab017f1..a8f711964 100644 --- a/docs/document/android/thread.md +++ b/docs/document/android/thread.md @@ -6,10 +6,6 @@ 如需查看消息相关内容,参见 [子区消息管理](thread_message.html)。 -:::notice -私有化版本不支持子区功能。 -::: - ## 技术原理 环信即时通讯 IM Android SDK 提供 `EMChatThreadManager`、`EMChatThread`、`EMChatThreadChangeListener` 和 `EMChatThreadEvent` 类,用于管理子区,支持你通过调用 API 在项目中实现如下功能: diff --git a/docs/document/android/thread_message.md b/docs/document/android/thread_message.md index 8feb4358a..6b32bf075 100644 --- a/docs/document/android/thread_message.md +++ b/docs/document/android/thread_message.md @@ -98,7 +98,7 @@ EMClient.getInstance().chatManager().removeMessageListener(msgListener); ### 撤回子区消息 -撤回消息的具体逻辑,请参考 [撤回消息](message_send_receive.html#撤回消息),此处只介绍子区消息和其他消息的区别。 +撤回消息的具体逻辑,请参考 [撤回消息](message_recall.html),此处只介绍子区消息和其他消息的区别。 子区有消息撤回时,子区所属群组的所有成员收到 `EMChatThreadChangeListener#onChatThreadUpdated` 回调,子区成员收到 `EMMessageListener#onMessageRecalled` 回调。 diff --git a/docs/document/android/user_relationship.md b/docs/document/android/user_relationship.md index bf14f7de1..95003d272 100644 --- a/docs/document/android/user_relationship.md +++ b/docs/document/android/user_relationship.md @@ -6,7 +6,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理: -- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请和删除好友等操作。 +- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请、删除好友和设置好友备注等操作。 - 黑名单管理:查询黑名单列表、添加用户至黑名单以及将用户移除黑名单等操作。 本文介绍如何通过环信即时通讯 IM SDK 管理好友关系。 @@ -32,9 +32,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理 本节展示如何在项目中管理好友的添加移除和黑名单的添加移除。 -### 管理好友列表 - -#### 添加好友 +### 添加好友 添加好友部分主要功能是发送好友请求、接收好友请求、处理好友请求和好友请求处理结果回调等。 @@ -89,7 +87,7 @@ EMClient.getInstance().contactManager().declineInvitation(username); 当你同意或者拒绝后,对方会通过好友事件回调,收到 `onContactAgreed` 或者 `onContactRefused`。 -#### 删除好友 +### 删除好友 删除联系人时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 @@ -103,9 +101,9 @@ EMClient.getInstance().contactManager().deleteContact(username); 调用 `deleteContact` 删除好友后,对方会收到 `onContactDeleted` 回调。 -#### 设置好友备注 +### 设置好友备注 -你可以调用 `asyncSetContactRemark` 方法设置单个好友的备注。 +自 4.2.1 版本开始,你可以调用 `asyncSetContactRemark` 方法设置单个好友的备注。 好友备注的长度不能超过 100 个字符。 @@ -123,14 +121,13 @@ EMClient.getInstance().contactManager().asyncSetContactRemark(userId, remark, ne }); ``` -#### 获取好友列表 +### 从服务端获取好友列表 -- 从服务端获取好友列表: +自 4.2.1 版本开始,你可以调用 `asyncFetchAllContactsFromServer` 方法从服务器一次性或分页获取好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 -调用以下两种方法返回好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 +- 一次性获取服务端好友列表。 ```java -//一次性从服务端获取整个好友列表 EMClient.getInstance().contactManager().asyncFetchAllContactsFromServer(new EMValueCallBack>() { @Override public void onSuccess(List value) { @@ -142,8 +139,11 @@ EMClient.getInstance().contactManager().asyncFetchAllContactsFromServer(new EMVa } }); +``` + +- 分页获取服务端好友列表。 -//从服务端分页获取好友列表 +```java // limit 的取值范围为 [1,50] List contacts=new ArrayList<>(); String cursor= ""; @@ -171,24 +171,24 @@ private void doAsyncFetchAllContactsFromServer(List contacts, String }); ``` -你也可以调用 `getAllContactsFromServer` 方法从服务器获取所有好友的列表,该列表只包含好友的用户 ID。 +此外,你也可以调用 `getAllContactsFromServer` 方法从服务器获取所有好友的列表,该列表只包含好友的用户 ID。 ```java -// 从服务器获取好友列表。 // 同步方法,会阻塞当前线程。异步方法为 asyncGetAllContactsFromServer(EMValueCallBack)。 List usernames = EMClient.getInstance().contactManager().getAllContactsFromServer(); ``` -- 从本地获取好友列表 +### 从本地获取好友列表 -调用以下两种方法返回好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 +自 4.2.1 版本开始,你可以调用 `fetchContactFromLocal` 方法从本地获取单个好友的用户 ID 和好友备注。你也可以调用 `asyncFetchAllContactsFromLocal` 方法一次性获取整个好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 -:::notice +:::tip 需要从服务器获取好友列表之后,才能从本地获取到好友列表。 ::: +- 获取本地单个好友。 + ```java -//从本地获取单个好友 try { EMContact emContact = EMClient.getInstance().contactManager().fetchContactFromLocal(userId); String remark = emContact.getRemark(); @@ -197,8 +197,11 @@ try { } catch (HyphenateException e) { EMLog.e(TAG, "fetchContactFromLocal error:" + e.getMessage()); }; +``` + +- 一次性获取本地好友列表。 -//一次性从本地获取整个好友列表 +```java EMClient.getInstance().contactManager().asyncFetchAllContactsFromLocal(new EMValueCallBack>() { @Override public void onSuccess(List value) { @@ -212,7 +215,7 @@ EMClient.getInstance().contactManager().asyncFetchAllContactsFromLocal(new EMVal }); ``` -你也可以调用 `getContactsFromLocal` 方法从本地获取所有好友的列表,该列表只包含好友的用户 ID。 +此外,你也可以调用 `getContactsFromLocal` 方法从本地一次性获取所有好友的列表,该列表只包含好友的用户 ID。 示例代码如下: @@ -220,14 +223,12 @@ EMClient.getInstance().contactManager().asyncFetchAllContactsFromLocal(new EMVal List usernames = EMClient.getInstance().contactManager().getContactsFromLocal(); ``` -### 管理黑名单 +### 添加用户到黑名单 黑名单是与好友无任何关系的独立体系。可以将任何用户加入黑名单,不论该用户与你是否是好友关系。 黑名单功能包括加入黑名单,从黑名单移出用户和获取黑名单列表。对于获取黑名单,你可从服务器获取黑名单列表,也可从本地数据库获取已保存的黑名单列表。 -#### 添加用户到黑名单 - 你可以调用 `addUserToBlackList` 添加用户到黑名单。用户被加入黑名单后,无法向你发送消息,也无法发送好友申请。 用户可以将任何其他用户添加到黑名单列表,无论该用户是否是好友。好友被加入黑名单后仍在好友列表上显示。 @@ -238,7 +239,7 @@ List usernames = EMClient.getInstance().contactManager().getContactsFrom EMClient.getInstance().contactManager().addUserToBlackList(username,true); ``` -#### 将用户从黑名单移除 +### 将用户从黑名单移除 你可以调用 `removeUserFromBlackList` 将用户从黑名单移除,用户发送消息等行为将恢复。 @@ -248,7 +249,7 @@ EMClient.getInstance().contactManager().addUserToBlackList(username,true); EMClient.getInstance().contactManager().removeUserFromBlackList(username); ``` -#### 从服务器获取黑名单列表 +### 从服务器获取黑名单列表 你可以调用 `getBlackListFromServer` 从服务端获取黑名单列表。示例代码如下: @@ -258,7 +259,7 @@ EMClient.getInstance().contactManager().removeUserFromBlackList(username); EMClient.getInstance().contactManager().getBlackListFromServer(); ``` -#### 从本地数据库获取黑名单列表 +### 从本地数据库获取黑名单列表 从服务器获取黑名单列表之后,才能从本地数据库获取到黑名单列表。 diff --git a/docs/document/applet/apidoc.md b/docs/document/applet/apidoc.md index a1efb8a86..6e9f1a4dc 100644 --- a/docs/document/applet/apidoc.md +++ b/docs/document/applet/apidoc.md @@ -2,4 +2,4 @@ -微信小程序的 IM 的 API 使用方法,与 Web Javascript 接入方式基本相同,可参照 [Web SDK API DOC](https://docs-im-beta.easemob.com/jsdoc/index.html) +微信小程序的 IM 的 API 使用方法,与 Web Javascript 接入方式基本相同,可参照 [Web SDK API DOC](https://doc.easemob.com/jsdoc/index.html) diff --git a/docs/document/applet/conversation_delete.md b/docs/document/applet/conversation_delete.md new file mode 100644 index 000000000..c30df234f --- /dev/null +++ b/docs/document/applet/conversation_delete.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/conversation_delete.html", + title: "删除会话" +} +--- \ No newline at end of file diff --git a/docs/document/applet/conversation_list.md b/docs/document/applet/conversation_list.md new file mode 100644 index 000000000..3c8da0869 --- /dev/null +++ b/docs/document/applet/conversation_list.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/conversation_list.html", + title: "会话列表" +} +--- \ No newline at end of file diff --git a/docs/document/applet/conversation_local.md b/docs/document/applet/conversation_local.md new file mode 100644 index 000000000..c59e4cdd3 --- /dev/null +++ b/docs/document/applet/conversation_local.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/conversation_local.html", + title: "本地会话" +} +--- \ No newline at end of file diff --git a/docs/document/applet/conversation_mark.md b/docs/document/applet/conversation_mark.md new file mode 100644 index 000000000..244bb1842 --- /dev/null +++ b/docs/document/applet/conversation_mark.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/conversation_mark.html", + title: "会话标记" +} +--- \ No newline at end of file diff --git a/docs/document/applet/conversation_overview.md b/docs/document/applet/conversation_overview.md new file mode 100644 index 000000000..a9f6c2485 --- /dev/null +++ b/docs/document/applet/conversation_overview.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/conversation_overview.html", + title: "会话介绍" +} +--- \ No newline at end of file diff --git a/docs/document/applet/conversation_pin.md b/docs/document/applet/conversation_pin.md new file mode 100644 index 000000000..59fa428ff --- /dev/null +++ b/docs/document/applet/conversation_pin.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/conversation_pin.html", + title: "置顶会话" +} +--- \ No newline at end of file diff --git a/docs/document/applet/message_delete.md b/docs/document/applet/message_delete.md new file mode 100644 index 000000000..db9961afa --- /dev/null +++ b/docs/document/applet/message_delete.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/message_delete.html", + title: "删除消息" +} +--- \ No newline at end of file diff --git a/docs/document/applet/message_deliver_only_online.md b/docs/document/applet/message_deliver_only_online.md new file mode 100644 index 000000000..8d882bddd --- /dev/null +++ b/docs/document/applet/message_deliver_only_online.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/message_deliver_only_online.html", + title: "消息只投在线用户" +} +--- \ No newline at end of file diff --git a/docs/document/applet/message_recall.md b/docs/document/applet/message_recall.md new file mode 100644 index 000000000..485074cb3 --- /dev/null +++ b/docs/document/applet/message_recall.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/message_recall.html", + title: "撤回消息" +} +--- \ No newline at end of file diff --git a/docs/document/applet/message_receipt.md b/docs/document/applet/message_receipt.md index 6b1e5364d..e4b3b29e6 100644 --- a/docs/document/applet/message_receipt.md +++ b/docs/document/applet/message_receipt.md @@ -1,6 +1,6 @@ --- { pageUri: "/document/web/message_receipt.html", - title: "管理消息回执" + title: "实现消息回执" } --- \ No newline at end of file diff --git a/docs/document/applet/message_retrieve.md b/docs/document/applet/message_retrieve.md index b54234fa4..7e9c5eb1f 100644 --- a/docs/document/applet/message_retrieve.md +++ b/docs/document/applet/message_retrieve.md @@ -1,6 +1,6 @@ --- { pageUri: "/document/web/message_retrieve.html", - title: "从服务器获取消息(消息漫游)" + title: "获取历史消息" } --- \ No newline at end of file diff --git a/docs/document/applet/message_send_receive.md b/docs/document/applet/message_send_receive.md index 630b2c1ae..86d88d3e6 100644 --- a/docs/document/applet/message_send_receive.md +++ b/docs/document/applet/message_send_receive.md @@ -19,7 +19,7 @@ ## 技术原理 -环信即时通讯 IM SDK 可以实现消息的发送、接收与撤回。 +环信即时通讯 IM SDK 可以实现消息的发送和接收。 发送和接收消息: @@ -98,6 +98,8 @@ function sendTextMessage() { } ``` +若初始化时打开了 `useReplacedMessageContents` 开关,发送文本消息时如果被内容审核(Moderation)进行了内容替换,发送方会收到替换后的内容。若该开关为关闭状态,则发送方不会收到替换后的内容。 + ### 接收消息 你可以通过 `addEventHandler` 注册监听器监听消息事件。你可以添加多个事件。当不再监听事件时,请确保删除监听器。 @@ -160,49 +162,13 @@ WebIM.conn.addEventHandler("eventName", { }); ``` -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)均会被移除。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 - -```javascript -let option = { - // 要撤回消息的消息 ID。 - mid: "msgId", - // 消息接收方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。 - to: "username", - // 会话类型:单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`。 - chatType: "singleChat", -}; -conn.recallMessage(option) - .then((res) => { - console.log("success", res); - }) - .catch((error) => { - // 消息撤回失败,原因可能是超过了撤销时限(超过 2 分钟)。 - console.log("fail", error); - }); -``` - -你还可以使用 `onRecallMessage` 监听消息撤回状态: - -```javascript -WebIM.conn.addEventHandler('MESSAGES',{ - onRecallMessage: (msg) => { - // 这里需要在本地删除对应的消息,也可以插入一条消息:“XXX撤回一条消息”。 - console.log('Recalling the message success',msg) - } -}) -``` - ### 发送附件消息 语音、图片、视频和文件消息本质上是附件消息。发送和接收附件消息的流程如下: 1. 创建和发送附件类型消息。SDK 将附件上传到环信服务器,获取消息的基本信息以及服务器上附件文件的路径。 - 对于图片消息来说,服务器会自动生成图片的缩略图;而对于视频消息来说,服务器不会自动生成视频缩略图。 + 对于图片消息来说,服务器会自动生成图片的缩略图;而对于视频消息来说,视频的首帧为缩略图。 2. 接收附件消息。 @@ -544,6 +510,10 @@ const sendLocMsg = () => { 透传消息是通知指定用户采取特定操作的命令消息。接收方自己处理透传消息。 +:::tip +透传消息发送后,不支持撤回。 +::: + 参考以下代码示例发送和接收透传消息: ```javascript diff --git a/docs/document/applet/message_translation.md b/docs/document/applet/message_translation.md index 7c5767039..830f57d70 100644 --- a/docs/document/applet/message_translation.md +++ b/docs/document/applet/message_translation.md @@ -1,6 +1,6 @@ --- { pageUri: "/document/web/message_translation.html", - title: "翻译" + title: "翻译消息" } --- \ No newline at end of file diff --git a/docs/document/applet/multi_device .md b/docs/document/applet/multi_device .md deleted file mode 100644 index bb631d71d..000000000 --- a/docs/document/applet/multi_device .md +++ /dev/null @@ -1,93 +0,0 @@ -# 在多个设备登录 - - - -即时通讯 IM 支持同一账号在多个设备上登录,所有已登录的设备同步以下信息和操作: - -- 在线消息、离线消息以及对应的回执和已读状态; -- 好友和群组操作; -- 子区相关操作。 - -环信服务器提供接口查询每个账号已登录设备列表以及[将账号从已登录设备强制下线](account_system.html#强制下线)。 - -多端登录时,即时通讯 IM 每端默认最多支持 4 个设备同时在线。如需增加支持的设备数量,可以联系环信即时通讯 IM 的商务经理。 - -你可以在环信控制台的**功能配置** > **功能配置总览**页面的**基础功能**页签下点击**多端多设备在线**操作栏中的**设置**,在弹出的对话框中设置设置各端设备的数量: - -![img](@static/images/common/multidevice_device_count.png) - -单端和多端登录场景下的互踢策略和自动登录时安全检查如下: - - - - -无标题文档 - - - - - - - - - - - - - - - - - - - - -
单端/多端登录互踢策略自动登录安全检查
单端登录新登录的设备会将当前在线设备踢下线。设备支持自动登录时,若设备下线后自动重连时需要判断是否踢掉当前在线的最早登录设备,请联系环信商务。
多端登录

若一端的登录设备数量达到了上限,最新登录的设备会将该端最早登录的设备踢下线。

-

即时通讯 IM 仅支持同端互踢,不支持各端之间互踢。

- - - -## 技术原理 - -即时通讯 IM Applet SDK 在用户每次登录时会生成一个新的唯一的登录 ID,并将该 ID 发送到服务器。服务器会自动将新消息发送到用户登录的设备,可以自动监听到其他设备上进行的好友或群组操作。 - -小程序端不存在用户获取其他登录设备的设备 ID 的 API,因此不支持查询其他同时登录的设备,也无法了解这些设备上进行的操作。 - -## 实现方法 - -你需要调用 `addEventHandler` 方法注册监听事件,监听其他设备上的操作。服务器同步信息之后,SDK 会回调这些事件,小程序端与其他端均会收到好友和群组相关操作的通知。 - -对于好友和群组的相关操作来说,多设备事件与单设备事件的名称相同,唯一区别在于事件中的 `from` 字段,即多端多设备事件中该字段的值为当前用户的用户 ID,而单设备事件中,该字段的值为操作方的用户 ID。详见[群组事件](group_manage.html#监听群组事件)和[用户关系事件](user_relationship.html#添加好友)。 - -子区和删除漫游消息事件会触发 `onMultiDeviceEvent` 事件,示例代码如下: - -```javascript -conn.addEventHandler("handlerId", { - onContactAgreed: (event) => {}, - onGroupEvent: (event) => {}, - onMultiDeviceEvent: (event) => { - switch (event.operation) { - case "chatThreadCreate": - //当前用户在其他设备上创建子区。 - break; - case "chatThreadDestroy": - //当前用户在其他设备上销毁子区。 - break; - case "chatThreadJoin": - //当前用户在其他设备上加入子区。 - break; - case "chatThreadLeave": - //当前用户在其他设备上离开子区。 - break; - case "chatThreadNameUpdate": - //当前用户在其他设备上修改子区名称。 - break; - case "deleteRoaming": - // 当前用户在其他设备上单向删除服务端某个会话的历史消息。 - break; - default: - break; - } - }, -}); -``` diff --git a/docs/document/applet/multi_device.md b/docs/document/applet/multi_device.md new file mode 100644 index 000000000..b90fa0302 --- /dev/null +++ b/docs/document/applet/multi_device.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/document/web/multi_device.html", + title: "在多个设备上登录" +} +--- \ No newline at end of file diff --git a/docs/document/applet/releasenote.md b/docs/document/applet/releasenote.md index a4eae9ebc..8cd6fb3fb 100644 --- a/docs/document/applet/releasenote.md +++ b/docs/document/applet/releasenote.md @@ -2,7 +2,72 @@ -## 版本 V4.2.0 Dev 2023-07-27(开发版) +## 版本 V4.5.1 Dev 2024-02-22(开发版) + +### 优化 + +- [IM SDK] 统一消息附件的 URL 格式。 + +### 修复 + +- [IM SDK] 修复 uni-app SDK 运行到 iOS 平台发送群组定向消息报错的问题。 + +## 版本 V4.5.0 Dev 2024-01-30(开发版) + +### 新增特性 + +- [IM SDK] 聊天室和群组成员进出事件增加成员人数 `memberCount` 字段。 +- [IM SDK] 新增 [deleteAllMessagesAndConversations](message_delete.html#单向清空服务端的聊天记录) 方法, 用于清空当前用户的聊天记录,包括消息和会话。 +- [IM SDK] 新增 [getSelfIdsOnOtherPlatform](multi_device.html#获取当前用户的其他登录设备的登录-id-列表) 方法, 可以获取当前用户其他登录设备的登录 ID 列表,实现对指定设备发送消息。 +- [IM SDK] 新增 [useReplacedMessageContents](message_send_receive.html#发送文本消息) 开关。开启后,发送消息时如果被内容审核进行了内容替换,发送方可以获取替换后的内容。 + +### 优化 + +- [IM SDK] 抖音小程序重连缓慢。 +- [IM SDK] 格式化会话列表中最近一条自定义消息的 `customExts` 字段。 +- [IM SDK] 重复拉消息问题。 + +### 修复 + +- [IM SDK] 修复 `onMessage` 回调消息顺序异常问题。 + +## 版本 V4.4.0 Dev 2023-12-22(开发版) + +### 新增特性 + +- [IM SDK] 新增[会话标记功能](conversation_mark.html)。 + - `addConversationMark`:[标记会话](conversation_mark.html#标记会话)。 + - `removeConversationMark`:[取消标记会话](conversation_mark.html#取消标记会话)。 + - `getServerConversationsByFilter`:[根据会话标记从服务器分页查询会话列表](conversation_mark.html#根据会话标记从服务器分页查询会话列表)。 + - `onMultiDeviceEvent#markConversation/unMarkConversation`:[多设备场景下的会话标记事件](multi_device.html#实现方法)。当前用户在一台登录设备上更新了会话标记,包括添加和移除会话标记,其他登录设备会收到该事件。 +- [IM SDK] 增加 `onMessage` 回调。在收到文本、图片、视频、语音、地理位置和文件等消息时,批量将消息回调给应用。 + +### 修复 + +- [IM SDK] SDK 类型修正。 + +## 版本 V4.3.0 Dev 2023-11-17 + +### 新增特性 + +- [IM SDK] 新增[好友备注功能](user_relationship.html#设置好友备注)。 +- [IM SDK] 消息结构新增 `broadcast` 字段, 用于判断该消息是否为聊天室全局广播消息。可通过[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 + +### 优化 + +- [IM SDK] Token 登录增加即将过期及已过期的回调,即 Token 已过期或有效期过半时也触发 `onTokenExpired` 和 `onTokenWillExpire` 回调。 + +### 修复 + +- [IM SDK] 修复会话列表最后一条消息中获取不到 `reaction` 的问题。 + +## 版本 V4.2.1 Dev 2023-09-27 + +### 新增特性 + +- [IM SDK] 用户申请加群被拒绝的回调 `joinPublicGroupDeclined` 中增加申请人的用户 ID。 + +## 版本 V4.2.0 Dev 2023-07-27 ### 新增特性 @@ -14,14 +79,14 @@ 修复发送不必要的消息送达回执的问题。 -## 版本 V4.1.6 Dev 2023-04-17(开发版) +## 版本 V4.1.6 Dev 2023-04-17 ### 新增特性 - [IM SDK] `getHistoryMessages` 方法的 `searchOptions` 中新增 `from`、`msgTypes`、`startTime` 和 `endTime` 参数,允许用户按消息发送方、消息类型或时间段从服务端拉取历史消息。 - [IM SDK] 新增错误码 511,即 MESSAGE_SIZE_LIMIT,若[消息体大小超过限制](message_overview.html#消息类型)时提示用户。 -## 版本 V4.1.4 Dev 2023-03-16(开发版) +## 版本 V4.1.4 Dev 2023-03-16 ### 新增特性 @@ -38,11 +103,11 @@ - [IM SDK] 修复 TypeScript 代码的一些类型错误。 - [IM SDK] 修复 `getHistoryMessages` 方法无法捕获错误的问题。 -## 版本 V4.1.3 Dev 2023-02-21(开发版) +## 版本 V4.1.3 Dev 2023-02-21 #### 新增特性 -- [IM SDK] 在 `getConversationlist` 方法中新增分页参数 `pageNum` 和 `pageSize`,支持[分页方法获取会话列表](message_retrieve.html#从服务器分页获取会话列表)。 +- [IM SDK] 在 `getConversationlist` 方法中新增分页参数 `pageNum` 和 `pageSize`,支持[分页方法获取会话列表](conversation_list.html#从服务器分页获取会话列表)。 - [IM SDK] 新增[群组创建事件 `create`](group_manage.html#监听群组事件)。群组创建后,群主的其他设备会收到该事件。 #### 优化 @@ -56,7 +121,7 @@ - [IM SDK] 修复 `getConversationlist` 方法的返回值缺少 `customExts` 字段的问题。 - [IM SDK] 修复设置 `useOwnUploadFun` 允许用户自己上传图片时图片消息中的 `size` 字段不生效的问题。 -## 版本 V4.1.2 Dev 2022-11-08(开发版) +## 版本 V4.1.2 Dev 2022-11-08 ### 新增特性 @@ -100,7 +165,7 @@ ### 新增特性 -- [IM SDK] 新增群组事件回调 [onGroupEvent](https://docs-im-beta.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onGroupEvent) 和聊天室事件回调 [onChatroomEvent](https://docs-im-beta.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onChatroomEvent)。原回调可继续使用; +- [IM SDK] 新增群组事件回调 [onGroupEvent](https://doc.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onGroupEvent) 和聊天室事件回调 [onChatroomEvent](https://doc.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onChatroomEvent)。原回调可继续使用; - [IM SDK] 新增群聊消息限流错误码 [MESSAGE_CURRENT_LIMITING](/document/web/error.html) - [IM SDK] 邀请加入群聊回调 `onGroupChange` 返回中新增 群名称 参数值。 @@ -113,7 +178,7 @@ ### 新增特性: - [IM SDK] 新增消息子区(message thread)功能; -- [IM SDK] 新增 [getConversationList](/document/web/message_retrieve.html) 方法解析会话中的最新一条消息; +- [IM SDK] 新增 [getConversationList](/document/web/conversation_list.html) 方法解析会话中的最新一条消息; ### 优化: diff --git a/docs/document/electron/annex.md b/docs/document/electron/annex.md new file mode 100644 index 000000000..08097e268 --- /dev/null +++ b/docs/document/electron/annex.md @@ -0,0 +1,53 @@ +# 附录 + +文档中用到的结构体定义 + +``` +Result +{ + code, //{Number} 0表示成功,其它值为失败 + description //{String} code为非0值时,表示失败原因 +} +ContactListResult +{ + code:result.errorCode, //{Number} 0表示成功,其它值为失败 + description:result.description, //{String} code为非0值时有效,表示失败原因 + data //{StringArray} 用户ID数组,code为0时有效,["ID1","ID2"] +} +GroupResult +{ + code:result.errorCode, //{Number} 0表示成功,其它值为失败 + description:result.description, //{String} code为非0值时有效,表示失败原因 + data //{StringArray} EMGroup对象,code为0时有效 +} +GroupListResult +{ + code:result.errorCode, //{Number} 0表示成功,其它值为失败 + description:result.description, //{String} code为非0值时有效,表示失败原因 + data //{Array} EMGroup对象数组,code为0时有效 +} +SharedFileResult +{ + code:result.errorCode, //{Number} 0表示成功,其它值为失败 + description:result.description, //{String} code为非0值时有效,表示失败原因 + data //{Object} EMMucSharedFile,code为0时有效 +} +SharedFileListResult +{ + code:result.errorCode, //{Number} 0表示成功,其它值为失败 + description:result.description, //{String} code为非0值时有效,表示失败原因 + data //{Array} EMMucSharedFile对象数组,code为0时有效 +} +AnnouncementResult +{ + code:result.errorCode, //{Number} 0表示成功,其它值为失败 + description:result.description, //{String} code为非0值时有效,表示失败原因 + data //{String} 群组公告内容,code为0时有效 +} +MessageListResult +{ + code:result.errorCode, //{Number} 0表示成功,其它值为失败 + description:result.description, //{String} code为非0值时有效,表示失败原因 + data //{Array} EMMessage对象数组,code为0时有效 +} +``` \ No newline at end of file diff --git a/docs/document/electron/chatroom.md b/docs/document/electron/chatroom.md new file mode 100644 index 000000000..3aec5f574 --- /dev/null +++ b/docs/document/electron/chatroom.md @@ -0,0 +1,106 @@ +# 聊天室管理 + +环信桌面端 SDK 支持聊天室功能的集成,集成后可以进行如下操作: + +- 查询聊天室信息 + +- 加入聊天室 + +- 退出聊天室 + +- 监听回调 + +通过这些操作,可以组合帮助您完成多种场景下的 IM 需求。 + +**注意:** 聊天室只能有服务端创建,客户端只可以查询、加入和退出聊天室 + +------ + +## 查询聊天室信息 + +``` +// 获取聊天室控制对象 +var chatroomManager = emclient.getChatroomManager(); +// 获取所有聊天室 +var chatroomlist = chatroomManager.fetchAllChatrooms(error); +// 获取聊天室属性 +chatroomlist.map((chatroom) => { + console.log("chatroom id:"+chatroom.chatroomId()); + console.log("chatroom chatroomSubject:"+chatroom.chatroomSubject()); + console.log("chatroom chatroomDescription:"+chatroom.chatroomDescription()); + console.log("chatroom owner:"+chatroom.owner()); + console.log("chatroom chatroomMemberCount:"+chatroom.chatroomMemberCount()); + console.log("chatroom chatroomMemberMaxCount:"+chatroom.chatroomMemberMaxCount()); + console.log("chatroom chatroomAnnouncement:"+chatroom.chatroomAnnouncement()); + var adminlist = chatroom.chatroomAdmins(); + var memberlist = chatroom.chatroomMembers(); + var banslist = chatroom.chatroomBans(); +}); +``` + +------ + +## 加入聊天室 + +接口 API 说明如下: + +``` +/** + * 加入聊天室 + * param chatroomid 聊天室 ID + * param error 操作结果 + * return Promise 对象,该对象的 response 参数 EMChatroom 对象 + */ +joinChatroom(chatroomid,error); +``` + +调用方法如下: + +``` +chatroomManager.joinChatroom(chatroomId, error).then((res)=>{},(error) => {}); +``` + +------ + +## 退出聊天室 + +接口 API 说明如下: + +``` +/** + * 离开聊天室 + * param chatroomid 聊天室 ID + * param error 操作结果 + * return Promise 对象,该对象的 response 参数为空 + */ +leaveChatroom(chatroomid,error); +``` + +调用方法如下: + +``` +chatroomManager.leaveChatroom(chatroomId, error).then((res)=>{},(error) => {}); +``` + +------ + +## 回调监听 + +``` +// 添加消息回调 +var emchatroomlistener = new easemob.EMChatroomManagerListener(); +console.log(emchatroomlistener); + +emchatroomlistener.onMemberJoinedChatroom((chatroom,member) => { + console.log("onMemberJoinedChatroom" + chatroom.chatroomSubject()); + console.log("onMemberJoinedChatroom" + member); +}); +emchatroomlistener.onMemberLeftChatroom((chatroom,member) => { + console.log("onMemberLeftChatroom" + chatroom.chatroomSubject()); + console.log("onMemberLeftChatroom" + member); +}); +//注册监听 +chatroomManager.addListener(emchatroomlistener); +// 移除监听 +chatroomManager.removeListener(emchatroomlistener); +``` \ No newline at end of file diff --git a/docs/document/electron/contact.md b/docs/document/electron/contact.md new file mode 100644 index 000000000..3d1afc810 --- /dev/null +++ b/docs/document/electron/contact.md @@ -0,0 +1,338 @@ +# 好友管理 + +环信桌面端 SDK 支持好友功能的集成,集成后可以进行如下操作: + +- 好友处理 + +- 黑名单处理 + +- 监听联系人变更 + +通过这些操作,可以组合帮助您完成多种场景下的 IM 需求。 + +好友管理模块为 EMContactManager ,由 EMClient 模块加载时主动创建,可以使用 EMClient 模块的 getContactManager 方法获取,代码如下: + +``` +var contactManager = emclient.getContactManager(); +``` + +------ + +## 好友处理 + +好友处理包含以下处理操作: + +- 获取好友列表 + +- 添加好友 + +- 删除好友 + +- 同意好友申请 + +- 拒绝好友申请 + +所有处理操作的示例下面会一一说明。 + +------ + +### 获取好友列表 + +好友列表可以从**本地**和**服务器**获取,各接口说明如下: + +#### 从本地中获取 + +接口 API 如下: + +``` +/** + * 获取当前缓存中的好友列表,若缓存中没有则从数据库中获取 + * return 返回 ContactListResult + */ +allContacts() +``` + +调用方法如下: + +``` +let res = contactManager.allContacts(); +console.log() +``` + +#### 从服务器获取 + +接口API如下: + +``` +/** + * 从服务端拉取好友列表,异步操作 + * return 返回 Promise 对象,response 参数为 ContactListResult + */ +getContactsFromServer(); +``` + +调用方法如下: + +``` +contactManager.getContactsFromServer().then(ContactListResult => { + },(error) => {}); +``` + +------ + +### 添加好友 + +接口API如下: + +``` +/** + * 添加好友 api,异步操作 + * param String,username 为对方用户名,输入参数 + * param String,message 为欢迎信息,输入参数,对方收到好友申请时可以看到 + * return Promise 对象,response 参数为 Result + */ +inviteContact(username, message); +``` + +调用方法如下: + +``` +contactManager.inviteContact("jwfan1", "welcome").then((res) => { + },(error) => {}) +``` + +------ + +### 删除好友 + +接口API如下: + +``` +/** + * 从好友列表移除好友 api,异步操作 + * param username 移除目标好友的用户名,输入参数 + * param keepConversation 移除好友后,是否保留会话,输入参数,布尔型,true 为保留,false 为不保留 + * return Promise 对象,response 参数 Result + */ +deleteContact(username,keepConversation); +``` + +调用方法如下: + +``` +contactManager.deleteContact("jwfan1", true).then((res) => { + },(error) => {}) +``` + +------ + +### 同意好友申请 + +接口 API 如下: + +``` +/** + * 用户收到好友申请后的操作,同意好友申请,异步操作 + * param username 发起好友申请的用户名,输入参数 + * return Promise 对象,response 参数为 Result + */ +acceptInvitation(username); +``` + +调用方法如下: + +``` +contactManager.acceptInvitation(username).then((res) => { + },(error) => {}) +``` + +------ + +### 拒绝好友申请 + +接口 API 如下: + +``` +/** + * 用户收到好友申请后的操作,拒绝好友申请,异步操作 + * param username 发起好友申请的用户名,输入参数 + * return Promise 对象,response 参数为 Result + */ +declineInvitation(username) +``` + +调用方法如下: + +``` +contactManager.declineInvitation(username).then((res) => { + },(error) => {}) +``` + +------ + +## 黑名单 + +黑名单包含以下处理操作: + +- 获取黑名单 + +- 设置黑名单 + +- 移入黑名单 + +- 从黑名单移除 + +所有处理操作的示例下面会一一说明。 + +------ + +### 获取黑名单 + +黑名单列表可以从**本地**和**服务器**获取,各接口说明如下: + +#### 从本地中获取 + +接口 API 如下: + +``` +/** + * 从本地获取用户的黑名单列表,黑名单的用户无法发送消息 + * return ContactListResult 黑名单列表,data 为 String 数组 + */ +blacklist(); +``` + +调用方法如下: + +``` +let res = contactManager.blacklist() +``` + +#### 从服务器获取 + +接口 API 如下: + +``` +/** + * 从服务器获取用户的黑名单列表,黑名单的用户无法发送消息 + * return Promise 对象,response 参数为 ContactListResult + */ +getBlackListFromServer(); +``` + +调用方法如下: + +``` +contactManager.getBlackListFromServer().then((res) => {},(error) => {}) +``` + +------ + +### 设置黑名单 + +接口 API 如下: + +``` +/** + * 设置用户的黑名单列表,异步操作 + * param blacklist 输入参数,黑名单列表,StringArray,["ID1","ID2"] + * return Promise 对象,response 参数为 Result + */ +saveBlackList(blacklist); +``` + +调用方法如下: + +``` +contactManager.saveBlackList(['jwfan2', 'jwfan3']).then((res)=>{},(error) => {}); +``` + +### 移入黑名单 + +接口 API 如下: + +``` +/** + * 添加用户到黑名单列表,异步操作 + * param username 输入参数,要添加的黑名单用户名,String + * return Promise 对象,response 参数为 Result + */ +addToBlackList(username); +``` + +调用方法如下: + +``` +contactManager.addToBlackList('jwfan2').then((res)=>{},(error) => {}); +``` + +------ + +### 从黑名单移除 + +接口 API 如下: + +``` +/** + * 从黑名单列表移除用户,异步操作 + * param username 输入参数,要从黑名单移除的用户名,String + * return Promise 对象,response 参数为 Result + */ +removeFromBlackList(username); +``` + +调用方法如下: + +``` +contactManager.removeFromBlackList('jwfan2').then((res)=>{},(error) => {}); +``` + +------ + +## 监听联系人变更 + +通过注册回调函数,监听联系人的变动,代码如下: + +``` +// 实例化监听对象 +var listener = new easemob.EMContactListener(); + +// 有好友添加的回调 +listener.onContactAdded((username) => { +console.log("onContactAdded username: " + username); +}); + +// 有好友删除的回调 +listener.onContactDeleted((username) => { +console.log("onContactDeleted username: " + username); +}); + +// 收到好友申请的回调,用户可以在这里同意或拒绝好友申请 +listener.onContactInvited((username, reason) => { +console.log("onContactInvited username: " + username + " reason: " + reason); +if (username == "jwfan1") { + let res = contactManager.acceptInvitation(username); +} else { + let res = contactManager.declineInvitation(username); +} +}); + +// 群组邀请成员同意 +listener.onContactAgreed((username) => { +console.log("onContactAgreed username: " + username); +}); + +// 群组邀请成员拒绝 +listener.onContactRefused((username) => { +console.log("onContactRefused username: " + username); +}); + +// 注册回调函数 +contactManager.registerContactListener(listener); + + +===== 结束联系人监听 ===== + +// 移除回调监听 +contactManager.removeContactListener(listener); +``` \ No newline at end of file diff --git a/docs/document/electron/conversation.md b/docs/document/electron/conversation.md new file mode 100644 index 000000000..cc5152285 --- /dev/null +++ b/docs/document/electron/conversation.md @@ -0,0 +1,458 @@ +# 会话管理 + +环信桌面端 SDK 支持会话管理的集成,集成后可以进行如下操作: + +- 会话处理 + +- 获取消息 + +- 消息处理 + +通过这些操作,可以组合帮助您完成多种场景下的 IM 需求。 + +会话管理模块为 EMChatManager,由 EMClient 模块加载时主动创建,可以使用 EMClient 模块的 getChatManager 方法获取,代码如下: + +``` +var chatManager = emclient.getChatManager(); +``` + +------ + +## 会话处理 + +会话处理包含以下处理操作: + +- 获取会话列表 + +- 根据 ID 获取会话 + +- 删除会话 + +- 获取会话属性 + +- 会话属性扩展 + +所有处理操作的示例下面会一一说明。 + +------ + +### 获取会话列表 + +接口 API 如下: + +``` +/** + * 获取会话列表 + * return 返回会话列表,EMConversation 数组 + */ +getConversations() +``` + +调用方法如下: + +``` +var convlist = chatManager.getConversations(); +``` + +------ + +### 根据 ID 获取会话 + +根据会话 ID 获取会话,接口 API 如下: + +``` +/** + * 获取会话 + * param conversationId 会话 ID,输入参数,String + * param type 会话类型,输入参数,0为单聊,1为群聊 + * return 会话,EMConversation + */ +conversationWithType(conversationId,type) +``` + +调用方法如下: + +``` +let conversationlist = chatManager.conversationWithType(conversationId,type); +``` + +------ + +### 删除会话 + +接口 API 如下: + +``` +/** 根据 ID 删除会话 + * param conversationId 会话 ID,输入参数 + * param isRemoveMessages 是否删除消息,ture 为删除 + */ +removeConversation(conversationId,isRemoveMessages) +``` + +调用方法如下: + +``` +chatManager.removeConversation(conversationId,true); +``` + +------ + +### 获取会话属性 + +``` +// 获取会话 ID +console.log("conversationId" + conversation.conversationId()); +// 获取会话类型,0为单聊,1为群聊 +console.log("conversationType" + conversation.conversationType()); +``` + +------ + +### 会话扩展属性 + +接口 API 如下: + +``` +/** + * 设置会话扩展属性 + * param ext 扩展属性,String + */ +setExtField(strAttr) +/** + * 获取会话扩展属性 + * return 扩展属性,String + */ +extField() +``` + +调用方法如下: + +``` +conversation.setExtField(ext); +var strAttr = conversation.extField(); +``` + +------ + +## 获取消息 + +获取消息包含以下处理操作: + +- 获取历史消息 + +- 根据 ID 获取当前会话消息 + +- 获取会话中的消息计数 + +- 获取会话中的未读消息计数 + +- 获取最新消息 + +所有处理操作的示例下面会一一说明。 + +------ + +### 获取历史消息 + +接口 API 如下: + +``` +/** + * 分页获取历史消息,从服务器获取 + * param conversationId 会话 ID,输入参数 + * param type 会话类型,1为群组,0为单聊 + * param pageSize 每页的消息计数 + * param startMsgId 起始消息 ID + * return 返回 Promise 对象,response 参数为 MessageListResult + */ +chatManager.fetchHistoryMessages(conversationId, type, pageSize, startMsgId) +``` + +调用方法如下: + +``` +chatManager.fetchHistoryMessages(conversationId, type, pageSize, startMsgId).then((res) => {},(error) => {}); +``` + +------ + +### 根据 ID 获取当前会话消息 + +根据消息 ID 获取当前会话消息,接口 API 如下: + +``` +/** + * 根据消息 ID 获取消息 + * param msgid 消息 ID + * return 未读消息计数 + */ +loadMessage(msgid) +``` + +调用方法如下: + +``` +var msg = conversation.loadMessage(msgid); +``` + +------ + +### 获取会话中的消息计数 + +接口 API 如下: + +``` +/** + * 获取会话中的消息计数 + * return 消息计数,Number + */ +messagesCount() +``` + +调用方法如下: + +``` +var msgCount = conversation.messagesCount(); +``` + +------ + +### 获取会话中的未读消息计数 + +接口 API 如下: + +``` +/** + * 获取会话中的未读消息计数 + * return 未读消息计数,Number + */ +unreadMessagesCount() +``` + +调用方法如下: + +``` +var unreaddMsgCount = conversation.unreadMessagesCount(); +``` + +------ + +### 获取最新一条消息 + +接口 API 如下: + +``` +/** + * 获取会话中的最新一条消息 + * return EMMessage 消息对象 + */ +latestMessage() +``` + +调用方法如下: + +``` +var msg = conversation.latestMessage(); +``` + +------ + +## 消息处理 + +消息处理包含以下处理操作: + +- 插入消息 + +- 添加消息 + +- 修改消息 + +- 加载会话消息 + +- 删除会话消息 + +- 清空会话消息 + +- 下载图片、附件 + +- 设置消息已读状态 + +所有处理操作的示例下面会一一说明。 + +------ + +### 插入消息 + +接口 API 如下: + +``` +/** + * 不发送消息,只是插入到本地,按照时间插入到本地数据库 + * param messagelist 要插入的消息列表,EMMessage 数组 + * return 返回操作结果,Bool +*/ +insertMessages(messagelist); +``` + +调用方法如下: + +``` +chatManager.insertMessages(messagelist); +``` + +------ + +### 添加消息 + +接口 API 如下: + +``` +/** + * 在末尾添加一条消息 + * param message 要插入的消息,EMMessage 对象 + * return 返回操作结果,Bool +*/ +appendMessage(message); +``` + +调用方法如下: + +``` +chatManager.appendMessage(message); +``` + +------ + +### 修改消息 + +接口 API 如下: + +``` +/** + * 修改一条消息,不能改变消息 ID + * param message 要插入的消息,EMMessage 对象 + * return 返回操作结果,Bool +*/ +updateMessage(message); +``` + +调用方法如下: + +``` +chatManager.updateMessage(message); +``` + +------ + +### 加载会话消息 + +接口 API 如下: + +``` +/** + * 按照 ID 加载会话消息 + * param refMsgId 起始消息 ID,输入参数,空为最新消息,String + * param count 加载的消息数,输入参数,Number + * param direction 消息加载方向填0 + * return 返回为 EMMessage 数组 + */ +loadMoreMessagesByMsgId(refMsgId, count, direction); + +/** + * 按照时间加载会话消息 + * param timeStamp 起始消息时间,输入参数 + * param count 加载的消息数,输入参数 + * param direction 消息加载方向,填0 + * return 返回EMMessage数组 + */ +conversation.loadMoreMessagesByTime(timeStamp, count, direction); +``` + +调用方法如下: + +``` +conversation.loadMoreMessagesByMsgId("", 20,0); +conversation.loadMoreMessagesByTime(timeStamp, 20,0); +``` + +------ + +### 删除会话消息 + +接口 API 如下: + +``` +/** + * 按照 ID 移除会话消息,只操作缓存和本地数据库 + * param messageId 要删除的消息 ID + * return 返回操作结果,bool 型 + */ +removeMessage(messageId) +``` + +调用方法如下: + +``` +conversation.removeMessage(messageId).then((res)=>{},(error) => {}); +``` + +------ + +### 清空会话消息 + +接口 API 如下: + +``` +/** + * 清空会话消息,只操作缓存和本地数据库 + * return 返回操作结果,bool 型 + */ +clearAllMessages() +``` + +调用方法如下: + +``` +conversation.clearAllMessages(); +``` + +------ + +### 下载图片、附件 + +``` +// 下载附件消息,message 为 EMMessage 对象,可在 message 中设置回调 +chatManager.downloadMessageAttachments(message); +// 下载图片缩略,message 为 EMMessage 对象,可在 message 中设置回调 +chatManager.downloadMessageThumbnail(message); +``` + +------ + +### 设置消息已读状态 + +接口 API 如下: + +``` +/** + * 根据消息 ID 标记消息已读状态 + * param msgid,消息 ID + * isread bool,已读状态 + * return 返回操作结果,bool 型 + */ +markMessageAsRead(msgid,isread); +/** + * 标记会话中所有消息的已读状态 + * isread bool,已读状态 + * return 返回操作结果,bool 型 + */ +markAllMessagesAsRead(isread); +``` + +调用方法如下: + +``` +conversation.markMessageAsRead(msgid,isread); +conversation.markAllMessagesAsRead(isread); +``` \ No newline at end of file diff --git a/docs/document/electron/demo_download.md b/docs/document/electron/demo_download.md new file mode 100644 index 000000000..d407a5e4e --- /dev/null +++ b/docs/document/electron/demo_download.md @@ -0,0 +1,8 @@ +# Demo 下载体验 + +------ + +- [Windows Demo](https://download-sdk.oss-cn-beijing.aliyuncs.com/downloads/DesktopDemo.3.8.4.win.setup.exe) +- [Mac Demo](https://download-sdk.oss-cn-beijing.aliyuncs.com/downloads/DesktopDemo.3.8.4.mac.dmg) +- [Demo 源码](https://github.com/easemob/sdkdemoapp_windows/tree/electron) + diff --git a/docs/document/electron/group.md b/docs/document/electron/group.md new file mode 100644 index 000000000..d96b96834 --- /dev/null +++ b/docs/document/electron/group.md @@ -0,0 +1,1018 @@ +# 群组 + +环信桌面端 SDK 支持群组功能的集成,集成后可以进行如下操作: + +- 获取群组 + +- 群组管理 + +- 群成员管理 + +- 加群处理 + +- 群消息 + +- 群文件 + +- 群组变更的监听 + +通过这些操作,可以组合帮助您完成多种场景下的 IM 需求。 + +群组管理模块为 EMGroupManager ,由 EMClient 模块加载时主动创建,可以使用 EMClient 模块的 getGroupManager 方法获取,代码如下 + +``` +var groupManager = emclient.getGroupManager(); +``` + +------ + +## 获取群组 + +获取群组包含以下处理操作: + +- 本地获取群组 + +- 服务器获取群组 + +- ID 获取群组 + +- 获取群组信息 + +- 获取公开群组 + +- 查找公开群组 + +所有处理操作的示例下面会一一说明。 + +------ + +### 本地获取群组 + +本地获取用户所在的所有群组,接口 API 如下: + +``` +/** + * 本地获取用户所有的组 + * return GroupListResult + */ +allMyGroups() +``` + +调用方法如下: + +``` +let res = groupManager.allMyGroups() +``` + +------ + +### 服务器获取群组 + +服务器获取用户所在的所有群组,接口 API 如下: + +``` +/** + * 服务器获取用户所有的组 + * return 返回 Promise 对象,response 参数为 GroupListResult + */ +fetchAllMyGroups() +``` + +调用方法如下: + +``` +groupManager.fetchAllMyGroups().then((res)=>{},(error) => {}); +``` + +------ + +### ID 获取群组 + +根据 ID 获取群组 + +``` +let group = groupManager.groupWithId(groupId); +``` + +------ + +### 获取群组信息 + +``` +// 获取组 ID +console.log("group.groupId" + group.groupId()); +// 获取组名 +console.log("group.groupSubject" + group.groupSubject()); +// 获取组描述 +console.log("group.groupDescription" + group.groupDescription()); +// 获取群主 +console.log("group.groupOwner" + group.groupOwner()); +// 获取成员计数 +console.log("group.groupMembersCount" + group.groupMembersCount()); +// 获取群设置类型 +console.log("group.groupMemberType" + group.groupMemberType()); +// 获取群成员 +console.log("members:"+group.groupMembers().join(' || ')); +// 获取群设置对象 +var set = group.groupSetting(); +console.log("set.style() = " + set.style()); +console.log("set.maxUserCount() = " + set.maxUserCount()); +console.log("set.extension() = " + set.extension()); +``` + +------ + +### 获取公开群组 + +接口 API 如下: + +``` +/** + * 分页获取公开群组 + * param pageNum 第几页,输入参数,Number,0表示不分页,获取所有公开组,1为分页起始 + * param pageSize 每页计数,输入参数,Number,最大200 + * return 返回 Promise 对象,response 参数为 GroupListResult + */ +fetchPublicGroupsWithPage(pageNum, pageSize); +``` + +调用方法如下: + +``` +groupManager.fetchPublicGroupsWithPage(1,20).then((res) => { + },(error) => {}) +``` + +------ + +### 查找公开群组 + +接口 API 如下: + +``` +/** + * 根据群 ID 查找公开群 + * param1 groupId 群组 ID,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +searchPublicGroup(groupId); +``` + +调用方法如下: + +``` +groupManager.searchPublicGroup(groupId).then((res) => { + },(error) => {}) +``` + +------ + +## 群组管理 + +群组管理包含以下处理操作: + +- 创建群组 + +- 解散群组 + +- 退出群组 + +- 转移群组 + +- 修改群信息 + +- 群组公告管理 + +所有处理操作的示例下面会一一说明。 + +------ + +### 创建群组 + +创建群组时,需要先实例化一个群组设置对象,然后创建群组。实例化群组设置接口 API 如下: + +``` +/** + * 实例化区群组设置 + * param style 组类型, Number ,0为私有群,只有群主可以邀请成员加入,1为私有群,成员也可以邀请成员加入,2为公开群,但申请入群需要群主同意,3为公开群,成员可以随意申请加入 + * param maxUserCount 最大成员数, Number ,最大200 + * param inviteNeedConfirm 邀请是否需要确认,Bool + * param extension 扩展信息,String + * return 返回组设置对象 + */ +EMMucSetting(style, maxUserCount, inviteNeedConfirm, extension) +``` + +调用方法如下: + +``` +var setting = new easemob.EMMucSetting(1, 20, false, "test"); +``` + +创建群组接口 API 如下: + +``` +/** + * 创建群组 api + * param subject 群组名称,输入参数,String + * param description 群组描述,输入参数,String + * param welcomeMessage 欢迎信息,输入参数,String + * param setting 群组设置,输入参数,Object + * param members 群组初始成员,输入参数,StringArray + * return 返回 Promise 对象,response 参数为 GroupResult + */ +createGroup(subject, description, welcomeMessage, setting, members) +``` + +调用方法如下: + +``` +groupManager.createGroup("subject","description","welcome message",setting,["jwfan1", "jwfan2"]).then((res) => {},(error) => {}) +``` + +------ + +### 解散群组 + +接口 API 如下: + +``` +/** + * 解散群组 api + * param groupId 组 ID,输入参数 + * return 返回 Promise 对象,response 参数为 Result + */ +destroyGroup(groupId); +``` + +调用方法如下: + +``` +groupManager.destroyGroup("55139673112577").then((res)=>{},(error) => {}) +``` + +------ + +### 退出群组 + +接口 API 如下: + +``` +/** + * 成员主动退出群组 + * param groupId 群组 ID,输入参数,String + * 返回 Promise 对象,response 参数为 Result + */ +leaveGroup(groupId) +``` + +调用方法如下: + +``` +groupManager.leaveGroup(groupId).then((res)=>{},(error) => {}) +``` + +------ + +### 转移群组 + +接口 API 如下: + +``` +/** + * 转移群主,只有群主能操作 + * param groupId 群组ID,输入参数,String + * param member 新群主用户名,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +transferGroupOwner(groupId, member) +``` + +调用方法如下: + +``` +groupManager.transferGroupOwner(groupId, member).then((res) =>{},(error) => {}); +``` + +------ + +### 修改群组信息 + +接口 API 如下: + +``` +/** + * 修改群标题 + * param groupId 群组 ID ,输入参数,String + * param newSubject 群组新组名,输入参数,String + * return 返回 Promise对象,response 参数为 GroupResult + */ +groupManager.changeGroupSubject(groupId, newSubject); + + +/** + * 修改群描述 + * param groupId 群组 ID,输入参数,String + * param newDescription 群组新描述,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +changeGroupDescription(groupId, newDescription) +``` + +调用方法如下: + +``` +groupManager.changeGroupSubject(groupId, "new Subject", error).then((res) =>{},(error) => {}); +groupManager.changeGroupDescription(groupId, "new Description", error).then((res) =>{},(error) => {}); +``` + +------ + +### 群组公告管理 + +接口 API 如下: + +``` +/** + * 设置群组公告 + * param groupId 群组 ID,输入参数,String + * param announcement 群组公告,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +updateGroupAnnouncement(groupId, announcement,error) + +/** + * 获取群组公告 + * param groupId 群组 ID,输入参数,String + * return 返回 Promise 对象,response 参数为 AnnouncementResult + */ +fetchGroupAnnouncement(groupId) +``` + +调用方法如下: + +``` +groupManager.fetchGroupAnnouncement(groupId).then((res) =>{},(error) => {}); groupManager.updateGroupAnnouncement(groupId, "new announcement").then((res) =>{},(error) => {}); +``` + +------ + +## 群成员管理 + +群成员管理包含以下处理操作: + +- 群成员邀请 + +- 群成员移除 + +- 添加管理员 + +- 删除管理员 + +- 获取禁言成员列表 + +- 成员禁言 + +- 取消成员禁言 + +- 加入群组黑名单 + +- 从群组黑名单移除 + +所有处理操作的示例下面会一一说明。 + +------ + +### 群成员邀请 + +接口 API 如下: + +``` +/** + * 邀请成员入群,一次可邀请多个成员 + * param groupId 群组 ID,输入参数,String + * param members 邀请的成员,输入参数,StringArray,["ID1","ID2"] + * param welcomeMessage 欢迎信息,输入参数,String + * 返回 Promise 对象,response 参数为 GroupResult + */ +addGroupMembers(groupId, members, welcomeMessage); +``` + +调用方法如下: + +``` +groupManager.addGroupMembers(groupId, ["jwfan3", "jwfan4"], "hahaha").then((res)=>{},(error) => {}) +``` + +------ + +### 群成员移除 + +接口 API 如下: + +``` +/** + * 将成员踢出群,同样可踢出多人 + * param groupId 群组ID,输入参数,String + * param members 踢出的成员,输入参数,StringArray,["ID1","ID2"] + * 返回 Promise 对象,response 参数为 Result + */ +removeGroupMembers(groupId, members, error); +``` + +调用方法如下: + +``` +groupManager.removeGroupMembers(groupId, ["jwfan3", "jwfan4"]).then((res)=>{},(error) => {}) +``` + +------ + +### 添加管理员 + +接口 API 如下: + +``` +/** + * 将普通群成员提升为管理员 + * param groupId 群组 ID,输入参数,String + * param member 成员用户名,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +addGroupAdmin(groupId, member) +``` + +调用方法如下: + +``` +groupManager.addGroupAdmin(groupId, member).then((res) =>{},(error) => {}); +``` + +------ + +### 删除管理员 + +接口 API 如下: + +``` +/** + * 将管理员降级为普通成员 + * param groupId 群组ID,输入参数,String + * param member 管理员用户名,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +removeGroupAdmin(groupId, member) +``` + +调用方法如下: + +``` +groupManager.removeGroupAdmin(groupId, member).then((res) =>{},(error) => {}); +``` + +------ + +### 获取禁言列表 + +接口API如下: + +``` +/** + * 获取禁言列表 + * param groupId 群组 ID,输入参数,String + * param pageNum 第几页,输入参数,Number,1为起始页 + * param pageSize 每页计数,输入参数,Number,最大200 + * return 返回 Promise 对象,response 参数为 GroupResult + */ +fetchGroupMutes(groupId, pageNum, pageSize) +``` + +------ + +### 群组禁言 + +接口API如下: + +``` +/** + * 将成员加入禁言列表,被禁言的成员无法在群组内发消息 + * param {String} groupId 群组ID,输入参数,String + * param {Array} members 成员列表,输入参数,String 数组 + * param {Number} muteDuration 禁言时间,单位毫秒 + * return 返回 Promise 对象,response 参数为 GroupResult + */ +muteGroupMembers(groupId,members,muteDuration) +``` + +------ + +### 取消禁言 + +接口API如下: + +``` +/** + * 将成员从禁言列表移除 + * param {String} groupId 群组ID,输入参数,String + * param {Array} members 成员列表,输入参数,String 数组 + * return 返回 Promise 对象,response 参数为 GroupResult + */ +unmuteGroupMembers(groupId,members) +``` + +------ + +### 获取群组黑名单列表 + +接口 API 如下: + +``` +/** + * 分页获取群组黑名单列表 + * param groupId 群组 ID,输入参数,String + * param pageNum 第几页,输入参数,Number,1为起始页 + * param pageSize 每页计数,输入参数,Number,最大200 + * return 返回 Promise 对象,response 参数为 GroupListResult + */ +fetchGroupBans(groupId,pageNum, pageSize) +``` + +调用方法如下: + +``` +groupManager.fetchGroupBans(groupId, 1, 20).then((res) =>{},(error) => {}); +``` + +------ + +### 加入群组黑名单 + +接口 API 如下: + +``` +/** + * 将成员加入群组黑名单,黑名单中的人员无法加入群组 + * param groupId 群组ID,输入参数,String + * param members 成员列表,输入参数,String 数组 + * param reason 加入黑名单原因,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +blockGroupMembers(groupId,members,reason) +``` + +调用方法如下: + +``` +groupManager.blockGroupMembers(groupId, members, "reason").then((res) =>{},(error) => {}); +``` + +------ + +### 从群组黑名单移除 + +接口 API 如下: + +``` +/** + * 将人员从群组黑名单移除 + * param groupId 群组 ID,输入参数,String + * param members 成员列表,输入参数,StringArray + * return 返回 Promise 对象,response 参数为 GroupResult + */ +unblockGroupMembers(groupId, members) +``` + +调用方法如下: + +``` +groupManager.unblockGroupMembers(groupId, members).then((res) =>{},(error) => {}); +``` + +------ + +## 加群处理 + +加群处理包含以下处理操作: + +- 加入公开群组 + +- 申请加入公开群组 + +- 接受群邀请 + +- 拒绝群邀请 + +- 接受入群申请 + +- 拒绝入群申请 + +所有处理操作的示例下面会一一说明。 + +------ + +### 加入公开群组 + +接口 API 如下: + +``` +/** + * 加入 PUBLIC_JOIN_OPEN 类型公开群组 + * param groupId 群组 ID,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +joinPublicGroup(groupId,error) +``` + +调用方法如下: + +``` +groupManager.joinPublicGroup(groupId,error).then((res) =>{},(error) => {}); +``` + +------ + +### 申请加入公开群组 + +接口 API 如下: + +``` +/** + * 申请加入 applyJoinPublicGroup 类型公开群组,需要群主或管理员同意 + * param groupId 群组 ID,输入参数,String + * param nickname 用户在群内的昵称,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +applyJoinPublicGroup(groupId,nickname,message) +``` + +调用方法如下: + +``` +groupManager.applyJoinPublicGroup(groupId,nickname,message).then((res) =>{},(error) => {}); +``` + +------ + +### 接受群邀请 + +接口 API 如下: + +``` +/** + * 接受群组发来的入群邀请 + * param groupId 群组ID,输入参数,String + * param inviter 邀请人,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +acceptInvitationFromGroup(groupId,inviter) +``` + +调用方法如下: + +``` +groupManager.acceptInvitationFromGroup(groupId,inviter).then((res) =>{},(error) => {}); +``` + +### 拒绝群邀请 + +接口 API 如下: + +``` +/** + * 拒绝群组发来的入群邀请 + * param groupId 群组 ID,输入参数,String + * param inviter 邀请人,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +declineInvitationFromGroup(groupId,inviter) +``` + +调用方法如下: + +``` +groupManager.declineInvitationFromGroup(groupId,inviter).then((res) =>{},(error) => {}); +``` + +------ + +### 接受加入群申请 + +接口 API 如下: + +``` +/** + * 同意成员的入群邀请,由群主操作 + * param groupId 群组ID,输入参数,String + * param from 入群申请人,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +acceptJoinGroupApplication(groupId,from) +``` + +调用方法如下: + +``` +groupManager.acceptJoinGroupApplication(groupId,from).then((res) =>{},(error) => {}); +``` + +------ + +### 拒绝加入群申请 + +接口 API 如下: + +``` +/** + * 拒绝成员的入群邀请,由群主操作 + * param groupId 群组 ID,输入参数,String + * param from 入群申请人,输入参数,String + * param reason 拒绝原因,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +declineJoinGroupApplication(groupId,from,reason) +``` + +调用方法如下: + +``` +groupManager.declineJoinGroupApplication(groupId,from,"decline reason").then((res) =>{},(error) => {}); +``` + +------ + +## 群消息 + +群消息包含以下处理操作: + +- 屏蔽群组消息 + +- 取消屏蔽群组消息 + +所有处理操作的示例下面会一一说明。 + +------ + +### 屏蔽群组消息 + +接口 API 如下: + +``` +/** + * 屏蔽群组消息 + * param groupId 群组ID,输入参数,String + * return 返回 Promise 对象,response 参数为 GroupResult + */ +blockGroupMessage(groupId) +``` + +调用方法如下: + +``` +groupManager.blockGroupMessage(groupId).then((res) =>{},(error) => {}); +``` + +------ + +### 取消屏蔽群组消息 + +接口 API 如下: + +``` +/** + * 取消屏蔽群组消息 + * param groupId 群组 ID,输入参数,String + * return 返回 Promise 对象,response 参数为GroupResult + */ +unblockGroupMessage(groupId) +``` + +调用方法如下: + +``` +groupManager.unblockGroupMessage(groupId).then((res) =>{},(error) => {}); +``` + +------ + +## 群文件 + +群文件包含以下处理操作: + +- 获取群文件列表 + +- 上传群文件 + +- 下载群文件 + +- 删除群文件 + +所有处理操作的示例下面会一一说明。 + +------ + +### 获取群文件列表 + +接口 API 如下: + +``` +/** + * 分页获取群文件列表 + * param groupId 群组ID,输入参数,String + * param pageNum 当前页数,从1开始 + * param pageSize 每页计数,最大200 + * return 返回 Promise 对象,response 参数为 SharedFileListResult + */ +fetchGroupSharedFiles(groupId, pageNum, pageSize) +``` + +调用方法如下: + +``` +groupManager.fetchGroupSharedFiles(groupId, 1, 20).then((res) => {},(error) => {}); +``` + +------ + +### 上传群文件 + +上传群文件过程中,需要使用回调监控上传进度及结果 + +``` +// 设置回调函数显示上传进度和结果 +var emUploadCallback = new easemob.EMCallback(); +console.log("create upload emCallback success"); + +// 上传成功 +emUploadCallback.onSuccess(() => { + console.log("upload emCallback call back success"); + return true; +}); +// 上传失败 +emUploadCallback.onFail((error) => { + console.log("upload emCallback call back fail"); + console.log(error.description); + console.log(error.errorCode); + return true; +}); +// 上传进度 +emUploadCallback.onProgress((progress) => { + if (progress >= 98) { + console.log("upload call back progress " + progress); + } +}); +``` + +接口 API 如下: + +``` +/** + * 上传群文件 + * param groupId 群组 ID,输入参数,String + * param filepath 文件路径,输入参数,String + * param emUploadCallback 设置回调,输入 + * 返回 Promise 对象,response 参数为 SharedFileResult + */ +uploadGroupSharedFile(groupId, filepath, emUploadCallback) +``` + +调用方法如下: + +``` +groupManager.uploadGroupSharedFile(groupId, filepath, emUploadCallback).then((res) => {},(error) => {}); +``` + +------ + +### 下载群文件 + +下载群文件过程中需要使用回调监控下载进度及结果 + +``` +var emDownloadCallback = new easemob.EMCallback(); +console.log("create download emCallback success"); + +// 下载成功 +emDownloadCallback.onSuccess(() => { + console.log("download emCallback call back success"); + return true; +}); +// 下载失败 +emDownloadCallback.onFail((error) => { + console.log("download emCallback call back fail"); + console.log(error.description); + console.log(error.errorCode); + return true; +}); +// 下载进度 +emDownloadCallback.onProgress((progress) => { + if (progress >= 98) { + console.log("download call back progress " + progress); + } +}); +``` + +接口 API 如下: + +``` +/** + * 下载群文件 + * param groupId 群组 ID,输入参数,String + * param filePath 文件本地存储路径,输入参数,String + * param fileId 文件 ID,输入参数,由文件列表数组获取 + * param callback 设置回调,输入 + * return 返回 Promise 对象,response 参数为 GroupResult + */ +downloadGroupSharedFile(groupId, filePath, fileId, callback) +``` + +调用方法如下: + +``` +let fileId = sharedFile.fileId(); +groupManager.downloadGroupSharedFile(groupid, filelocalpath, fileId, emDownloadCallback); +``` + +------ + +### 删除群文件 + +接口 API 如下: + +``` +/** + * 删除群文件 + * param groupId 群组 ID,输入参数,String + * param fileId 文件 ID,输入参数,由文件列表获取 + * return 返回 Promise 对象,response 参数为 GroupResult + */ +deleteGroupSharedFile(groupId, fileId) +``` + +调用方法如下: + +``` +let fileId = sharedFile.fileId(); +groupManager.deleteGroupSharedFile(groupId, fileId).then((res) =>{},(error) => {}); +``` + +------ + +## 群组变更的监听 + +``` +groupManager = emclient.getGroupManager(); +groupListener = new easemob.EMGroupManagerListener(groupManager); +// 添加群管理员时触发(只有是自己时才能收到通知) +// group : 发生操作的群组 +// admin : 被提升的群管理员 +groupListener.onAddAdminFromGroup((groupId, admin) => { + console.log("onAddAdminFromGroup:"+groupId+" admin:"+admin); +}); + +// 删除群管理员时触发(只有是自己时才能收到通知) +// group : 发生操作的群组 +// admin : 被删除的群管理员(群管理员变成普通群成员) +groupListener.onRemoveAdminFromGroup((groupId, admin) => { + console.log("onRemoveAdminFromGroup:"+groupId+" admin:"+admin); +}); + +// 转让群主的时候触发 +// group : 发生操作的群组 +// newOwner : 新群主 +// oldOwner : 原群主 +groupListener.onAssignOwnerFromGroup((groupId, newOwner, oldOwner) => { + console.log("onAssignOwnerFromGroup:"+groupId+" newOwner:"+newOwner + " oldOwner:" + oldOwner); +}); + +// 我接收到自动进群时被触发 +// group : 发生操作的群组 +// inviter : 邀请人 +// inviteMessage : 邀请信息 +groupListener.onAutoAcceptInvitationFromGroup((groupId, inviter, inviteMessage)=>{ + console.log("onAutoAcceptInvitationFromGroup:"+groupId+" inviter:"+inviter + " inviteMessage:" + inviteMessage); + }); + +// 成员加入群组时触发 +// group : 发生操作的群组 +// member : 加入群组的成员名称 +groupListener.onMemberJoinedGroup((groupId, member)=>{ + console.log("onMemberJoinedGroup:"+groupId+" member:"+member); +}); + +// 成员离开群组时触发 +// group : 发生操作的群组 +// member : 离开群组的成员名称 +groupListener.onMemberLeftGroup((groupId, member)=>{ + console.log("onMemberLeftGroup:"+groupId+" member:"+member); +}); + +// 离开群组时触发 +// group : 发生操作的群组 +// reason : 离开群组的原因(0: 被踢出 1:群组解散 2:被服务器下线) +groupListener.onLeaveGroup((groupId, reason)=>{ + console.log("onLeaveGroup:"+groupId+" reason:"+reason); +}); +groupManager.addListener(groupListener); +// 移除监听 +groupManager.removeListener(groupListener); +``` \ No newline at end of file diff --git a/docs/document/electron/message.md b/docs/document/electron/message.md new file mode 100644 index 000000000..fc540a967 --- /dev/null +++ b/docs/document/electron/message.md @@ -0,0 +1,257 @@ +# 消息 + +消息是桌面端集成中最重要的功能之一,消息的使用方法主要为 : + +- 发送消息 + +- 接受消息 + +同时对于发送不超过2分钟的消息,允许主动撤回。 + +通过对消息的集成,您可以最快速的集成体验 IM 收发消息的流畅体验。 + +------ + +## 发送消息 + +发送消息类型主要有以下几种: + +- 文本消息 + +- 文件消息 + +- 图片消息 + +- CMD 消息 +- 自定义 消息 + +- 位置消息 + +通过这些操作,可以组合帮助您完成多种场景下的 IM 需求。 + +发送文本、文件、图片等消息(单聊/群聊通用)。完整的消息发送过程,包括创建消息体,创建消息,设置属性,设置回调,然后发送消息,不同的消息类型只是在创建消息体过程不同,其他步骤一样。 + +------ + +### 发送文本消息 + +``` +/** + * 创建文本消息体 + * param1 文本消息正文,输入参数,String + * return 消息体 EMTextMessageBody + */ +var textMsgBody = new easemob.EMTextMessageBody("wahhahahaha"); +/** + * 创建消息 + * param1 发送者用户名,输入参数 + * param2 目的端,会话 ID,输入参数 + * param3 消息体 EMTextMessageBody + * return 消息 EMMessage + */ +var textSendMsg = easemob.createSendMessage("jwfan", "jwfan1", textMsgBody); +// 消息可以设置扩展属性,用户界面可通过自定义属性,实现自定义等功能 +textSendMsg.setAttribute("data", 120); +data = textSendMsg.getAttribute("data"); +// 设置消息类型,0为单聊,1为群聊,2为聊天室 +textSendMsg.setChatType(0); +// 设置回调 +var emCallback = new easemob.EMCallback(); +emCallback.onSuccess(() => { + console.log("emCallback call back success"); + if(me.cfr){ + console.log(sendMessage); + console.log(sendMessage.msgId()); + return true; + }); + emCallback.onFail((error) => { + console.log("emCallback call back fail"); + console.log(error.description); + console.log(error.errorCode); + return true; + }); + emCallback.onProgress((progress) => { + console.log(progress); + console.log("call back progress"); + }); +sendMessage.setCallback(emCallback); +// 发送消息 +chatManager.sendMessage(textMsg); +``` + +------ + +### 发送文件 + +``` +/** + * 创建文件消息体 + * param1 文件路径,输入参数,String + * return 消息体 EMFileMessageBody + */ +var fileMsgBody = new easemob.EMFileMessageBody("/Users/jiangwei/Code/fanjiangwei7/emclient-linux/testapp/file.txt"); +// 创建消息 +var fileMsg = easemob.createSendMessage("jwfan", "jwfan1", fileMsgBody); +//setCallback(callback) 设置消息回调函数,通过回调函数显示消息发送成功失败,以及附件上传百分比 +//callback easemob.EMCallback的实例,设置onSuccess、onFail和onProgress三个回调函数。 +fileMsg.setCallback(emCallback); +chatManager.sendMessage(fileMsg); +``` + +------ + +### 发送图片 + +``` +/** + * 创建图片消息体 + * param1 图片文件路径,输入参数,String + * param2 图片缩略图路径,输入参数 + * return 消息体EMFileMessageBody + */ +var imageMsgBody = new easemob.EMImageMessageBody('/Users/jiangwei/Code/fanjiangwei7/emclient-linux/testapp/image_960x718.jpg', '/Users/jiangwei/Code/fanjiangwei7/emclient-linux/testapp/thumb_image.jpg'); +var imageMsg = easemob.createSendMessage("jwfan", "jwfan1", imageMsgBody); +imageMsg.setCallback(emCallback); +chatManager.sendMessage(imageMsg); +``` + +------ + +### 发送 CMD 消息 + +``` +var cmdMsgBody = new easemob.EMCmdMessageBody("action"); +console.log("cmdMsgBody.type() = " + cmdMsgBody.type()); + +console.log("cmdMsgBody.action() = " + cmdMsgBody.action()); +cmdMsgBody.setAction("displayName"); +console.log("cmdMsgBody.action() = " + cmdMsgBody.action()); + +var obj1 = {"key" : "1", "value" : "1"}; +var obj2 = {"key" : "2", "value" : "2"}; +console.log("cmdMsgBody.params() = " + cmdMsgBody.params()); +cmdMsgBody.setParams([obj1, obj2]); +var cmdMsg = easemob.createSendMessage("jwfan", "jwfan1", cmdMsgBody); +chatManager.sendMessage(cmdMsg); +``` + +------ + +### 发送 自定义 消息 + +自定义消息包括消息event和消息扩展exts,构造及发送过程如下 + +``` +let customMsgBody = new easemob.EMCustomMessageBody("userCard"); +customMsgBody.setExts({'avatar':'https://download-sdk.oss-cn-beijing.aliyuncs.com/downloads/IMDemo/avatar/Image5.png','nickname':'xiaoming','uid':'uid'}); +let customMsg = easemob.createSendMessage('lxm9','lxm',customMsgBody); +chatManager.sendMessage(customMsg); +``` + +------ + +### 位置消息 + +``` +/** + * 创建位置消息体 + * param1 位置经度,输入参数,String + * param2 位置纬度,输入参数 + * param3 地址,输入参数 + * return 消息体EMFileMessageBody + */ +var locationMsgBody = new easemob.EMLocationMessageBody(123.45, 35.67, 'USA'); +console.log("locationMsgBody.type() = " + locationMsgBody.type()); +console.log("locationMsgBody.latitude() = " + locationMsgBody.latitude()); +console.log("locationMsgBody.longitude() = " + locationMsgBody.longitude()); +console.log("locationMsgBody.address() = " + locationMsgBody.address()); +locationMsgBody.setLatitude(87.87); +locationMsgBody.setLongitude(45.45); +locationMsgBody.setAddress('china'); +var locationMsg = easemob.createSendMessage("jwfan", "jwfan1", locationMsgBody); +chatManager.sendMessage(locationMsg); +``` + +------ + +## 撤回消息 + +默认发送两分钟内的消息可以撤回,撤回使用recallMessage接口 + +``` +/** + * 撤回消息 + * param msg {EMMessage} 要撤回的消息 + */ +chatManager.recallMessage(msg); +``` + +------ + +## 接收消息 + +接收消息在会话管理中通过设置回调函数实现,在回调函数中处理 + +``` +// 实例化监听回调,并添加到client +chatManager = emclient.getChatManager(); +listener = new easemob.EMChatManagerListener(); +chatManager.addListener(listener); + +// 收到会话消息 +listener.onReceiveMessages((messages) => { + console.log("onReceiveMessages messages.length = " + messages.length); + for (var index = 0, len = messages.length; index < len; index++) { + var msg = messages[index]; + var bodies = msg.bodies(); + console.log("bodies.length = " + bodies.length); + var body = bodies[0]; + var type = body.type(); + console.log("msg.from() = " + msg.from()); + console.log("msg.to() = " + msg.to()); + console.log("body.type() = " + type); + if (type == 0) { //text message + console.log("body.text() = " + body.text()); + } else if (type == 1) { //image message + console.log("body.displayName() = " + body.displayName()); + console.log("body.localPath() = " + body.localPath()); + chatManager.downloadMessageAttachments(msg); + chatManager.downloadMessageThumbnail(msg); + } else if (type == 5) { //file message + console.log("body.displayName() = " + body.displayName()); + console.log("body.localPath() = " + body.localPath()); + chatManager.downloadMessageAttachments(msg); + } +}); +// 收到命令消息 +listener.onReceiveCmdMessages ((messages) => { + for (var index = 0, len = messages.length; index < len; index++) { + var msg = messages[index]; + var bodies = msg.bodies(); + console.log("bodies.length = " + bodies.length); + var body = bodies[0]; + var type = body.type(); + console.log("msg.from() = " + msg.from()); + console.log("msg.to() = " + msg.to()); + console.log("msg.type() = " + type); + console.log("body.action() = " + body.action()); + var params = cmdMsgBody.params() + console.log("cmdMsgBody.params().length = " + params.length); + if (params.length > 0) { + console.log("cmdMsgBody.params()[0] = " + JSON.stringify(params[0])); + } +} +}); + +// 收到消息撤回 +listener.onReceiveRecallMessages ((message) => { + console.log("onReceiveRecallMessages messages.length = " + messages.length); + for (var index = 0, len = messages.length; index < len; index++) { + var message = messages[index]; + console.log("message.msgId() = " + message.msgId()); + console.log("message.from() = " + message.from()); + console.log("message.to() = " + message.to()); +} +}); +// addListener(listener) 添加消息回调监听,从监听中获取接收消息。 +``` \ No newline at end of file diff --git a/docs/document/electron/multi_device.md b/docs/document/electron/multi_device.md new file mode 100644 index 000000000..cdcb7950a --- /dev/null +++ b/docs/document/electron/multi_device.md @@ -0,0 +1,24 @@ +# 多设备管理监听 + +当同一账号同时使用桌面端,移动端登录时,需要使用多设备管理监听事件,使用回调实现 + +``` +// 实例化监听,并添加到客户端 +var listener = new easemob.EMMultiDevicesListener(); +emclient.addMultiDevicesListener(listener); + +// 设置回调 +// 收到其他设备的会话操作 +listener.onContactMultiDevicesEvent((operation, target, ext) => { + console.log('operation = ' + operation); + console.log('target = ' + target); + console.log('ext = ' + ext); +}); +// 收到其他设备的组操作 +listener.onGroupMultiDevicesEvent((operation, target, usernames) => { + console.log('operation = ' + operation); + console.log('target = ' + target); + console.log('usernames = ' + usernames); +}); +``` + diff --git a/docs/document/electron/overview.md b/docs/document/electron/overview.md new file mode 100644 index 000000000..ad53f1b77 --- /dev/null +++ b/docs/document/electron/overview.md @@ -0,0 +1,152 @@ +# 桌面端集成说明 + +桌面端 SDK 为用户在 Windows/Mac OS 平台上进行开发的 js 接口及二进制文件,开发框架使用 electron 。 + +目前支持登录、注册、单聊、群聊、聊天室、文本消息、图片、语音、位置等消息以及透传消息,还可以实现好友管理、群组管理等功能。 + +**注意:** 之前的 Windows SDK 将不再维护,同时对应的 demo ,文档也一并下线。如需查看旧版文档,点击[Windows SDK 集成说明](https://docs-im.easemob.com/im/windows/intro/integration) + +------ + +## 准备 + +### 开发环境需求 + +#### 操作系统 + +- win7/win8/win10 64位操作系统 + +- mac OS 10.10 及以上 + +#### 开发工具 + +- nodejs + +版本 10.0 以上,[官网地址](http://nodejs.cn/) + +- electron + +版本 4.0 以上,[官网地址](https://electronjs.org/),nodejs 安装完成后,可以在命令行使用 npm 命令安装,安装命令: + +``` +npm install electron -g +``` + +------ + +## SDK 目录结构 + +Windows SDK 目录结构如下。使用时将 SDK 拷贝到工程目录下。 + +``` +|-node + |-modules + |-message + index.js + load.js +|-easemob + easemobMac.node + easemobWin.node + libcurl.dll + libcurl.lib + libcrypto.1.0.0.dylib +``` + +------ + +## SDK 模块介绍 + +SDK 采用模块化设计,每一模块的功能相对独立和完善,用户可以根据自己的需求选择使用下面的模块: + +![img](@static/images/electron/sdk_design.png) + +### 模块化设计 + +- EMClient + +SDK 的入口,主要完成登录、退出、注册、配置管理等功能,管理连接监听模块 EMConnectionListener 。也是获取其他模块的入口。 + +- EMChatManager + +管理消息的收发,完成会话管理等功能,管理会话监听模块 EMChatManagerListener 。 + +- EMContactManager + +负责好友的添加删除,黑名单的管理等功能,管理好友变更监听模块 EMContactListener。 + +- EMGroupManager + +负责群组的管理,创建、删除群组,管理群组成员等功能,管理群组监听模块 EMGroupManagerListener。 + +- EMChatroomManager + +负责聊天室的查询、加入、退出功能管理,管理聊天室监听模块 EMChatroomManagerListener。 + +------ + +## SDK 对象说明 + +SDK 中使用到的对象包括: + +- 系统配置信息 EMChatConfigs + +- 群组信息 EMGroup + +- 群组配置信息 EMMucSetting + +- 群文件信息 EMMucSharedFile + +- 聊天室信息 EMChatroom + +- 会话信息 EMConversation + +- 消息 EMMessage + +- 文本消息体 EMFileMessageBody + +- 图片消息体 EMImageMessageBody + +- 文件消息体 EMTextMessageBody + +- 命令消息体 EMCmdMessageBody + +具体接口详见 [API 参考](https://downloads.easemob.com/doc/desktop/apidoc/index.html)。 + +### 依赖模块安装 + +electron 开发中依赖的模块及版本写在 package.json 中,安装依赖模块时,在 sdkdemoapp_windows 目录下使用命令: + +``` +npm install +``` + +如果安装过程中出现 error,可能是网络原因,可以选择使用 yarn 镜像下载安装: + +``` +npm install -g yarn +yarn install +``` + +------ + +### 软件调试 + +首先需要编译软件,运行命令: + +``` +npm run build:app +``` + +调试过程需要使用热启动,运行命令: + +``` +npm run hot-server +``` + +然后另启动一个命令行工具,运行命令: + +``` +npm run start:hot +``` + +可启动软件。调试过程中修改代码后,hot-server 会自动编译新代码,在界面上使用 F5 按键可以立即刷新界面,应用新代码。在界面上点击鼠标右键,弹出右键菜单,点击检查元素,可以打开开发者工具,查看 console 控制台输出,在 Source 中加断点调试。 \ No newline at end of file diff --git a/docs/document/electron/releasenote.md b/docs/document/electron/releasenote.md new file mode 100644 index 000000000..02fb773d0 --- /dev/null +++ b/docs/document/electron/releasenote.md @@ -0,0 +1,61 @@ +# 桌面端SDK 更新日志 + +## 版本 V3.8.4 2021-12-09 + +仅 V3.8.4 及以下版本支持私有化部署。 + +新增 + +- 增加支持自定义消息的收发 + +## 版本 V3.8.0 2021-03-13 + +修复 + +- 去掉音视频功能 +- 修复部分Demo bug + +## 版本 V3.6.0 2019-07-16 + +新增 + +- 1v1音视频会话功能 + +修复 + +- 修复了上传附件token过期时,重新获取的token在重试过程中未应用的bug +- 修复了音视频消息体中remotePath路径为空的问题 +- 修复Demo UI层的bug + +## 版本 V3.5.5 2019-05-09 + +新增 + +- sdk 新增私有化部署的接口 + +修复 + +- 修复 Demo 在 mac 系统某些版本(如10.12)上,存在兼容性问题,无法启动的问题 +- 修改 sdk 收到消息后 ack 确认的发送为消息存储到数据库之后,防止突然崩溃导致的消息丢失 +- 修复 Demo UI 层的部分 bug + +优化 + +- 离线消息的下载存储由单条存储改为多条批量存储,提升效率 + +## 版本:V3.5.4 2019-03-26 + +实现功能: + +- 账户的登录、登出、注册。 + +- 聊天:单聊、群聊消息收发。 + +- 消息类型: + +1. 可发送:文本、emoji表情、图片、文件。 +2. 可接收:文本、emoji表情、图片、文件、位置、语音消息。 + +- 好友管理:添加好友、删除好友。 + +- 群管理:创建群、退出群、解散群、修改群标题、邀请加入群、搜索公开群、申请加入公开群。 \ No newline at end of file diff --git a/docs/document/electron/sdk_api.md b/docs/document/electron/sdk_api.md new file mode 100644 index 000000000..70f5caeac --- /dev/null +++ b/docs/document/electron/sdk_api.md @@ -0,0 +1,4 @@ +# 桌面端 SDK API + +若要查看桌面端 SDK API 文档,请点击[这里](https://downloads.easemob.com/doc/desktop/apidoc/index.html)。 + diff --git a/docs/document/electron/sdk_basic_function.md b/docs/document/electron/sdk_basic_function.md new file mode 100644 index 000000000..1efdc17fc --- /dev/null +++ b/docs/document/electron/sdk_basic_function.md @@ -0,0 +1,228 @@ +# SDK基础功能 + +## 加载SDK + +直接加载 index.js 模块,代码如下: + +``` +var easemob = require('../../node/index'); +``` + +------ + +## 用户登录 + +登录前,需要先创建配置对象和 client 对象,用户可以使用 **用户名+密码** 和 **用户名+token** 两种方式登录。 + +### 创建配置对象 + +``` +/** + * 首先构造 sdk 配置信息 + * param1 为资源存储路径,输入参数 + * param2 为工作路径,输入参数,日志存储在这里 + * param3 为 appkey ,输入参数,easemob-demo#chatdemoui 为 DemoAppKey ,需填写自己的 Appkey + * param4 为设备 ID ,默认 0 + * return 配置模块对象 + */ +var emchatconfigs = new easemob.EMChatConfig(".", ".", "easemob-demo#chatdemoui", 0); +``` + +### 创建 client 对象 + +``` +var emclient = new easemob.EMClient(emchatconfigs); +``` + +#### 用户名+密码登录方式代码如下: + +``` +/** + * 密码登录 api ,异步操作 + * param username 为用户名,输入, String + * param password 为密码,输入, String + * return 返回 Promise 对象,response 参数为 #Result + */ +login(username, password) +``` + +调用用方法如下: + +``` +emclient.login("jwfan", "jwfan").then((res) =>{ +if(res.code == 0) + console.log("login success"); +},(error) => {}); +``` + +#### 用户名+token 登录方式代码如下: + +``` +/** + * token 登录 api ,异步操作 + * param username 用户名,输入, String + * param token 用户 token ,输入, String + * return 返回 Promise 对象,response 参数为 #Result + */ +loginWithToken(username, token) +``` + +调用方法如下: + +``` +emclient.loginWithToken("jwfan", "Mytoken").then((res) =>{ +if(res.code == 0) + console.log("login success"); +},(error) => {}); +``` + +登录接口返回值 ret 为 EMError 对象,登录成功则 ret 的 errorCode 为 0,否则可以用 description 获取错误信息 登录后获取用户信息方法如下: + +``` +// 获取用户信息,包括用户名,密码,token +var loginInfo = emclient.getLoginInfo(); +console.log("loginInfo.loginUser = " + loginInfo.loginUser); +console.log("loginInfo.loginPassword = " + loginInfo.loginPassword); +console.log("loginInfo.loginToken = " + loginInfo.loginToken); +``` + +------ + +## 用户退出 + +用户退出代码如下: + +``` +// 返回退出结果 EMError 对象 +emclient.logout().then((res) => { +if(res.code == 0) + console.log("logout success"); +},(error) => {}); +``` + +------ + +## 用户注册 + +接口API如下: + +``` +/** + * 账户注册api,异步操作 + * param username 用户名,输入,String + * param password 密码,输入,String + * return Promise对象,该对象的response参数为Result + */ +createAccount(username, password); + + +调用方法如下: + +emclient.createAccount("newAccount","password").then((res) => { + if(res.errorCode == 0) + console.log("createAccount success"); + else + console.log("createAccount fail:" + res.description); + },(error) => {}) +``` + +------ + +## 连接监听管理 + +通过注册回调函数,可以监听 SDK 的连接与断开状态,在用户登录成功后调用,代码如下 + +``` +// 实例化监听模块 +var listener = new easemob.EMConnectionListener(); +// 添加到client +emclient.addConnectionListener(listener); + +// 连接成功,什么都不需要做 +listener.onConnect(() => { +console.log("EMConnectionListener onConnect"); +}); + +// 连接断开,可能是断网或异地登录被踢,可通过error.errorCode判断,若为206,即为被踢,需要退出登录 +listener.onDisconnect((res) => { +console.log(res.errorCode); +console.log(res.description); +console.log("EMConnectionListener onDisconnect"); +if(res.errorCode == 206) + emclient.logout(); + console.log("你的账户已在其他地方登录"); +}); + +// 移除监听 +emclient.removeConnectionListener(listener); +``` + +------ + +## 系统配置 + +系统配置信息模块为 EMChatConfig ,可以使用 emclient 的 getChatConfigs() 接口获取 + +``` +let config = emclient.getChatConfigs(); +``` + +配置信息包括日志路径,资源路径、下载路径、是否自动同意好友申请、是否自动同意组邀请、退出群组时是否删除消息等,[详见](https://github.com/easemob/sdkdemoapp_windows/blob/electron/jsdoc/out/EmChatConfigs.html) + +------ + +## 私有化部署 + +sdk 提供私有化部署中的服务器设置接口,私有化部署设置使用 api 中的 **EMChatPrivateConfigs**,可以由系统配置模块的 **privateConfigs** 接口获取,代码如下: + +``` +let privateconfigs = config.privateConfigs(); +``` + +**EMChatPrivateConfigs** 使用属性配置服务器部署信息,设置及获取的方法如下: + +``` +privateconfigs.enableDns=false; +privateconfigs.chatServer="192.168.1.100"; +privateconfigs.chatPort=5000; +privateconfigs.restServer="http://192.168.1.101:5001"; +privateconfigs.resolverServer="http://192.168.1.101:5002"; +console.log(privateconfigs.enableDns); +console.log(privateconfigs.chatServer); +console.log(privateconfigs.chatPort); +console.log(privateconfigs.restServer); +console.log(privateconfigs.resolverServer); +``` + +------ + +## 日志输出 + +SDK 提供输出到日志文件的 js 接口,需要先创建 EMLog 对象,可以输出 String 和数字,代码如下: + +``` +// 实例化日志对象,日志按等级可分为error,warn,Debug 3级 +var log = new easemob.EMLog(); + +// 设置日志等级,0为debug,1为warn,2为error +log.setLogLevel(0); + +// 可以控制日志是否输出到控制台,默认不输出 +log.setIsDisplayOnConsole(true); + +//输出日志 +log.Log("Log Test"); +log.Log(5); +log.Debug("Debug Test"); +log.Debug(5); +log.Warn("Warn Test"); +log.Warn(5); +log.Error("Error Test"); +log.Error(5); +``` + +**注:** 由于 EMChatConfig 对象创建时会指定日志输出路径,日志对象的创建一般放到 EMChatConfig 创建之后。 + +Windows 桌面端日志生成在 c:/用户/{user}/AppData/Roaming/{ProcessName}/easemob-desktop/easemobLog 路径下的`easemob.log`,{user}为操作系统用户名,{ProcessName}为进程名称,热启动时为**electron**,安装后启动时为**IM-SDK桌面端Demo**。 + +Mac 桌面端日志生成在 /Users/{user}/Library/Application Support/{ProcessName}/easemob-desktop/easemobLog 路径下的`easemolog.log`,{user}为操作系统用户名,{ProcessName}为进程名称,热启动时为**electron**,安装后启动时为**IM-SDK桌面端Demo**。 \ No newline at end of file diff --git a/docs/document/flutter/conversation_delete.md b/docs/document/flutter/conversation_delete.md new file mode 100644 index 000000000..1cd4539b9 --- /dev/null +++ b/docs/document/flutter/conversation_delete.md @@ -0,0 +1,61 @@ +# 删除会话 + + + +删除好友或退出群组后,SDK 不会自动删除对应的单聊或群聊会话。你可以调用相应的接口从服务器和本地删除单个会话及其历史消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地删除单个会话及其历史消息,主要方法如下: + +- `EMChatManager#deleteRemoteConversation`:单向删除服务端会话及其历史消息。 +- `EMChatManager#deleteConversation`:删除本地单个会话及其历史消息。 + +## 实现方法 + +### 单向删除服务端会话及其历史消息 + +你可以调用 `deleteRemoteConversation` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 + +```dart +// 会话 ID。 +String conversationId = "conversationId"; +// 删除会话时是否同时删除服务端的历史消息。 +bool deleteMessage = true; +EMConversationType conversationType = EMConversationType.Chat; +await EMClient.getInstance.chatManager.deleteRemoteConversation( + conversationId, + conversationType: conversationType, + isDeleteMessage: deleteMessage, +); +``` + +### 删除本地会话及其历史消息 + +- 删除会话时是否同时删除本地的历史消息。 + +```dart +// 会话 ID。 +String conversationId = "conversationId"; +// 删除会话时是否同时删除本地的历史消息 +bool deleteMessage = true; +await EMClient.getInstance.chatManager + .deleteConversation(conversationId, deleteMessage); +``` + +- 删除本地指定会话中的指定消息。 + +```dart +EMConversation? conversation = + await EMClient.getInstance.chatManager.getConversation( + conversationId, +); +conversation?.deleteMessage(messageId); +``` diff --git a/docs/document/flutter/conversation_list.md b/docs/document/flutter/conversation_list.md new file mode 100644 index 000000000..6b2e1031f --- /dev/null +++ b/docs/document/flutter/conversation_list.md @@ -0,0 +1,68 @@ +# 会话列表 + + + +对于单聊、群组聊天和聊天室会话,用户发消息时 SDK 会自动创建会话并将会话添加至用户的会话列表。 + +环信服务器和本地均存储会话,你可以获取会话列表。**服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地获取会话列表,主要方法如下: + +- `EMChatManager#fetchConversation`:从服务器获取会话列表。 +- `EMChatManager#loadAllConversations`:获取本地所有会话。 + +## 实现方法 + +### 从服务器分页获取会话列表 + +你可以调用 `fetchConversation` 方法从服务端分页获取会话列表,包含单聊和群组聊天会话,不包含聊天室会话。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 + +:::tip +1. **若使用该功能,需在环信控制台开通该功能,并将 SDK 升级至 4.0.0。只有开通该功能,你才能使用置顶会话功能。** +2. 建议在 app 安装时或本地没有会话时调用该方法,否则调用 `loadAllConversations` 获取本地会话即可。 +3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +::: + +示例代码如下: + +```dart +// pageSize: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。若获取数据时传空字符串(""),SDK 从最新活跃的会话开始获取。 +try { + int pageSize = 10; + String cursor = ""; + EMCursorResult result = + await EMClient.getInstance.chatManager.fetchConversation( + pageSize: pageSize, + cursor: cursor, + ); + // 获取到的会话列表 + List conversations = result.data; + // 下一次请求的 cursor + String? nextCursor = result.cursor; +} on EMError catch (e) {} +``` + +### 获取本地所有会话 + +你可以调用 `loadAllConversations` 方法获取本地所有会话。本地会话列表包含单聊和群组聊天会话,至于是否包含聊天室会话,取决于在 SDK 初始化时 `EMOptions#deleteMessagesAsExitChatRoom` 参数的设置。若设置为 `true`,即离开聊天室时删除该聊天室的所有本地消息,则本地会话列表中不包含聊天室会话。若设置为 `false`,即保留该聊天室的所有本地消息,则本地会话列表中包含聊天室会话。 + +若在初始化时,将 `EMOptions#enableEmptyConversation` 设置为 `true` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 + +```dart +try { + List lists = + await EMClient.getInstance.chatManager.loadAllConversations(); + // 成功加载会话。 +} on EMError catch (e) { +} +``` \ No newline at end of file diff --git a/docs/document/flutter/conversation_overview.md b/docs/document/flutter/conversation_overview.md new file mode 100644 index 000000000..bbba20239 --- /dev/null +++ b/docs/document/flutter/conversation_overview.md @@ -0,0 +1,66 @@ + +# 会话介绍 + + + +会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息、查看或清空历史消息等操作。 + +环信即时通讯 IM SDK 提供 `EMChatManager` 和 `EMConversation` 类以会话为单位对消息数据进行管理,如获取会话列表、置顶会话、添加会话标记、删除会话和管理未读消息等。 + +## 会话类 + +环信即时通讯 IM 提供会话类 `EMConversation`。该类定义了以下内容: + +| 方法 | 描述 | +| :--------- | :------- | +| id | 会话 ID,取决于会话类型。
- 单聊/help desk:会话 ID 为对方的用户 ID;
- 群聊:会话 ID 为群组 ID;
- 聊天室:会话 ID 为聊天室的 ID。| +| type | 会话类型枚举。
- `Chat`:单聊会话;
- `GroupChat`:群聊会话;
- `ChatRoom`:聊天室会话。
- `HelpDesk`:客服会话。 | +| isChatThread | 是否为子区会话。 | +| isPinned | 是否为置顶会话。 | +| pinnedTime | 会话置顶的 UNIX 时间戳,单位为毫秒。未置顶时值为 `0`。 | +| setExt | 获取会话扩展属性。 | +| latestMessage | 获取会话的最新一条消息。 | +| lastReceivedMessage | 获取最近收到的一条消息。 | +| unreadCount | 获取会话的消息未读数。 | +| markMessageAsRead | 将消息标为已读。 | +| markAllMessagesAsRead | 将所有消息标为已读。 | +| insertMessage | 插入一条消息在 SDK 本地数据库,消息的 conversation ID 应该和会话的 conversation ID 一致,消息会根据消息里的时间戳被插入 SDK 本地数据库,并且更新会话的 `latestMessage` 等属性。 | +| appendMessage | 插入一条消息到会话尾部。 | +| updateMessage | 更新 SDK 本地数据库的消息。 | +| deleteMessage(String messageId) | 删除会话中的一条消息,同时清除内存和数据库中的消息。 | +| deleteAllMessages() | 同时从内存和本地数据库中删除会话中的所有消息。 | +| deleteMessagesWithTs | 从本地数据库中删除指定时间段内的消息。 | +| loadMessage | 获取指定 ID 的消息。优先从内存中加载,如果内存中没有则从数据库中加载,并将其插入到内存中。 | +| loadMessagesWithMsgType | 根据消息类型、搜索消息的时间点、搜索结果的最大条数、搜索来源和搜索方向从 SDK 本地数据库中搜索指定数量的消息。 | +| loadMessages | 从本地数据库加载消息。加载到的消息也会加入到当前会话的缓存中,通过 getAllMessages 方法将会返回所有加载的消息。| +| loadMessagesWithKeyword | 根据消息中的关键词、搜索消息的时间点、搜索结果的最大条数、搜索来源和搜索方向从 SDK 本地数据库中搜索指定数量的消息。 | +| loadMessagesFromTime | 加载一个时间段内的消息,不超过 `count` 参数指定的最大数量。 | + +## 会话事件 + +`EMConversationListener` 中提供会话事件的监听接口。开发者可以通过设置此监听,获取会话事件,并做出相应处理。如果不再使用该监听,需要移除,防止出现内存泄漏。 + +示例代码如下: + +```dart + +EMClient.getInstance.chatManager.addEventHandler( + sdkEventKey, + EMChatEventHandler( + // 收到会话已读的事件。该事件在以下场景中触发: + // 1. 当消息接收放调用 `sendConversationReadAck` 方法,SDK 会执行此回调, + // 并将本地数据库中 `Message` 的 `hasReadAck` 置为 `true`. + // 2. 多端多设备登录时,若一端发送会话已读回执(sendConversationReadAck), + // 服务器端会将该会话的未读消息数置为 0, + // 同时其他端会回调此方法,并将本地数据库中该会话中消息的 `hasRead` 属性置为 `true`。 + onConversationRead: (from, to) {}, + ), +); + +``` + + + + + + diff --git a/docs/document/flutter/conversation_pin.md b/docs/document/flutter/conversation_pin.md new file mode 100644 index 000000000..bb57db8c4 --- /dev/null +++ b/docs/document/flutter/conversation_pin.md @@ -0,0 +1,73 @@ +# 会话置顶 + + + +会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 + +**若使用会话置顶功能,需将 SDK 升级至 4.0.3,并[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 技术原理 + +环信即时通讯 IM 支持会话置顶,主要方法如下: + +- `EMChatManager#pinConversation`:置顶会话。 +- `EMChatManager#fetchPinnedConversations`:分页获取服务器保存的置顶会话列表。 + +## 实现方法 + +### 置顶会话 + +你可以调用 `pinConversation` 方法设置是否置顶会话。多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他设备分别会收到 `EMMultiDevicesEvent.CONVERSATION_PINNED` 和 `EMMultiDevicesEvent.CONVERSATION_UNPINNED` 事件。 + +你最多可以置顶 50 个会话。 + +:::tip +若使用该功能,需将 SDK 升级至 4.0.3。 +::: + +示例代码如下: + +```dart +try { + await EMClient.getInstance.chatManager.pinConversation( + conversationId: conversationId, + isPinned: true, + ); +} on EMError catch (e) {} +``` + +你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 + +## 获取服务端的置顶会话列表 + +你可以调用 `fetchPinnedConversations` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 + +你最多可以拉取 50 个置顶会话。 + +示例代码如下: + +```dart +// pageSize: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新置顶的会话开始查询。 +try { + int pageSize = 10; + String cursor = ""; + EMCursorResult result = + await EMClient.getInstance.chatManager.fetchPinnedConversations( + pageSize: pageSize, + cursor: cursor, + ); + // 获取到的会话列表 + List conversations = result.data; + // 下一次请求的 cursor + String? nextCursor = result.cursor; +} on EMError catch (e) {} +``` \ No newline at end of file diff --git a/docs/document/flutter/conversation_unread.md b/docs/document/flutter/conversation_unread.md new file mode 100644 index 000000000..131da2458 --- /dev/null +++ b/docs/document/flutter/conversation_unread.md @@ -0,0 +1,65 @@ +## 会话未读数 + + + +你可以查看本地所有会话或指定会话的未读消息数,并针对会话的未读消息数清零。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM Flutter SDK 通过 `EMChatManager` 和 `EMConversation` 类实现对本地会话的未读消息数的管理,其中核心方法如下: + +- `EMChatManager#getUnreadMessageCount`:获取本地所有会话的未读消息数。 +- `EMConversation#unreadCount`:获取本地指定会话的未读消息数。 +- `EMChatManager#markAllConversationsAsRead`:将本地所有会话的未读消息数清零。 +- `EMConversation#markAllMessagesAsRead`:对于本地指定会话的未读消息数清零。 +- `EMConversation#markMessageAsRead`:将指定会话的单条未读消息置为已读。 + +## 实现方法 + +### 获取所有会话的未读消息数 + +你可以调用 `getUnreadMessageCount` 方法获取本地所有会话的未读消息数量,示例代码如下: + +```dart +int unreadCount = + await EMClient.getInstance.chatManager.getUnreadMessageCount(); +``` + +### 获取指定会话的未读消息数 + +你可以调用 `unreadCount` 方法获取本地指定会话的未读消息数,示例代码如下: + +```dart +int unreadCount = await conversation.unreadCount(); +``` + +### 将所有会话的未读消息数清零 + +你可以调用 `markAllConversationsAsRead` 方法将本地所有会话的未读消息数清零,示例代码如下: + +```dart +await EMClient.getInstance.chatManager.markAllConversationsAsRead(); +``` + +### 指定会话的未读消息数清零 + +你可以调用 `markAllMessagesAsRead` 方法对指定会话的未读消息数清零,示例代码如下: + +```dart +await conversation.markAllMessagesAsRead(); +``` + +### 将指定会话的单条未读消息置为已读 + +你可以调用 `markMessageAsRead` 方法将指定会话的单条未读消息置为已读。 + +```dart +await conversation.markMessageAsRead(message.msgId); +``` diff --git a/docs/document/flutter/group_attributes.md b/docs/document/flutter/group_attributes.md index ddc42fbfb..642d4a088 100644 --- a/docs/document/flutter/group_attributes.md +++ b/docs/document/flutter/group_attributes.md @@ -93,7 +93,7 @@ try { #### 上传共享文件 -所有群组成员均可以调用 `EMGroupManager#uploadGroupSharedFile` 方法上传共享文件至群组,群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `EMGroupEventHandler#onSharedFileAddedFromGroup` 事件。 +所有群组成员均可以调用 `EMGroupManager#uploadGroupSharedFile` 方法上传共享文件至群组,单个群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `EMGroupEventHandler#onSharedFileAddedFromGroup` 事件。 示例代码如下: diff --git a/docs/document/flutter/group_manage.md b/docs/document/flutter/group_manage.md index 3cbf8b2c3..6f9c2e68e 100644 --- a/docs/document/flutter/group_manage.md +++ b/docs/document/flutter/group_manage.md @@ -15,6 +15,7 @@ - 获取群组详情 - 获取群成员列表 - 获取群组列表 +- 查询当前用户已加入的群组数量 - 屏蔽、解除屏蔽群消息 - 监听群组事件 @@ -210,6 +211,21 @@ try { } ``` +### 查询当前用户已加入的群组数量 + +自 4.2.0 版本开始,你可以调用 `EMGroupManager#fetchJoinedGroupCount` 方法从服务器获取当前用户已加入的群组数量。单个用户可加入群组数量的上限取决于订阅的即时通讯的套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + +```dart +void fetchJoinedGroupCount() async { + try { + int count = + await EMClient.getInstance.groupManager.fetchJoinedGroupCount(); + } on EMError catch (e) { + // error. + } +} +``` + ### 屏蔽和解除屏蔽群消息 群成员可以屏蔽群消息和解除屏蔽群消息。 diff --git a/docs/document/flutter/group_members.md b/docs/document/flutter/group_members.md index adf76799d..02f714b10 100644 --- a/docs/document/flutter/group_members.md +++ b/docs/document/flutter/group_members.md @@ -44,7 +44,7 @@ try { ### 群组踢人 -1. 仅群主和群管理员可以调用 `EMGroupManager#removeMembers` 方法将指定成员移出群组。 +1. 仅群主和群管理员可以调用 `EMGroupManager#removeMembers` 方法将单个或多个成员移出群组。 2. 被移出群组后,该成员收到 `EMGroupEventHandler#onUserRemovedFromGroup` 事件,其他群成员收到 `EMGroupEventHandler#onMemberExitedFromGroup` 事件。 3. 被移出群组后,该用户还可以再次加入群组。 @@ -225,6 +225,7 @@ try { 示例代码如下: ```dart +// duration:禁言时间。若传 -1,表示永久禁言。 try { await EMClient.getInstance.groupManager.muteMembers( groupId, @@ -271,7 +272,9 @@ try { #### 开启全员禁言 -仅群主和群管理员可以调用 `EMGroupManager#muteAllMembers` 方法开启全员禁言。群组全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。 +仅群主和群管理员可以调用 `EMGroupManager#muteAllMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `EMGroupManager#unMuteAllMembers` 方法解除禁言。 + +群组全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。 示例代码如下: diff --git a/docs/document/flutter/message_delete.md b/docs/document/flutter/message_delete.md new file mode 100644 index 000000000..a5b2c5d45 --- /dev/null +++ b/docs/document/flutter/message_delete.md @@ -0,0 +1,81 @@ +# 删除消息 + + + +本文介绍用户如何单向删除服务端和本地的历史消息。 + +## 技术原理 + +使用环信即时通讯 IM Flutter SDK 可以通过 `EMChatManager` 类单向删除服务端和本地的历史消息,主要方法如下: + +- `EMChatManager#deleteRemoteMessagesBefore`/`EMChatManager#deleteRemoteMessagesWithIds`:根据消息时间或消息 ID 单向删除服务端的历史消息。 +- `EMChatManager#deleteAllMessages`:删除本地指定会话的所有消息。 +- `EMChatManager#deleteMessagesWithTs`:删除指定时间段的本地消息。 +- `EMChatManager#deleteMessage`:删除本地单个会话的指定消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 单向删除服务端的历史消息 + +你可以调用 `deleteRemoteMessagesBefore` 和 `deleteRemoteMessagesWithIds` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。删除后,消息自动从设备本地移除且该用户无法从服务端拉取到该消息。其他用户不受该操作影响。 + +登录该账号的其他设备会收到 `EMMultiDeviceEventHandler` 中的 `onRemoteMessagesRemoved` 回调,已删除的消息自动从设备本地移除。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.0.0 或以上版本并联系商务。 +::: + +```dart +try { + await EMClient.getInstance.chatManager.deleteRemoteMessagesBefore( + conversationId: conversationId, + type: convType, + timestamp: timestamp, + ); +} on EMError catch (e) {} + +try { + await EMClient.getInstance.chatManager.deleteRemoteMessagesWithIds( + conversationId: conversationId, + type: convType, + msgIds: msgIds, + ); +} on EMError catch (e) {} +``` + +### 删除本地指定会话的所有消息 + +你可以删除本地指定会话的所有消息,示例代码如下: + +```dart +EMConversation? conversation = await EMClient.getInstance.chatManager + .getConversation(conversationId); +await conversation?.deleteAllMessages(); +``` + +### 删除单个本地会话指定时间段的消息 + +你可以删除本地指定会话在一段时间内的本地消息,示例代码如下: + +```dart +EMConversation? conversation = await EMClient.getInstance.chatManager + .getConversation(conversationId); +await conversation?.deleteMessagesWithTs(startTs, endTs); +``` + +### 删除本地单个会话的指定消息 + +你可以删除本地单个会话的指定消息,示例代码如下: + +```dart +EMConversation? conversation = await EMClient.getInstance.chatManager + .getConversation(conversationId); +await conversation?.deleteMessage(messageId); +``` \ No newline at end of file diff --git a/docs/document/flutter/message_deliver_only_online.md b/docs/document/flutter/message_deliver_only_online.md new file mode 100644 index 000000000..b63076d0d --- /dev/null +++ b/docs/document/flutter/message_deliver_only_online.md @@ -0,0 +1,45 @@ +# 消息仅投递在线用户 + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **支持本地存储**:消息成功发送后,写入数据库。 +3. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 技术原理 + +环信即时通讯 IM 通过 `EMMessage` 类支持只将消息投递给在线用户: + +- `deliverOnlineOnly`:设置消息是否只投递给在线用户。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +要将消息只投递给在线用户,你需要在发送消息时将 `EMMessage#deliverOnlineOnly` 设置为 `true`。 + +下面以发送文本消息为例进行说明: + +```dart +// 创建一条文本消息。 +final msg = EMMessage.createTxtSendMessage( + // `targetId` 为接收方,单聊为对端用户 ID、群聊为群组 ID。 + targetId: conversationId, + // `content` 为消息文字内容。 + content: 'hello', + // 会话类型:单聊为 `Chat`,群聊为 `GroupChat`,默认为单聊。 + chatType: ChatType.Chat, + deliverOnlineOnly: true, +); + +// 发送消息。 +EMClient.getInstance.chatManager.sendMessage(msg); +``` + diff --git a/docs/document/flutter/message_import_insert.md b/docs/document/flutter/message_import_insert.md new file mode 100644 index 000000000..e853e5c89 --- /dev/null +++ b/docs/document/flutter/message_import_insert.md @@ -0,0 +1,58 @@ +# 导入和插入消息 + + + +本文介绍环信即时通讯 IM Android SDK 如何在本地导入和插入消息。 + +## 技术原理 + +环信即时通讯 IM Flutter SDK 通过 `EMChatManager` 和 `EMConversation` 类支持在本地导入和插入消息,其中包含如下主要方法: + +- `EMChatManager#importMessages`:批量导入消息到数据库。 +- `EMConversation#insertMessage`:在本地会话中加入一条消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 批量导入消息到数据库 + +如果你需要使用批量导入方式在本地会话中插入消息,可以使用下面的接口,构造 `EMMessage` 对象,将消息导入本地数据库。 + +当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 + +推荐一次导入 1,000 条以内的数据。 + +示例代码如下: + +```dart +// messages: 需要导入的消息。 +await EMClient.getInstance.chatManager.importMessages(messages); +``` + +### 插入消息 + +如果你需要在本地会话中加入一条消息,比如收到某些通知消息时,可以构造一条消息写入会话。 + +例如插入一条无需发送但有需要显示给用户看的内容,类似 “XXX 撤回一条消息”、“XXX 入群”、“对方正在输入” 等。 + +消息会根据消息中的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 + +示例代码如下: + +```dart +// 将消息插入到指定会话中。 + EMConversation? conversation = + await EMClient.getInstance.chatManager.getConversation( + username, + ); + conversation?.insertMessage(message); + + // 直接插入消息。 + await EMClient.getInstance.chatManager.importMessages(messages); +``` diff --git a/docs/document/flutter/message_manage.md b/docs/document/flutter/message_manage.md deleted file mode 100644 index 45dca995a..000000000 --- a/docs/document/flutter/message_manage.md +++ /dev/null @@ -1,224 +0,0 @@ -# 管理本地会话和消息 - - - -本文介绍环信即时通讯 IM Flutter SDK 如何管理本地会话和消息。 - -除了发送和接收消息外,环信即时通讯 IM Flutter SDK 还支持以会话为单位对本地的消息数据进行管理,如获取与管理未读消息、搜索和删除历史消息等。其中,会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息以及查看或清空历史消息。 - -本文介绍如何使用环信即时通讯 IM Flutter SDK 在 app 中实现这些功能。 - -## 技术原理 - -环信即时通讯 IM Flutter SDK 通过 `EMChatManager` 和 `EMConversation` 类实现对本地消息的管理,其中核心方法如下: - -- `EMChatManager.loadAllConversations` 获取本地会话列表; -- `EMChatManager.getConversation` 读取指定会话的消息; -- `EMConversation.unreadCount` 获取指定会话的未读消息数; -- `EMChatManager.getUnreadMessageCount` 获取所有会话的未读消息数; -- `EMConversation.markMessageAsRead` 指定会话的未读消息置为已读; -- `EMConversation.markAllMessagesAsRead` 指定会话所有未读数清零; -- `EMChatManager.markAllConversationsAsRead` 将所有会话消息设为已读; -- `EMChatManager.deleteConversation` 删除本地存储的会话及其历史消息; -- `EMChatManager.loadMessage` 根据消息 ID 获取消息; -- `EMConversation.loadMessagesWithMsgType` 获取指定会话中特定类型的消息; -- `EMConversation.loadMessagesFromTime` 获取指定会话中一定时间段内的消息; -- `EMChatManager.searchMsgFromDB` 根据关键字搜索会话消息; -- `EMChatManager.importMessages`批量导入消息到数据库。 - -## 前提条件 - -开始前,请确保满足以下条件: - -- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 - -## 实现方法 - -### 获取本地所有会话 - -你可以获取本地所有会话: - -```dart -try { - List lists = - await EMClient.getInstance.chatManager.loadAllConversations(); - // 成功加载会话。 -} on EMError catch (e) { -} -``` - -### 读取指定会话的消息 - -你可以根据会话 ID 和会话类型调用 API 获取本地会话: - -```dart -// 会话 ID。 -String convId = "convId"; -// 如果会话不存在是否创建。设置为 `true`,则会返回会话对象。 -bool createIfNeed = true; -// 会话类型。详见 `EMConversationType` 枚举类型。 -EMConversationType conversationType = EMConversationType.Chat; -// 执行操作。 -EMConversation? conversation = - await EMClient.getInstance.chatManager.getConversation( - convId, - conversationType, - true, -); -List? list = await conversation?.loadMessages(); -``` - -### 获取指定会话的未读消息数 - -你可以调用接口获取指定会话的未读消息数,示例代码如下: - -```dart -int unreadCount = await conversation.unreadCount(); -``` - -### 获取所有会话的未读消息数 - -你可以通过接口获取所有会话的未读消息数量,示例代码如下: - -```dart -// 获取所有未读消息数 -int unreadCount = - await EMClient.getInstance.chatManager.getUnreadMessageCount(); -``` - -### 指定会话的未读消息数清零 - -你可以调用接口对会话中的特定消息设置为已读,示例代码如下: - -```dart -await conversation.markMessageAsRead(message.msgId); -``` - -标记指定会话的所有消息已读: - -```dart -await conversation.markAllMessagesAsRead(); -``` - -将所有消息设为已读: - -```dart -await EMClient.getInstance.chatManager.markAllConversationsAsRead(); -``` - -### 删除会话及其历史消息 - -SDK 提供两个接口,分别可以删除本地会话和历史消息或者删除当前用户在服务器端的会话和历史消息。 - -- 删除本地会话和历史消息示例代码如下: - -```dart -// 会话 ID。 -String conversationId = "conversationId"; -// 删除会话时是否同时删除本地的历史消息。 -bool deleteMessage = true; -await EMClient.getInstance.chatManager - .deleteConversation(conversationId, deleteMessage); -``` - -```dart -// 删除本地指定会话中的指定消息。 -EMConversation? conversation = - await EMClient.getInstance.chatManager.getConversation( - conversationId, -); -conversation?.deleteMessage(messageId); -``` - -- 删除服务器端会话和历史消息,示例代码如下: - -```dart -// 会话 ID。 -String conversationId = "conversationId"; -// 删除会话时是否同时删除服务端的历史消息。 -bool deleteMessage = true; -EMConversationType conversationType = EMConversationType.Chat; -await EMClient.getInstance.chatManager.deleteRemoteConversation( - conversationId, - conversationType: conversationType, - isDeleteMessage: deleteMessage, -); -``` - -### 根据消息 ID 搜索消息 - -你可以调用 `loadMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 - -```dart -// msgId:要获取消息的消息 ID。 -EMMessage? msg = await EMClient.getInstance.chatManager.loadMessage("msgId"); -``` - -### 获取指定会话中特定类型的消息 - -你可以调用 `loadMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 - -```dart -EMConversation? conv = - await EMClient.getInstance.chatManager.getConversation("convId"); - List? list = await conv?.loadMessagesWithMsgType( - // 消息类型。 - type: MessageType.TXT, - // 每次获取的消息数量。取值范围为 [1,400]。 - count: 50, - // 消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 - direction: EMSearchDirection.Up, - ); -``` - -### 获取指定会话中一定时间段内的消息 - -你可以调用 `loadMessagesFromTime` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。每次最多可获取 400 条消息。 - -```dart -EMConversation? conv = - await EMClient.getInstance.chatManager.getConversation("convId"); - List? list = await conv?.loadMessagesFromTime( - // 搜索的起始时间戳,单位为毫秒。 - startTime: startTime, - // 搜索的结束时间戳,单位为毫秒。 - endTime: endTime, - // 每次获取的消息数量。取值范围为 [1,400]。 - count: 50, - ); -``` - -### 根据关键字搜索会话消息 - -你可以调用 `loadMessagesWithKeyword` 方法从本地数据库获取会话中的指定用户发送的包含特定关键字的消息,示例代码如下: - - -```dart -EMConversation? conv = - await EMClient.getInstance.chatManager.getConversation("convId"); - - List? msgs = await conv?.loadMessagesWithKeyword( - // 搜索关键字。 - "key", - // 消息发送方。 - sender: "tom", - // 搜索开始的 Unix 时间戳,单位为毫秒。 - timestamp: 1653971593000, - // 搜索的最大消息数。 - count: 10, - // 消息的搜索方向:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 - direction: EMSearchDirection.Up, - ); -``` - -### 批量导入消息到数据库 - -如果你需要使用批量导入方式在本地会话中插入消息,可以使用下面的接口,构造 `EMMessage` 对象,将消息导入本地数据库。 - -示例代码如下: - -```dart -// messages: 需要导入的消息。 -await EMClient.getInstance.chatManager.importMessages(messages); -``` diff --git a/docs/document/flutter/message_modify.md b/docs/document/flutter/message_modify.md index f38d1d5a7..afeddcf0a 100644 --- a/docs/document/flutter/message_modify.md +++ b/docs/document/flutter/message_modify.md @@ -1,6 +1,15 @@ # 修改消息 -对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。消息内容修改流程如下: +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。 + +:::tip +1. 若使用该功能,需将 SDK 升级至 4.1.0 或以上版本。 +2. 聊天室会话不支持消息修改功能。 +::: + +## 技术原理 + +消息内容修改流程如下: 1. 用户调用 SDK 的 API 修改一条消息。 2. 服务端存储的该条消息,修改成功后回调给 SDK。 @@ -13,10 +22,14 @@ - 对于单聊会话,只有消息发送方才能对消息进行修改。 - 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -:::notice -1. 若使用该功能,需将 SDK 升级至 4.1.0 或以上版本。 -2. 聊天室会话不支持消息修改功能。 -::: +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 你可以调用 `EMChatManager#modifyMessage` 方法修改已经发送成功的消息, 目前只支持文本消息。一条消息默认最多可修改 10 次,若要提升修改次数,需联系商务。 diff --git a/docs/document/flutter/message_recall.md b/docs/document/flutter/message_recall.md new file mode 100644 index 000000000..be739a62c --- /dev/null +++ b/docs/document/flutter/message_recall.md @@ -0,0 +1,47 @@ +# 撤回消息 + + + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能**页面设置消息撤回时长,该时长不超过 7 天。 + +:::tip +除了透传消息,其他各类型的消息都支持撤回。 +::: + +## 技术原理 + +环信即时通讯 IM 通过 `EMChatManager` 和 `EMMessage` 类支持你撤回一条发送成功的消息: + +- `recallMessage`:撤回一条发送成功的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 撤回消息 + +你可以调用 `recallMessage` 方法撤回一条发送成功的消息。 + +调用该方法后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `onMessagesRecalled` 事件。 + +```dart +try { + await EMClient.getInstance.chatManager.recallMessage(msgId); +} on EMError catch (e) { +} +``` + +### 设置消息撤回监听 + +你可以设置消息撤回监听,通过 `onMessagesRecalled` 事件监听发送方对已接收的消息的撤回。 + +```dart +void onMessagesRecalled(List messages) {} +``` \ No newline at end of file diff --git a/docs/document/flutter/message_receipt.md b/docs/document/flutter/message_receipt.md index 6752bc22f..541748a04 100644 --- a/docs/document/flutter/message_receipt.md +++ b/docs/document/flutter/message_receipt.md @@ -1,10 +1,10 @@ -# 管理消息回执 +# 实现消息回执 单聊会话支持消息送达回执、会话已读回执和消息已读回执,发送方发送消息后可及时了解接收方是否及时收到并阅读了信息,也可以了解整个会话是否已读。 -群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 本文介绍如何使用环信即时通讯 IM Flutter SDK 实现单聊和群聊的消息回执功能。 @@ -37,7 +37,7 @@ - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 -- 群消息已读回执功能仅在环信 IM 旗舰版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +- 群消息已读回执功能仅在环信 IM 专业版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 ## 实现方法 @@ -120,6 +120,8 @@ EMClient.getInstance.chatManager.addEventHandler( ##### 消息已读回执 +单聊消息的已读回执有效期与消息在服务端的存储时间一致,即在服务器存储消息期间均可发送已读回执。消息在服务端的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + 参考如下步骤在单聊中实现消息已读回执。 1. 开启全局的消息已读回执开关。如果全局设置不开启,消息和会话的相应设置也无法生效。 @@ -155,9 +157,9 @@ try { ### 群聊 -对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。 +对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。群聊已读回执的有效期为 3 天,即群组中的消息发送时间超过 3 天,服务器不记录阅读该条消息的群组成员,也不会发送已读回执。 -仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 1. 消息发送方需要知道群组消息是否已读,需要监听 `onGroupMessageRead` 事件。 diff --git a/docs/document/flutter/message_retrieve.md b/docs/document/flutter/message_retrieve.md index d3c134663..921bf00a8 100644 --- a/docs/document/flutter/message_retrieve.md +++ b/docs/document/flutter/message_retrieve.md @@ -1,23 +1,22 @@ -# 管理服务端的会话和消息 +# 获取历史消息 -环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。本文介绍用户如何从消息服务器获取会话和消息。 +本文介绍环信即时通讯 IM Flutter SDK 如何从服务器和本地获取历史消息。 -:::tip -本文介绍的功能均为增值服务,需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 -::: +- 环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 + +- SDK 内部使用 SQLite 保存本地消息,你可以获取本地消息。 ## 技术原理 -使用环信即时通讯 IM Flutter SDK 可以通过 `EMChatManager` 类的以下方法从服务器获取历史消息: +环信即时通讯 IM Flutter SDK 通过 `EMChatManager` 和 `EMConversation` 类实现对本地消息的管理,其中核心方法如下: -- `fetchConversation` 分页获取服务器保存的会话列表; -- `fetchPinnedConversations` 分页获取服务器保存的置顶会话列表; -- `pinConversation` 置顶会话。 -- `fetchHistoryMessages` 获取服务器保存的指定会话中的消息。 -- `deleteRemoteMessagesBefore`/`deleteRemoteMessagesWithIds` 根据消息时间或消息 ID 单向删除服务端的历史消息; -- `deleteRemoteConversation` 删除服务端的会话及其历史消息。 +- `EMChatManager#fetchHistoryMessages`:获取服务器保存的指定会话中的消息。 +- `EMChatManager.getConversation`:读取本地指定会话的消息。 +- `EMChatManager.loadMessage`:根据消息 ID 获取消息。 +- `EMConversation.loadMessagesWithMsgType`:获取本地存储的指定会话中特定类型的消息。 +- `EMConversation.loadMessagesFromTime`:获取一定时间段内本地指定会话中发送和接收的消息 ## 前提条件 @@ -28,101 +27,17 @@ ## 实现方法 -### 从服务器分页获取会话列表 - -对于单聊或群聊,用户发消息时会自动将对方添加到用户的会话列表。 - -你可以调用 `fetchConversation` 方法从服务端分页获取会话列表。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 - -服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。 - -:::tip -1. 若使用该功能,需将 SDK 升级至 4.0.0。 -2. 建议在 app 安装时或本地没有会话时调用该方法,否则调用 `loadAllConversations` 获取本地会话即可。 -3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 -::: - -示例代码如下: - -```dart -// pageSize: 每页返回的会话数。取值范围为 [1,50]。 -// cursor: 开始获取数据的游标位置。若获取数据时传空字符串(""),SDK 从最新活跃的会话开始获取。 -try { - int pageSize = 10; - String cursor = ""; - EMCursorResult result = - await EMClient.getInstance.chatManager.fetchConversation( - pageSize: pageSize, - cursor: cursor, - ); - // 获取到的会话列表 - List conversations = result.data; - // 下一次请求的 cursor - String? nextCursor = result.cursor; -} on EMError catch (e) {} -``` - -## 获取服务端的置顶会话列表 - -你可以调用 `fetchPinnedConversations` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 - -你最多可以拉取 50 个置顶会话。 - -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 -::: - -示例代码如下: - -```dart -// pageSize: 每页返回的会话数。取值范围为 [1,50]。 -// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新置顶的会话开始查询。 -try { - int pageSize = 10; - String cursor = ""; - EMCursorResult result = - await EMClient.getInstance.chatManager.fetchPinnedConversations( - pageSize: pageSize, - cursor: cursor, - ); - // 获取到的会话列表 - List conversations = result.data; - // 下一次请求的 cursor - String? nextCursor = result.cursor; -} on EMError catch (e) {} -``` - -### 置顶会话 - -会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 - -置顶状态会存储在服务器上,多设备登录情况下,更新置顶状态会同步到其他登录设备。你最多可以置顶 50 个会话。 - -你可以调用 `pinConversation` 方法设置是否置顶会话。多设备登录情况下,会话置顶或取消置顶后,其他登录设备分别会收到 `EMMultiDevicesEvent.CONVERSATION_PINNED` 和 `EMMultiDevicesEvent.CONVERSATION_UNPINNED` 事件。 - -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 -::: - -示例代码如下: - -```dart -try { - await EMClient.getInstance.chatManager.pinConversation( - conversationId: conversationId, - isPinned: true, - ); -} on EMError catch (e) {} -``` - -你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 - ### 分页获取指定会话的历史消息 你可以调用 `fetchHistoryMessages` 方法从服务器获取指定会话的消息(消息漫游)。 为确保数据可靠,我们建议你多次调用该方法,且每次获取的消息数小于 50 条。获取到数据后,SDK 会自动将消息更新到本地数据库。 +:::tip +1. 历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +2. 各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 +::: + ```dart try { // 会话 ID @@ -144,40 +59,70 @@ try { } ``` -### 单向删除服务端的历史消息 +### 读取指定会话的消息 -你可以调用 `deleteRemoteMessagesBefore` 和 `deleteRemoteMessagesWithIds` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息。其他用户不受该操作影响。已删除的消息自动从设备本地移除。 +你可以根据会话 ID 和会话类型调用 API 获取本地会话: -:::tip -若使用该功能,需将 SDK 升级至 V4.0.0 或以上版本并联系商务。 -::: +```dart +// 会话 ID。 +String convId = "convId"; +// 如果会话不存在是否创建。设置为 `true`,则会返回会话对象。 +bool createIfNeed = true; +// 会话类型。详见 `EMConversationType` 枚举类型。 +EMConversationType conversationType = EMConversationType.Chat; +// 执行操作。 +EMConversation? conversation = + await EMClient.getInstance.chatManager.getConversation( + convId, + conversationType, + true, +); +List? list = await conversation?.loadMessages(); +``` + +### 根据消息 ID 获取消息 + +你可以调用 `loadMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 ```dart -try { - await EMClient.getInstance.chatManager.deleteRemoteMessagesBefore( - conversationId: conversationId, - type: convType, - timestamp: timestamp, - ); -} on EMError catch (e) {} +// msgId:要获取消息的消息 ID。 +EMMessage? msg = await EMClient.getInstance.chatManager.loadMessage("msgId"); +``` -try { - await EMClient.getInstance.chatManager.deleteRemoteMessagesWithIds( - conversationId: conversationId, - type: convType, - msgIds: msgIds, - ); -} on EMError catch (e) {} +### 获取指定会话中特定类型的消息 + +你可以调用 `loadMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。 + +每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 + +```dart +EMConversation? conv = + await EMClient.getInstance.chatManager.getConversation("convId"); + List? list = await conv?.loadMessagesWithMsgType( + // 消息类型。 + type: MessageType.TXT, + // 每次获取的消息数量。取值范围为 [1,400]。 + count: 50, + // 消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 + direction: EMSearchDirection.Up, + ); ``` -### 单向删除服务端会话及其历史消息 +### 获取指定会话中一定时间段内的消息 + +你可以调用 `loadMessagesFromTime` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。 -你可以调用 `deleteRemoteConversation` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 +每次最多可获取 400 条消息。 ```dart -try { - await EMClient.getInstance.chatManager.deleteRemoteConversation( - conversationId, - ); -} on EMError catch (e) {} +EMConversation? conv = + await EMClient.getInstance.chatManager.getConversation("convId"); + List? list = await conv?.loadMessagesFromTime( + // 查询的起始时间戳,单位为毫秒。 + startTime: startTime, + // 查询的结束时间戳,单位为毫秒。 + endTime: endTime, + // 每次获取的消息数量。取值范围为 [1,400]。 + count: 50, + ); ``` \ No newline at end of file diff --git a/docs/document/flutter/message_search.md b/docs/document/flutter/message_search.md new file mode 100644 index 000000000..8e1ee4007 --- /dev/null +++ b/docs/document/flutter/message_search.md @@ -0,0 +1,43 @@ +# 搜索消息 + + + +本文介绍环信即时通讯 IM Flutter SDK 如何搜索本地消息。 + +## 技术原理 + +环信即时通讯 IM Flutter SDK 支持搜索用户设备上存储的消息数据,其中包含如下主要方法: + +- `EMChatManager.searchMsgFromDB`:根据关键字搜索会话消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 根据关键字搜索会话消息 + +你可以调用 `loadMessagesWithKeyword` 方法根据关键字搜索本地数据库中单个会话中指定用户发送的消息,示例代码如下: + + +```dart +EMConversation? conv = + await EMClient.getInstance.chatManager.getConversation("convId"); + + List? msgs = await conv?.loadMessagesWithKeyword( + // 搜索关键字。 + "key", + // 消息发送方。 + sender: "tom", + // 搜索开始的 Unix 时间戳,单位为毫秒。 + timestamp: 1653971593000, + // 搜索的最大消息数。 + count: 10, + // 消息的搜索方向:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 + direction: EMSearchDirection.Up, + ); +``` \ No newline at end of file diff --git a/docs/document/flutter/message_send_receive.md b/docs/document/flutter/message_send_receive.md index 124590b0c..0b9e15a07 100644 --- a/docs/document/flutter/message_send_receive.md +++ b/docs/document/flutter/message_send_receive.md @@ -19,7 +19,7 @@ ## 技术原理 -环信即时通讯 IM Flutter SDK 通过 `EMChatManager` 和 `EMMessage` 类实现消息的发送、接收与撤回。 +环信即时通讯 IM Flutter SDK 通过 `EMChatManager` 和 `EMMessage` 类实现消息的发送和接收。 其中,发送和接收消息的逻辑如下: @@ -124,10 +124,12 @@ EMClient.getInstance.chatManager.sendMessage(message).then((value) { 你可以添加 `EMChatEventHandler` 监听器接收消息。 -该 `EMChatEventHandler` 可以多次添加。请记得在不需要的时候移除该监听器,如在 `dispose` 时。 +`EMChatEventHandler` 可以多次添加。请记得在不需要的时候移除该监听器,如在 `dispose` 时。 在新消息到来时,你会收到 `onMessagesReceived` 的事件,消息接收时可能是一条,也可能是多条。你可以在该回调里遍历消息队列,解析并显示收到的消息。 +对于聊天室消息,你可以通过消息的 `EMMessage#isBroadcast` 属性判断该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 + ```dart // 继承并实现 EMChatEventHandler class _ChatMessagesPageState extends State { @@ -157,26 +159,6 @@ class _ChatMessagesPageState extends State { } ``` -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `onMessagesRecalled` 事件。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 -```dart -try { - await EMClient.getInstance.chatManager.recallMessage(msgId); -} on EMError catch (e) { -} -``` - -### 设置消息撤回监听 - -```dart -// 消息被撤回时触发的回调(此回调位于 EMChatEventHandler 中)。 -void onMessagesRecalled(List messages) {} -``` - - ### 发送和接收附件类型的消息 附件消息的发送和接收过程如下: @@ -206,7 +188,6 @@ EMClient.getInstance.chatManager.addMessageEvent( /// 移除监听 EMClient.getInstance.chatManager.removeMessageEvent('UNIQUE_HANDLER_ID'); - ``` #### 发送和接收语音消息 @@ -423,6 +404,10 @@ EMClient.getInstance.chatManager.sendMessage(localMsg); 透传消息可视为命令消息,通过发送这条命令给对方,通知对方要进行的操作,收到消息可以自定义处理。(透传消息不会存入本地数据库中,所以在 UI 上不会显示)。具体功能可以根据自身业务需求自定义,例如实现头像、昵称的更新等。另外,以 “em_” 和 “easemob::” 开头的 action 为内部保留字段,注意不要使用。 +:::tip +透传消息发送后,不支持撤回。 +::: + ```dart final cmdMsg = EMMessage.createCmdSendMessage( targetId: targetId, @@ -469,10 +454,8 @@ EMClient.getInstance.chatManager.removeEventHandler( - 收到消息后,如果用户 B 与用户 A 的聊天页面处于打开状态,则显示用户 A 的输入指示器。 - 如果用户 B 在几秒后未收到用户 A 的输入,则自动取消输入指示器。 -:::notice - +:::tip 用户 A 可根据需要设置透传消息发送间隔。 - ::: 以下示例代码展示如何发送输入状态的透传消息。 @@ -574,7 +557,7 @@ EMClient.getInstance.chatManager.sendMessage(customMsg); | `msgIds` | List | 合并消息的原始消息 ID 列表。该列表最多包含 300 个消息 ID。 | | `targetId` | String | 消息接收方。该字段的设置取决于会话类型:
- 单聊:对方用户 ID;
- 群聊:群组 ID;
- 子区会话:子区 ID;
- 聊天室聊天:聊天室 ID。| -:::notice +:::tip 1. 合并转发支持嵌套,最多支持 10 层嵌套,每层最多 300 条消息。 2. 不论 `EMOptions#serverTransfer` 设置为 `false` 或 `true`,SDK 都会将合并消息附件上传到环信服务器。 ::: @@ -622,7 +605,7 @@ try { 该功能适用于文本消息、图片消息和音视频消息等全类型消息,最多可向群组或聊天室的 20 个成员发送定向消息。 -:::notice +:::tip 1. 仅 SDK 4.1.0 及以上版本支持。 2. 定向消息不写入服务端会话列表,不计入服务端会话的未读消息数。 3. 定向消息不支持消息漫游功能,因此从服务器拉取漫游消息时,不包含定向消息。 diff --git a/docs/document/flutter/message_translation.md b/docs/document/flutter/message_translation.md index f1066021c..b99cd334e 100644 --- a/docs/document/flutter/message_translation.md +++ b/docs/document/flutter/message_translation.md @@ -7,10 +7,6 @@ - 按需翻译:接收方在收到文本消息后,将消息内容翻译为目标语言。 - 自动翻译:发送方发送消息时,SDK 根据发送方设置的目标语言自动翻译文本内容,然后将消息原文和译文一起发送给接收方。 -:::notice -私有化版本不支持消息翻译功能。 -::: - ## 前提条件 开始前,请确保满足以下条件: diff --git a/docs/document/flutter/message_update.md b/docs/document/flutter/message_update.md new file mode 100644 index 000000000..08fe94baa --- /dev/null +++ b/docs/document/flutter/message_update.md @@ -0,0 +1,41 @@ +# 更新消息 + + + +本文介绍环信即时通讯 IM Flutter SDK 如何更新本地消息。 + +## 技术原理 + +环信即时通讯 IM Flutter SDK 支持更新本地数据库中的消息,其中包含如下主要方法: + +- `EMChatManager#updateMessage`:更新消息到本地数据库。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 更新消息到本地数据库 + +你可以通过以下方式更新本地数据库中的消息: + +- 直接调用 `EMChatManager#updateMessage` 方法更新 SDK 本地数据库中的消息。 + +```dart +await EMClient.getInstance.chatManager.updateMessage(message); +``` + +- 若正在使用 `EMConversation` 类,可以先获取会话,再调用 `EMConversation#updateMessage` 方法更新 SDK 本地数据库会话中的消息。 + +```dart +EMConversation? conversation = + await EMClient.getInstance.chatManager.getConversation( + conversationId, + ); + conversation?.updateMessage(message); +``` + diff --git a/docs/document/flutter/moderation.md b/docs/document/flutter/moderation.md index 8b9d6d4dc..9e052761e 100644 --- a/docs/document/flutter/moderation.md +++ b/docs/document/flutter/moderation.md @@ -2,7 +2,14 @@ -环信即时通讯 IM SDK 提供消息举报接口。开发者可以在客户端调用该接口举报违规消息。当服务器端审核服务收到举报消息后,会将举报消息存储到数据库,并在 Console 展示。审核员可在 Console 查看举报记录,并进行相应处理。 +即时通讯 IM SDK 提供消息举报接口。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +:::tip +1. 使用前,你需要在[环信即时通讯云控制台](https://console.easemob.com/user/login) 开通该功能。 +2. 消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +关于如何开通消息举报和查看举报记录,详见[环信即时通讯云控制台文档说明](/product/enable_and_configure_IM.html#消息举报)。 ## 技术原理 @@ -13,7 +20,7 @@ 开始前,请确保满足以下条件: - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 开通消息审核服务,详见管理后台。 +- 已在 [环信即时通讯云控制台开通消息举报功能](/product/enable_and_configure_IM.html#消息举报)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 @@ -23,7 +30,7 @@ ```typescript // messageId:要举报的消息 ID。 // tag:非法消息的标签。你需要自定义标签,例如`涉政`或`广告`。该字段对应环信即时通讯云控制台的消息举报记录页面的`词条标记`字段。 -// reason:举报原因。你需要自行填写举报原因。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 +// reason:举报原因。你需要自行填写举报原因,最长不能超过 512 字节。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 try { await EMClient.getInstance.chatManager.reportMessage( messageId: messageId, diff --git a/docs/document/flutter/presence.md b/docs/document/flutter/presence.md index 906b1103f..2ce09c4dd 100644 --- a/docs/document/flutter/presence.md +++ b/docs/document/flutter/presence.md @@ -6,10 +6,6 @@ 本文介绍如何在即时通讯应用中发布、订阅和查询用户的在线状态。 -:::notice -私有化版本不支持在线状态订阅。 -::: - ## 技术原理 环信 IM SDK 提供 `EMPresence`、`EMPresenceManager` 和 `EMPresenceEventHandler` 类,用于管理在线状态订阅,包含如下核心方法: diff --git a/docs/document/flutter/reaction.md b/docs/document/flutter/reaction.md index 3872dfd8c..e4eb746e7 100644 --- a/docs/document/flutter/reaction.md +++ b/docs/document/flutter/reaction.md @@ -5,8 +5,7 @@ 环信即时通讯 IM 提供消息表情回复(下文统称 “Reaction”)功能。用户可以在单聊和群聊中对消息添加、删除表情。表情可以直观地表达情绪,利用 Reaction 可以提升用户的使用体验。同时在群组中,利用 Reaction 可以发起投票,根据不同表情的追加数量来确认投票。 :::notice -1. 目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 -2. 私有化版本不支持 Reaction 功能。 +目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 ::: ## 技术原理 diff --git a/docs/document/flutter/releasenote.md b/docs/document/flutter/releasenote.md index 656d7cbd9..2a8c9c8d9 100644 --- a/docs/document/flutter/releasenote.md +++ b/docs/document/flutter/releasenote.md @@ -2,6 +2,29 @@ +## 4.2.0 2024-1-4 + +#### 新增特性 + +- 新增[设置好友备注功能](user_relationship.html#设置好友备注)。 +- 新增 `EMContactManager#fetchContacts` 和 `EMContactManager#fetchAllContacts` 方法分别[从服务器一次性和分页获取好友列表](user_relationship.html#从服务端获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。从服务器一次性获取好友列表(只包含好友的用户 ID)的原接口 `getAllContactsFromServer` 已废弃,由 `fetchAllContactIds` 替换。 +- 新增 `EMContactManager#getContact` 方法[从本地获取单个好友的用户 ID 和好友备注](user_relationship.html#从本地获取好友列表)。 +- 新增 `EMContactManager#getAllContacts` 方法[从本地一次性获取好友列表](user_relationship.html#从本地获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。一次性获取本地好友列表(只包含好友的用户 ID)的原接口 `getAllContactsFromDB` 已废弃,由 `getAllContactIds` 替换。 +- 新增 `EMMessage#isBroadcast` 属性用于判断该消息是否为聊天室全局广播消息。可通过[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 +- 新增 `EMGroupManager#fetchJoinedGroupCount` 方法用于从服务器获取当前用户已加入的群组数量。 +- 新增[错误码 706](/document/android/error.html),表示聊天室所有者不允许离开聊天室。若初始化时,`EMOptions#isChatRoomOwnerLeaveAllowed` 参数设置为 false,聊天室所有者调用 `EMChatRoomManager#leaveChatroom` 方法离开聊天室时会提示该错误。 +- 新增 `EMOptions#enableEmptyConversation` 属性用于在初始化时配置获取会话列表时是否允许返回空会话。 +- 申请入群被拒绝的回调 `EMGroupEventHandler#onRequestToJoinDeclinedFromGroup` 中新增 decliner 和 applicant 参数表示申请者和拒绝者的用户 ID。 + +#### 优化 + +- 统一 Agora Token 和 EaseMob Token 登录方式,原 `EMClient#login` 方法废弃,使用 `EMClient#loginWithToken` 和 `EMClient#loginWithPassword` 方法代替。此外,新增 EaseMob Token 即将过期及已过期的回调,即 EaseMob Token 已过期或有效期过半时也返回 `EMConnectionEventHandler#onTokenDidExpire` 和 `EMClientDelegate#onTokenWillExpire` 回调。 + +#### 修复 + +- 修复网络恢复时重连 2 次的问题。 +- 修复未登录时调用 leaveChatroom 方法返回的错误提示不准确。 + ## 版本 4.1.3 2023-11-1 #### 新增 @@ -30,14 +53,14 @@ - 新增[消息修改功能](message_modify.html): - 新增 `EMChatManager#modifyMessage` 方法用户修改已发送的消息,目前只支持文本消息; - 新增 `EMChatEventHandler#onMessageContentChanged` 回调,用户监听消息修改实现; -- 新增[会话置顶功能](message_retrieve.html#置顶会话): +- 新增[会话置顶功能](conversation_pin.html#置顶会话): - 新增 `EMChatManager#pinConversation` 方法,实现在服务器会话列表中置顶/取消置顶会话; - 新增 `EMChatManager#fetchPinnedConversations` 方法,从服务器获取已置顶会话; - [以下方法新增支持用户 token](multi_device.html#获取指定账号的在线登录设备列表): - 新增 `EMClient#fetchLoggedInDevices` 方法,可使用 token 获取已登录的设备列表; - 新增 `EMClient#kickDevice` 方法,可以使用 token 踢掉指定设备; - 新增 `EMClient#kickAllDevices` 方法,可以使用 token 踢掉所有已登录设备; -- 新增 `EMChatManager#fetchConversation` 方法,[获取服务器会话列表](message_retrieve.html#从服务器分页获取会话列表),原方法 `EMChatManager#getConversationsFromServer` 作废; +- 新增 `EMChatManager#fetchConversation` 方法,[获取服务器会话列表](conversation_list.html#从服务器分页获取会话列表),原方法 `EMChatManager#getConversationsFromServer` 作废; - 新增 `EMMessage#receiverList` 属性,用于在群组/聊天室中[发送定向消息](message_send_receive.html#发送和接收定向消息); ### 优化 diff --git a/docs/document/flutter/room_attributes.md b/docs/document/flutter/room_attributes.md index 1f217c88d..f147ea7ac 100644 --- a/docs/document/flutter/room_attributes.md +++ b/docs/document/flutter/room_attributes.md @@ -13,7 +13,7 @@ - 获取和更新聊天室基本属性; - 获取聊天室自定义属性; - 设置聊天室自定义属性; -- 删除聊天室自定义属性。 +- 删除聊天室自定义属性。 ## 前提条件 diff --git a/docs/document/flutter/room_manage.md b/docs/document/flutter/room_manage.md index 7e0f14767..34facdf7c 100644 --- a/docs/document/flutter/room_manage.md +++ b/docs/document/flutter/room_manage.md @@ -38,7 +38,7 @@ 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 可以调用 `EMChatRoomManager#createChatRoom` 方法创建聊天室,并设置聊天室的名称、描述、最大成员数等信息。成功创建聊天室后,该超级管理员为该聊天室的所有者。 -你也可以直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 +建议直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 示例代码如下: @@ -114,7 +114,8 @@ EMOptions options = EMOptions( ); ``` -与群主无法退出群组不同,聊天室所有者可以离开聊天室,例如所有者从服务器下线则 2 分钟后自动离开聊天室。如果所有者重新进入聊天室仍是该聊天室的所有者。 +与群主无法退出群组不同,聊天室所有者可以离开聊天室,离开后重新进入仍是该聊天室的所有者。若 `ChatOptions#isChatRoomOwnerLeaveAllowed +` 参数在初始化时设置为 `true` 时,聊天室所有者可以离开聊天室;若该参数设置为 `false`,聊天室所有者调用 `leaveChatRoom` 方法离开聊天室时会提示错误 706。 ### 解散聊天室 diff --git a/docs/document/flutter/room_members.md b/docs/document/flutter/room_members.md index 8a32e1d91..44b55834e 100644 --- a/docs/document/flutter/room_members.md +++ b/docs/document/flutter/room_members.md @@ -47,7 +47,7 @@ try { ### 将成员移出聊天室 -仅聊天室所有者和管理员可调用 `EMChatRoomManager#removeChatRoomMembers` 方法将指定成员移出聊天室。 +仅聊天室所有者和管理员可调用 `EMChatRoomManager#removeChatRoomMembers` 方法将单个或多个成员移出聊天室。 被移出后,该成员收到 `EMChatRoomEventHandler#onRemovedFromChatRoom` 回调,其他成员收到 `EMChatRoomEventHandler#onMemberExitedFromChatRoom` 回调。 被移出的成员可以重新进入聊天室。 @@ -179,6 +179,7 @@ try { 示例代码如下: ```dart +// duration:禁言时间。若传 -1,表示永久禁言。 try { await EMClient.getInstance.chatRoomManager.muteChatRoomMembers( roomId, @@ -232,7 +233,9 @@ try { #### 开启聊天室全员禁言 -仅聊天室所有者和管理员可以调用 `EMChatRoomManager#muteAllChatRoomMembers` 方法开启全员禁言。全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `EMChatRoomEventHandler#onAllChatRoomMemberMuteStateChanged` 事件。 +仅聊天室所有者和管理员可以调用 `EMChatRoomManager#muteAllChatRoomMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `unmuteAllMembers` 方法解除全员禁言。 + +全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `EMChatRoomEventHandler#onAllChatRoomMemberMuteStateChanged` 事件。 示例代码如下: diff --git a/docs/document/flutter/thread.md b/docs/document/flutter/thread.md index 576c97f7d..ac43f1634 100644 --- a/docs/document/flutter/thread.md +++ b/docs/document/flutter/thread.md @@ -6,10 +6,6 @@ 本文介绍如何使用环信即时通讯 IM Flutter SDK 在实时互动 app 中创建和管理子区,并实现子区相关功能。 -:::notice -私有化版本不支持子区功能。 -::: - ## 技术原理 环信即时通讯 IM Flutter SDK 提供 `EMChatThreadManager`、`EMChatThread`、`EMChatThreadEventHandler` 和 `EMChatThreadEvent` 类,用于管理子区,支持你通过调用 API 在项目中实现如下功能: diff --git a/docs/document/flutter/thread_message.md b/docs/document/flutter/thread_message.md index 758032fec..0881e7369 100644 --- a/docs/document/flutter/thread_message.md +++ b/docs/document/flutter/thread_message.md @@ -47,13 +47,14 @@ ```dart // `chatThreadId` 为子区 ID + EMMessage msg = EMMessage.createTxtSendMessage( - chatThreadId: threadId, + targetId: threadId, content: content, + // `chatType` 设置为 `GroupChat`,即群聊 + chatType: ChatType.GroupChat, ); -// `chatType` 设置为 `GroupChat`,即群聊 -msg.chatType = ChatType.GroupChat; -// isChatThreadMessage: 是否是子区消息,这里设置为 `true`,即是子区消息 +// isChatThreadMessage: 是否是子区消息,这里设置为 `true`,即是子区消息。 msg.isChatThreadMessage = true; EMClient.getInstance.chatManager.sendMessage(msg); ``` @@ -91,7 +92,7 @@ EMClient.getInstance.chatThreadManager.removeEventHandler("UNIQUE_HANDLER_ID"); ### 撤回子区消息 -接收消息的具体逻辑,请参考 [撤回消息](message_send_receive.html#撤回消息),此处只介绍子区消息和其他消息的区别。 +接收消息的具体逻辑,请参考 [撤回消息](message_recall.html),此处只介绍子区消息和其他消息的区别。 子区有消息撤回时,子区所属群组的所有成员收到 `EMChatThreadEventHandler#onChatThreadUpdated` 事件,子区成员收到 `EMChatEventHandler#onMessagesRecalled` 事件。 @@ -160,8 +161,8 @@ try { String threadId = "threadId"; // 会话类型,即群聊 `GroupChat`。 EMConversationType convType = EMConversationType.GroupChat; - EMConversation? conversation = await EMClient.getInstance.chatManager - .getConversation(threadId, type: convType); + EMConversation? converrsation = + await EMClient.getInstance.chatManager.getThreadConversation(threadId); // 搜索的起始消息 ID。 String startMsgId = "startMsgId"; // 每页期望获取的消息数量。 diff --git a/docs/document/flutter/user_relationship.md b/docs/document/flutter/user_relationship.md index 1bbde6e24..2abe776f4 100644 --- a/docs/document/flutter/user_relationship.md +++ b/docs/document/flutter/user_relationship.md @@ -6,7 +6,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理: -- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请和删除好友等操作。 +- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请、删除好友和设置好友备注等操作。 - 黑名单管理:查询黑名单列表、添加用户至黑名单以及将用户移除黑名单等操作。 本文介绍如何通过环信即时通讯 IM Flutter SDK 管理用户关系。 @@ -19,8 +19,12 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理 - `deleteContact` 删除好友; - `acceptInvitation` 同意好友申请; - `declineInvitation` 拒绝好友申请; -- `getAllContactsFromServer` 从服务器获取好友列表; -- `getAllContactsFromDB` 从本地数据库中获取好友列表; +- `setContactRemark` 设置好友备注; +- `fetchAllContacts`/`fetchContacts`:一次性/分页从服务器获取好友列表(每个好友对象包含好友的用户 ID 和好友备注); +- `fetchAllContactIds` 一次性从服务器获取好友列表(列表只包含好友的用户 ID); +- `getContact`:获取本地单个好友(单个好友的用户 ID 和好友备注); +- `getAllContacts`:一次性获取本地好友列表(每个好友对象包含好友的用户 ID 和好友备注); +- `getAllContactIds`:一次性获取本地好友列表(列表只包含好友的用户 ID); - `addUserToBlockList` 添加用户到黑名单; - `removeUserFromBlockList` 将用户从黑名单移除; - `getBlockListFromServer` 从服务器获取黑名单列表。 @@ -34,8 +38,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理 ## 实现方法 -### 管理好友列表 -#### 添加好友 +### 添加好友 1. 用户添加指定用户为好友 @@ -104,21 +107,7 @@ EMClient.getInstance.contactManager.removeEventHandler("UNIQUE_HANDLER_ID"); EMClient.getInstance.contactManager.removeEventHandler("UNIQUE_HANDLER_ID"); ``` -#### 获取好友列表 - -1. 从服务器获取好友列表 - -```dart -List contacts = await EMClient.getInstance.contactManager.getAllContactsFromServer(); -``` - -2. 从本地数据库中获取好友列表 - -```dart -List contacts = await EMClient.getInstance.contactManager.getAllContactsFromDB(); -``` - -#### 删除好友 +### 删除好友 删除联系人时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 @@ -138,14 +127,126 @@ try { } ``` -### 管理黑名单 +### 设置好友备注 -黑名单是与好友无任何关系的独立体系。可以将任何用户加入黑名单,不论该用户与你是否是好友关系。 +自 4.2.0 版本开始,你可以调用 `asyncSetContactRemark` 方法设置单个好友的备注。 -黑名单功能包括加入黑名单,从黑名单移出用户和获取黑名单列表。对于获取黑名单,你可从服务器获取黑名单列表,也可从本地数据库获取已保存的黑名单列表。 +好友备注的长度不能超过 100 个字符。 + +```dart +void updateRemark(String userId, String newRemark) async { + try { + await EMClient.getInstance.contactManager.setContactRemark( + userId: userId, + remark: newRemark, + ); + } on EMError catch (e) { + // error. + } +} +``` + +### 从服务端获取好友列表 + +自 4.2.0 版本开始,你可以调用 `fetchAllContactsFromServer` 方法从服务器一次性或分页获取好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 + +- 一次性获取服务端好友列表。 + +```dart +void fetchAllContactsFromServer() async { + try { + List list = await EMClient.getInstance.contactManager.fetchAllContacts(); + } on EMError catch (e) { + // error. + } +} +``` + +- 分页获取服务端好友列表。 + +```dart +// pageSize 的取值范围为 [1,50] +void fetchContactsFromServer(String cursor, int pageSize) async { + try { + EMCursorResult result = + await EMClient.getInstance.contactManager.fetchContacts( + cursor: cursor, + pageSize: pageSize, + ); + } on EMError catch (e) { + // error. + } +} +``` + +此外,你也可以调用 `fetchAllContactIds` 方法从服务器获取所有好友的列表,该列表只包含好友的用户 ID。 + +```dart +void fetchAllContactIds() async { + try { + List userIds = + await EMClient.getInstance.contactManager.fetchAllContactIds(); + } on EMError catch (e) { + // error. + } +} +``` + +### 从本地获取好友列表 + +自 4.2.0 版本开始,你可以调用 `getContact` 方法从本地获取单个好友的用户 ID 和好友备注;你也可以调用 `getAllContacts` 方法一次性获取整个好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 + +:::tip +需要从服务器获取好友列表之后,才能从本地获取到好友列表。 +::: + +- 获取本地单个好友。 + +```dart +void getLocalContact(String userId) async { + try { + EMContact? contact = + await EMClient.getInstance.contactManager.getContact(userId: userId); + } on EMError catch (e) { + // error. + } +} +``` + +- 一次性获取本地好友列表。 + +```dart +void getAllLocalContact() async { + try { + List contacts = + await EMClient.getInstance.contactManager.getAllContacts(); + } on EMError catch (e) { + // error. + } +} +``` + +此外,你也可以调用 `getAllContactIds` 方法从本地一次性获取所有好友的列表,该列表只包含好友的用户 ID。 + +示例代码如下: + +```dart +void getAllLocalContactIds() async { + try { + List userIds = + await EMClient.getInstance.contactManager.getAllContactIds(); + } on EMError catch (e) { + // error. + } +} +``` #### 将用户加入黑名单 +黑名单是与好友无任何关系的独立体系。可以将任何用户加入黑名单,不论该用户与你是否是好友关系。 + +黑名单功能包括加入黑名单,从黑名单移出用户和获取黑名单列表。对于获取黑名单,你可从服务器获取黑名单列表,也可从本地数据库获取已保存的黑名单列表。 + 你可以调用 `addUserToBlockList` 将指定用户加入黑名单。用户被加入黑名单后将无法向你发送消息,也无法发送好友申请。 用户可以将任何其他用户添加到黑名单列表,无论该用户是否是好友。好友被加入黑名单后仍在好友列表上显示。 @@ -159,7 +260,7 @@ try { } ``` -#### 查看当前用户黑名单列表 +### 查看当前用户黑名单列表 1. 通过服务器获取黑名单列表 @@ -183,7 +284,7 @@ try { } ``` -#### 将用户从黑名单移除 +### 将用户从黑名单移除 你可以调用 `removeUserFromBlockList` 将用户从黑名单移除,用户发送消息等行为将恢复。 diff --git a/docs/document/ios/conversation_delete.md b/docs/document/ios/conversation_delete.md new file mode 100644 index 000000000..87ec6b340 --- /dev/null +++ b/docs/document/ios/conversation_delete.md @@ -0,0 +1,50 @@ +# 删除会话 + + + +删除好友或退出群组后,SDK 不会自动删除对应的单聊或群聊会话。你可以调用相应的接口从服务器和本地删除单个会话及其历史消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地删除单个会话及其历史消息,主要方法如下: + +- `deleteConversationFromServer`:单向删除服务端的单个会话及其历史消息。 +- `IEMChatManager.deleteConversations`:删除本地单个会话及其历史消息。 + +### 单向删除服务端会话及其历史消息 + +你可以调用 `deleteServerConversation` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 + +```objectivec +// 删除指定会话,如果需要保留历史消息,`isDeleteServerMessages` 参数传 `NO`,异步方法。 +[[EMClient sharedClient].chatManager deleteServerConversation:@"conversationId1" conversationType:EMConversationTypeChat isDeleteServerMessages:YES completion:^(NSString *aConversationId, EMError *aError) { + // 删除回调 +}]; +``` + +### 删除本地会话及历史消息 + +你可以删除本地会话和历史消息,示例代码如下: + +```objectivec +// 删除指定会话,如果需要保留历史消息,`isDeleteMessages` 参数传 `NO`,异步方法。 +[[EMClient sharedClient].chatManager deleteConversation:conversationId isDeleteMessages:YES completion:nil]; +// 删除一组会话。 +NSArray *conversations = @{@"conversationID1",@"conversationID2"}; +[[EMClient sharedClient].chatManager deleteConversations:conversations isDeleteMessages:YES completion:nil]; +``` + +```objectivec +// 删除当前会话中指定的一条历史消息。 +EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; +[conversation deleteMessageWithId:.messageId error:nil]; +``` + + diff --git a/docs/document/ios/conversation_list.md b/docs/document/ios/conversation_list.md new file mode 100644 index 000000000..4e780f834 --- /dev/null +++ b/docs/document/ios/conversation_list.md @@ -0,0 +1,63 @@ +# 会话列表 + + + +对于单聊、群组聊天和聊天室会话,用户发消息时 SDK 会自动创建会话并将会话添加至用户的会话列表。 + +环信服务器和本地均存储会话,你可以获取会话列表。**服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地获取会话列表,主要方法如下: + +- `IEMChatManager#getConversationsFromServerWithCursor:pageSize:completion`:从服务器获取会话列表。 +- `IEMChatManager#getAllConversations:`:获取本地所有会话。 + +## 实现方法 + +### 从服务器分页获取会话列表 + +你可以调用 `IEMChatManager#getConversationsFromServerWithCursor:pageSize:completion` 方法从服务端分页获取会话列表,包含单聊和群组聊天会话,不包含聊天室会话。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 + +:::tip +1. **若使用该功能,需在环信控制台开通该功能,并将 SDK 升级至 4.0.3。只有开通该功能,你才能使用置顶会话和会话标记功能。** +2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `getAllConversations:` 或 `getAllConversations` 方法获取本地所有会话即可。 +3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +::: + +示例代码如下: + +```objectivec +// pageSize: 每页返回的会话数。取值范围为 [1,50]。 +// cursor:查询的开始位置。若传入 `nil` 或 `@""`,SDK 从最新活跃的会话开始获取。 +NSString *cursor = @""; +[EMClient.sharedClient.chatManager getConversationsFromServerWithCursor:cursor pageSize:20 completion:^(EMCursorResult * _Nullable result, EMError * _Nullable error) { +}]; +``` + +### 获取本地所有会话 + +你可以调用 `getAllConversations:` 方法一次性获取本地所有会话。SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 + +本地会话列表包含单聊和群组聊天会话,至于是否包含聊天室会话,取决于在 SDK 初始化时 `EMOptions#isDeleteMessagesWhenExitChatRoom` 参数的设置。若设置为 `true`,即离开聊天室时删除该聊天室的所有本地消息,则本地会话列表中不包含聊天室会话。若设置为 `false`,即保留该聊天室的所有本地消息,则本地会话列表中包含聊天室会话。 + +若在初始化时,将 `EMOptions#loadEmptyConversations` 设置为 `YES` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 + +:::tip +若使用该功能,需将 SDK 升级至 4.0.3。 +::: + +示例代码如下: + +```objectivec +NSArray *conversations = [EMClient.sharedClient.chatManager getAllConversations:YES]; +``` + +你也可以调用 `getAllConversations` 方法返回 `NSArray ` 结构的会话。 \ No newline at end of file diff --git a/docs/document/ios/conversation_mark.md b/docs/document/ios/conversation_mark.md new file mode 100644 index 000000000..61ba2e5b1 --- /dev/null +++ b/docs/document/ios/conversation_mark.md @@ -0,0 +1,106 @@ +# 会话标记 + + + +某些情况下,你可能需要对会话添加标记,例如会话标星或将会话标为已读或未读。即时通讯云 IM 支持对单聊和群聊会话添加标记,最大支持 20 个标记,所以一个会话最多可添加 20 个标记。 + +**如果要使用会话标记功能,你需要确保开通了[会话列表服务](conversation_list.html#从服务器分页获取会话列表)并将 SDK 版本升级至 4.3.0 或以上版本。** + +你需要自行维护会话标记与具体业务含义(比如 `EMMarkType0` 为重要会话)之间的映射关系。例如: + +```Objective-C +NSDictionary* mapping = @{ + @(EMMarkType0): @"important", + @(EMMarkType1): @"normal", + @(EMMarkType2): @"unimportant", + @(EMMarkType3): @"boys", + @(EMMarkType4): @"girls", + }; +``` + +## 技术原理 + +环信即时通讯 IM 支持会话标记功能,主要方法如下: + +- `EMChatManager#addConversationMark:completion`:标记会话。 +- `EMChatManager#removeConversationMark:completion`:取消标记会话。 +- `EMChatManager#getConversationsFromServerWithCursor:filter:completion`:根据会话标记从服务器分页查询会话列表。 +- 根据会话标记从本地查询会话列表:调用 `getAllConversations` 方法获取本地所有会话后自己进行会话过滤。 +- 获取本地单个会话的所有标记:调用 `getConversationWithConvId` 方法获取本地单个会话,然后从会话的 `marks` 属性中查看该会话的所有标记。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 实现方法 + +### 标记会话 + +你可以调用 `addConversationMark` 方法标记会话。每次最多可为 20 个会话添加标记。调用该方法会同时为本地和服务器端的会话添加标记。 + +添加会话标记后,若调用 `getConversationsFromServerWithCursor:pageSize:completion` 接口从服务器分页获取会话列表,返回的会话对象中包含会话标记,即 `EMConversation#marks` 字段。若你已经达到了服务端会话列表长度限制(默认 100 个会话),服务端会根据会话的活跃度删除不活跃会话,这些会话的会话标记也随之删除。 + +:::tip +对会话添加标记,例如会话标星,并不影响会话的其他逻辑,例如会话的未读消息数。 +::: + +```Objective-C +[EMClient.sharedClient.chatManager addConversationMark:@[@"conversationId1"] mark:EMMarkType0 completion:^(EMError * _Nullable aError) { + + }]; +``` + +### 取消标记会话 + +你可以调用 `removeConversationMark` 方法删除会话标记。每次最多可移除 20 个会话的标记。 + +调用该方法会同时移除本地和服务器端会话的标记。 + +```Objective-C +[EMClient.sharedClient.chatManager removeConversationMark:@[@"conversationId1"] mark:EMMarkType0 completion:^(EMError * _Nullable aError) { + + }]; +``` + +### 根据会话标记从服务器分页查询会话列表 + +你可以调用 `getConversationsFromServerWithCursor` 方法根据会话标记从服务器分页获取会话列表。SDK 会按会话标记的时间的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)、会话标记以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 + + +```Objective-C +//cursor:查询的开始位置。若传入空字符串,SDK 从最新标记操作的会话开始获取。 +// filter:会话查询选项,包括会话标记和每页获取的会话条数(最多可获取 10 条)。 +EMConversationFilter* filter = [[EMConversationFilter alloc] initWithMark:EMMarkType0 pageSize:10]; +[EMClient.sharedClient.chatManager getConversationsFromServerWithCursor:@"" filter:filter completion:^(EMCursorResult * _Nullable result, EMError * _Nullable error) { + + }]; +``` + +### 根据会话标记从本地查询会话列表 + +对于本地会话,你可以调用 `getAllConversations` 方法获取本地所有会话后自己进行会话过滤。下面以查询标记了 `EMMarkType0` 的所有本地会话为例。 + +```Objective-C +//最终的查询结果全部放入 result 中。 +NSMutableArray* result = [NSMutableArray array]; + NSArray* allConversations = [EMClient.sharedClient.chatManager getAllConversations]; +for (EMConversation* conversation in allConversations) { + if ([conversation.marks containsObject:@(EMMarkType0)]) { + [result addObject:conversation]; + } +} +``` + +### 获取本地单个会话的所有标记 + +要获取本地单个会话的所有标记,你需要首先调用 `getConversationWithConvId` 方法获取本地单个会话,然后从会话的 `marks` 属性中查看该会话的所有标记,示例代码如下: + +```Objective-C +EMConversation* conversation = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; + NSArray* marks = conversation.marks; +``` + diff --git a/docs/document/ios/conversation_overview.md b/docs/document/ios/conversation_overview.md new file mode 100644 index 000000000..60447b9d0 --- /dev/null +++ b/docs/document/ios/conversation_overview.md @@ -0,0 +1,68 @@ +# 会话介绍 + + + +会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息、查看或清空历史消息等操作。 + +环信即时通讯 IM SDK 提供 `IEMChatManager` 和 `EMConversation` 类以会话为单位对消息数据进行管理,如获取会话列表、置顶会话、添加会话标记、删除会话和管理未读消息等。 + +## 会话类 + +环信即时通讯 IM 提供会话类 `EMConversation`。该类定义了以下内容: + +| 类/方法 | 描述 | +| :--------- | :------- | +| EMConversationType | 会话类型枚举。
- `Chat`:单聊会话;
- `GroupChat`:群聊会话;
- `ChatRoom`:聊天室会话。
- `HelpDesk`:客服会话。 | +| EMMarkType | 会话标记枚举类型:EMMarkType0、EMMarkType1、EMMarkType2、EMMarkType3、EMMarkType4、EMMarkType5、EMMarkType6、EMMarkType7、EMMarkType8、EMMarkType9、EMMarkType10、EMMarkType11、EMMarkType12、EMMarkType13、EMMarkType14、EMMarkType15、EMMarkType16、EMMarkType16、EMMarkType17、EMMarkType18 和 EMMarkType19。 | +| EMMessageSearchDirection | 消息搜索方向枚举。
- EMMessageSearchDirectionUp:按照消息中的 Unix 时间戳的逆序搜索。
- EMMessageSearchDirectionDown:按照消息中的时间戳的正序搜索。 | +| EMConversation | 聊天会话类。 | +| conversationId | 会话 ID,取决于会话类型。
- 单聊:会话 ID 为对方的用户 ID;
- 群聊:会话 ID 为群组 ID;
- 聊天室:会话 ID 为聊天室的 ID。 | +| type | 会话类型。 | +| messagesCount | 会话中的消息数量。 | +| ext | 会话扩展属性。 | +| isChatThread | 是否为 thread 会话。 | +| isPinned | 是否为置顶会话。 | +| pinnedTime | 会话置顶的 UNIX 时间戳,单位为毫秒。未置顶时值为 `0`。 | +| marks | 会话标记。 | +| lastReceivedMessage | 收到的对方发送的最后一条消息。 | +| insertMessage | 插入一条消息在 SDK 本地数据库。消息的会话 ID 应与会话的 ID 保持一致。消息会根据消息里的时间戳被插入 SDK 本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 | +| appendMessage | 插入一条消息到 SDK 本地数据库会话尾部。消息的会话 ID 应该和目标会话的 ID 一致。消息会被插入 SDK 本地数据库,并且更新会话的 `latestMessage` 等属性。 | +| deleteMessageWithId | 从 SDK 本地数据库删除一条消息。 | +| deleteAllMessages | 清除内存和数据库中指定会话中的消息。 | +| removeMessagesFromServerMessageIds | 从会话中删除消息(包括本地存储和服务器存储)。 | +| removeMessagesFromServerWithTimeStamp | 从会话中删除消息(包括本地存储和服务器存储)。 | +| updateMessageChange | 更新 SDK 本地数据库的消息。 | +| markMessageAsReadWithId | 将 SDK 本地数据库中的指定消息设置为已读。 | +| markAllMessagesAsRead | 将 SDK 本地数据库所有未读消息设置为已读。 | +| loadMessageWithId | 从 SDK 本地数据库获取指定 ID 的消息。 | +| loadMessagesStartFromId | 从 SDK 本地数据库获取指定数量的消息。 | +| loadMessagesWithType | 从本地数据库中获取会话中指定用户发送的一定数量的特定类型的消息。 | +| loadMessagesWithKeyword | 从本地数据库获取会话中的指定用户发送的包含特定关键词的消息。 | +| loadCustomMsgWithKeyword | 从本地数据库获取会话中的指定用户发送的包含特定关键词的自定义消息。 | +| loadMessagesFrom | 从本地数据库中搜索指定时间段内发送或接收的一定数量的消息。 | +| removeMessagesStart | 从本地数据库中删除指定时间段内的消息。 | + +## 会话事件 + +`EMChatManagerDelegate` 中提供会话事件的监听接口。开发者可以通过设置此监听,获取会话事件,并做出相应处理。如果不再使用该监听,需要移除,防止出现内存泄漏。 + +示例代码如下: + +```Objective-C +// 收到会话已读的事件。该事件在以下场景中触发: +// 1. 当消息接收方调用 `ackConversationRead()` 方法,SDK 会执行此回调, +// 会将本地数据库中该会话中消息的 `isAcked` 属性置为 `true`。 +// 2. 多端多设备登录时,若一端发送会话已读回执(conversation ack), +// 服务器端会将会话的未读消息数置为 0, +// 同时其他端会回调此方法,并将本地数据库中该会话中消息的 `isRead` 属性置为 `true`。 +- (void)onConversationRead:(NSString *)from to:(NSString *)to +{ + +} +``` + + + + + + diff --git a/docs/document/ios/conversation_pin.md b/docs/document/ios/conversation_pin.md new file mode 100644 index 000000000..012738bcd --- /dev/null +++ b/docs/document/ios/conversation_pin.md @@ -0,0 +1,61 @@ +# 会话置顶 + + + +会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 技术原理 + +环信即时通讯 IM 支持会话置顶,主要方法如下: + +- `pinConversation:isPinned:completionBlock:`:置顶会话。 +- `getPinnedConversationsFromServerWithCursor:limit:completion:`:获取服务端置顶会话列表。 + +## 实现方法 + +### 置顶会话 + +你可以调用 `pinConversation:isPinned:completionBlock:` 方法设置是否置顶会话。置顶状态会存储在服务器上,多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他设备分别会收到 `EMMultiDevicesEventConversationPinned` 和 `EMMultiDevicesEventConversationUnpinned` 事件。 + +你最多可以置顶 50 个会话。 + +:::notice +若使用该功能,需将 SDK 升级至 4.0.3。 +::: + +示例代码如下: + +```objectivec +[EMClient.sharedClient.chatManager pinConversation:self.conversation.conversationId isPinned:aSwitch.isOn completionBlock:^(EMError * _Nullable error) { +}]; +``` + +你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `pinnedTime` 方法获取会话置顶时间。 + +### 获取服务端的置顶会话列表 + +你可以调用 `getPinnedConversationsFromServerWithCursor:limit:completion:` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 + +你最多可以拉取 50 个置顶会话。 + +:::notice +若使用该功能,需将 SDK 升级至 4.0.3。 +::: + +示例代码如下: + +```objectivec +// pageSize: 每页返回的会话数。取值范围为 [1,50]。 +// cursor:查询的开始位置。若传入 `nil` 或 `@""`,SDK 从最新置顶的会话开始查询。 +NSString *cursor = @""; +[EMClient.sharedClient.chatManager getPinnedConversationsFromServerWithCursor:cursor pageSize:20 completion:^(EMCursorResult * _Nullable result, EMError * _Nullable error) { +}]; +``` \ No newline at end of file diff --git a/docs/document/ios/conversation_unread.md b/docs/document/ios/conversation_unread.md new file mode 100644 index 000000000..103f0613c --- /dev/null +++ b/docs/document/ios/conversation_unread.md @@ -0,0 +1,64 @@ +## 会话未读数 + + + +你可以查看本地所有会话或指定会话的未读消息数,并针对会话的未读消息数清零。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM iOS SDK 通过 `IEMChatManager` 和 `EMConversation` 类实现对本地会话的未读消息数的管理,其中核心方法如下: + +- `IEMChatManager#getAllConversations`:获取本地所有会话的未读消息数。 +- `EMConversation#unreadMessagesCount`:获取本地指定会话的未读消息数。 +- `EMConversation#markAllMessagesAsRead`:对于本地指定会话的未读消息数清零。 +- `EMConversation#markMessageAsReadWithId`:将指定会话的单条未读消息置为已读。 + +## 实现方法 + +### 获取所有会话的未读消息数 + +你可以调用 `getAllConversations` 方法获取本地所有会话的未读消息数量,示例代码如下: + +```objectivec +NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations]; +NSInteger unreadCount = 0; +for (EMConversation *conversation in conversations) { + unreadCount += conversation.unreadMessagesCount; +} +``` + +### 获取指定会话的未读消息数 + +你可以调用 `unreadMessagesCount` 方法获取本地指定会话的未读消息数,示例代码如下: + +```objectivec +// 获取指定会话 ID 的会话。 +EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; +// 获取未读消息数。 +NSInteger unreadCount = conversation.unreadMessagesCount; +``` + +### 指定会话的未读消息数清零 + +你可以调用 `markAllMessagesAsRead` 方法对指定会话的未读消息数清零,示例代码如下: + +```objectivec +EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; +[conversation markAllMessagesAsRead:nil]; +``` + +### 将指定会话的单条未读消息置为已读 + +你可以调用 `markMessageAsReadWithId` 方法将指定会话的单条未读消息置为已读。 + +```objectivec +EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; +[conversation markMessageAsReadWithId:messageId error:nil]; +``` diff --git a/docs/document/ios/elite_sdk.md b/docs/document/ios/elite_sdk.md new file mode 100644 index 000000000..2310e80fd --- /dev/null +++ b/docs/document/ios/elite_sdk.md @@ -0,0 +1,385 @@ +# 精简版 SDK + +精简版 SDK 4.2.0 支持 Android 和 iOS 平台,包含基础的单聊和聊天室功能,适用于 SDK 包体积尽量小、仅需基础收发消息功能、而无需离线推送通知等功能的情况。 + +精简版 SDK 对应用的体积增量不大,android 为 1.11 MB,iOS 为 1.09 MB。 + +要下载 iOS 端精简版 SDK,点击[这里](https://downloadsdk.easemob.com/downloads/SDK-mini/iOS_IMLite_SDK_4.2.0_1116.zip)。 + +:::tip +精简版 SDK 无本地存储,可以升级为标准版 SDK,但标准版不能降级为精简版。 +::: + +## 功能列表 + +精简版 SDK 的功能如下表所示: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
功能模块功能功能细分/描述 接口文档 精简版 SDK标准版 SDK
消息管理发送和接收消息发送和接收消息

发送和接收消息

接收消息
发送和接收附件类型的消息
发送和接收位置消息
发送和接收透传消息
发送自定义类型消息
发送和接收合并消息
发送和接收定向消息
使用消息的扩展字段
管理本地消息管理本地消息

获取本地历史消息

+

搜索消息

+

导入和插入消息

+

更新消息

+

删除消息

管理服务端消息管理服务端消息

从服务器分页获取指定会话的历史消息

+

单向删除服务端的历史消息

管理消息回执消息送达回执

消息送达回执

消息已读回执

消息已读回执

撤回消息

撤回消息

+

设置消息撤回监听

 
修改消息单聊会话中已经发送成功的文本消息进行修改

修改消息

获取消息流量统计获取消息流量统计获取消息流量统计  
翻译消息翻译

消息翻译

会话管理会话列表获取本地所有会话 获取本地所有会话
从服务器分页获取会话列表

从服务器分页获取会话列表

会话未读数获取或清零本地会话的未读数

 

+

会话未读数

置顶会话置顶会话置顶会话
删除会话单向删除服务端会话及其历史消息单向删除服务端会话及其历史消息
删除本地会话及历史消息删除本地会话及历史消息
管理用户属性设置和获取用户属性用户属性指实时消息互动用户的信息,如用户昵称、头像、邮箱、电话、性别、签名、生日等管理用户属性
管理用户关系好友列表管理和黑名单管理

添加、删除好友;

+

设置和获取好友备注;

+

从服务器获取好友列表;

+

将用户添加到或移除黑名单

+

从服务器获取黑名单列表

管理用户关系
群组管理群组为多人聊天,有稳定的成员关系。

创建、管理群组;

+

管理群成员;

+

管理群成员属性

群组管理
聊天室管理聊天室为多人聊天,没有固定的成员关系。

聊天室概述

聊天室概述  
创建和管理聊天室创建聊天室创建和管理聊天室
加入聊天室
获取聊天室详情
退出聊天室
解散聊天室
监听聊天室事件
管理聊天室成员获取聊天室成员列表管理聊天室成员
将成员移出聊天室
管理聊天室黑名单
管理聊天室白名单
管理聊天室禁言列表
开启和关闭聊天室全员禁言
管理聊天室所有者和管理员
管理聊天室基本属性获取聊天室公告管理聊天室基本属性
更新聊天室公告
修改聊天室名称
修改聊天室描述
管理聊天室自定义属性管理聊天室自定义属性管理聊天室自定义属性
进阶功能离线推送集成第三方消息推送服务离线推送
登录多个设备支持同一账号在多个设备上登录并接收消息 
多设备管理多设备登录
管理在线状态订阅管理在线状态订阅在线状态订阅
消息表情回复 Reaction对单聊和群聊中的消息通过表情回复消息表情回复
子区管理子区是群组成员的子集子区管理
消息举报开发者可以在客户端调用该接口举报违规消息消息举报
+ +## 错误码 + +[iOS 错误码](error.html) + + + + + + + + + + + + + + + + + diff --git a/docs/document/ios/group_attributes.md b/docs/document/ios/group_attributes.md index e064d5b71..a9449baf5 100644 --- a/docs/document/ios/group_attributes.md +++ b/docs/document/ios/group_attributes.md @@ -71,7 +71,7 @@ #### 上传共享文件 -所有群组成员均可以调用 `uploadGroupSharedFileWithId` 方法上传共享文件至群组,群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `EMGroupManagerDelegate#addedSharedFile` 回调。 +所有群组成员均可以调用 `uploadGroupSharedFileWithId` 方法上传共享文件至群组,单个群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `EMGroupManagerDelegate#addedSharedFile` 回调。 示例代码如下: diff --git a/docs/document/ios/group_manage.md b/docs/document/ios/group_manage.md index 1338bb047..76467eb09 100644 --- a/docs/document/ios/group_manage.md +++ b/docs/document/ios/group_manage.md @@ -65,7 +65,7 @@ 2. 受邀用户需要确认才能进群。 -只有 `AgoraChatGroupOptions#IsInviteNeedConfirm` 设置为 `true` 和 `isAutoAcceptGroupInvitation` 设置为 `false` 时,受邀用户需要确认才能进群。这种情况下,受邀用户收到 `EMGroupManagerDelegate#onInvitationReceived` 回调,并选择同意或拒绝进群邀请: +只有 `EMGroupOptions#IsInviteNeedConfirm` 设置为 `true` 和 `isAutoAcceptGroupInvitation` 设置为 `false` 时,受邀用户需要确认才能进群。这种情况下,受邀用户收到 `EMGroupManagerDelegate#onInvitationReceived` 回调,并选择同意或拒绝进群邀请: - 用户同意入群邀请后,邀请人收到 `EMGroupManagerDelegate#groupInvitationDidAccept` 回调和 `EMGroupManagerDelegate#userDidJoinGroup` 回调;其他群成员收到 `EMGroupManagerDelegate#userDidJoinGroup` 回调; - 用户拒绝入群邀请后,邀请人收到 `EMGroupManagerDelegate#groupInvitationDidDecline` 回调。 @@ -115,7 +115,8 @@ NSArray *members = @{@"member1",@"member2"}; ### 获取群组详情 :::notice -从 3.7.4 版本开始支持是否获取群组成员参数 `fetchMembers` 。 +从 3.7.4 版本开始支持是否获取群组成员参数 `fetchMembers`。 +对于公有群,用户即使不加入群也能获取群组详情,而对于私有群,用户只有加入了群组才能获取群详情。 ::: 群成员也可以调用 `getGroupSpecificationFromServerWithId` 方法从服务器获取群组详情。返回的结果包括群组 ID、群组名称、群组描述、群组基本属性、群主、群组管理员列表、是否已屏蔽群组消息以及群组是否禁用。另外,若将该方法的 `fetchMembers` 参数设置为 `true`,可获取群成员列表,默认最多包括 200 个成员。 @@ -216,7 +217,7 @@ do { ### 查询当前用户已加入的群组数量 -你可以调用 `EMGroupManager#getJoinedGroupsCountFromServerWithCompletion` 方法用于从服务器获取当前用户已加入的群组数量。单个用户可加入群组数量的上限取决于你订阅的即时通讯的套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +自 4.2.0 版本开始,你可以调用 `EMGroupManager#getJoinedGroupsCountFromServerWithCompletion` 方法用于从服务器获取当前用户已加入的群组数量。单个用户可加入群组数量的上限取决于你订阅的即时通讯的套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。 ```objectivec [EMClient.sharedClient.groupManager getJoinedGroupsCountFromServerWithCompletion:^(NSInteger groupCount, EMError * _Nullable aError) { diff --git a/docs/document/ios/group_members.md b/docs/document/ios/group_members.md index a6b3a98ce..327f333c3 100644 --- a/docs/document/ios/group_members.md +++ b/docs/document/ios/group_members.md @@ -138,7 +138,7 @@ do { ```objective-c [[EMClient sharedClient].groupManager acceptInvitationFromGroup:@"groupId" inviter:@"userId" completion:^(EMGroup *aGroup, EMError *aError) { - }; + }]; ``` - 受邀人拒绝入群组,需要调用 `declineGroupInvitation` 方法。 @@ -166,15 +166,15 @@ do { #### 群成员被移出群组 -仅群主和群管理员可以调用 `removeMembers` 方法将指定成员移出群组。被踢出群组后,被踢群成员将会收到群组事件回调 `EMGroupManagerDelegate#didLeaveGroup`,其他成员将会收到回调 `EMGroupManagerDelegate#userDidLeaveGroup`。被移出群组后,该用户还可以再次加入群组。 +仅群主和群管理员可以调用 `removeMembers` 方法将单个或多个成员移出群组。被踢出群组后,被踢群成员将会收到群组事件回调 `EMGroupManagerDelegate#didLeaveGroup`,其他成员将会收到回调 `EMGroupManagerDelegate#userDidLeaveGroup`。被移出群组后,该用户还可以再次加入群组。 示例代码如下: ```objectivec // 异步方法 -[[EMClient sharedClient].groupManager removeMembers:@{@"member"} - fromGroup:@"groupsID" - completion:nil]; + [EMClient.sharedClient.groupManager removeMembers:@[@"member1",@"member2"] fromGroup:@"groupId" completion:^(EMGroup * _Nullable aGroup, EMError * _Nullable aError) { + + }]; ``` ### 管理群成员的自定义属性 @@ -390,6 +390,7 @@ do { ```objectivec // 异步方法 +// `muteMilliseconds`:禁言时间。传 -1 表示永久禁言。 [[EMClient sharedClient].groupManager muteMembers:members muteMilliseconds:60 fromGroup:@"groupID" @@ -425,10 +426,12 @@ do { #### 开启群组全员禁言 -仅群主和群管理员可以调用 `muteAllMembersFromGroup` 方法开启全员禁言。 +仅群主和群管理员可以调用 `muteAllMembersFromGroup` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `unmuteAllMembersFromGroup` 方法解除全员禁言。 群主和群管理员开启群组全员禁言后,除了白名单中的群成员,其他成员将不能发言。开启群组全员禁言后,群成员会收到群组事件回调 `EMGroupManagerDelegate#groupAllMemberMuteChanged`。 +群组全员禁言状态(`EMGroup#isMuteAllMembers`)存储在本地数据库中,下次登录时可以直接从本地获取到。 + 示例代码如下: ```objectivec diff --git a/docs/document/ios/message_delete.md b/docs/document/ios/message_delete.md new file mode 100644 index 000000000..c98ab19f5 --- /dev/null +++ b/docs/document/ios/message_delete.md @@ -0,0 +1,108 @@ +# 删除消息 + + + +本文介绍用户如何单向删除服务端和本地的历史消息。 + +## 技术原理 + +使用环信即时通讯 IM iOS SDK 可以通过 `EMConversation` 类单向删除服务端和本地的历史消息,主要方法如下: + +- `EMChatManager#deleteAllMessagesAndConversations:completion:`:清空当前用户的聊天记录,包括消息和会话,同时可以选择是否单向清除服务端的聊天记录。 +- `EMConversation#removeMessagesFromServerWithTimeStamp`/`removeMessagesFromServerMessageIds`:按消息时间或消息 ID 单向删除服务端的历史消息。 +- `EMConversation#deleteAllMessages`:删除本地指定会话的所有消息。 +- `EMConversation#removeMessagesStart`:删除本地单个会话在指定时间段的消息。 +- `EMConversation#deleteMessage`:删除本地单个会话的指定消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 清空聊天记录 + +你可以调用 `EMChatManager#deleteAllMessagesAndConversations:completion:` 方法清空当前用户的聊天记录,包括消息和会话。同时你也可以选择是否清除服务端的聊天记录。若你清除了服务端的聊天记录,当前用户无法从服务端拉取到该消息。其他用户不受该操作影响。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.4.0 或以上版本。 +::: + +```swift + EMClient.shared().chatManager?.deleteAllMessagesAndConversations(true, completion: { aError in + if let aError = aError { + print("deleteAllMessagesAndConversations failed") + } else { + print("deleteAllMessagesAndConversations success") + } +}) +``` + +### 单向删除服务端的历史消息 + +你可以调用 `removeMessagesFromServerWithTimeStamp` 或 `removeMessagesFromServerMessageIds` 方法按消息时间或消息 ID 单向删除服务端的历史消息。每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息。其他用户不受该操作影响。登录该账号的其他设备会收到 `EMMultiDevicesDelegate` 中的 `multiDevicesMessageBeRemoved` 回调,已删除的消息自动从设备本地移除。 + +:::tip +若使用该功能,需将 SDK 升级至 V3.9.8 或以上版本并联系商务开通。 +::: + +示例代码如下: + +```Objectivec +// 按时间删除消息 +[self.conversation removeMessagesFromServerWithTimeStamp:message.timestamp completion:^(EMError * _Nullable aError) { + +}]; + +// 按消息 ID 删除消息 +[self.conversation removeMessagesFromServerMessageIds:@[@"123314142214"] completion:^(EMError * _Nullable aError) { + +}]; +``` + +### 删除本地指定会话的所有消息 + +你可以删除本地指定会话的所有消息,示例代码如下: + +```swift +if let conversation = EMClient.shared().chatManager?.getConversationWithConvId("conversationId") { + var err: EMError? = nil + conversation.deleteAllMessages(&err) + if let err = err { + // 删除消息失败 + } else { + // 成功删除消息 + } +} +``` + +### 删除本地单个会话在指定时间段的消息 + +你可以删除本地指定会话在一段时间内的本地消息,示例代码如下: + +```swift +if let conversation = EMClient.shared().chatManager?.getConversationWithConvId("conversationId") { + conversation.removeMessagesStart(startTime, to: endTime) +} +``` + +### 删除本地单个会话的指定消息 + +你可以删除本地单个会话的指定消息,示例代码如下: + +```swift +if let conversation = EMClient.shared().chatManager?.getConversationWithConvId("conversationId") { + var err: EMError? = nil + conversation.deleteMessage(withId: "messageId", error:&err) + if let err = err { + // 删除消息失败 + } else { + // 成功删除消息 + } +} +``` + + diff --git a/docs/document/ios/message_deliver_only_online.md b/docs/document/ios/message_deliver_only_online.md new file mode 100644 index 000000000..06d764f9f --- /dev/null +++ b/docs/document/ios/message_deliver_only_online.md @@ -0,0 +1,48 @@ +# 消息仅投递在线用户 + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **支持本地存储**:消息成功发送后,写入数据库。 +3. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 技术原理 + +环信即时通讯 IM 通过 `EMChatMessage` 类支持只将消息投递给在线用户: + +- `deliverOnlineOnly`:设置消息是否只投递给在线用户。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +要将消息只投递给在线用户,你需要在发送消息时将 `EMChatMessage#deliverOnlineOnly` 设置为 `YES`。 + +下面以发送文本消息为例进行说明: + +```objective-c +// 调用 initWithText 创建文本消息。`content` 为文本消息的内容。 +EMTextMessageBody *textMessageBody = [[EMTextMessageBody alloc] initWithText:content]; +// 消息接收方:单聊为对端用户的 ID,群聊为群组 ID。 +NSString* conversationId = @"remoteUserId"; +EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:conversationId + body:textMessageBody + ext:messageExt]; +// 会话类型:单聊为 `EMChatTypeChat`,群聊为 `EMChatTypeGroupChat`。 +message.chatType = EMChatTypeChat; +// 消息是否只投递在线用户。(默认)`NO`:不论用户是否在线均投递;`YES`:只投递给在线用户。若用户离线,消息不投递。 +message.deliverOnlineOnly = YES; +// 发送消息。 +[[EMClient sharedClient].chatManager sendMessage:message + progress:nil + completion:nil]; + +``` + diff --git a/docs/document/ios/message_import_insert.md b/docs/document/ios/message_import_insert.md new file mode 100644 index 000000000..a45c9b858 --- /dev/null +++ b/docs/document/ios/message_import_insert.md @@ -0,0 +1,48 @@ +# 导入和插入消息 + + + +本文介绍环信即时通讯 IM iOS SDK 如何在本地导入和插入消息。 + +## 技术原理 + +环信即时通讯 IM iOS SDK 支持提供 `IEMChatManager` 和 `EMConversation` 类支持在本地导入和插入消息,其中包含如下主要方法: + +- `IEMChatManager.importMessages`:批量导入消息到数据库; +- `EMConversation.insertMessage`:在本地指定会话中插入一条消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 批量导入消息到数据库 + +如果你需要使用批量导入方式在本地会话中插入消息,可以调用 `importMessages` 方法,构造 `Message` 对象,将消息导入本地数据库。 + +当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 + +推荐一次导入 1,000 条以内的数据。 + +```objectivec +// 异步方法 +[[EMClient sharedClient].chatManager importMessages:messages completion:nil]; +``` + +### 插入消息 + +如果你需要在本地会话中加入一条消息,比如收到某些通知消息时,可以构造一条消息写入会话。 + +例如插入一条无需发送但有需要显示给用户看的内容,类似 “XXX 撤回一条消息”、“XXX 入群”、“对方正在输入” 等。 + +消息会根据消息中的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 + +```objectivec +EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; +[conversation insertMessage:message error:nil]; +``` + diff --git a/docs/document/ios/message_manage.md b/docs/document/ios/message_manage.md deleted file mode 100644 index 088e427db..000000000 --- a/docs/document/ios/message_manage.md +++ /dev/null @@ -1,254 +0,0 @@ -# 管理本地会话和消息 - - - -本文介绍环信即时通讯 IM iOS SDK 如何管理本地会话和消息。SDK 内部使用 SQLite 保存本地消息,方便消息处理。 - -除了发送和接收消息外,环信即时通讯 IM SDK 还支持以会话为单位对本地的消息数据进行管理,如获取与管理未读消息、删除聊天记录、搜索历史消息以及统计消息流量等。其中,会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息或查看历史消息,还可进行清空聊天记录等操作。 - -## 技术原理 - -环信即时通讯 IM iOS SDK 支持管理用户设备上存储的消息会话数据,其中包含如下主要方法: - -- `IEMChatManager.getAllConversations:` 获取本地所有会话; -- `EMConversation.loadMessagesStartFromId` 从数据库中读取指定会话的消息; -- `EMConversation.unreadMessagesCount` 获取指定会话的未读消息数; -- `EMConversation.unreadMessagesCount` 获取所有会话的未读消息数; -- `EMConversation.markMessageAsReadWithId` 指定会话的未读消息数清零; -- `IEMChatManager.deleteConversations` 删除本地会话及历史消息; -- `IEMChatManager.getMessageWithMessageId` 根据消息 ID 搜索消息; -- `EMConversation.loadMessagesWithType` 获取指定会话中特定类型的消息; -- `EMConversation.loadMessagesFrom:to:count:completion:` 获取指定会话中一定时间段内的消息; -- `IEMChatManager.loadMessagesWithKeyword` 根据关键字搜索会话消息; -- `IEMChatManager.importMessages` 批量导入消息到数据库; -- `EMConversation.insertMessage` 插入消息; -- `IEMChatManager.updateMessage` 更新消息到本地数据库; -- `getMessageStatisticsById` 根据消息 ID 获取消息流量统计信息; -- `getMessageCountWithStart` 获取一定时间段内发送和/或接收的指定或全部类型的消息条数; -- `getMessageStatisticsSizeWithStart` 获取一定时间段内发送和/或接收的指定或全部类型的消息的总流量。 - -## 前提条件 - -开始前,请确保满足以下条件: - -- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 - -## 实现方法 - -### 获取本地所有会话 - -你可以调用 `getAllConversations:` 方法一次性获取本地所有会话。若在初始化时,将 `EMOptions#loadEmptyConversations` 设置为 `YES` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 - -SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 - -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 -::: - -示例代码如下: - -```objectivec -NSArray *conversations = [EMClient.sharedClient.chatManager getAllConversations:YES]; -``` - -你也可以调用 `getAllConversations` 方法返回 `NSArray ` 结构的会话。 - -### 从数据库中读取指定会话的消息 - -可以从数据库中读取指定会话的消息: - -```objectivec -// 获取指定会话 ID 的会话。 -EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; -//startMsgId:查询的起始消息 ID; count:每次获取的消息条数。如果设为小于等于 0,SDK 获取 1 条消息。 -//searchDirection:消息搜索方向。若消息方向为 `UP`,按消息时间戳的降序获取;若为 `DOWN`,按消息时间戳的升序获取。 -NSArray *messages = [conversation loadMessagesStartFromId:startMsgId count:count searchDirection:MessageSearchDirectionUp]; -``` - -### 获取指定会话的未读消息数 - -你可以调用接口获取特定会话的未读消息数,示例代码如下: - -```objectivec -// 获取指定会话 ID 的会话。 -EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; -// 获取未读消息数。 -NSInteger unreadCount = conversation.unreadMessagesCount; -``` - -### 获取所有会话的未读消息数 - -示例代码如下: - -```objectivec -NSArray *conversations = [[EMClient sharedClient].chatManager getAllConversations]; -NSInteger unreadCount = 0; -for (EMConversation *conversation in conversations) { - unreadCount += conversation.unreadMessagesCount; -} -``` - -### 指定会话的未读消息数清零 - -你可以调用接口将指定会话的未读消息数清零,示例代码如下: - -```objectivec -EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; -// 将指定会话的消息未读数清零。 -[conversation markAllMessagesAsRead:nil]; -// 将一条消息置为已读。 -[conversation markMessageAsReadWithId:messageId error:nil]; -``` - -### 删除会话及历史消息 - -你可以删除本地会话和历史消息,示例代码如下: - -```objectivec -// 删除指定会话,如果需要保留历史消息,`isDeleteMessages` 参数传 `NO`,异步方法。 -[[EMClient sharedClient].chatManager deleteConversation:conversationId isDeleteMessages:YES completion:nil]; -// 删除一组会话。 -NSArray *conversations = @{@"conversationID1",@"conversationID2"}; -[[EMClient sharedClient].chatManager deleteConversations:conversations isDeleteMessages:YES completion:nil]; -``` - -```objectivec -// 删除当前会话中指定的一条历史消息。 -EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; -[conversation deleteMessageWithId:.messageId error:nil]; -``` - -删除服务端的会话及其历史消息,详见 [删除服务端会话及其历史消息](message_retrieve.html#单向删除服务端会话及其历史消息)。 - -### 根据消息 ID 搜索消息 - -你可以调用 `getMessageWithMessageId` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 - -```objectivec -// 同步方法 -EMConversation* conv = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; -EMError* err = nil; -// messageId:要获取消息的消息 ID。 -EMChatMessage* message = [EMClient.sharedClient.chatManager getMessageWithMessageId:@"messageId"]; -``` - -### 获取指定会话中特定类型的消息 - -你可以调用 `loadMessagesWithType` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 - -```objectivec -// 异步方法 -EMConversation* conv = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; -// timestamp:消息搜索的起始时间戳,单位为毫秒。该参数设置后,SDK 从指定的时间戳的消息开始,按照搜索方向对消息进行搜索。若设置为负数,SDK 从当前时间开始,按消息时间戳的逆序搜索。 -// count:每次搜索的消息数量。取值范围为 [1,400]。 -// searchDirection:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -[conv loadMessagesWithType:EMMessageBodyTypeText timestamp:1671761876000 count:50 fromUser:@"" searchDirection:EMMessageSearchDirectionUp completion:^(NSArray * _Nullable aMessages, EMError * _Nullable aError) { - -}]; -``` - -### 获取指定会话中一定时间段内的消息 - -你可以调用 `loadMessagesFrom:to:count:completion:` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。每次最多可获取 400 条消息。 - -```objectivec -// 异步方法 -EMConversation* conv = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; -// startTime:搜索的起始时间戳,单位为毫秒;endTime:搜索的结束时间戳,单位为毫秒;count:每次获取的消息数量。取值范围为 [1,400]。 -[conv loadMessagesFrom:startTime to:endTime count:50 completion:^(NSArray * _Nullable aMessages, EMError * _Nullable aError) { - -}]; -``` - -### 根据关键字搜索会话消息 - -你可以调用 `loadMessagesWithKeyword` 方法从本地数据库获取会话中的指定用户发送的包含特定关键字的消息,示例代码如下: - -```objectivec -// 同步方法,异步方法见[EMConversation loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:completion] - EMConversation* conversation = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; - NSArray *messages = [conversation loadMessagesWithKeyword:@"keyword" timestamp:0 count:50 fromUser:nil searchDirection:EMMessageSearchDirectionDown]; -``` - -### 批量导入消息到数据库 - -如果你需要使用批量导入方式在本地会话中插入消息可以使用下面的接口,构造 `Message` 对象,将消息导入本地数据库。 - -```objectivec -// 异步方法 -[[EMClient sharedClient].chatManager importMessages:messages completion:nil]; -``` - -### 插入消息 - -如果你需要在本地会话中加入一条消息,比如收到某些通知消息时,可以构造一条消息写入会话。 -例如插入一条无需发送但有需要显示给用户看的内容,类似 “XXX 撤回一条消息”、“XXX 入群”、“对方正在输入” 等。 - -```objectivec -// 将消息插入到指定会话中。 -EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; -[conversation insertMessage:message error:nil]; -``` - -### 更新消息到本地数据库 - -如果需要更新消息用以下方法: - -```objectivec -// 异步方法 -[EMClient.sharedClient.chatManager updateMessage:message completion:^(EMChatMessage *aMessage, EMError *aError) { - if (!aError) { - // 更新本地消息完成。 - } -}]; -``` - -### 获取本地消息的流量统计信息 - -本地消息的流量统计功能默认关闭。若要使用该功能,需在 SDK 初始化前设置 `EMOptions#enableStatistics` 开启。 - -SDK 只支持统计该功能开启后最近 30 天内发送和接收的消息。各类消息的流量计算方法如下: - -- 对于文本、透传、位置消息,消息流量为消息体的流量; -- 对于图片和视频消息,消息流量为消息体、图片或视频文件以及缩略图的流量之和; -- 对于文件和语音消息,消息流量为消息体和附件的流量。 - -:::notice - 1. 统计时间段的开始时间和结束时间均为服务器接收消息的 Unix 时间戳。 - 2. 对于携带附件的消息,下载成功后 SDK 才统计附件的流量。若附件下载多次,则会对下载的流量进行累加。 - 3. 对于从服务器拉取的漫游消息,如果本地数据库中已经存在,则不进行统计。 -::: - -SDK 仅统计本地消息的流量,而非消息的实际流量。一般而言,该统计数据小于实际流量,原因如下: -- 未考虑发送消息时通用协议数据的流量; -- 对于接收到的消息,服务端会进行消息聚合,添加通用字段,而消息流量统计为各消息的流量,未考虑通用字段的流量消耗。 - -#### 根据消息 ID 获取消息流量统计信息 - -你可以根据消息 ID 获取指定消息的统计信息。该方法返回的消息流量统计信息包括消息 ID、消息的发送方和接收方 -、消息体类型、会话类型、消息方向、消息流量大小(单位为字节)以及服务器收到该消息的 Unix 时间戳。 - -示例代码如下: - -```objectivec -EMChatMessageStatistics * msgStatistics = [[[EMClient sharedClient] statisticsManager] getMessageStatisticsById:@"msgId"]; -``` - -#### 获取一定时间段内发送和/或接收的消息条数 - -你可以统计一定时间段内发送和/或接收的指定或全部类型的消息,示例代码如下: - -```objectivec -NSInteger count = [EMClient.sharedClient.statisticsManager getMessageCountWithStart:startTime end:endTime direction:EMMessageStatisticsDirectionAll type:EMMessageStatisticsTypeText]; -``` - -#### 获取一定时间段内发送和/或接收的消息的总流量 - -你可以统计一定时间段内发送和/或接收的指定或全部类型的消息的总流量,流量单位为字节。 - -示例代码如下: - -```objectivec -NSInteger bytes = [EMClient.sharedClient.statisticsManager getMessageStatisticsSizeWithStart:startTime end:endTime direction:EMMessageStatisticsDirectionAll type:EMMessageStatisticsTypeAll]; -``` \ No newline at end of file diff --git a/docs/document/ios/message_modify.md b/docs/document/ios/message_modify.md index 0711e3f98..9a5dc1ed5 100644 --- a/docs/document/ios/message_modify.md +++ b/docs/document/ios/message_modify.md @@ -1,6 +1,15 @@ # 修改消息 -对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。消息内容修改流程如下: +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。 + +:::tip +1. 若使用该功能,需将 SDK 升级至 4.1.0 或以上版本。 +2. 聊天室会话不支持消息修改功能。 +::: + +## 技术原理 + +消息内容修改流程如下: 1. 用户调用 SDK 的 API 修改一条消息。 2. 服务端存储的该条消息,修改成功后回调给 SDK。 @@ -13,10 +22,7 @@ - 对于单聊会话,只有消息发送方才能对消息进行修改。 - 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -:::notice -1. 若使用该功能,需将 SDK 升级至 4.1.0 或以上版本。 -2. 聊天室会话不支持消息修改功能。 -::: +## 实现方法 你可以调用 `EMChatManager::modifyMessage:body:completion:` 方法修改已经发送成功的消息。一条消息默认最多可修改 10 次,若要提升修改次数,需联系商务。 diff --git a/docs/document/ios/message_recall.md b/docs/document/ios/message_recall.md new file mode 100644 index 000000000..caab74a94 --- /dev/null +++ b/docs/document/ios/message_recall.md @@ -0,0 +1,53 @@ +# 撤回消息 + + + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息、离线消息或漫游消息。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能**页面设置消息撤回时长,该时长不超过 7 天。 + +:::tip +除了透传消息,其他各类型的消息都支持撤回。 +::: + +## 技术原理 + +环信即时通讯 IM 通过 `ChatManager` 类和 `EMChatMessage` 类支持你撤回一条发送成功的消息: + +- `recallMessageWithMessageId`:撤回一条发送成功的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 撤回消息 + +你可以调用 `recallMessageWithMessageId` 方法撤回一条发送成功的消息。 + +调用该方法后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `messagesInfoDidRecall` 事件。 + +```objectivec +// 异步方法 +[[EMClient sharedClient].chatManager recallMessageWithMessageId:messageId completion:^(EMError *aError) { + if (!aError) { + NSLog(@"撤回消息成功"); + } else { + NSLog(@"撤回消息失败的原因 --- %@", aError.errorDescription); + } +}]; +``` + +### 设置消息撤回监听 + +你可以设置消息撤回监听,通过 `messagesInfoDidRecall` 事件监听发送方对已接收的消息的撤回。 + +```objectivec +- (void)messagesInfoDidRecall:(NSArray * _Nonnull)aRecallMessagesInfo; +{ +} +``` diff --git a/docs/document/ios/message_receipt.md b/docs/document/ios/message_receipt.md index eedb4826e..2cd7cc23a 100644 --- a/docs/document/ios/message_receipt.md +++ b/docs/document/ios/message_receipt.md @@ -1,10 +1,10 @@ -# 管理消息回执 +# 实现消息回执 单聊会话支持消息送达回执、会话已读回执和消息已读回执,发送方发送消息后可及时了解接收方是否及时收到并阅读了信息,也可以了解整个会话是否已读。 -群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 本文介绍如何使用环信即时通讯 IM iOS SDK 实现单聊和群聊的消息回执功能。 @@ -41,7 +41,7 @@ - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 -- 群消息已读回执功能仅在环信 IM 旗舰版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +- 群消息已读回执功能仅在环信 IM 专业版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 ## 实现方法 @@ -122,6 +122,8 @@ EMChatManagerDelegate ##### 消息已读回执 +单聊消息的已读回执有效期与消息在服务端的存储时间一致,即在服务器存储消息期间均可发送已读回执。消息在服务端的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + 参考如下步骤在单聊中实现消息已读回执。 1. 接收方发送已读回执消息。 @@ -189,7 +191,9 @@ EMChatManagerDelegate 对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。 -仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊已读回执的有效期为 3 天,即群组中的消息发送时间超过 3 天,服务器不记录阅读该条消息的群组成员,也不会发送已读回执。 + +仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 1. 群主或群管理员设置 `EMChatMessage` 的属性 `isNeedGroupAck` 为 `YES`。 diff --git a/docs/document/ios/message_retrieve.md b/docs/document/ios/message_retrieve.md index a501de334..93f1c49f9 100644 --- a/docs/document/ios/message_retrieve.md +++ b/docs/document/ios/message_retrieve.md @@ -1,139 +1,102 @@ -# 管理服务端的消息 +# 获取历史消息 -环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。本文介绍用户如何获取和删除服务端的会话和消息。 +本文介绍环信即时通讯 IM SDK 如何从服务器和本地获取历史消息。 -:::tip -本文介绍的功能均为增值服务,需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 -::: +- 环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 + +- SDK 内部使用 SQLite 保存本地消息,你可以获取本地消息。 ## 技术原理 -使用环信即时通讯 IM iOS SDK 可以管理服务端的会话和历史消息。 +环信即时通讯 IM iOS SDK 提供 `IEMChatManager` 和 `EMConversation` 类支持获取服务器和本地的消息,包含如下主要方法: -- `getConversationsFromServerWithCursor:pageSize:completion` 分页获取服务器上保存的会话列表; -- `getPinnedConversationsFromServerWithCursor:limit:completion:` 获取服务端的置顶会话列表; -- `pinConversation:isPinned:completionBlock:` 置顶会话; -- `asyncFetchHistoryMessagesFromServer` 获取服务器保存的指定会话中的消息; -- `removeMessagesFromServerWithTimeStamp`/`removeMessagesFromServerMessageIds` 按消息时间或消息 ID 单向删除服务端的历史消息; -- `deleteServerConversation` 删除服务器端会话及其历史消息。 +- `IEMChatManager#asyncFetchHistoryMessagesFromServer`:从服务器分页获取指定会话的历史消息 +- `EMConversation#loadMessagesStartFromId`:从数据库中读取指定会话的消息; +- `IEMChatManager#getMessageWithMessageId`:根据消息 ID 获取本地消息; +- `EMConversation#loadMessagesWithType`:获取本地存储的指定会话中特定类型的消息; +- `EMConversation#loadMessagesFrom:to:count:completion:` 获取指定时间段内本地指定会话中发送和接收的消息; ## 前提条件 开始前,请确保满足以下条件: - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 -### 从服务器分页获取会话列表 +### 从服务器获取指定会话的消息 -你可以调用 `getConversationsFromServerWithCursor:pageSize:completion` 方法从服务端分页获取会话列表。若在初始化时,将 `EMOptions#loadEmptyConversations` 设置为 `YES` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 +你可以调用 `asyncFetchHistoryMessagesFromServer` 方法从服务器获取指定会话的消息(消息漫游)。你可以指定消息查询方向,即明确按时间顺序或逆序获取。 -SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 +为确保数据可靠,我们建议你每次最多获取 50 条消息,可多次获取。拉取后,SDK 会自动将消息更新到本地数据库。 -服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。 +若你在初始化时打开了 `EMOptions#regardImportMessagesAsRead` 开关,调用该接口获取的[通过服务端接口](/server-side/message_import.html)导入的消息为已读状态,即会话中未读取的消息数量 `EMConversation#unreadMessagesCount` 不发生变化。若该开关为关闭状态,`EMConversation#unreadMessagesCount` 的数量会增加。 -:::notice -1. 若使用该功能,需将 SDK 升级至 4.0.3。 -2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `getAllConversations:` 或 `getAllConversations` 方法获取本地所有会话即可。 -3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +:::tip +1. 历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +2. 各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 ::: -示例代码如下: - ```objectivec -// pageSize: 每页返回的会话数。取值范围为 [1,50]。 -// cursor:查询的开始位置。若传入 `nil` 或 `@""`,SDK 从最新活跃的会话开始获取。 -NSString *cursor = @""; -[EMClient.sharedClient.chatManager getConversationsFromServerWithCursor:cursor pageSize:20 completion:^(EMCursorResult * _Nullable result, EMError * _Nullable error) { -}]; +// 异步方法 + [[EMClient sharedClient].chatManager asyncFetchHistoryMessagesFromServer:conversation.conversationId conversationType:conversation.type startMessageId:self.moreMsgId pageSize:10 completion:^(EMCursorResult *aResult, EMError *aError) { + [self.conversation loadMessagesStartFromId:self.moreMsgId count:10 searchDirection:EMMessageSearchDirectionUp completion:block]; + }]; ``` -### 获取服务端的置顶会话列表 - -你可以调用 `getPinnedConversationsFromServerWithCursor:limit:completion:` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 +### 从本地读取指定会话的消息 -你最多可以拉取 50 个置顶会话。 - -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 -::: - -示例代码如下: +你可以调用以下方法从数据库中读取指定会话的消息: ```objectivec -// pageSize: 每页返回的会话数。取值范围为 [1,50]。 -// cursor:查询的开始位置。若传入 `nil` 或 `@""`,SDK 从最新置顶的会话开始查询。 -NSString *cursor = @""; -[EMClient.sharedClient.chatManager getPinnedConversationsFromServerWithCursor:cursor pageSize:20 completion:^(EMCursorResult * _Nullable result, EMError * _Nullable error) { -}]; +// 获取指定会话 ID 的会话。 +EMConversation *conversation = [[EMClient sharedClient].chatManager getConversation:conversationId type:type createIfNotExist:YES]; +//startMsgId:查询的起始消息 ID; count:每次获取的消息条数。如果设为小于等于 0,SDK 获取 1 条消息。 +//searchDirection:消息搜索方向。若消息方向为 `UP`,按消息时间戳的降序获取;若为 `DOWN`,按消息时间戳的升序获取。 +NSArray *messages = [conversation loadMessagesStartFromId:startMsgId count:count searchDirection:MessageSearchDirectionUp]; ``` -### 置顶会话 - -会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 +### 根据消息 ID 获取本地消息 -置顶状态会存储在服务器上,多设备登录情况下,更新置顶状态会同步到其他登录设备。你最多可以置顶 50 个会话。 - -你可以调用 `pinConversation:isPinned:completionBlock:` 方法设置是否置顶会话。多设备登录情况下,会话置顶或取消置顶后,其他登录设备分别会收到 `EMMultiDevicesEventConversationPinned` 和 `EMMultiDevicesEventConversationUnpinned` 事件。 - -:::notice -若使用该功能,需将 SDK 升级至 4.0.3。 -::: - -示例代码如下: +你可以调用 `getMessageWithMessageId` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 ```objectivec -[EMClient.sharedClient.chatManager pinConversation:self.conversation.conversationId isPinned:aSwitch.isOn completionBlock:^(EMError * _Nullable error) { -}]; +// 同步方法 +EMConversation* conv = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; +EMError* err = nil; +// messageId:要获取消息的消息 ID。 +EMChatMessage* message = [EMClient.sharedClient.chatManager getMessageWithMessageId:@"messageId"]; ``` -你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `pinnedTime` 方法获取会话置顶时间。 +### 获取本地会话中特定类型的消息 - -### 分页获取指定会话的历史消息 - -你可以调用 `asyncFetchHistoryMessagesFromServer` 方法从服务器获取指定会话的消息(消息漫游)。你可以指定消息查询方向,即明确按时间顺序或逆序获取。为确保数据可靠,我们建议你每次最多获取 50 条消息,可多次获取。拉取后,SDK 会自动将消息更新到本地数据库。 +你可以调用 `loadMessagesWithType` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 ```objectivec // 异步方法 - [[EMClient sharedClient].chatManager asyncFetchHistoryMessagesFromServer:conversation.conversationId conversationType:conversation.type startMessageId:self.moreMsgId pageSize:10 completion:^(EMCursorResult *aResult, EMError *aError) { - [self.conversation loadMessagesStartFromId:self.moreMsgId count:10 searchDirection:EMMessageSearchDirectionUp completion:block]; - }]; -``` - -### 单向删除服务端的历史消息 - -你可以调用 `removeMessagesFromServerWithTimeStamp` 或 `removeMessagesFromServerMessageIds` 方法按消息时间或消息 ID 单向删除服务端的历史消息。每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息。其他用户不受该操作影响。登录该账号的其他设备会收到 `EMMultiDevicesDelegate` 中的 `multiDevicesMessageBeRemoved` 回调,已删除的消息自动从设备本地移除。 - -:::tip -若使用该功能,需将 SDK 升级至 V3.9.8 或以上版本并联系商务开通。 -::: - -示例代码如下: - -```Objectivec -// 按时间删除消息 -[self.conversation removeMessagesFromServerWithTimeStamp:message.timestamp completion:^(EMError * _Nullable aError) { - -}]; - -// 按消息 ID 删除消息 -[self.conversation removeMessagesFromServerMessageIds:@[@"123314142214"] completion:^(EMError * _Nullable aError) { - +EMConversation* conv = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; +// timestamp:消息搜索的起始时间戳,单位为毫秒。该参数设置后,SDK 从指定的时间戳的消息开始,按照搜索方向对消息进行搜索。若设置为负数,SDK 从当前时间开始,按消息时间戳的逆序搜索。 +// count:每次搜索的消息数量。取值范围为 [1,400]。 +// searchDirection:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +[conv loadMessagesWithType:EMMessageBodyTypeText timestamp:1671761876000 count:50 fromUser:@"" searchDirection:EMMessageSearchDirectionUp completion:^(NSArray * _Nullable aMessages, EMError * _Nullable aError) { + }]; ``` -### 单向删除服务端会话及其历史消息 +### 获取一定时间内本地会话的消息 + +你可以调用 `loadMessagesFrom:to:count:completion:` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。 -你可以调用 `deleteServerConversation` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 +每次最多可获取 400 条消息。 ```objectivec -// 删除指定会话,如果需要保留历史消息,`isDeleteServerMessages` 参数传 `NO`,异步方法。 -[[EMClient sharedClient].chatManager deleteServerConversation:@"conversationId1" conversationType:EMConversationTypeChat isDeleteServerMessages:YES completion:^(NSString *aConversationId, EMError *aError) { - // 删除回调 +// 异步方法 +EMConversation* conv = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; +// startTime:查询的起始时间戳,单位为毫秒;endTime:查询的结束时间戳,单位为毫秒;count:每次获取的消息数量。取值范围为 [1,400]。 +[conv loadMessagesFrom:startTime to:endTime count:50 completion:^(NSArray * _Nullable aMessages, EMError * _Nullable aError) { + }]; -``` \ No newline at end of file +``` diff --git a/docs/document/ios/message_search.md b/docs/document/ios/message_search.md new file mode 100644 index 000000000..36682e724 --- /dev/null +++ b/docs/document/ios/message_search.md @@ -0,0 +1,62 @@ +# 搜索消息 + + + +本文介绍环信即时通讯 IM iOS SDK 如何搜索本地消息。 + +## 技术原理 + +环信即时通讯 IM iOS SDK 支持搜索用户设备上存储的消息数据,其中包含如下主要方法: + +- `IEMChatManager.loadMessagesWithKeyword` 根据关键字搜索本地数据库中单个会话中指定用户发送的消息。 +- `EMChatManager#loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:scope:completion:`: 根据关键字搜索消息时,可以选择搜索范围在所有会话中进行消息搜索。 +- `EMConversation#loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:scope:completion:`:根据关键字搜索消息时,可以选择搜索范围在当前会话中进行消息搜索。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 根据关键字搜索会话中的用户发送的消息 + +你可以调用 `loadMessagesWithKeyword` 方法根据关键字搜索本地数据库中单个会话中指定用户发送的消息,示例代码如下: + +```swift +// 同步方法,异步方法见[EMConversation loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:completion] +EMConversation* conversation = [EMClient.sharedClient.chatManager getConversationWithConvId:@"conversationId"]; +NSArray *messages = [conversation loadMessagesWithKeyword:@"keyword" timestamp:0 count:50 fromUser:nil searchDirection:EMMessageSearchDirectionDown]; +``` + +### 根据搜索范围搜索所有会话中的消息 + +你可以调用 `EMChatManager#loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:scope:completion:` 方法,除了设置关键字、消息时间戳、消息数量、发送方、搜索方向等条件搜索所有会话中的消息时,你还可以选择搜索范围,如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.4.0 或以上版本。 +::: + +```swift +EMClient.shared().chatManager?.loadMessages(withKeyword: "keyword", timestamp: 0, count: 50, fromUser: "", searchDirection: .down, scope: .content, completion: { messages, aError in + + }) +``` + +### 根据搜索范围搜索当前会话中的消息 + +你可以调用 `EMConversation#loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:scope:completion:` 方法除了设置关键字、消息时间戳、消息数量、发送方、搜索方向等条件搜索当前会话中的消息,你还可以选择搜索范围,如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.4.0 或以上版本。 +::: + +```swift +if let conversation = EMClient.shared().chatManager?.getConversationWithConvId("conversationsId") { + conversation.loadMessages(withKeyword: "keyword", timestamp: 0, count: 50, fromUser: "", searchDirection: .down, scope: .content, completion: { messages, aError in + + }) +} +``` \ No newline at end of file diff --git a/docs/document/ios/message_send_receive.md b/docs/document/ios/message_send_receive.md index 8ef078fe2..6f3cbbafd 100644 --- a/docs/document/ios/message_send_receive.md +++ b/docs/document/ios/message_send_receive.md @@ -80,13 +80,15 @@ message.priority = EMChatRoomMessagePriorityHigh; [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:nil]; ``` +若初始化时打开了 `EMOptions#useReplacedMessageContents` 开关,发送文本消息时如果被内容审核(Moderation)进行了内容替换,发送方会收到替换后的内容。若该开关为关闭状态,则发送方不会收到替换后的内容。该属性只能在调用 `initializeSDKWithOptions` 时设置,而且 app 运行过程中不能修改该参数的设置。 + ### 接收消息 你可以用注册监听 `EMChatManagerDelegate` 接收消息。该 `EMChatManagerDelegate` 可以多次添加,请记得在不需要的时候移除 `Delegate`,如在`ViewController` `dealloc()` 时。 -在新消息到来时,你会收到 `messagesDidReceive` 的回调,消息接收时可能是一条,也可能是多条。你可以在该回调里遍历消息队列,解析并显示收到的消息。 +在新消息到来时,你会收到 `messagesDidReceive` 的回调,消息接收时可能是一条,也可能是多条。你可以在该回调里遍历消息队列,解析并显示收到的消息。若在初始化时打开了 `EMOptions#includeSendMessageInMessageListener` 开关,则该回调中会返回发送成功的消息。 -对于聊天室消息,你可以通过消息的 `EMChatMessage#broadcast` 属性判断通过该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 +对于聊天室消息,你可以通过消息的 `EMChatMessage#broadcast` 属性判断该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 ```objectivec // 添加代理。 @@ -108,33 +110,6 @@ message.priority = EMChatRoomMessagePriorityHigh; { [[EMClient sharedClient].chatManager removeDelegate:self]; } - -``` - -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `messagesInfoDidRecall` 事件。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 - -```objectivec -// 异步方法 -[[EMClient sharedClient].chatManager recallMessageWithMessageId:messageId completion:^(EMError *aError) { - if (!aError) { - NSLog(@"撤回消息成功"); - } else { - NSLog(@"撤回消息失败的原因 --- %@", aError.errorDescription); - } -}]; -``` - -#### 设置消息撤回回执 - -```objectivec -- (void)messagesDidRecall:(NSArray *)aMessages -{ - // `aMessages` 为被撤回的消息列表 -} ``` ### 发送和接收附件类型的消息 @@ -336,10 +311,14 @@ message.chatType = EMChatTypeGroupChat; ### 发送透传消息 -可以把透传消息理解为一条指令,通过发送这条指令给对方,通知对方要执行的操作,收到消息可以自定义处理。(透传消息不会存入本地数据库中,所以在 UI 上不会显示)。另外,以 “em_” 和 “easemob::” 开头的 `action` 为内部保留字段,注意不要使用。 +可以把透传消息理解为一条指令,通过发送这条指令给对方,通知对方要执行的操作,收到消息可以自定义处理。(透传消息不会存入本地数据库中,所以在 UI 上不会显示)。具体功能可以根据自身业务需求自定义,例如实现头像、昵称的更新等。另外,以 “em_” 和 “easemob::” 开头的 `action` 为内部保留字段,注意不要使用。 透传消息适用于更新头像、更新昵称等场景。 +:::tip +透传消息发送后,不支持撤回。 +::: + ```objectivec // `action` 自定义 `NSString` 类型的命令内容。 EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:action]; @@ -381,7 +360,7 @@ EMCmdMessageBody *body = [[EMCmdMessageBody alloc] initWithAction:action]; - 收到消息后,如果用户 B 与用户 A 的聊天页面处于打开状态,则显示用户 A 的输入指示器。 - 如果用户 B 在几秒后未收到用户 A 的输入,则自动取消输入指示器。 -:::notice +:::tip 用户 A 可根据需要设置透传消息发送间隔。 ::: @@ -494,19 +473,19 @@ message.chatType = EMChatTypeGroupChat; 创建合并消息体时,需要设置以下参数: -| 属性 | 类型 | 描述 | -| :--------------- | :----- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `title` | String | 合并消息的标题。 | -| `summary` | String | 合并消息的概要。 | +| 属性 | 类型 | 描述 | +| :--------------- | :----- | :------------------------------- | +| `title` | String | 合并消息的标题。 | +| `summary` | String | 合并消息的概要。 | | `compatibleText` | String | 合并消息的兼容文本。
兼容文本起向下兼容不支持消息合并转发的版本的作用。当支持合并消息的 SDK 向不支持合并消息的低版本 SDK 发送消息时,低版本的 SDK 会将该属性解析为文本消息的消息内容。 | -| `messageIdList` | List | 合并消息的原始消息 ID 列表。该列表最多包含 300 个消息 ID。 | +| `messageIdList` | List | 合并消息的原始消息 ID 列表。该列表最多包含 300 个消息 ID。 | -:::notice +:::tip 1. 合并转发支持嵌套,最多支持 10 层嵌套,每层最多 300 条消息。 2. 只有成功发送或接收的消息才能合并转发。 3. 不论 `EMOptions#isAutoTransferMessageAttachments` 设置为 `false` 或 `true`,SDK 都会将合并消息附件上传到环信服务器。 - ::: +::: 示例代码如下: @@ -552,7 +531,7 @@ EMChatMessage* msg = [[EMChatMessage alloc] initWithConversationID:@"conversatio 该功能适用于文本消息、图片消息和音视频消息等全类型消息,最多可向群组或聊天室的 20 个成员发送定向消息。 -:::notice +:::tip 1. 仅 SDK 4.0.3 及以上版本支持。 2. 定向消息不写入服务端会话列表,不计入服务端会话的未读消息数。 3. 定向消息不支持消息漫游功能,因此从服务器拉取漫游消息时,不包含定向消息。 diff --git a/docs/document/ios/message_traffic_statis.md b/docs/document/ios/message_traffic_statis.md new file mode 100644 index 000000000..8c04b4295 --- /dev/null +++ b/docs/document/ios/message_traffic_statis.md @@ -0,0 +1,66 @@ +# 获取本地消息的流量统计信息 + + + +即时通讯 IM 提供本地消息的流量统计功能。该功能默认关闭。若要使用该功能,需在 SDK 初始化前设置 `EMOptions#enableStatistics` 开启。 + +SDK 只支持统计该功能开启后最近 30 天内发送和接收的消息。各类消息的流量计算方法如下: + +- 对于文本、透传、位置消息,消息流量为消息体的流量; +- 对于图片和视频消息,消息流量为消息体、图片或视频文件以及缩略图的流量之和; +- 对于文件和语音消息,消息流量为消息体和附件的流量。 + +:::tip + 1. 统计时间段的开始时间和结束时间均为服务器接收消息的 Unix 时间戳。 + 2. 对于携带附件的消息,下载成功后 SDK 才统计附件的流量。若附件下载多次,则会对下载的流量进行累加。 + 3. 对于从服务器拉取的漫游消息,如果本地数据库中已经存在,则不进行统计。 +::: + +SDK 仅统计本地消息的流量,而非消息的实际流量。一般而言,该统计数据小于实际流量,原因如下: +- 未考虑发送消息时通用协议数据的流量; +- 对于接收到的消息,服务端会进行消息聚合,添加通用字段,而消息流量统计为各消息的流量,未考虑通用字段的流量消耗。 + +## 技术原理 + +环信即时通讯 IM Android SDK 提供 `IEMStatisticsManager` 类支持获取本地消息的流量统计信息,包含如下主要方法: + +- `IEMStatisticsManager#getMessageStatisticsById`:根据消息 ID 获取消息流量统计信息; +- `IEMStatisticsManager#getMessageCountWithStart`:获取一定时间段内发送和/或接收的指定或全部类型的消息条数; +- `IEMStatisticsManager#getMessageStatisticsSizeWithStart`:获取一定时间段内发送和/或接收的指定或全部类型的消息的总流量。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 根据消息 ID 获取消息流量统计信息 + +你可以根据消息 ID 获取指定消息的统计信息。该方法返回的消息流量统计信息包括消息 ID、消息的发送方和接收方、消息体类型、会话类型、消息方向、消息流量大小(单位为字节)以及服务器收到该消息的 Unix 时间戳。 + +示例代码如下: + +```objectivec +EMChatMessageStatistics * msgStatistics = [[[EMClient sharedClient] statisticsManager] getMessageStatisticsById:@"msgId"]; +``` + +### 获取一定时间段内发送和/或接收的消息条数 + +你可以统计一定时间段内发送和/或接收的指定或全部类型的消息,示例代码如下: + +```objectivec +NSInteger count = [EMClient.sharedClient.statisticsManager getMessageCountWithStart:startTime end:endTime direction:EMMessageStatisticsDirectionAll type:EMMessageStatisticsTypeText]; +``` + +### 获取一定时间段内发送和/或接收的消息的总流量 + +你可以统计一定时间段内发送和/或接收的指定或全部类型的消息的总流量,流量单位为字节。 + +示例代码如下: + +```objectivec +NSInteger bytes = [EMClient.sharedClient.statisticsManager getMessageStatisticsSizeWithStart:startTime end:endTime direction:EMMessageStatisticsDirectionAll type:EMMessageStatisticsTypeAll]; +``` \ No newline at end of file diff --git a/docs/document/ios/message_update.md b/docs/document/ios/message_update.md new file mode 100644 index 000000000..09eb4c83b --- /dev/null +++ b/docs/document/ios/message_update.md @@ -0,0 +1,34 @@ +# 更新消息 + + + +本文介绍环信即时通讯 IM SDK 如何更新本地消息。 + +## 技术原理 + +环信即时通讯 IM iOS SDK 支持更新本地数据库中的消息,其中包含如下主要方法: + +- `IEMChatManager.updateMessage` 更新消息到本地数据库; + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 更新消息到本地数据库 + +你可以调用 `updateMessage` 方法更新本地数据库中的消息。 + +```objectivec +// 异步方法 +[EMClient.sharedClient.chatManager updateMessage:message completion:^(EMChatMessage *aMessage, EMError *aError) { + if (!aError) { + // 更新本地消息完成。 + } +}]; +``` + diff --git a/docs/document/ios/moderation.md b/docs/document/ios/moderation.md index 5bce9758a..9cff37915 100644 --- a/docs/document/ios/moderation.md +++ b/docs/document/ios/moderation.md @@ -2,7 +2,14 @@ -即时通讯 IM SDK 提供消息举报接口。开发者可以在客户端调用该接口举报违规消息。当服务器端审核服务收到举报消息后,会将举报消息存储到数据库,并在 Console 展示。审核员可在 Console 查看举报记录,并进行相应处理。 +即时通讯 IM SDK 提供消息举报接口。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +:::tip +1. 使用前,你需要在[环信即时通讯云控制台](https://console.easemob.com/user/login) 开通该功能。 +2. 消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +关于如何开通消息举报和查看举报记录,详见[环信即时通讯云控制台文档说明](/product/enable_and_configure_IM.html#消息举报)。 ## 技术原理 @@ -13,7 +20,7 @@ 开始前,请确保满足以下条件: - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 已在 [环信即时通讯云控制台](https://console.easemob.com/user/login) 开通消息审核服务。 +- 已在 [环信即时通讯云控制台开通消息举报功能](/product/enable_and_configure_IM.html#消息举报)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 @@ -24,7 +31,7 @@ // 异步方法 // msgId:要举报的消息 ID。 // tag:非法消息的标签。你需要自定义标签,例如`涉政`或`广告`。该字段对应环信即时通讯云控制台的消息举报记录页面的`词条标记`字段。 -// reason:举报原因。你需要自行填写举报原因。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 +// reason:举报原因。你需要自行填写举报原因,最长不能超过 512 字节。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 [EMClient.sharedClient.chatManager reportMessageWithId:msgId tag:tag reason:reason diff --git a/docs/document/ios/multi_device.md b/docs/document/ios/multi_device.md index c47cef817..891ac0fac 100644 --- a/docs/document/ios/multi_device.md +++ b/docs/document/ios/multi_device.md @@ -72,11 +72,11 @@ iOS SDK 初始化时会生成登录 ID 用于在多设备登录和消息推送 ```objectivec [EMClient.sharedClient.contactManager getSelfIdsOnOtherPlatformWithCompletion:^(NSArray * _Nullable aList, EMError * _Nullable aError) { - // 选择一个登录 ID 作为消息发送方。 + // 选择一个登录 ID 作为消息接收方。 NSString *to = aList.firstObject; if (to.length > 0) { EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithText:@"Hello World"]; - // 创建一条文本消息,content 为消息文字内容,to 传入登录 ID 作为消息发送方。 + // 创建一条文本消息,content 为消息文字内容,to 传入登录 ID 作为消息接收方。 EMChatMessage *message = [[EMChatMessage alloc] initWithConversationID:to body:body ext:nil]; // 发送消息。 [EMClient.sharedClient.chatManager sendMessage:message progress:nil completion:^(EMChatMessage * _Nullable message, EMError * _Nullable error) { @@ -316,6 +316,9 @@ NSString *password = @""; // 当前用户在其他设备上删除了服务端的会话。 case EMMultiDevicesEventConversationDelete: break; + //当前用户在其他设备上更新了会话标记,包括添加和移除会话标记。 + case EMMultiDevicesEventConversationUpdateMark: + break; default: break; } diff --git a/docs/document/ios/overview.md b/docs/document/ios/overview.md index 0484a96d0..d3a92e00f 100644 --- a/docs/document/ios/overview.md +++ b/docs/document/ios/overview.md @@ -190,20 +190,32 @@ EMOptions *options = [EMOptions optionsWithAppkey:@"<#appkey#>"]; ## 输出信息到日志文件 -SDK 默认的日志输出级别为 `DEBUG`,开发阶段如果希望在环信即时通讯云管理后台上输出 SDK 日志,可在 SDK 初始化时开启以下开关: +环信即时通讯 IM 日志记录 SDK 相关的信息和事件。环信技术支持团队帮你排查问题时可能会请你发送 SDK 日志。 + +默认情况下,SDK 最多可生成和保存三个文件,`easemob.log` 和两个 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件。这些文件为 UTF-8 编码,每个不超过 2 MB。SDK 会将最新的日志写入 `easemob.log` 文件,写满时则会将其重命名为对应时间点的 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件,若日志文件超过三个,则会删除最早的文件。 + +例如,SDK 在 2024 年 1 月 1 日上午 8:00:00 记录日志时会生成 `easemob.log` 文件,若在 8:30:00 将 `easemob.log` 文件写满则会将其重命名为 `easemob_2024-01-01_08-30-00.log` 文件,随后在 9:30:30 和 10:30:30 分别生成了 `easemob_2024-01-01_09-30-30.log` 和 `easemob_2024-01-01_10-30-30.log` 文件,则此时 `easemob_2024-01-01_08-30-00.log` 文件会被移除。 + +SDK 的 `EMOptions#logLevel` 指定了日志输出级别,默认为 `EMLogLevelDebug`,即所有等级日志。 + +- (默认)EMLogLevelDebug:所有等级的日志; +- EMLogLevelWarning:警告及错误; +- EMLogLevelError:错误。 + +开发阶段若希望在 XCode console 上输出 SDK 日志,可在 SDK 初始化时打开开关。 ```objectivec EMOptions* option = [EMOptions optionsWithAppkey:@"<#appkey#>"]; -// 日志输出到环信即时通讯管理后台 +// 日志输出到 XCode console option.enableConsoleLog = YES; -// 调整日志输出级别,默认为 `Debug` +// 调整日志输出级别,默认为所有级别。 option.logLevel = EMLogLevelDebug; [EMClient.sharedClient initializeSDKWithOptions:option]; ``` ### 获取本地日志 -SDK 会写入日志文件到本地。日志文件路径如下:沙箱 Library/Application Support/HyphenateSDK/easemobLog/easemob.log。 +SDK 会写入日志文件到本地。日志文件路径如下:沙箱 Library/Application Support/HyphenateSDK/easemobLog。 以真机为例,获取本地日志过程如下: diff --git a/docs/document/ios/push.md b/docs/document/ios/push.md index 7bf3e552e..e64b43963 100644 --- a/docs/document/ios/push.md +++ b/docs/document/ios/push.md @@ -184,7 +184,7 @@ DeviceToken 注册后,iOS 系统会通过以下方式将 DeviceToken 回调给 - 设置推送通知,包含设置推送通知方式和免打扰模式。 - 配置推送翻译和推送模板。 -其中,设置推送通知方式、免打扰模式和推送模板为推送的高级功能,使用前需要在[环信即时通讯云控制后台](https://console.easemob.com/user/login)上开通。 +其中,设置推送通知方式、免打扰模式和推送模板为推送的高级功能,使用前需要在 [环信控制台](https://console.easemob.com/user/login)的**即时通讯 > 功能配置 > 功能配置总览**页面激活。如需关闭推送高级功能必须联系商务,因为该操作会删除所有相关配置。 ![image](@static/images/ios/push/push_ios_27_enable_push.png) @@ -474,19 +474,77 @@ NSArray *conversations = @[conversation1,conversation2]; #### 4.4 设置推送模板 -环信 IM 支持自定义推送通知模板。使用前,你可参考以下步骤在环信即时通讯云管理后台上创建推送模板: +你可以使用推送模板设置推送标题和内容。推送模板包括默认推送模板 `default` 和自定义推送模板,你可以通过以下两种方式设置: -1. 登录环信 IM Console,进入首页。 -2. 在 **应用列表** 区域中,点击对应 app 的 **操作** 一栏中的 **查看** 按钮。 -3. 在环信 IM 配置页面的左侧导航栏,选择 **即时通讯 > 功能配置 > 消息推送 > 模板管理**,进入推送模板管理页面。 +- [调用 REST API 配置](/document/server-side/push.html#使用推送模板)。 +- 在[环信即时通讯云控制台](https://console.easemob.com/user/login)设置推送模板,详见[控制台文档](/document/product/enable_and_configure_IM.html#配置推送模板)。 -![image](@static/images/ios/push/push_ios_28_template_mgmt.png) +使用推送模板有以下优势: -4. 点击 **添加推送模板**。弹出以下页面,进行参数配置。 +1. 自定义修改环信服务端默认推送内容。 -![image](@static/images/ios/push/push_ios_29_template_add.png) +2. 接收方可以决定使用哪个模板。 -在环信即时通讯云管理后台中完成模板创建后,用户可以在发送消息时选择此推送模板作为默认布局,如下代码示例所示: +3. 按优先级选择模板使用方式。 + +**推送通知栏内容设置的使用优先级** + +通知栏中显示的推送标题和内容可通过以下方式设置,优先级为由低到高: + +1. 发送消息时使用默认的推送标题和内容:设置推送通知的展示方式 `DisplayStyle`。推送标题为“您有一条新消息”,推送内容为“请点击查看”。 +2. 发送消息时使用默认模板:若有默认模板 `default`,发消息时无需指定。 +3. 发送消息时使用扩展字段自定义要显示的推送标题和推送内容,即 `em_push_title` 和 `em_push_content`。 +4. 接收方设置了推送模板。 +5. 发送消息时通过消息扩展字段指定模板名称。 + +##### **发送消息时使用推送模板** + +创建模板后,你可以在发送消息时选择此推送模板,分为以下三种情况: + +:::tip +若使用默认模板 **default**,消息推送时自动使用默认模板,创建消息时无需传入模板名称。 +::: + +1. 使用固定内容的推送模板,通过 `ext` 扩展字段指定推送模板名称。 + +这种情况下,创建消息时无需传入 `title_args` 和 `content_args` 参数。 + +```objectivec +//下面以文本消息为例,其他类型的消息设置方法相同。 +EMTextMessageBody *body = [[EMTextMessageBody alloc]initWithText:@"test"]; +EMChatMessage *message = [[EMChatMessage alloc]initWithConversationID:@"conversationId" from:@"currentUsername" to:@"conversationId" body:body ext:nil]; +//设置推送模板。设置前需在环信即时通讯云管理后台或调用 REST 接口创建推送模板。 +NSDictionary *pushObject = @{ + //设置推送模板名称。 + //若为默认模板 `default`,无需传入模板名称。若为自定义模板,需传入模板名称。 + @"name":@"templateName", +}; +message.ext = @{ + @"em_push_template":pushObject, +}; +message.chatType = EMChatTypeChat; +[[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:nil]; +``` + +2. 使用自定义或者默认推送模板,模板中的推送标题和推送内容使用以下内置参数: +- `{$dynamicFrom}`:服务器按优先级从高到底的顺序填充备注、群昵称(仅限群消息)和推送昵称。 +- `{$fromNickname}`:推送昵称。 +- `{$msg}`:消息内容。 + +内置参数的介绍,详见[环信即时通讯控制台文档](/product/enable_and-configure_IM.html#使用默认推送模板)。 + +这种方式的示例代码与“使用固定内容的推送模板”的相同。 + +3. 使用自定义推送模板,而且推送标题和推送内容为自定义参数: + +例如,推送模板的设置如下图所示: + +![img](@static/images/android/push/push_template_custom.png) + +使用下面的示例代码后,通知栏中弹出的推送通知为: + +您收到了一条消息
+请及时查看 ```objectivec //下面以文本消息为例,其他类型的消息设置方法相同。 @@ -494,9 +552,11 @@ EMTextMessageBody *body = [[EMTextMessageBody alloc]initWithText:@"test"]; EMChatMessage *message = [[EMChatMessage alloc]initWithConversationID:@"conversationId" from:@"currentUsername" to:@"conversationId" body:body ext:nil]; //设置推送模板。设置前需在环信即时通讯云管理后台上创建推送模板。 NSDictionary *pushObject = @{ - @"name":@"templateName",//设置推送模板名称。 - @"title_args":@[@"titleValue1"],//设置填写模板标题的 value 数组。 - @"content_args":@[@"contentValue1"]//设置填写模板内容的 value 数组。 + //设置推送模板名称。若不指定,设置默认推送模板的信息。 + //设置前需在环信即时通讯云管理后台或调用 REST 接口创建推送模板。 + @"name":@"templateName", + @"title_args":@[@"您",@"消息"],//设置填写模板标题的 value 数组。 + @"content_args":@[@"请",@"查看"]//设置填写模板内容的 value 数组。 }; message.ext = @{ @"em_push_template":pushObject, @@ -505,9 +565,36 @@ message.chatType = EMChatTypeChat; [[EMClient sharedClient].chatManager sendMessage:message progress:nil completion:nil]; ``` +##### **消息接收方使用推送模板** + +消息接收方可以调用 `setPushTemplate` 方法传入推送模板名称,选择要使用的模板。 + +:::tip +若发送方在发送消息时使用了推送模板,则推送通知栏中的显示内容以发送方的推送模板为准。 +::: + +```objective-C +[EMClient.sharedClient.pushManager setPushTemplate:@"templateName" completion:^(EMError * _Nullable aError) { + +}]; +``` + ### 5. 解析收到的推送字段 -当设备收到推送并点击时,iOS 会通过 `launchOptions` 将推送中的 JSON 传递给 app,这样就可以根据推送的内容定制 app 的一些行为,比如页面跳转等。 当收到推送通知并点击推送时,app 获取推送内容的方法: +当设备收到推送通知并点击时,iOS 系统会将推送通知中的自定义推送内容(JSON)传递给 app,这样你就可以根据推送内容自定义点击推送通知触发的行为,例如,页面跳转等。当收到推送通知并点击时,app 获取推送内容的方式如下: + +- 若 app 中使用了 `SceneDelegate`,app 的启动流程通过场景系统进行管理。当你点击离线推送的消息打开 app 时,app 将首先启动场景,然后调用 `SceneDelegate` 中的相应方法处理场景的连接和配置。你需要在 `SceneDelegate` 的 `scene(_:willConnectTo:options:)` 方法中查看 `connectionOptions` 参数获取推送内容,示例代码如下: + +```objectivec +- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { + // 获取启动选项 + NSDictionary *launchOptions = connectionOptions.notificationResponse.notification.request.content.userInfo; + // 进行相应的处理 + // ... +} +``` + +- 若 app 中不使用 `SceneDelegate`,iOS 系统会通过 `application:didFinishLaunchingWithOptions:` 方法中的 `launchOptions` 将推送中的用户自定义信息传递给 app。你需要查看 `launchOptions` 参数获取推送内容。 ```plaintext - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { @@ -516,7 +603,7 @@ message.chatType = EMChatTypeChat; ``` -userInfo: +推送中的用户自定义信息的数据结构: ```plaintext { @@ -539,8 +626,8 @@ userInfo: | `body` | 显示内容。 | | `badge` | 角标数。 | | `sound` | 提示铃声。 | -| `f` | 消息发送方 ID。 | -| `t` | 消息接收方 ID。 | +| `f` | 消息发送方的用户 ID。 | +| `t` | 消息接收方的与用户 ID。 | | `g` | 群组 ID,单聊无该字段。 | | `m` | 消息 ID。 | diff --git a/docs/document/ios/reaction.md b/docs/document/ios/reaction.md index 44641f3f4..2fa87e725 100644 --- a/docs/document/ios/reaction.md +++ b/docs/document/ios/reaction.md @@ -5,8 +5,7 @@ 环信即时通讯 IM 提供消息表情回复(下文统称 “Reaction”)功能。用户可以在单聊和群聊中对消息添加、删除表情。表情可以直观地表达情绪,利用 Reaction 可以提升用户的使用体验。同时在群组中,利用 Reaction 可以发起投票,根据不同表情的追加数量来确认投票。 :::notice -1. 目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 -2. 私有化版本不支持 Reaction 功能。 +目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 ::: ## 技术原理 diff --git a/docs/document/ios/releasenote.md b/docs/document/ios/releasenote.md index 32a136c5a..95dd4865f 100644 --- a/docs/document/ios/releasenote.md +++ b/docs/document/ios/releasenote.md @@ -2,12 +2,55 @@ -## 版本 V4.2.0 Dev 2023-11-13(开发版) +## 版本 V4.4.0 Dev 2024-01-30(开发版) ### 新增特性 -- [IM SDK] 新增[好友备注功能](user_relationship.html#设置好友备注)。 -- [IM SDK] 新增 `EMChatMessage#broadcast` 属性用于判断通过该消息是否为聊天室全局广播消息。可通过[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 +- [IM SDK] 新增 [EMChatManager#deleteAllMessagesAndConversations:completion:](message_delete.html#清空聊天记录) 方法,用于清空当前用户的聊天记录,包括消息和会话,同时可以选择是否清除服务端的聊天记录。 +- [IM SDK] 新增 [EMChatManager#loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:scope:completion:](message_search.html#根据搜索范围搜索所有会话中的消息) 和[EMConversation#loadMessagesWithKeyword:timestamp:count:fromUser:searchDirection:scope:completion:](message_search.html#根据搜索范围搜索当前会话中的消息),可以在根据关键字搜索消息时,选择搜索范围,如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。 +- [IM SDK] 新增 [EMOptions#useReplacedMessageContents](message_send_receive.html#发送文本消息) 开关。开启后,发送消息时如果被内容审核进行了内容替换,发送方可以获取替换后的内容。 +- [IM SDK] 新增 [EMOptions#includeSendMessageInMessageListener](message_send_receive.html#接收消息) 开关。开启后,在 `messagesDidReceive` 回调里增加发送成功的消息。 +- [IM SDK] 新增 [EMOptions#regardImportMessagesAsRead](message_retrieve.html#从服务器获取指定会话的消息) 开关。开启后,[利用服务端接口](/document/server-side/message_import.html)导入的消息,客户端上通过[漫游拉取](message_retrieve.html#从服务器获取指定会话的消息)到后,这些消息为已读状态,会话中未读取的消息数量 `EMConversation#unreadMessagesCount` 不发生变化。若该开关为关闭状态,`EMConversation#unreadMessagesCount` 的数量会增加。 + +### 优化 + +- [IM SDK] 群组全员禁言状态(`EMGroup#isMuteAllMembers`)存储到本地数据库,下次登录时可以直接从本地获取到。 +- [IM SDK] 转发合并消息时导致的附件重复上传问题。 + +### 修复 + +- [IM SDK] 部分场景下群成员人数计算重复问题。 +- [IM SDK] 搜索消息的关键字中带有单引号 `‘` 引起的 SQL 语句报错问题。 +- [IM SDK] 修复数据上报模块偶现的崩溃问题。 +- [IM SDK] 修复多线程同时调用 `EMClient.sharedClient.chatManager.addDelegate` 导致的偶现崩溃问题。 +- [IM SDK] 修复绑定 APNs Token 时,偶现的 Token 绑定失败的问题。 + +## 版本 V4.3.0 Dev 2023-12-22(开发版) + +### 新增特性 + +[IM SDK] 支持[会话标记功能](conversation_mark.html)。 +- `EMChatManager#addConversationMark:completion`:[标记会话](conversation_mark.html#标记会话)。 +- `EMChatManager#removeConversationMark:completion`:[取消标记会话](conversation_mark.html#取消标记会话)。 +- `EMChatManager#getConversationsFromServerWithCursor:filter:completion`:[根据会话标记从服务器分页查询会话列表](conversation_mark.html#根据会话标记从服务器分页查询会话列表)。 +- `EMConversation#marks`:[获取本地单个会话的所有标记](conversation_mark.html#获取本地单个会话的所有标记)。 +- `multiDevicesConversationEvent#EMMultiDevicesEventConversationUpdateMark`:[多设备场景下的会话标记事件](multi_device.html#获取其他设备上的操作)。当前用户在一台登录设备上更新了会话标记,包括添加和移除会话标记,其他登录设备会收到该事件。 + +### 优化 + +- [IM SDK] 移除 FPA 功能,减小 SDK 体积。 +- [IM SDK] 单个日志文件大小由 2 MB 提升到 5 MB。 +- [IM SDK] 优化附件类型消息发送时中的附件上传,支持分片上传。 + +## 版本 V4.2.0 Dev 2023-11-13 + +### 新增特性 + +- [IM SDK] 新增[设置好友备注功能](user_relationship.html#设置好友备注)。 +- [IM SDK] 新增 `getAllContactsFromServerWithCompletion` 和 `getContactsFromServerWithCursor` 方法分别[从服务器一次性和分页获取好友列表](user_relationship.html#从服务端获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。 +- [IM SDK] 新增 `getContact` 方法[从本地获取单个好友的用户 ID 和好友备注](user_relationship.html#从本地获取好友列表)。 +- [IM SDK] 新增 `getAllContacts` 方法[从本地分页获取好友列表](user_relationship.html#从本地获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。 +- [IM SDK] 新增 `EMChatMessage#broadcast` 属性用于判断该消息是否为聊天室全局广播消息。可通过[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 - [IM SDK] 新增 `EMGroupManager#getJoinedGroupsCountFromServerWithCompletion` 方法用于[从服务器获取当前用户已加入的群组数量](group_manage.html#查询当前用户已加入的群组数量)。 - [IM SDK] 新增[错误码 706](error.html) `EMErrorChatroomOwnerNotAllowLeave`,表示聊天室所有者不允许离开聊天室。若初始化时,`EMOptions#canChatroomOwnerLeave` 参数设置为 `false`,聊天室所有者调用 `leaveChatroom` 方法离开聊天室时会提示该错误。 - [IM SDK] 新增 `EMOptions#loadEmptyConversations` 属性用于在初始化时配置获取会话列表时是否允许返回空会话。 @@ -70,11 +113,11 @@ ### 新增特性 -- [IM SDK] 新增 `IEMChatManager#getConversationsFromServerWithCursor:pageSize:completion:` 方法,实现[从服务器拉取会话](message_retrieve.html#从服务器分页获取会话列表)的功能,原接口标记为已废弃。 +- [IM SDK] 新增 `IEMChatManager#getConversationsFromServerWithCursor:pageSize:completion:` 方法,实现[从服务器拉取会话](conversation_list.html#从服务器分页获取会话列表)的功能,原接口 `getConversationsFromServer` 和 `getConversationsFromServerByPage:pageSize:completion:` 标记为已废弃。 - [IM SDK] 新增置顶服务器会话的功能: - - 新增 `IEMChatManager#pinConversation:completionBlock:` 方法,实现[置顶或取消置顶服务器会话](message_retrieve.html#置顶会话): - - 新增 `IEMChatManager#getPinnedConversationsFromServerWithCursor:pageSize:completion` 方法,实现[获取置顶的服务器会话](message_retrieve.html#获取服务端的置顶会话列表)。 -- [IM SDK] 新增 `IEMChatManager#getAllConversations:` 方法,实现[从本地获取排序后的会话列表](message_manage.html#获取本地所有会话)。 + - 新增 `IEMChatManager#pinConversation:completionBlock:` 方法,实现[置顶或取消置顶服务器会话](conversation_pin.html#置顶会话): + - 新增 `IEMChatManager#getPinnedConversationsFromServerWithCursor:pageSize:completion` 方法,实现[获取置顶的服务器会话](conversation_pin.html#获取服务端的置顶会话列表)。 +- [IM SDK] 新增 `IEMChatManager#getAllConversations:` 方法,实现[从本地获取排序后的会话列表](conversation_list.html#获取本地所有会话)。 - [IM SDK] 新增在群组或聊天室中[发送定向消息](message_send_receive.html#发送和接收定向消息)功能。 ### 优化 @@ -121,7 +164,7 @@ ### 新增特性 -[IM SDK] [新增 `EMChatManager#getConversationsFromServerByPage:pageSize:completion` 方法实现从服务端分页获取会话列表](message_retrieve.html#从服务器分页获取会话列表)。 +[IM SDK] [新增 `EMChatManager#getConversationsFromServerByPage:pageSize:completion` 方法实现从服务端分页获取会话列表](conversation_list.html#从服务器分页获取会话列表)。 ### 优化 @@ -132,7 +175,7 @@ ### 新增特性 -[IM SDK] 新增[消息流量统计功能](message_manage.html#获取本地消息的流量统计信息)。 +[IM SDK] 新增[消息流量统计功能](message_traffic_statis.html#获取本地消息的流量统计信息)。 ### 修复 @@ -236,7 +279,7 @@ ### 优化 - [IM SDK] 优化网络链路,提升网络访问性能; -- [IM SDK] 优化 [拉取漫游消息接口](message_retrieve.html),增加指定拉取消息方向的参数; +- [IM SDK] 优化 [拉取漫游消息接口](message_retrieve.html#从服务器获取指定会话的消息),增加指定拉取消息方向的参数; ## 版本 V3.9.2.1 2022-5-25 diff --git a/docs/document/ios/room_attributes.md b/docs/document/ios/room_attributes.md index ac023fd45..c53a386ba 100644 --- a/docs/document/ios/room_attributes.md +++ b/docs/document/ios/room_attributes.md @@ -12,8 +12,8 @@ - 获取和更新聊天室基本属性; - 获取聊天室自定义属性; -- 设置聊天室自定义属性; -- 删除聊天室自定义属性。 +- 设置和强制设置聊天室自定义属性; +- 删除和强制删除聊天室自定义属性。 ## 前提条件 @@ -121,7 +121,9 @@ EMError *error = nil; }]; ``` -若要覆盖其他聊天室成员设置的自定义属性,需调用 `setChatroomAttributesForced` 方法。设置成功后,其他聊天室成员收到 `EMChatRoomManagerDelegate` 中的 `chatroomAttributesDidUpdated` 回调。 +#### 强制设置单个聊天室属性 + +如果除了设置自己的单个自定义属性还需覆盖其他聊天室成员设置的该属性,需调用 `setChatroomAttributesForced` 方法。设置成功后,其他聊天室成员收到 `EMChatRoomManagerDelegate` 中的 `chatroomAttributesDidUpdated` 回调。 示例代码如下: @@ -145,7 +147,9 @@ EMError *error = nil; }]; ``` -若要覆盖其他聊天室成员设置的自定义属性,需调用 `setChatroomAttributesForced` 方法。设置成功后,其他聊天室成员收到 `EMChatRoomManagerDelegate` 中的 `chatroomAttributesDidUpdated` 回调。 +#### 强制设置多个聊天室属性 + +如果除了设置自己的多个自定义属性还需覆盖其他聊天室成员设置的这些属性,需调用 `setChatroomAttributesForced` 方法。设置成功后,其他聊天室成员收到 `EMChatRoomManagerDelegate` 中的 `chatroomAttributesDidUpdated` 回调。 示例代码如下: @@ -168,7 +172,9 @@ EMError *error = nil; }]; ``` -若要删除其他聊天室成员设置的自定义属性,需调用 `removeChatroomAttributesForced` 方法。删除后聊天室其他成员收到 `EMChatRoomManagerDelegate` 中 `chatroomAttributesDidRemoved` 回调。 +#### 强制删除单个聊天室自定义属性 + +如果除了删除自己设置的单个自定义属性还需删除其他聊天室成员设置的该属性,需调用 `removeChatroomAttributesForced` 方法。删除后聊天室其他成员收到 `EMChatRoomManagerDelegate` 中 `chatroomAttributesDidRemoved` 回调。 示例代码如下: @@ -192,7 +198,9 @@ EMError *error = nil; }]; ``` -若要删除其他聊天室成员设置的自定义属性,需调用 `removeChatroomAttributesForced` 方法。删除后,聊天室其他成员收到 `EMChatRoomManagerDelegate` 中 `chatroomAttributesDidRemoved` 回调。 +#### 强制删除多个聊天室自定义属性 + +如果除了删除自己设置的多个自定义属性还需删除其他聊天室成员设置的这些属性,需调用 `removeChatroomAttributesForced` 方法。删除后,聊天室其他成员收到 `EMChatRoomManagerDelegate` 中 `chatroomAttributesDidRemoved` 回调。 示例代码如下: diff --git a/docs/document/ios/room_manage.md b/docs/document/ios/room_manage.md index df4563246..bd3566097 100644 --- a/docs/document/ios/room_manage.md +++ b/docs/document/ios/room_manage.md @@ -38,7 +38,7 @@ 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 可以调用 `createChatroomWithSubject` 方法创建聊天室,并设置聊天室的名称、描述、最大成员数等信息。成功创建聊天室后,该超级管理员为该聊天室的所有者。 -你也可以直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 +建议直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 示例代码如下: @@ -101,7 +101,7 @@ EMOptions *retOpt = [EMOptions optionsWithAppkey:@"appkey"]; retOpt.isDeleteMessagesWhenExitChatRoom = NO; ``` -与群主无法退出群组不同,聊天室所有者可以离开聊天室,例如所有者从服务器下线则 2 分钟后自动离开聊天室。如果所有者重新进入聊天室仍是该聊天室的所有者。若 `EMOptions#canChatroomOwnerLeave` 参数在初始化时设置为 `false`,聊天室所有者调用 `leaveChatroom` 方法离开聊天室时会提示错误 706 `EMErrorChatroomOwnerNotAllowLeave`。 +与群主无法退出群组不同,聊天室所有者可以离开聊天室,重新进入聊天室仍是该聊天室的所有者。若 `EMOptions#canChatroomOwnerLeave` 参数在初始化时设置为 `YES` 时,聊天室所有者可以离开聊天室;若该参数设置为 `NO`,聊天室所有者调用 `leaveChatroom` 方法离开聊天室时会提示错误 706 `EMErrorChatroomOwnerNotAllowLeave`。 ### 解散聊天室 diff --git a/docs/document/ios/room_members.md b/docs/document/ios/room_members.md index b44bb258d..1c8836497 100644 --- a/docs/document/ios/room_members.md +++ b/docs/document/ios/room_members.md @@ -42,7 +42,7 @@ EMCursorResult * result = [[EMClient sharedClient].roomManager getCha ### 将成员移出聊天室 -仅聊天室所有者和管理员可调用 `removeMembers` 方法将指定成员移出聊天室。 +仅聊天室所有者和管理员可调用 `removeMembers` 方法将单个或多个成员移出聊天室。 被移出后,该成员收到 `didDismissFromChatroom` 回调,其他成员收到 `EMChatRoomChangeListener#userDidLeaveChatroom` 回调。 @@ -52,8 +52,9 @@ EMCursorResult * result = [[EMClient sharedClient].roomManager getCha ```objectivec // 同步方法,阻塞线程,异步方法参见[EMChatroomManager removeMembers:fromChatroom:completion] -EMError *error = nil; -[[EMClient sharedClient].roomManager removeMembers:@[@"userName"] fromChatroom:@"chatroomId" error:&error]; + [EMClient.sharedClient.roomManager removeMembers:@[@"member1",@"member2"] fromChatroom:@"roomId" completion:^(EMChatroom * _Nullable aChatroom, EMError * _Nullable aError) { + + }]; ``` ### 管理聊天室黑名单 @@ -164,6 +165,7 @@ EMError *error = nil; ```objectivec // 同步方法,阻塞线程,异步方法参见[EMChatroomManager muteMembers:muteMilliseconds:fromChatroom:completion] +// `muteMilliseconds`:禁言时间。传 -1 表示永久禁言。 EMError *error = nil; [[EMClient sharedClient].roomManager muteMembers:@[@"userName"] muteMilliseconds:-1 fromChatroom:@"chatroomId" error:&error]; ``` @@ -202,7 +204,9 @@ NSArray * muteMembers = [[EMClient sharedClient].roomManager getChat #### 开启聊天室全员禁言 -仅聊天室所有者和管理员可以调用 `muteAllMembersFromChatroom` 方法开启全员禁言。全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `chatroomMuteListDidUpdate: addedMutedMembers: muteExpire` 回调。 +仅聊天室所有者和管理员可以调用 `muteAllMembersFromChatroom` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `unmuteAllMembersFromChatroom` 方法解除全员禁言。 + +全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `chatroomMuteListDidUpdate: addedMutedMembers: muteExpire` 回调。 示例代码如下: diff --git a/docs/document/ios/thread.md b/docs/document/ios/thread.md index 594924d5e..facf794b3 100644 --- a/docs/document/ios/thread.md +++ b/docs/document/ios/thread.md @@ -4,10 +4,6 @@ 子区是群组成员的子集,是支持多人沟通的即时通讯系统,本文介绍如何使用环信即时通讯 IM iOS SDK 在实时互动 app 中创建和管理子区,并实现子区相关功能。 -:::notice -私有化版本不支持子区功能。 -::: - ## 技术原理 环信即时通讯 IM iOS SDK 提供 `EMChatThreadManager`、`EMChatThread`、`EMChatThreadManagerDelegate` 和 `EMChatThreadEvent` 类,用于管理子区,支持你通过调用 API 在项目中实现如下功能: diff --git a/docs/document/ios/thread_message.md b/docs/document/ios/thread_message.md index e09af9b6a..6e4e3348e 100644 --- a/docs/document/ios/thread_message.md +++ b/docs/document/ios/thread_message.md @@ -84,7 +84,7 @@ message.isChatThread = self.isChatThread; ### 撤回子区消息 -撤回消息的具体逻辑,请参考 [撤回消息](message_send_receive.html#撤回消息),此处只介绍子区消息和其他消息的区别。 +撤回消息的具体逻辑,请参考 [撤回消息](message_recall.html),此处只介绍子区消息和其他消息的区别。 子区成员可以设置消息监听回调 `EMChatManagerDelegate#messagesInfoDidRecall` 对子区消息的撤回进行监听。 diff --git a/docs/document/ios/user_relationship.md b/docs/document/ios/user_relationship.md index ca3e731aa..683ecedfe 100644 --- a/docs/document/ios/user_relationship.md +++ b/docs/document/ios/user_relationship.md @@ -3,10 +3,12 @@ 用户登录后,可进行添加联系人、获取好友列表等操作。 + 本文介绍如何通过环信即时通讯 IM SDK 管理好友关系,包括添加、同意、拒绝、删除、查询好友,以及管理黑名单,包括添加、移出、查询黑名单。 + SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理: -- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请和删除好友等操作。 +- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请、删除好友和设置好友备注等操作。 - 黑名单管理:查询黑名单列表、将添加用户至黑名单以及从黑名单中移出用户等操作。 ## 技术原理 @@ -33,9 +35,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理 本节展示如何在项目中管理好友的添加移除和黑名单的添加移除。 -### 管理好友列表 - -#### 添加好友 +### 添加好友 添加好友部分主要功能是发送好友请求、接收好友请求、处理好友请求和好友请求处理结果回调等。 @@ -110,7 +110,7 @@ if (!aError) { { } ``` -#### 删除好友 +### 删除好友 删除联系人时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 @@ -136,9 +136,9 @@ if (!aError) { { } ``` -#### 设置好友备注 +### 设置好友备注 -你可以调用 `setContactRemark` 方法设置好友备注。 +自 4.2.0 版本开始,你可以调用 `setContactRemark` 方法设置好友备注。 好友备注的长度不能超过 100 个字符。 @@ -148,32 +148,32 @@ if (!aError) { }]; ``` -#### 获取好友列表 +### 从服务端获取好友列表 你可以从服务器获取好友列表,也可以从本地获取已保存的好友列表。 -- 从服务端获取好友列表 +自 4.2.0 版本开始,你可以调用 `getAllContactsFromServerWithCompletion` 或 `getContactsFromServerWithCursor` 方法从服务器一次性或分页获取好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 -调用以下两种方法返回好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 +- 一次性获取服务端的好友列表。 ```objectivec - -//一次性从服务端获取整个好友列表 [EMClient.sharedClient.contactManager getAllContactsFromServerWithCompletion:^(NSArray * _Nullable aList, EMError * _Nullable aError) { }]; +``` + +- 分页获取服务端的好友列表。 -//从服务端分页获取好友列表 +```objectivec //pageSize 的取值范围为 [1,50] [EMClient.sharedClient.contactManager getContactsFromServerWithCursor:@"" pageSize:50 completion:^(EMCursorResult * _Nullable aResult, EMError * _Nullable aError) { }]; ``` -你也可以调用 `getContactsFromServerWithCompletion` 方法从服务器获取所有好友的列表。该列表只包含好友的用户 ID。 +此外,你也可以调用 `getContactsFromServerWithCompletion` 方法从服务器获取所有好友的列表。该列表只包含好友的用户 ID。 ```objectivec -// 从服务器获取好友列表。 // 异步方法 [[EMClient sharedClient].contactManager getContactsFromServerWithCompletion:^(NSArray *aList, EMError *aError) { if (!aError) { @@ -184,25 +184,27 @@ if (!aError) { }]; ``` -- 从本地获取好友列表 +### 从本地获取好友列表 -:::notice +:::tip 需要从服务器获取好友列表之后,才能从本地获取到好友列表。 ::: -调用以下两种方法返回好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 +自 4.2.0 版本开始,你可以调用 `getContact` 方法从本地获取单个好友的用户 ID 和好友备注;你也可以调用 `getAllContacts` 方法一次性获取整个好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 + +- 获取本地单个好友。 ```objectivec -//从本地获取单个好友 EMContact* contact = [EMClient.sharedClient.contactManager getContact:@"userId"]; +``` +- 一次性获取本地好友列表。 -//一次性从本地获取整个好友列表 +```objectivec NSArray* contacts = [EMClient.sharedClient.contactManager getAllContacts]; - ``` -你也可以调用 `getContacts` 方法从本地获取所有好友的列表,该列表只包含好友的用户 ID。 +此外,你也可以调用 `getContacts` 方法从本地一次性获取所有好友的列表,该列表只包含好友的用户 ID。 示例代码如下: @@ -210,14 +212,12 @@ NSArray* contacts = [EMClient.sharedClient.contactManager getAllCont NSArray *userlist = [[EMClient sharedClient].contactManager getContacts]; ``` -### 管理黑名单 +### 查看当前用户黑名单列表 黑名单是与好友无任何关系的独立体系。可以将任何用户加入黑名单,不论该用户与你是否是好友关系。 黑名单功能包括加入黑名单,从黑名单移出用户和获取黑名单列表。对于获取黑名单,你可从服务器获取黑名单列表,也可从本地数据库获取已保存的黑名单列表。 -#### 查看当前用户黑名单列表 - 1. 通过服务器获取黑名单列表 从服务器获取黑名单列表之后,才能从本地数据库获取到黑名单列表。 @@ -241,7 +241,7 @@ NSArray *userlist = [[EMClient sharedClient].contactManager getContacts]; NSArray *blockList = [[EMClient sharedClient].contactManager getBlackList]; ``` -#### 将用户加入黑名单 +### 将用户加入黑名单 你可以调用 `addUserToBlackList` 将指定用户加入黑名单。用户被加入黑名单后将无法向你发送消息,也无法发送好友申请。 @@ -260,7 +260,7 @@ NSArray *blockList = [[EMClient sharedClient].contactManager getBlackList]; }]; ``` -#### 将用户移出黑名单 +### 将用户移出黑名单 你可以调用 `removeUserFromBlackList` 将用户从黑名单移除,用户发送消息等行为将恢复。 diff --git a/docs/document/linux/overview.md b/docs/document/linux/overview.md new file mode 100644 index 000000000..aa5a7aed9 --- /dev/null +++ b/docs/document/linux/overview.md @@ -0,0 +1,105 @@ +# Linux SDK 集成说明 + +------ + +环信 IM Linux SDK 是为在 Linux 及嵌入式设备中集成 IM 功能提供的 SDK,用户可以用 SDK 收发消息,目前支持文本消息、图片、语音、位置等消息以及透传消息,目前为测试版,已经可以应用在 Linux、Mac 及树莓派平台上。 + +## 集成准备 + +获取环信 IM Linux SDK,SDK 中包含如下文件: + +- libeasemob_v0.1.a +- include +- doc +- demo + +libeasemob_v0.1.a 是 SDK 静态库文件,include 目录包含 sdk 的头文件,doc 目录包含对 sdk 的详细说明,demo 包含使用 SDK 的 demo 程序。 + +## 集成示例 + +### 获取 EMChatClient + +EMChatClient 是 IM 服务的入口,可以直接调用 EMChatClient 的入口,也可以通过 EMChatClient 获得相应 EMContactManager、EMChatManager 进行相应的操作。 + +``` +#include "emchatclient.h" +... +using namespace easemob; + +EMChatClient::EMChatConfigs configs(resourcePath, workPath, "easemob-demo#chatdemoui"); +chatClient = EMChatClient::create(configs); +``` + +### 注册及登录 + +调用 chatclient 的 register()、login() 接口可以实现注册,登录功能。 + +``` +easemob::EMErrorPtr result = chatClient->register("test01", "test02"); +if(result->mErrorCode == EMError::NO_ERROR) { + cout << "login success" << endl; +} else { + cout << result->mDescription << endl; +} +``` + +登录的示例 + +``` +easemob::EMErrorPtr result = chatClient->login("test01", "test02"); +if(result->mErrorCode == EMError::NO_ERROR) { + cout << "login success" << endl; +} else { + cout << result->mDescription << endl; +} +``` + +注意:register()、login() 是需要与后台服务器通讯的操作,可能需要一定时间,如果程序想同时显示 UI 的话,需要放在单独线程中处理。 + +### 添加好友 + +管理好友的操作需要通过 EMChatManager 进行。 + +``` +chatClient->getContactManager().inviteContact("contact01", "hi, contact01"); +``` + +添加好友需要等待对方的确认,也可以由程序设置成自动接受好友邀请。 + +### 与好友聊天 + +接收消息需要实现 EMChatManagerListener 的 onReceiveMessage() 方法并且注册该 listener。 + +``` +class Chat : public easemob::EMChatManagerListener { + void onReceiveMessage(const easemob::EMMessagePtr message); +} + +chatClient->getChatManager().addListener(this); +``` + +发送消息需要创建 EMMessage 实例,目前支持文本、图片、音频文件等消息类型。 + +``` +EMTextMessageBody* body = new EMTextMessageBody("How are you, du"); +easemob::EMMessagePtr msg = EMMessage::createSendMessage(loginUser, to, body); +easemob::EMCallbackPtr callback(new easemob::EMCallback(mHandle, + [=]()->bool{ + window_->AddOutput("Msg send success"); + return true; + }, + [=](const easemob::EMErrorPtr error)->bool{ + window_->AddOutput( "Send message failed: " + error->mDescription); + return true; + })); + +chatClient->getChatManager().sendMessage(msg, callback); +``` + +请注意 callback 的定义,为了能够获知 callback 的拥有者是否仍然存在,需要在您的类中定义'EMCallbackObserverHandle'。 + +``` +easemob::EMCallbackObserverHandle mHandle; +``` + +具体接口说明及使用可以参考 SDK 中的文档和 demo 程序。 \ No newline at end of file diff --git a/docs/document/linux/releasenote.md b/docs/document/linux/releasenote.md new file mode 100644 index 000000000..6b735a0a6 --- /dev/null +++ b/docs/document/linux/releasenote.md @@ -0,0 +1,43 @@ +# Linux SDK 更新日志 + +## 版本:V0.3 2015-09-25 + +公开测试版 + +1. Support chat room. + +2. Linux demo can detect network status now. + +3. Fix the issue when user login from other device or removed from server. + +4. Add timeout when login. + +5. Remove conversation when remove a contact. + +6. optimize memory usage and performance. + +## 版本:V0.2 2015-08-25 + +公开测试版 + +1. Support group chat. + +2. Fix login delay time error. + +3. Report error when user login on another device. + +## 版本:V0.1.1 2015-08-10 + +公开测试版 + +1. Fix multi user login issue. + +2. Add auto login feature. + +3. Fix Blacklist error. + +4. optimize memory using. + +## 版本:V0.1 2015-08-03 + +公开测试版,支持文本消息、图片、语音、位置等消息以及透传消息,目前已经可以应用在 Linux、Mac 及树莓派平台上。 \ No newline at end of file diff --git a/docs/document/linux/technical_parameter.md b/docs/document/linux/technical_parameter.md new file mode 100644 index 000000000..9395e3e22 --- /dev/null +++ b/docs/document/linux/technical_parameter.md @@ -0,0 +1,8 @@ +# 技术参数 + +------ + +- 开发语言:C++11 +- 编译器:GCC 4.8.3 +- 已适配系统:Ubuntu 14.04、树莓派 +- 第三方库:libpthread、libidn、libsqlite3、libcurl、libssl、libz、libresolv \ No newline at end of file diff --git a/docs/document/react-native/conversation_delete.md b/docs/document/react-native/conversation_delete.md new file mode 100644 index 000000000..f3f878264 --- /dev/null +++ b/docs/document/react-native/conversation_delete.md @@ -0,0 +1,58 @@ +# 删除会话 + + + +删除好友或退出群组后,SDK 不会自动删除对应的单聊或群聊会话。你可以调用相应的接口从服务器和本地删除单个会话及其历史消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地删除单个会话及其历史消息,主要方法如下: + +- `ChatManager.removeConversationFromServer`:单向删除服务端的单个会话及其历史消息。 +- `ChatManager.deleteConversation`:删除本地单个会话及其历史消息。 + +## 实现方法 + +#### 单向删除服务端会话及其历史消息 + +你可以调用 `removeConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 + +示例代码如下: + +```typescript +// convId: 会话 ID。 +// convType:会话类型。 +// isDeleteMessage:删除会话时是否同时删除该会话中的消息。 +ChatClient.getInstance() + .chatManager.removeConversationFromServer(convId, convType, isDeleteMessage) + .then(() => { + console.log("remove conversions success"); + }) + .catch((reason) => { + console.log("remove conversions fail.", reason); + }); +``` + +### 删除本地会话及历史消息 + +你可以调用 `deleteConversation` 方法删除本地保存的指定会话,示例代码如下: + +```typescript +// convId: 会话 ID。 +// withMessage:删除会话时是否同时删除该会话中的消息。 +ChatClient.getInstance() + .chatManager.deleteConversation(convId, withMessage) + .then(() => { + console.log("remove conversions success"); + }) + .catch((reason) => { + console.log("remove conversions fail.", reason); + }); +``` diff --git a/docs/document/react-native/conversation_list.md b/docs/document/react-native/conversation_list.md new file mode 100644 index 000000000..76328a974 --- /dev/null +++ b/docs/document/react-native/conversation_list.md @@ -0,0 +1,71 @@ +# 会话列表 + + + +对于单聊、群组聊天和聊天室会话,用户发消息时 SDK 会自动创建会话并将会话添加至用户的会话列表。 + +环信服务器和本地均存储会话,你可以获取会话列表。**服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地获取会话列表,主要方法如下: + +- `ChatManager.fetchConversationsFromServerWithCursor`:从服务器获取会话列表。 +- `ChatManager.getAllConversationsBySort`:获取本地所有会话。 + +## 实现方法 + +### 从服务器分页获取会话列表 + +你可以调用 `fetchConversationsFromServerWithCursor` 方法从服务端分页获取会话列表,包含单聊和群组聊天会话,不包含聊天室会话。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)、会话标记以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 + +:::tip +1. **若使用该功能,需在环信控制台开通,并将 SDK 升级至 1.2.0。而且,只有开通该功能,你才能使用置顶会话功能。** +2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `getAllConversations` 方法获取本地所有会话即可。 +3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +::: + +示例代码如下: + +```typescript +// pageSize: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。如果为空字符串或传 `undefined`,SDK 从最新活跃的会话开始获取。 +ChatClient.getInstance() + .chatManager.fetchConversationsFromServerWithCursor(cursor, pageSize) + .then(() => { + console.log("get conversions success"); + }) + .catch((reason) => { + console.log("get conversions fail.", reason); + }); +``` + +若不支持 `fetchConversationsFromServerWithCursor`,你可以调用 `fetchConversationsFromServerWithPage` 接口从服务器获取会话列表。利用该接口,你总共可获取服务器最近 7 天内存储的 100 个会话。若提升这两个上限,需联系环信商务。 + +### 获取本地所有会话 + +你可以调用 `getAllConversations` 方法一次性获取本地所有会话。 + +本地会话列表包含单聊和群组聊天会话,至于是否包含聊天室会话,取决于在 SDK 初始化时 `ChatOptions#deleteMessagesAsExitChatRoom` 参数的设置。若设置为 `true`,即离开聊天室时删除该聊天室的所有本地消息,则本地会话列表中不包含聊天室会话。若设置为 `false`,即保留该聊天室的所有本地消息,则本地会话列表中包含聊天室会话。 + +若在初始化时,将 `ChatOptions#enableEmptyConversation` 设置为 `true` 允许返回空会话,则会话列表中会包含空会话,否则不包含。 + +示例代码如下: + +```typescript +ChatClient.getInstance() + .chatManager.getAllConversations() + .then(() => { + console.log("get conversions success"); + }) + .catch((reason) => { + console.log("get conversions fail.", reason); + }); +``` \ No newline at end of file diff --git a/docs/document/react-native/conversation_overview.md b/docs/document/react-native/conversation_overview.md new file mode 100644 index 000000000..4555d7fa8 --- /dev/null +++ b/docs/document/react-native/conversation_overview.md @@ -0,0 +1,69 @@ +# 会话介绍 + + + +会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息、查看或清空历史消息等操作。 + +环信即时通讯 IM SDK 提供 `ChatManager` 和 `ChatConversation` 类以会话为单位对消息数据进行管理,如获取会话列表、置顶会话、添加会话标记、删除会话和管理未读消息等。 + +## 会话类 + +环信即时通讯 IM 提供会话类 `ChatConversation`。该类定义了以下内容: + +| 类/方法 | 描述 | +| :--------- | :------- | +| ChatSearchDirection | 消息搜索方向枚举。
- `UP`:按照消息中的 Unix 时间戳的逆序搜索。
- `DOWN`:按照消息中的时间戳的正序搜索。 | +| ChatConversationType | 会话类型枚举。
- `PeerChat`:单聊会话;
- `GroupChat`:群聊会话;
- `RoomChat`:聊天室会话。| +| convId | 会话 ID,取决于会话类型。
- 单聊:会话 ID 为对方的用户 ID;
- 群聊:会话 ID 为群组 ID;
- 聊天室:会话 ID 为聊天室的 ID。 | +| convType | 会话类型。
- `Chat`:单聊会话;
- `GroupChat`:群聊会话;
- `ChatRoom`:聊天室会话。
- `HelpDesk`:客服会话。 | +| isChatThread | 是否为 thread 会话。 | +| ext | 会话扩展属性。 | +| isPinned | 是否为置顶会话。 | +| pinnedTime | 会话置顶的 UNIX 时间戳,单位为毫秒。未置顶时值为 `0`。 | +| name | 获取会话 ID。 | +| getUnreadCount | 获取会话的未读消息数量。 | +| getMessageCount | 获取会话中的消息数量。 | +| getLatestMessage | 获取指定会话的最新消息。 | +| getLatestReceivedMessage | 获取指定会话中最近接收到的消息。 | +| setConversationExtension | 设置指定会话的自定义扩展信息。 | +| markMessageAsRead | 标记指定消息为已读。 | +| markAllMessagesAsRead | 标记所有消息为已读。 | +| updateMessage | 更新本地数据库的指定消息。 | +| deleteMessage | 删除本地数据库中的指定消息。 | +| deleteMessagesWithTimestamp | 从本地数据库中删除指定时间段内的消息。 | +| deleteAllMessages | 删除内存和本地数据库中的所有消息。 | +| getMessagesWithMsgType | 从本地数据库获取会话中的指定用户发送的某些类型的消息。 | +| getMessages | 从本地数据库获取指定会话中一定数量的消息。 | +| getMessagesWithKeyword | 从本地数据库获取会话中的指定用户发送的一定数量的特定消息。 | +| getMessageWithTimestamp | 从本地数据库获取指定会话在一段时间内的消息。 | +| fetchHistoryMessages | 分页获取指定会话的历史消息。 | +| fetchHistoryMessagesByOptions | 根据消息拉取参数配置从服务器分页获取指定会话的历史消息。 | +| removeMessagesFromServerWithMsgIds | 根据消息 ID 单向删除漫游消息。 | +| removeMessagesFromServerWithTimestamp | 根据消息时间戳单向删除漫游消息。 | +| pinConversation | 置顶会话。 | + + +## 会话事件 + +`IEMChatManager` 类中提供会话事件的监听接口。开发者可以通过设置此监听,获取会话事件,并做出相应处理。如果不再使用该监听,需要移除,防止出现内存泄漏。 + +示例代码如下: + +```typescript +ChatClient.getInstance().chatManager.addMessageListener({ + onConversationRead(from: string, to?: string): void { + // 收到会话已读的事件。该事件在以下场景中触发: + // 1. 当消息接收方调用 `sendConversationReadAck` 方法,SDK 会执行此回调, + // 并将本地数据库中 `Message` 的 `hasReadAck` 置为 `true`. + // 2. 多端多设备登录时,若一端发送会话已读回执(sendConversationReadAck), + // 服务器端会将该会话的未读消息数置为 0, + // 同时其他端会回调此方法,并将本地数据库中该会话中消息的 `hasRead` 属性置为 `true`。 + }, +}); +``` + + + + + + diff --git a/docs/document/react-native/conversation_pin.md b/docs/document/react-native/conversation_pin.md new file mode 100644 index 000000000..cee099811 --- /dev/null +++ b/docs/document/react-native/conversation_pin.md @@ -0,0 +1,67 @@ +# 会话置顶 + + + +会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 + +**若使用会话置顶功能,需将 SDK 升级至 1.2.0,并[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 技术原理 + +环信即时通讯 IM 支持会话置顶,主要方法如下: + +- `ChatManager.pinConversation`:置顶会话。 +- `ChatManager.asyncFetchPinnedConversationsFromServer`:获取服务端置顶会话列表。 + +## 实现方法 + +### 置顶会话 + +你可以调用 `pinConversation` 方法设置是否置顶会话。置顶状态会存储在服务器上,多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。 + +你最多可以置顶 50 个会话。 + +示例代码如下: + +```typescript +// isPinned: 设置是否置顶会话。 +ChatClient.getInstance() + .chatManager.pinConversation(convId, isPinned) + .then(() => { + console.log("pin conversions success"); + }) + .catch((reason) => { + console.log("pin conversions fail.", reason); + }); +``` + +你可以通过 `ChatConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或查看 `pinnedTime` 字段获取会话置顶时间。 + +### 获取服务端的置顶会话列表 + +你可以调用 `fetchPinnedConversationsFromServerWithCursor` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 + +你最多可以拉取 50 个置顶会话。 + +示例代码如下: + +```typescript +// pageSize: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。若获取数据时传 `undefined` 或者空字符串(""),SDK 从最新置顶的会话开始查询。 +ChatClient.getInstance() + .chatManager.fetchPinnedConversationsFromServerWithCursor(cursor, pageSize) + .then(() => { + console.log("get conversions success"); + }) + .catch((reason) => { + console.log("get conversions fail.", reason); + }); +``` \ No newline at end of file diff --git a/docs/document/react-native/conversation_unread.md b/docs/document/react-native/conversation_unread.md new file mode 100644 index 000000000..6732ff8ad --- /dev/null +++ b/docs/document/react-native/conversation_unread.md @@ -0,0 +1,108 @@ +## 会话未读数 + + + +你可以查看本地所有会话或指定会话的未读消息数,并针对会话的未读消息数清零。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM React Native SDK 通过 `ChatManager` 类实现对本地会话的未读消息数的管理,其中核心方法如下: + +- `ChatManager#getUnreadCount`:获取本地所有会话的未读消息数。 +- `ChatManager#getConversationUnreadCount`:获取本地指定会话的未读消息数。 +- `ChatManager#markAllConversationsAsRead`:将本地所有会话的未读消息数清零。 +- `ChatManager#markAllMessagesAsRead`:对于本地指定会话的未读消息数清零。 +- `ChatManager#markMessageAsRead`:将指定会话的单条未读消息置为已读。 + +## 实现方法 + +### 获取所有会话的未读消息数 + +你可以调用 `getUnreadCount` 方法获取所有本地会话的未读消息数,示例代码如下: + +```typescript +// convId: 会话 ID +// convType:会话类型 +ChatClient.getInstance() + .chatManager.getUnreadCount() + .then((count) => { + console.log("get count success"); + }) + .catch((reason) => { + console.log("get count fail.", reason); + }); +``` + +### 获取指定会话的未读消息数 + +你可以调用 `getConversationUnreadCount` 方法获取本地指定会话的未读消息数,示例代码如下: + +```typescript +// convId: 会话 ID +// convType:会话类型 +ChatClient.getInstance() + .chatManager.getConversationUnreadCount(convId, convType) + .then((count) => { + console.log("get count success"); + }) + .catch((reason) => { + console.log("get count fail.", reason); + }); +``` + +### 将所有会话的未读消息数清零 + +你可以调用 `markAllConversationsAsRead` 方法将本地所有会话的未读消息数清零,示例代码如下: + +```typescript +ChatClient.getInstance() + .chatManager.markAllConversationsAsRead() + .then(() => { + console.log("conversions had read success"); + }) + .catch((reason) => { + console.log("conversions had read fail.", reason); + }); +``` + +### 指定会话的未读消息数清零 + +你可以调用 `markAllMessagesAsRead` 方法对本地指定会话的未读消息数清零,示例代码如下: + +```typescript +// convId:会话 ID +// convType: 会话类型 +ChatClient.getInstance() + .chatManager.markAllMessagesAsRead(convId, convType) + .then(() => { + console.log("conversions had read success"); + }) + .catch((reason) => { + console.log("conversions had read fail.", reason); + }); +``` + +### 将指定会话的单条未读消息置为已读 + +你可以调用 `markMessageAsRead` 方法将本地指定会话的单条未读消息置为已读。 + +```typescript +// convId:会话 ID +// convType: 会话类型 +// msgId:消息 ID +ChatClient.getInstance() + .chatManager.markMessageAsRead(convId, convType, msgId) + .then(() => { + console.log("conversions had read success"); + }) + .catch((reason) => { + console.log("conversions had read fail.", reason); + }); +``` diff --git a/docs/document/react-native/group_attributes.md b/docs/document/react-native/group_attributes.md index 0faf432de..c21067291 100644 --- a/docs/document/react-native/group_attributes.md +++ b/docs/document/react-native/group_attributes.md @@ -102,7 +102,7 @@ ChatClient.getInstance() #### 上传共享文件 -所有群组成员均可以调用 `uploadGroupSharedFile` 方法上传共享文件至群组,群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `ChatGroupEventListener#onSharedFileAdded` 回调。 +所有群组成员均可以调用 `uploadGroupSharedFile` 方法上传共享文件至群组,单个群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `ChatGroupEventListener#onSharedFileAdded` 回调。 示例代码如下: diff --git a/docs/document/react-native/group_manage.md b/docs/document/react-native/group_manage.md index d72c6622f..a7ac5daea 100644 --- a/docs/document/react-native/group_manage.md +++ b/docs/document/react-native/group_manage.md @@ -13,6 +13,7 @@ - 创建、解散群组 - 获取群组详情 - 获取群组列表 +- 查询当前用户已加入的群组数量 - 屏蔽和解除屏蔽群消息 - 监听群组事件 @@ -136,6 +137,10 @@ ChatClient.getInstance() - `getGroupWithId`:从内存获取群组详情。返回的结果包括群组 ID、群组名称、群组描述、群主、公告信息、群成员列表数量、消息屏蔽、是否全体禁言、权限类型等,默认不包含群成员。 - `fetchGroupInfoFromServer`:从服务器获取群组详情。返回的结果包括群组 ID、群组名称、群组描述、群组基本属性、群主、群组管理员列表、是否已屏蔽群组消息和群组是否禁用等信息。若将该方法的 `fetchMembers` 参数设置为 `true`,可获取群成员列表,默认最多包括 200 个成员。 +:::tip +对于公有群,用户即使不加入群也能获取群组详情,而对于私有群,用户只有加入了群组才能获取群详情。 +::: + ```typescript // 从本地获取群组详情。 ChatClient.getInstance() @@ -207,6 +212,19 @@ ChatClient.getInstance() }); ``` +### 查询当前用户已加入的群组数量 + +自 1.3.0 版本开始,你可以调用 `fetchJoinedGroupCount` 方法从服务器获取当前用户已加入的群组数量。单个用户可加入群组数量的上限取决于订阅的即时通讯的套餐包,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + +```typescript +ChatClient.getInstance() + .groupManager.fetchJoinedGroupCount() + .then((count: number) => { + // todo: 获取已加入群组的数目。 + }) + .catch(); +``` + ### 屏蔽和解除屏蔽群消息 群成员可以屏蔽群消息和解除屏蔽群消息。 @@ -308,6 +326,7 @@ const groupListener: ChatGroupEventListener = new (class groupId: string; decliner: string; groupName?: string | undefined; + applicant?: string; reason?: string | undefined; }): void { console.log( @@ -315,6 +334,7 @@ const groupListener: ChatGroupEventListener = new (class params.groupId, params.decliner, params.groupName, + params.applicant params.reason ); } diff --git a/docs/document/react-native/group_members.md b/docs/document/react-native/group_members.md index 28d78d8bc..b594ee137 100644 --- a/docs/document/react-native/group_members.md +++ b/docs/document/react-native/group_members.md @@ -224,7 +224,7 @@ ChatClient.getInstance() ### 群组踢人 -仅群主和群管理员可以调用 `removeMembers` 方法将指定成员移出群组。被移出群组后,该成员收到 `ChatGroupEventListener#onUserRemoved` 回调,其他群成员收到 `ChatGroupEventListener#onMemberExited` 回调。被移出群组后,该用户还可以再次加入群组。 +仅群主和群管理员可以调用 `removeMembers` 方法将单个或多个成员移出群组。被移出群组后,该成员收到 `ChatGroupEventListener#onUserRemoved` 回调,其他群成员收到 `ChatGroupEventListener#onMemberExited` 回调。被移出群组后,该用户还可以再次加入群组。 示例代码如下: @@ -423,7 +423,7 @@ ChatClient.getInstance() ```typescript // groupId:群组 ID // members:将要被禁言的成员列表 -// duration:禁言时间 +// duration:禁言时间。若传 -1,表示永久禁言。 ChatClient.getInstance() .groupManager.muteMembers(groupId, members, duration) .then(() => { @@ -477,7 +477,9 @@ ChatClient.getInstance() #### 开启全员禁言 -仅群主和群管理员可以调用 `muteAllMembers` 方法开启全员禁言。群组全员禁言开启后,所有成员收到 `ChatGroupEventListener#onAllGroupMemberMuteStateChanged` 回调,除了在白名单中的群成员,其他成员不能发言。 +仅群主和群管理员可以调用 `muteAllMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `unMuteAllMembers` 方法解除全员禁言。 + +群组全员禁言开启后,所有成员收到 `ChatGroupEventListener#onAllGroupMemberMuteStateChanged` 回调,除了在白名单中的群成员,其他成员不能发言。 示例代码如下: diff --git a/docs/document/react-native/message_delete.md b/docs/document/react-native/message_delete.md new file mode 100644 index 000000000..f4e432925 --- /dev/null +++ b/docs/document/react-native/message_delete.md @@ -0,0 +1,110 @@ +# 删除消息 + + + +本文介绍用户如何单向删除服务端以及删除本地的历史消息。 + +## 技术原理 + +环信即时通讯 IM React Native SDK 通过 `ChatManager` 类实现单向删除服务端以及本地的历史消息,主要方法如下: + +- `ChatManager#removeMessagesFromServerWithTimestamp`/`removeMessagesFromServerWithMsgIds` :单向删除服务端的历史消息; +- `ChatManager#deleteAllMessages`:删除本地指定会话的所有消息; +- `ChatManager#deleteMessagesWithTimestamp`:删除本地单个会话在指定时间段的消息。 +- `ChatManager#deleteMessage`:删除本地单个会话的指定消息; + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 单向删除服务端的历史消息 + +你可以调用 `removeMessagesFromServerWithTimestamp` 或者 `removeMessagesFromServerWithMsgIds` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息,已删除的消息自动从设备本地移除。其他用户不受该操作影响。 + +:::tip +若使用该功能,需将 SDK 升级至 V1.1.0 或以上版本并联系商务开通。 +::: + +示例代码如下: + +```typescript +// 按消息 ID 删除 +ChatClient.getInstance() + .chatManager.removeMessagesFromServerWithMsgIds(convId, convType, msgIds) + .then((result) => { + console.log("test:success:", result); + }) + .catch((error) => { + console.warn("test:error:", error); + }); +// 按时间戳删除 +ChatClient.getInstance() + .chatManager.removeMessagesFromServerWithTimestamp( + convId, + convType, + timestamp + ) + .then((result) => { + console.log("test:success:", result); + }) + .catch((error) => { + console.warn("test:error:", error); + }); +``` + +### 删除本地指定会话的所有消息 + +你可以调用 `deleteAllMessages` 方法删除指定会话的所有消息。 + +```typescript +// convId:会话 ID +// convType:会话类型 +ChatClient.getInstance() + .chatManager.deleteAllMessages(convId, convType) + .then(() => { + console.log("delete message success"); + }) + .catch((reason) => { + console.log("delete message fail.", reason); + }); +``` + +### 删除本地单个会话在指定时间段的消息 + +你可以调用 `deleteMessagesWithTimestamp` 方法删除指定时间段的本地消息。 + +```typescript +// startTs: 开始点的时间戳 +// endTs: 结束点的时间戳 +ChatClient.getInstance() + .chatManager.deleteMessagesWithTimestamp({ startTs, endTs }) + .then(() => { + console.log("delete message success"); + }) + .catch((reason) => { + console.log("delete message fail.", reason); + }); +``` + +### 删除本地单个会话的指定消息 + +你可以调用 `deleteMessage` 方法删除本地单个会话的指定消息。 + +```typescript +// convId:会话 ID +// convType: 会话类型 +// msgId:消息 ID +ChatClient.getInstance() + .chatManager.deleteMessage(convId, convType, msgId) + .then(() => { + console.log("delete message success"); + }) + .catch((reason) => { + console.log("delete message fail.", reason); + }); +``` \ No newline at end of file diff --git a/docs/document/react-native/message_deliver_only_online.md b/docs/document/react-native/message_deliver_only_online.md new file mode 100644 index 000000000..47c92c013 --- /dev/null +++ b/docs/document/react-native/message_deliver_only_online.md @@ -0,0 +1,47 @@ +# 消息仅投递在线用户 + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **支持本地存储**:消息成功发送后,写入数据库。 +3. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 技术原理 + +环信即时通讯 IM 通过 `ChatMessage` 类支持只将消息投递给在线用户: + +- `deliverOnlineOnly`:设置消息是否只投递给在线用户。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +要将消息只投递给在线用户,你需要在发送消息时将 `ChatMessage#deliverOnlineOnly` 设置为 `true`。 + +下面以发送文本消息为例进行说明: + +```ts +// 创建一条文本消息,`content` 为消息文字内容。 +// `conversationId` 为消息接收方,单聊时为对端用户 ID、群聊时为群组 ID。 +// `conversationIdType` 会话类型:单聊为 ChatMessageChatType.PeerChat,群聊为 ChatMessageChatType.GroupChat +// 消息是否只投递在线用户。(默认)`false`:不论用户是否在线均投递;`true`:只投递给在线用户。若用户离线,消息不投递。 +const message = createTextMessage(conversationId, content, conversationIdType, { + deliverOnlineOnly: true, +}); +// 发送消息。 +ChatClient.getInstance().chatManager.sendMessage(msg, { + onError: (localMsgId: string, error: ChatError) => { + // todo: 发送消息失败 + }, + onSuccess: (message: ChatMessage) => { + // todo: 发送消息成功, + }, +}); +``` diff --git a/docs/document/react-native/message_import_insert.md b/docs/document/react-native/message_import_insert.md new file mode 100644 index 000000000..6b621fdd8 --- /dev/null +++ b/docs/document/react-native/message_import_insert.md @@ -0,0 +1,58 @@ +# 导入和插入消息 + + + +本文介绍环信即时通讯 IM React Native SDK 如何在本地导入消息。 + +## 技术原理 + +环信即时通讯 IM React Native SDK 支持提供 `ChatManager` 类支持在本地导入消息,其中包含如下主要方法: + +- `importMessages`:批量导入消息到数据库。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +#### 批量导入消息到数据库 + +你可以调用 `importMessages` 方法通过导入消息列表插入多条消息。典型应用为导入历史消息到本地数据库。 + +当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 + +推荐一次导入 1,000 条以内的数据。 + +```typescript +// msgs:将要插入的消息数组 +ChatClient.getInstance() + .chatManager.importMessages(msgs) + .then(() => { + console.log("update message success"); + }) + .catch((reason) => { + console.log("update message fail.", reason); + }); +``` + +### 插入消息 + +如果你需要在本地会话中加入一条消息,比如收到某些通知消息时,可以构造一条消息写入会话。 + +例如插入一条无需发送但有需要显示给用户看的内容,类似 “XXX 撤回一条消息”、“XXX 入群”、“对方正在输入” 等。 + +消息会根据消息中的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 + +示例代码如下: + +```typescript +ChatClient.getInstance().chatManager.insertMessage(msg).then(() => { + console.log('insert message success.'); +}).catch((e) => { + console.log('insert message failed.'); +}); +``` diff --git a/docs/document/react-native/message_manage.md b/docs/document/react-native/message_manage.md deleted file mode 100644 index d3c5e0459..000000000 --- a/docs/document/react-native/message_manage.md +++ /dev/null @@ -1,608 +0,0 @@ -# 管理会话和消息 - - - -会话是一个单聊、群聊或者聊天室所有消息的集合。除了在会话中发送和接收消息,环信即时通讯 IM React Native SDK 支持以会话为单位对消息数据进行管理,如获取与管理未读消息、搜索和删除历史消息等。 - -本文介绍环信即时通讯 IM React Native SDK 如何管理会话和消息。 - -## 技术原理 - -环信即时通讯 IM React Native SDK 通过 `ChatManager` 和 `ChatConversation` 类实现对会话和消息的管理。 - -- 管理服务器端和本地的会话; -- 管理本地消息。 - -## 前提条件 - -开始前,请确保满足以下条件: - -- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 -- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 - -## 实现方法 - -### 管理服务端和本地的会话 - -#### 获取会话列表 - -对于单聊或群聊,用户发消息时会自动将对方添加到用户的会话列表。 - -你可以调用 `fetchConversationsFromServerWithCursor` 方法从服务端分页获取会话列表。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 - -服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。 - -:::tip -1. 若使用该功能,需将 SDK 升级至 1.2.0。 -2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `getAllConversations` 方法获取本地所有会话即可。 -3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 -::: - -示例代码如下: - -```typescript -// pageSize: 每页返回的会话数。取值范围为 [1,50]。 -// cursor: 开始获取数据的游标位置。如果为空字符串或传 `undefined`,SDK 从最新活跃的会话开始获取。 -ChatClient.getInstance() - .chatManager.fetchConversationsFromServerWithCursor(cursor, pageSize) - .then(() => { - console.log("get conversions success"); - }) - .catch((reason) => { - console.log("get conversions fail.", reason); - }); -``` - -你可以调用 `getAllConversations` 方法获取本地所有会话,示例代码如下: - -```typescript -ChatClient.getInstance() - .chatManager.getAllConversations() - .then(() => { - console.log("get conversions success"); - }) - .catch((reason) => { - console.log("get conversions fail.", reason); - }); -``` - -#### 获取服务端的置顶会话列表 - -你可以调用 `fetchPinnedConversationsFromServerWithCursor` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 - -你最多可以拉取 50 个置顶会话。 - -:::notice -若使用该功能,需将 SDK 升级至 1.2.0。 -::: - -示例代码如下: - -```typescript -// pageSize: 每页返回的会话数。取值范围为 [1,50]。 -// cursor: 开始获取数据的游标位置。若获取数据时传 `undefined` 或者空字符串(""),SDK 从最新置顶的会话开始查询。 -ChatClient.getInstance() - .chatManager.fetchPinnedConversationsFromServerWithCursor(cursor, pageSize) - .then(() => { - console.log("get conversions success"); - }) - .catch((reason) => { - console.log("get conversions fail.", reason); - }); -``` - -#### 置顶会话 - -会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 - -你可以调用 `pinConversation` 方法设置是否置顶会话。置顶状态会存储在服务器上,多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他登录设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。你最多可以置顶 50 个会话。 - -:::notice -若使用该功能,需将 SDK 升级至 1.2.0。 -::: - -示例代码如下: - -```typescript -// isPinned: 设置是否置顶会话。 -ChatClient.getInstance() - .chatManager.pinConversation(convId, isPinned) - .then(() => { - console.log("pin conversions success"); - }) - .catch((reason) => { - console.log("pin conversions fail.", reason); - }); -``` - -你可以通过 `ChatConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或查看 `pinnedTime` 字段获取会话置顶时间。 - -#### 分页获取指定会话的历史消息 - -环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 - -你可以调用 `fetchHistoryMessages` 方法从服务器分页获取指定会话的历史消息。该功能需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 - -为确保数据可靠,我们建议你多次调用该方法,且每次获取的消息数小于 50 条。获取到数据后,SDK 会自动将消息更新到本地数据库。 - -```typescript -// 会话 ID。 -const convId = "convId"; -// 会话类型。详见 `ChatConversationType` 枚举类型。 -const convType = ChatConversationType.PeerChat; -// 获取的最大消息数目。 -const pageSize = 10; -// 搜索的起始消息 ID。 -const startMsgId = ""; -// 消息搜索方向 -const direction = ChatSearchDirection.UP; -ChatClient.getInstance() - .chatManager.fetchHistoryMessages(convId, chatType, { - pageSize, - startMsgId, - direction, - }) - .then((messages) => { - console.log("get message success: ", messages); - }) - .catch((reason) => { - console.log("load conversions fail.", reason); - }); -``` - -你可以调用 `getConversation` 方法从本地获取指定会话 ID 的会话,如果不存在可以创建。 - -```typescript -// convId: 会话 ID。 -// convType: 会话类型。 -// createIfNeed:如果不存在则创建设置该值为 true。 -ChatClient.getInstance() - .chatManager.getConversation(convId, convType, createIfNeed) - .then(() => { - console.log("get conversions success"); - }) - .catch((reason) => { - console.log("get conversions fail.", reason); - }); -``` - -### 单向删除服务端的历史消息 - -你可以调用 `removeMessagesFromServerWithTimestamp` 或者 `removeMessagesFromServerWithMsgIds` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息,已删除的消息自动从设备本地移除。其他用户不受该操作影响。 - -:::tip -若使用该功能,需将 SDK 升级至 V1.1.0 或以上版本并联系商务。 -::: - -示例代码如下: - -```typescript -// 按消息 ID 删除 -ChatClient.getInstance() - .chatManager.removeMessagesFromServerWithMsgIds(convId, convType, msgIds) - .then((result) => { - console.log("test:success:", result); - }) - .catch((error) => { - console.warn("test:error:", error); - }); -// 按时间戳删除 -ChatClient.getInstance() - .chatManager.removeMessagesFromServerWithTimestamp( - convId, - convType, - timestamp - ) - .then((result) => { - console.log("test:success:", result); - }) - .catch((error) => { - console.warn("test:error:", error); - }); -``` - -#### 单向删除服务端会话及其历史消息 - -你可以调用 `removeConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。该功能需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 - -示例代码如下: - -```typescript -// convId: 会话 ID。 -// convType:会话类型。 -// isDeleteMessage:删除会话时是否同时删除该会话中的消息。 -ChatClient.getInstance() - .chatManager.removeConversationFromServer(convId, convType, isDeleteMessage) - .then(() => { - console.log("remove conversions success"); - }) - .catch((reason) => { - console.log("remove conversions fail.", reason); - }); -``` - -你可以调用 `deleteConversation` 方法删除本地保存的指定会话,示例代码如下: - -```typescript -// convId: 会话 ID。 -// withMessage:删除会话时是否同时删除该会话中的消息。 -ChatClient.getInstance() - .chatManager.deleteConversation(convId, withMessage) - .then(() => { - console.log("remove conversions success"); - }) - .catch((reason) => { - console.log("remove conversions fail.", reason); - }); -``` - -#### 更新本地会话中的消息 - -你可以调用 `updateConversationMessage` 方法更新本地会话中的消息,示例代码如下: - -```typescript -// convId: 会话 ID。 -// contType:会话类型。 -// msg: 要更新的消息。 -ChatClient.getInstance() - .chatManager.updateConversationMessage(convId, convType, msg) - .then(() => { - console.log("update success"); - }) - .catch((reason) => { - console.log("update fail.", reason); - }); -``` - -### 管理本地消息 - -#### 根据消息 ID 搜索消息 - -你可以调用 `getMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 - -```typescript -// msgId: 要获取的消息的消息 ID。 -ChatClient.getInstance() - .chatManager.getMessage(msgId) - .then((message) => { - console.log("get message success"); - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取指定会话中特定类型的消息 - -你可以调用 `getMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 - -```typescript -// convId: 会话 ID。 -// convType:会话类型:单聊、群聊和聊天室分别为 `PeerChat`、`GroupChat` 和 `RoomChat`。 -// msgType: 消息类型。 -// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -// timestamp:消息搜索的起始时间戳,单位为毫秒。该参数设置后,SDK 从指定的时间戳的消息开始,按照搜索方向对消息进行搜索。若设置为负数,SDK 从当前时间开始,按消息时间戳的逆序搜索。 -// count: 每次搜索的消息数量。取值范围为 [1,400]。 -// sender:消息发送方。 -ChatClient.getInstance() - .getMessagesWithMsgType( - convId, - convType, - msgType, - direction, - timestamp, - count, - sender - ) - .then((messages) => { - console.log("get message success"); - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取指定会话中一定时间段内的消息 - -你可以调用 `getMessageWithTimestamp` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。每次最多可获取 400 条消息。 - -```typescript -// convId:会话 ID。 -// convType:会话类型:单聊、群聊和聊天室分别为 `PeerChat`、`GroupChat` 和 `RoomChat`。 -// startTime:搜索的起始时间戳,单位为毫秒。 -// endTime:搜索的结束时间戳,单位为毫秒。 -// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -// count:每次获取的消息数量。取值范围为 [1,400]。 -ChatClient.getInstance() - .getMessageWithTimestamp( - convId, - convType, - startTime, - endTime, - direction, - count - ) - .then((messages) => { - console.log("get message success"); - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取指定会话中包含特定关键字的消息 - -你可以调用 `getMessagesWithKeyword` 方法从本地数据库获取会话中的指定用户发送的包含特定关键字的消息,示例代码如下: - -```typescript -// convId: 会话 ID。 -// convType:会话类型。 -// keywords: 搜索关键字。 -// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -// timestamp:搜索起始时间戳。 -// count: 每次获取的消息数量。取值范围为 [1,400]。 -// sender:消息发送方。 -ChatClient.getInstance() - .getMessagesWithKeyword( - convId, - convType, - keywords, - direction, - timestamp, - count, - sender - ) - .then((messages) => { - console.log("get message success"); - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取指定用户在一定时间内发送包含关键字的消息 - -你可以调用 `searchMsgFromDB` 方法获取指定用户在一定时间内发送的包含关键字的消息。 - -```typescript -// keywords: 搜索消息的关键字。 -// timestamp:搜索起始时间戳。 -// maxCount: 每次获取的消息数量。取值范围为 [1,400]。 -// from: 消息发送方。 -// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -ChatClient.getInstance() - .chatManager.searchMsgFromDB(keywords, timestamp, maxCount, from, direction) - .then((messages) => { - console.log("get message success"); - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取指定会话中一定数量的消息 - -你可以调用 `getMessages` 获取指定会话中一定数量的消息。 - -```typescript -// convId: 会话 ID。 -// convType:会话类型。 -// startMsgId: 搜索的起始消息 ID。 -// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -// loadCount: 每次获取的消息数量。取值范围为 [1,400]。 -ChatClient.getInstance() - .getMessages(convId, convType, startMsgId, direction, loadCount) - .then((messages) => { - console.log("get message success"); - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取指定会话的最新消息 - -你可以调用 `getLatestMessage` 方法获取指定会话中的最新一条消息。 - -```typescript -// convId: 会话 ID。 -// convType:会话类型。 -ChatClient.getInstance() - .getLatestMessage(convId, convType) - .then((message) => { - console.log("get message success"); - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取指定会话最新接收到的消息 - -你可以调用 `getLastReceivedMessage` 方法获取指定会话中最新收到的一条消息。 - -```typescript -// convId: 会话 ID -// convType:会话类型 -ChatClient.getInstance() - .getLastReceivedMessage(convId, convType) - .then((message) => { - if (message) { - console.log("get message success"); - } else { - console.log("message not find."); - } - }) - .catch((reason) => { - console.log("get message fail.", reason); - }); -``` - -#### 获取所有会话的未读消息数 - -你可以调用 `getUnreadCount` 方法获取所有会话的未读消息数。 - -```typescript -// convId: 会话 ID -// convType:会话类型 -ChatClient.getInstance() - .chatManager.getUnreadCount() - .then((count) => { - console.log("get count success"); - }) - .catch((reason) => { - console.log("get count fail.", reason); - }); -``` - -#### 获取指定会话的未读消息数 - -你可以调用 `getConversationUnreadCount` 方法获取指定会话的未读消息数。 - -```typescript -// convId: 会话 ID -// convType:会话类型 -ChatClient.getInstance() - .chatManager.getConversationUnreadCount(convId, convType) - .then((count) => { - console.log("get count success"); - }) - .catch((reason) => { - console.log("get count fail.", reason); - }); -``` - -#### 标记所有会话中的消息已读 - -你可以调用 `markAllConversationsAsRead` 方法标记所有会话中的消息已读。 - -```typescript -ChatClient.getInstance() - .chatManager.markAllConversationsAsRead() - .then(() => { - console.log("conversions had read success"); - }) - .catch((reason) => { - console.log("conversions had read fail.", reason); - }); -``` - -#### 标记指定会话所有消息已读 - -你可以调用 `markAllMessagesAsRead` 方法标记指定会话所有消息已读。 - -```typescript -// convId:会话 ID -// convType: 会话类型 -ChatClient.getInstance() - .chatManager.markAllMessagesAsRead(convId, convType) - .then(() => { - console.log("conversions had read success"); - }) - .catch((reason) => { - console.log("conversions had read fail.", reason); - }); -``` - -#### 标记指定会话中的指定消息已读 - -你可以调用 `markMessageAsRead` 方法标记指定会话中的指定消息已读。 - -```typescript -// convId:会话 ID -// convType: 会话类型 -// msgId:消息 ID -ChatClient.getInstance() - .chatManager.markMessageAsRead(convId, convType, msgId) - .then(() => { - console.log("conversions had read success"); - }) - .catch((reason) => { - console.log("conversions had read fail.", reason); - }); -``` - -#### 更新指定消息 - -你可以调用 `updateMessage` 方法更新指定消息。 - -```typescript -ChatClient.getInstance() - .chatManager.updateMessage(newMsg) - .then(() => { - console.log("update message success"); - }) - .catch((reason) => { - console.log("update message fail.", reason); - }); -``` - -#### 导入消息列表 - -你可以调用 `importMessages` 方法通过导入消息列表插入多条消息。典型应用为导入历史消息到本地数据库。 - -当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 - -```typescript -// msgs:将要插入的消息数组 -ChatClient.getInstance() - .chatManager.importMessages(msgs) - .then(() => { - console.log("update message success"); - }) - .catch((reason) => { - console.log("update message fail.", reason); - }); -``` - -#### 删除指定会话的指定本地消息 - -你可以调用 `deleteMessage` 方法删除指定会话的指定本地消息。 - -```typescript -// convId:会话 ID -// convType: 会话类型 -// msgId:消息 ID -ChatClient.getInstance() - .chatManager.deleteMessage(convId, convType, msgId) - .then(() => { - console.log("delete message success"); - }) - .catch((reason) => { - console.log("delete message fail.", reason); - }); -``` - -#### 删除指定会话的所有本地消息 - -你可以调用 `deleteAllMessages` 方法删除指定会话的所有本地消息。 - -```typescript -// convId:会话 ID -// convType:会话类型 -ChatClient.getInstance() - .chatManager.deleteAllMessages(convId, convType) - .then(() => { - console.log("delete message success"); - }) - .catch((reason) => { - console.log("delete message fail.", reason); - }); -``` - -#### 删除指定时间段的本地消息 - -你可以调用 `deleteMessagesWithTimestamp` 方法删除指定时间段的消息。 - -```typescript -// startTs: 开始点的时间戳 -// endTs: 结束点的时间戳 -ChatClient.getInstance() - .chatManager.deleteMessagesWithTimestamp({ startTs, endTs }) - .then(() => { - console.log("delete message success"); - }) - .catch((reason) => { - console.log("delete message fail.", reason); - }); -``` diff --git a/docs/document/react-native/message_modify.md b/docs/document/react-native/message_modify.md index 3df116e48..fbc595242 100644 --- a/docs/document/react-native/message_modify.md +++ b/docs/document/react-native/message_modify.md @@ -1,6 +1,15 @@ # 修改消息 -对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。消息内容修改流程如下: +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。 + +:::tip +1. 若使用该功能,需将 SDK 升级至 1.2.0 或以上版本。 +2. 聊天室会话不支持消息修改功能。 +::: + +## 技术原理 + +消息内容修改流程如下: 1. 用户调用 SDK 的 API 修改一条消息。 2. 服务端存储的该条消息,修改成功后回调给 SDK。 @@ -13,10 +22,14 @@ - 对于单聊会话,只有消息发送方才能对消息进行修改。 - 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -:::notice -1. 若使用该功能,需将 SDK 升级至 1.2.0 或以上版本。 -2. 聊天室会话不支持消息修改功能。 -::: +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 你可以调用 `modifyMessageBody` 方法修改已经发送成功的消息。一条消息默认最多可修改 10 次,若要提升修改次数,需联系商务。 diff --git a/docs/document/react-native/message_recall.md b/docs/document/react-native/message_recall.md new file mode 100644 index 000000000..2000178ff --- /dev/null +++ b/docs/document/react-native/message_recall.md @@ -0,0 +1,56 @@ +# 撤回消息 + + + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能**页面设置消息撤回时长,该时长不超过 7 天。 + +:::tip +除了透传消息,其他各类型的消息都支持撤回。 +::: + +## 技术原理 + +环信即时通讯 IM 通过 `ChatManager` 类和 `ChatMessage` 类支持你撤回一条发送成功的消息: + +- `recallMessage`:撤回一条发送成功的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 撤回消息 + +你可以调用 `recallMessage` 方法撤回一条发送成功的消息。 + +调用该方法后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `onMessagesRecalled` 事件。 + +```typescript +ChatClient.getInstance() + .chatManager.recallMessage(msgId) + .then(() => { + console.log("recall message success"); + }) + .catch((reason) => { + console.log("recall message fail.", reason); + }); +``` + +### 设置消息撤回监听 + +你可以设置消息撤回监听,通过 `onMessagesRecalled` 事件监听发送方对已接收的消息的撤回。 + +```typescript +let listener = new (class implements ChatMessageEventListener { + onMessagesRecalled(messages: ChatMessage[]): void { + // 消息撤回通知,messages 为撤销的消息 + } +})(); +ChatClient.getInstance().chatManager.addMessageListener(listener); +``` \ No newline at end of file diff --git a/docs/document/react-native/message_receipt.md b/docs/document/react-native/message_receipt.md index 851431c2d..d0f793cf4 100644 --- a/docs/document/react-native/message_receipt.md +++ b/docs/document/react-native/message_receipt.md @@ -1,9 +1,9 @@ -# 管理消息回执 +# 实现消息回执 单聊会话支持消息送达回执、会话已读回执和消息已读回执,发送方发送消息后可及时了解接收方是否及时收到并阅读了信息,也可以了解整个会话是否已读。 -群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 本文介绍如何使用环信即时通讯 IM React Native SDK 实现单聊和群聊的消息回执功能。 @@ -37,7 +37,7 @@ - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 -- 群消息已读回执功能仅在环信 IM 旗舰版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +- 群消息已读回执功能仅在环信 IM 专业版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 ## 实现方法 @@ -151,6 +151,8 @@ ChatClient.getInstance().chatManager.addMessageListener(listener); ##### 消息已读回执 +单聊消息的已读回执有效期与消息在服务端的存储时间一致,即在服务器存储消息期间均可发送已读回执。消息在服务端的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + 参考如下步骤在单聊中实现消息已读回执。 1. 开启全局的消息已读回执开关。如果全局设置不开启,消息和会话的相应设置也无法生效。 @@ -230,7 +232,9 @@ ChatClient.getInstance() 对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。 -仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊已读回执的有效期为 3 天,即群组中的消息发送时间超过 3 天,服务器不记录阅读该条消息的群组成员,也不会发送已读回执。 + +仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 1. 消息发送方需要知道群组消息是否已读,需要监听 `onGroupMessageRead` 事件。 diff --git a/docs/document/react-native/message_retrieve.md b/docs/document/react-native/message_retrieve.md new file mode 100644 index 000000000..549d2ce37 --- /dev/null +++ b/docs/document/react-native/message_retrieve.md @@ -0,0 +1,215 @@ +# 获取历史消息 + + + +本文介绍环信即时通讯 IM React Native SDK 如何从服务器和本地获取历史消息。 + +- 环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 + +- SDK 内部使用 SQLite 保存本地消息,你可以获取本地消息。 + +## 技术原理 + +环信即时通讯 IM React Native SDK 通过 `ChatManager` 和 `ChatConversation` 类实现对会话和消息的管理。 + +- `fetchHistoryMessages`:从服务器分页获取指定会话的历史消息; +- `getMessage`:根据消息 ID 获取本地消息; +- `getMessagesWithMsgType`:获取本地指定会话中特定类型的消息; +- `getMessageWithTimestamp` :获取本地指定会话中一定时间段内的消息; +- `getMessages`:获取本地指定会话中一定数量的消息; +- `getLatestMessage`:获取本地指定会话的最新消息; +- `getLastReceivedMessage`:获取本地指定会话最新接收到的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 从服务器获取指定会话的消息 + +对于单聊或群聊,用户发消息时,会自动将对方添加到用户的会话列表。 + +你可以调用 `fetchHistoryMessages` 方法从服务器分页获取指定会话的历史消息(消息漫游)。为确保数据可靠,我们建议你多次调用该方法,且每次获取的消息数小于 50 条。获取到数据后,SDK 会自动将消息更新到本地数据库。 + +:::tip +1. 历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +2. 各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 +::: + +```typescript +// 会话 ID。 +const convId = "convId"; +// 会话类型。详见 `ChatConversationType` 枚举类型。 +const convType = ChatConversationType.PeerChat; +// 获取的最大消息数目。 +const pageSize = 10; +// 搜索的起始消息 ID。 +const startMsgId = ""; +// 消息搜索方向 +const direction = ChatSearchDirection.UP; +ChatClient.getInstance() + .chatManager.fetchHistoryMessages(convId, chatType, { + pageSize, + startMsgId, + direction, + }) + .then((messages) => { + console.log("get message success: ", messages); + }) + .catch((reason) => { + console.log("load conversions fail.", reason); + }); +``` + +你可以调用 `getConversation` 方法从本地获取指定会话 ID 的会话,如果不存在可以创建。 + +```typescript +// convId: 会话 ID。 +// convType: 会话类型。 +// createIfNeed:如果不存在则创建设置该值为 true。 +ChatClient.getInstance() + .chatManager.getConversation(convId, convType, createIfNeed) + .then(() => { + console.log("get conversions success"); + }) + .catch((reason) => { + console.log("get conversions fail.", reason); + }); +``` + +### 根据消息 ID 获取本地消息 + +你可以调用 `getMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 + +```typescript +// msgId: 要获取的消息的消息 ID。 +ChatClient.getInstance() + .chatManager.getMessage(msgId) + .then((message) => { + console.log("get message success"); + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` + +### 获取本地会话中特定类型的消息 + +你可以调用 `getMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 + +```typescript +// convId: 会话 ID。 +// convType:会话类型:单聊、群聊和聊天室分别为 `PeerChat`、`GroupChat` 和 `RoomChat`。 +// msgType: 消息类型。 +// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +// timestamp:消息搜索的起始时间戳,单位为毫秒。该参数设置后,SDK 从指定的时间戳的消息开始,按照搜索方向对消息进行搜索。若设置为负数,SDK 从当前时间开始,按消息时间戳的逆序搜索。 +// count: 每次搜索的消息数量。取值范围为 [1,400]。 +// sender:消息发送方。 +ChatClient.getInstance() + .getMessagesWithMsgType( + convId, + convType, + msgType, + direction, + timestamp, + count, + sender + ) + .then((messages) => { + console.log("get message success"); + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` + +### 获取一定时间内本地会话的消息 + +你可以调用 `getMessageWithTimestamp` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。每次最多可获取 400 条消息。 + +```typescript +// convId:会话 ID。 +// convType:会话类型:单聊、群聊和聊天室分别为 `PeerChat`、`GroupChat` 和 `RoomChat`。 +// startTime:搜索的起始时间戳,单位为毫秒。 +// endTime:搜索的结束时间戳,单位为毫秒。 +// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +// count:每次获取的消息数量。取值范围为 [1,400]。 +ChatClient.getInstance() + .getMessageWithTimestamp( + convId, + convType, + startTime, + endTime, + direction, + count + ) + .then((messages) => { + console.log("get message success"); + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` + +### 获取本地会话中一定数量的消息 + +你可以调用 `getMessages` 获取本地指定会话中一定数量的消息。 + +```typescript +// convId: 会话 ID。 +// convType:会话类型。 +// startMsgId: 搜索的起始消息 ID。 +// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +// loadCount: 每次获取的消息数量。取值范围为 [1,400]。 +ChatClient.getInstance() + .getMessages(convId, convType, startMsgId, direction, loadCount) + .then((messages) => { + console.log("get message success"); + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` + +### 获取指定会话的最新消息 + +你可以调用 `getLatestMessage` 方法获取指定会话中的最新一条消息。 + +```typescript +// convId: 会话 ID。 +// convType:会话类型。 +ChatClient.getInstance() + .getLatestMessage(convId, convType) + .then((message) => { + console.log("get message success"); + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` + +### 获取指定会话最新接收到的消息 + +你可以调用 `getLastReceivedMessage` 方法获取指定会话中最新收到的一条消息。 + +```typescript +// convId: 会话 ID +// convType:会话类型 +ChatClient.getInstance() + .getLastReceivedMessage(convId, convType) + .then((message) => { + if (message) { + console.log("get message success"); + } else { + console.log("message not find."); + } + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` + diff --git a/docs/document/react-native/message_search.md b/docs/document/react-native/message_search.md new file mode 100644 index 000000000..23609a18c --- /dev/null +++ b/docs/document/react-native/message_search.md @@ -0,0 +1,71 @@ +# 搜索消息 + + + +本文介绍环信即时通讯 IM React Native SDK 如何搜索本地消息。 + +## 技术原理 + +环信即时通讯 IM React Native SDK 通过 `ChatManager` 类支持搜索用户设备上存储的消息数据,其中包含如下主要方法: + +- `getMessagesWithKeyword`:根据关键字搜索本地数据库中单个会话中指定用户发送的消息。 +- `searchMsgFromDB`:根据关键字搜索指定用户在一定时间内发送的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 获取指定会话中包含特定关键字的消息 + +你可以调用 `getMessagesWithKeyword` 方法根据关键字搜索本地数据库中单个会话中指定用户发送的消息,示例代码如下: + +```typescript +// convId: 会话 ID。 +// convType:会话类型。 +// keywords: 搜索关键字。 +// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +// timestamp:搜索起始时间戳。 +// count: 每次获取的消息数量。取值范围为 [1,400]。 +// sender:消息发送方。 +ChatClient.getInstance() + .getMessagesWithKeyword( + convId, + convType, + keywords, + direction, + timestamp, + count, + sender + ) + .then((messages) => { + console.log("get message success"); + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` + +### 获取指定用户在一定时间内发送包含关键字的消息 + +你可以调用 `searchMsgFromDB` 方法根据关键字搜索指定用户在一定时间内发送的消息。 + +```typescript +// keywords: 搜索消息的关键字。 +// timestamp:搜索起始时间戳。 +// maxCount: 每次获取的消息数量。取值范围为 [1,400]。 +// from: 消息发送方。 +// direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +ChatClient.getInstance() + .chatManager.searchMsgFromDB(keywords, timestamp, maxCount, from, direction) + .then((messages) => { + console.log("get message success"); + }) + .catch((reason) => { + console.log("get message fail.", reason); + }); +``` diff --git a/docs/document/react-native/message_send_receive.md b/docs/document/react-native/message_send_receive.md index 1d545be63..cb6db1340 100644 --- a/docs/document/react-native/message_send_receive.md +++ b/docs/document/react-native/message_send_receive.md @@ -19,14 +19,13 @@ ## 技术原理 -环信即时通讯 IM React Native SDK 通过 `ChatManager` 类和 `ChatMessage` 类实现消息的发送、接收与撤回。 +环信即时通讯 IM React Native SDK 通过 `ChatManager` 类和 `ChatMessage` 类实现消息的发送和接收。 其中,发送和接收消息的逻辑如下: 1. 发送方调用相应创建方法创建文本、文件、附件等类型的消息; -2. 发送方再调用发送方法发送消息; -3. 发送方可通过撤销方法撤回自己发出的消息; -4. 通过监听器接收消息。 +2. 发送方调用发送方法发送消息; +3. 通过监听器接收消息。 消息收发流程如下: @@ -115,6 +114,8 @@ ChatClient.getInstance().chatManager.sendMessage(msg!, callback).then().catch(); 在新消息到来时,你会收到 `onMessagesReceived` 的回调,消息接收时可能是一条,也可能是多条。你可以在该回调里遍历消息队列,解析并显示收到的消息。 +对于聊天室消息,你可以通过消息的 `ChatMessage.isBroadcast` 属性判断该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 + ```typescript // 继承并实现 ChatMessageEventListener class ChatMessageEvent implements ChatMessageEventListener { @@ -135,34 +136,6 @@ ChatClient.getInstance().chatManager.removeMessageListener(listener); ChatClient.getInstance().chatManager.removeAllMessageListener(); ``` -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `onMessagesRecalled` 事件。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 - -```typescript -ChatClient.getInstance() - .chatManager.recallMessage(msgId) - .then(() => { - console.log("recall message success"); - }) - .catch((reason) => { - console.log("recall message fail.", reason); - }); -``` - -### 设置消息撤回监听 - -```typescript -let listener = new (class implements ChatMessageEventListener { - onMessagesRecalled(messages: ChatMessage[]): void { - // 消息撤回通知,messages 为撤销的消息 - } -})(); -ChatClient.getInstance().chatManager.addMessageListener(listener); -``` - ### 发送和接收附件类型的消息 除文本消息外,SDK 还支持发送附件类型消息,包括语音、图片、视频和文件消息。 @@ -338,7 +311,6 @@ ChatClient.getInstance() ```typescript // 构建位置消息 // 位置消息可以传递经纬度和地名信息 -// 当你需要发送位置时,需要集成第三方的地图服务,获取到位置点的经纬度信息。接收方接收到位置消息时,需要将该位置的经纬度,借由第三方的地图服务,将位置在地图上显示出来。 const latitude = "114.78"; const longitude = "39,89"; const address = "darwin"; @@ -356,6 +328,10 @@ EMClient.getInstance().chatManager().sendMessage(msg, callback).then().catch(); 透传消息可视为命令消息,通过发送这条命令给对方,通知对方要进行的操作,收到消息可以自定义处理。(透传消息不会存入本地数据库中,所以在 UI 上不会显示)。具体功能可以根据自身业务需求自定义,例如实现头像、昵称的更新等。另外,以 “em_” 和 “easemob::” 开头的 action 为内部保留字段,注意不要使用。 +:::tip +透传消息发送后,不支持撤回。 +::: + ```typescript // 构建透传消息 // 根据透传消息可以执行具体的命令,命令的内容格式支持自定义 @@ -389,7 +365,7 @@ ChatClient.getInstance().chatManager.addMessageListener(listener); - 收到消息后,如果用户 B 与用户 A 的聊天页面处于打开状态,则显示用户 A 的输入指示器。 - 如果用户 B 在几秒后未收到用户 A 的输入,则自动取消输入指示器。 -:::notice +:::tip 用户 A 可根据需要设置透传消息发送间隔。 @@ -457,15 +433,15 @@ EMClient.getInstance().chatManager().sendMessage(msg, callback).then().catch(); | `title` | String | 合并消息的标题。 | | `summary` | String | 合并消息的概要。 | | `compatibleText` | String | 合并消息的兼容文本。
兼容文本起向下兼容不支持消息合并转发的版本的作用。当支持合并消息的 SDK 向不支持合并消息的低版本 SDK 发送消息时,低版本的 SDK 会将该属性解析为文本消息的消息内容。 | -| `chatType` | String | 会话类型:单聊、群聊或聊天室。 | +| `chatType` | String | 会话类型:单聊、群聊或聊天室。 | | `targetId` | String | 消息接收方。该字段的设置取决于会话类型:
- 单聊:对方用户 ID;
- 群聊:群组 ID;
- 子区会话:子区 ID;
- 聊天室聊天:聊天室 ID。| | `msgIdList` | List | 合并消息的原始消息 ID 列表。该列表最多包含 300 个消息 ID。 | -:::notice +:::tip 1. 合并转发支持嵌套,最多支持 10 层嵌套,每层最多 300 条消息。 2. 不论 `ChatOptions.serverTransfer` 设置为 `false` 或 `true`,SDK 都会将合并消息附件上传到环信服务器。 - ::: +::: 示例代码如下: @@ -510,7 +486,7 @@ ChatClient.getInstance() 该功能适用于文本消息、图片消息和音视频消息等全类型消息,最多可向群组或聊天室的 20 个成员发送定向消息。 -:::notice +:::tip 1. 仅 SDK 1.2.0 及以上版本支持该功能。 2. 定向消息不写入服务端会话列表,不计入服务端会话的未读消息数。 3. 定向消息不支持消息漫游功能,因此从服务器拉取漫游消息时,不包含定向消息。 diff --git a/docs/document/react-native/message_update.md b/docs/document/react-native/message_update.md new file mode 100644 index 000000000..8998d40d8 --- /dev/null +++ b/docs/document/react-native/message_update.md @@ -0,0 +1,35 @@ +# 更新消息 + + + +本文介绍环信即时通讯 IM React Native SDK 如何更新本地消息。 + +## 技术原理 + +环信即时通讯 IM React Native SDK 通过 `ChatManager` 和 `ChatConversation` 支持更新本地数据库中的消息,其中包含如下主要方法: + +- `updateMessage` + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 更新消息 + +你可以调用 `updateMessage` 方法更新指定消息。该方法会同时更新本地内存和数据库中的消息。 + +```typescript +ChatClient.getInstance() + .chatManager.updateMessage(newMsg) + .then(() => { + console.log("update message success"); + }) + .catch((reason) => { + console.log("update message fail.", reason); + }); +``` \ No newline at end of file diff --git a/docs/document/react-native/moderation.md b/docs/document/react-native/moderation.md index 5f47cf11e..2f85a408c 100644 --- a/docs/document/react-native/moderation.md +++ b/docs/document/react-native/moderation.md @@ -2,7 +2,14 @@ -环信即时通讯 IM SDK 提供消息举报接口。开发者可以在客户端调用该接口举报违规消息。当服务器端审核服务收到举报消息后,会将举报消息存储到数据库,并在环信即时通讯 IM Console 展示。审核员可在环信即时通讯 IM Console 查看举报记录,并进行相应处理。 +即时通讯 IM SDK 提供消息举报接口。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +:::tip +1. 使用前,你需要在[环信即时通讯云控制台](https://console.easemob.com/user/login) 开通该功能。 +2. 消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +关于如何开通消息举报和查看举报记录,详见[环信即时通讯云控制台文档说明](/product/enable_and_configure_IM.html#消息举报)。 ## 技术原理 @@ -14,7 +21,7 @@ 1. 完成 SDK 初始化,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 2. 了解环信即时通讯 IM API 的 [使用限制](/product/limitation.html)。 -3. 在 [环信即时通讯 IM 管理后台](https://console.easemob.com/app/im-service/func/function-config) 开通消息审核服务。 +3. 已在 [环信即时通讯云控制台开通消息举报功能](/product/enable_and_configure_IM.html#消息举报)。 ## 实现方法 @@ -23,7 +30,7 @@ ```typescript // msgId:要举报的消息 ID。 // tag:非法消息的标签。你需要自定义标签,例如`涉政`或`广告`。该字段对应环信即时通讯云控制台的消息举报记录页面的`词条标记`字段。 -// reason:举报原因。你需要自行填写举报原因。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 +// reason:举报原因。你需要自行填写举报原因,最长不能超过 512 字节。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 ChatClient.getInstance() .chatManager.reportMessage(msgId, tag, reason) .then((result) => { diff --git a/docs/document/react-native/releasenote.md b/docs/document/react-native/releasenote.md index 2bf6c4f2a..51cb38c8f 100644 --- a/docs/document/react-native/releasenote.md +++ b/docs/document/react-native/releasenote.md @@ -2,6 +2,19 @@ +## 版本 V1.3.0 2024-1-4 + +#### 新增特性 + +- 依赖的原生 SDK 升级到版本(`iOS` 4.2.0 和`Android` 4.2.1)。添加原生 SDK 提供的新功能。 +- 新增[设置好友备注功能](user_relationship.html#设置好友备注)。 +- 新增 `ChatContactManager.fetchAllContacts` 和 `ChatContactManager.fetchContacts` 方法分别[从服务器一次性和分页获取好友列表](user_relationship.html#从服务端获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。 +- 新增 `ChatContactManager.getContact` 方法[从本地获取单个好友的用户 ID 和好友备注](user_relationship.html#从本地获取好友列表)。 +- 新增 `ChatContactManager.getAllContacts` 方法[从本地一次性获取好友列表](user_relationship.html#从本地获取好友列表),每个好友对象包含好友的用户 ID 和好友备注。 +- 新增 `ChatMessage.isBroadcast` 属性用于判断通该消息是否为聊天室全局广播消息。可通过[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 +- 新增 `ChatGroupManager.fetchJoinedGroupCount` 方法用于从服务器获取当前用户已加入的群组数量。 +- [申请入群被拒绝的回调](group_manage.html#监听群组事件) `EMGroupEventHandler#onRequestToJoinDeclinedFromGroup` 中新增 `decliner` 和 `applicant` 参数表示申请者和拒绝者的用户 ID。 + ## 版本 V1.2.1 2023-8-16 ### 修复 @@ -14,8 +27,8 @@ - React-Native 从 0.66.5 升级到 0.71.11。 - 依赖的原生 SDK(iOS 和 Android)升级到版本 4.1.1。添加原生 SDK 提供的新功能。 -- 新增 `ChatManager.fetchConversationsFromServerWithCursor` 方法[从服务器分页获取会话列表](message_manage.html#获取会话列表)。 -- 新增[置顶服务器会话的功能](message_manage.html#获取服务端的置顶会话列表): +- 新增 `ChatManager.fetchConversationsFromServerWithCursor` 方法[从服务器分页获取会话列表](conversation_list.html#获取会话列表)。 +- 新增[置顶服务器会话的功能](conversation_list.html#获取服务端的置顶会话列表): - 新增 `ChatManager.pinConversation` 方法,实现置顶或取消置顶服务器会话; - 新增 `ChatManager.fetchPinnedConversationsFromServerWithCursor` 从服务器分页获取置顶会话列表。 - 新增 `ChatManager.modifyMessageBody` 方法,用于修改本地消息或服务器端消息。 @@ -71,7 +84,7 @@ - 新增 `ChatGroupManager.setMemberAttribute` 方法用于[设置单个群组成员的属性](group_members.html#设置群组成员自定义属性)。 - 新增 `ChatGroupManager.fetchMemberAttributes` 方法用于[从服务器获取单个群成员的所有自定义属性](group_members.html#获取单个群成员的所有自定义属性)以及[根据属性 key 获取多个群成员的自定义属性](group_members.html#根据属性-key-获取多个群成员的自定义属性)。 - 添加 `ChatManager.fetchHistoryMessagesByOptions` 根据消息拉取参数配置类(`ChatFetchMessageOptions`)从服务器分页获取指定会话的历史消息。`ChatFetchMessageOptions` 类中包括起始时间戳、消息类型和消息发送方等参数。 -- 新增 `ChatManager.deleteMessagesWithTimestamp` 方法实现[删除指定时间段内的本地消息](message_manage.html#删除指定时间段的本地消息)。 +- 新增 `ChatManager.deleteMessagesWithTimestamp` 方法实现[删除指定时间段内的本地消息](message_delete.html#删除指定时间段的本地消息)。 - 新增 [`ChatGroupEventListener.onMemberAttributesChanged` 事件](group_manage.html#监听群组事件),在单个群成员的属性发生变更时,群内其他成员会收到该事件。 - 新增 `ChatConnectEventListener.onAppActiveNumberReachLimit` 事件,在应用程序的日活跃用户数量(DAU)或月活跃用户数量(MAU)达到上限时触发该事件。 - 新增日志回调接口 `handler`。 diff --git a/docs/document/react-native/room_manage.md b/docs/document/react-native/room_manage.md index 43b101b8c..3ec03baef 100644 --- a/docs/document/react-native/room_manage.md +++ b/docs/document/react-native/room_manage.md @@ -37,7 +37,7 @@ 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 可以调用 `createChatRoom` 方法创建聊天室,并设置聊天室的名称、描述、最大成员数等信息。成功创建聊天室后,该超级管理员为该聊天室的所有者。 -你也可以直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 +建议直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 示例代码如下: @@ -150,7 +150,7 @@ ChatOptions options = new ChatOptions(); options.deleteMessagesAsExitChatRoom = false; ``` -与群主无法退出群组不同,聊天室所有者可以离开聊天室,例如所有者从服务器下线则 2 分钟后自动离开聊天室。如果所有者重新进入聊天室仍是该聊天室的所有者。 +与群主无法退出群组不同,聊天室所有者可以离开聊天室,离开后重新进入仍是该聊天室的所有者。若 `ChatOptions.isChatRoomOwnerLeaveAllowed` 参数在初始化时设置为 `true` 时,聊天室所有者可以离开聊天室;若该参数设置为 `false`,聊天室所有者调用 `leaveChatRoom` 方法离开聊天室时会提示错误 706。 ### 解散聊天室 diff --git a/docs/document/react-native/room_members.md b/docs/document/react-native/room_members.md index 6e6716c9a..682f25938 100644 --- a/docs/document/react-native/room_members.md +++ b/docs/document/react-native/room_members.md @@ -47,7 +47,7 @@ ChatClient.getInstance() ### 将成员移出聊天室 -仅聊天室所有者和管理员可调用 `removeChatRoomMembers` 方法将指定成员移出聊天室。 +仅聊天室所有者和管理员可调用 `removeChatRoomMembers` 方法将单个或多个成员移出聊天室。 被移出后,该成员收到 `ChatRoomEventListener#onRemoved` 回调,其他成员收到 `ChatRoomEventListener#onMemberExited` 回调。 被移出的成员可以重新进入聊天室。 @@ -206,6 +206,7 @@ ChatClient.getInstance() 示例代码如下: ```typescript +// duration:禁言时间。若传 -1,表示永久禁言。 ChatClient.getInstance() .roomManager.muteChatRoomMembers(roomId, muteMembers, duration) .then(() => { @@ -260,7 +261,9 @@ ChatClient.getInstance() #### 开启聊天室全员禁言 -仅聊天室所有者和管理员可以调用 `muteAllChatRoomMembers`方法开启全员禁言。全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `onAllChatRoomMemberMuteStateChanged` 回调。 +仅聊天室所有者和管理员可以调用 `muteAllChatRoomMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动解除禁言,需要调用 `unMuteAllChatRoomMembers` 方法解除全员禁言。 + +全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `onAllChatRoomMemberMuteStateChanged` 回调。 示例代码如下: diff --git a/docs/document/react-native/thread_message.md b/docs/document/react-native/thread_message.md index 455dc7de6..be8803e70 100644 --- a/docs/document/react-native/thread_message.md +++ b/docs/document/react-native/thread_message.md @@ -100,7 +100,7 @@ ChatClient.getInstance().chatManager.removeAllMessageListener(); ### 撤回子区消息 -接收消息的具体逻辑,请参考 [撤回消息](message_send_receive.html#撤回消息),此处只介绍子区消息和其他消息的区别。 +接收消息的具体逻辑,请参考 [撤回消息](message_recall.html),此处只介绍子区消息和其他消息的区别。 子区有消息撤回时,子区所属群组的所有成员收到 `ChatMessageEventListener#onChatMessageThreadUpdated` 回调,子区成员收到 `ChatMessageEventListener#onMessagesRecalled` 回调。 diff --git a/docs/document/react-native/user_relationship.md b/docs/document/react-native/user_relationship.md index f4300bc18..3aa7a43de 100644 --- a/docs/document/react-native/user_relationship.md +++ b/docs/document/react-native/user_relationship.md @@ -119,15 +119,70 @@ ChatClient.getInstance().contactManager.addContactListener( ); ``` -### 获取好友列表 +### 删除好友 + +删除好友时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 + +```typescript +// 用户 ID +const userId = "tom"; +// 是否保留聊天会话 +const keepConversation = true; +ChatClient.getInstance() + .contactManager.deleteContact(userId, keepConversation) + .then(() => { + console.log("remove success."); + }) + .catch((reason) => { + console.log("remove fail.", reason); + }); +``` -你可以从服务器获取好友列表,也可以从本地数据库获取已保存的好友列表。 +#### 设置好友备注 -**注意** +自 1.3.0 版本开始,你可以调用 `setContactRemark` 方法设置单个好友的备注。 -需要从服务器获取好友列表之后,才能从本地数据库获取到好友列表。 +好友备注的长度不能超过 100 个字符。 + +```typescript +ChatClient.getInstance() + .contactManager.setContactRemark({ userId: "xxx", remark: "user remark" }) + .then() + .catch(); +``` + +#### 从服务端获取好友列表 + +自 1.3.0 版本开始,你可以调用 `fetchAllContacts` 或者 `fetchContacts` 方法从服务器一次性或分页获取好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 + +- 一次性获取服务端好友列表。 + +```typescript +ChatClient.getInstance() + .contactManager.fetchAllContacts() + .then((contactList: Contact[]) => { + // todo: 从服务器返回所有的联系人列表。包括好友备注信息。 + }) + .catch(); +``` + +- 分页获取服务端好友列表。 + +```typescript +// cursor 数据获取的起始位置,获取第一页设置为 `空字符串` 或者 `undefined`。 +// pageSize 获取每页的最大数目,取值范围为 [1,50]。 +ChatClient.getInstance() + .contactManager.fetchContacts({ + cursor: undefined, + pageSize: 20, + }) + .then((contactList: Contact[]) => { + // todo: 从服务器返回所有的联系人列表。包括好友备注信息。 + }) + .catch(); +``` -1. 从服务器获取好友列表 +此外,你也可以调用 `getAllContactsFromServer` 方法从服务器获取所有好友的列表,该列表只包含好友的用户 ID。 ```typescript ChatClient.getInstance() @@ -140,9 +195,40 @@ ChatClient.getInstance().contactManager.addContactListener( }); ``` - 2. 从本地数据库中获取好友列表 +#### 从本地获取好友列表 + +自 1.3.0 版本开始,你可以调用 `getContact` 方法从本地获取单个好友的用户 ID 和好友备注;你也可以调用 `getAllContacts` 方法一次性获取整个好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 + +:::tip +需要从服务器获取好友列表之后,才能从本地获取到好友列表。 +::: + +- 获取本地单个好友。 + +```typescript +// userId 获取指定用户的好友备注。 +ChatClient.getInstance() + .contactManager.getContact(userId) + .then((contactList: Contact | undefined) => { + // todo: 获取好友备注对象。 + }) + .catch(); +``` + +- 一次性获取本地好友列表。 - ```typescript +```typescript +ChatClient.getInstance() + .contactManager.getAllContacts() + .then((contactList: Contact[]) => { + // todo: 从服务器返回所有的联系人列表。包括好友备注信息。 + }) + .catch(); +``` + +此外,你也可以调用 `getAllContactsFromDB` 方法从本地一次性获取所有好友的列表,该列表只包含好友的用户 ID。 + +```typescript ChatClient.getInstance() .contactManager.getAllContactsFromDB() .then((value) => { @@ -153,25 +239,6 @@ ChatClient.getInstance().contactManager.addContactListener( }); ``` -### 删除好友 - -删除好友时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 - -```typescript -// 用户 ID -const userId = "tom"; -// 是否保留聊天会话 -const keepConversation = true; -ChatClient.getInstance() - .contactManager.deleteContact(userId, keepConversation) - .then(() => { - console.log("remove success."); - }) - .catch((reason) => { - console.log("remove fail.", reason); - }); -``` - ### 将用户加入黑名单 你可以调用 `addUserToBlockList` 添加用户到黑名单。用户被加入黑名单后,无法向你发送消息,也无法发送好友申请。 diff --git a/docs/document/server-side/account_system.md b/docs/document/server-side/account_system.md index 9eeaa2279..1f4dcfb7f 100644 --- a/docs/document/server-side/account_system.md +++ b/docs/document/server-side/account_system.md @@ -648,9 +648,13 @@ curl -X DELETE -H 'Accept: application/json' -H 'Authorization: Bearer 替换为你在服务端生成的 App Token curl --location 'http://XXXX/XXXX/XXXX/users/XXXX/resources' \ -H 'Accept: application/json' \ --H 'Authorization: Bearer ' +-H 'Authorization: Bearer ' ``` #### 响应示例 diff --git a/docs/document/server-side/callback.md b/docs/document/server-side/callback.md index e59ed66a3..a2cffa7c0 100644 --- a/docs/document/server-side/callback.md +++ b/docs/document/server-side/callback.md @@ -4,13 +4,13 @@ 回调功能,即环信 IM 服务器会在事件发生之前或之后,向你的应用服务器发送请求,你可以根据业务需求来干预事件的后续处理流程(发送前回调),或据此进行必要的数据同步(发送后回调)。 -一般发送前回调是对用户发送的消息内容的处理,发送后回调还包括送达回执和已读回执、群组或聊天室操作、好友关系操作和用户状态变化等事件,具体见 [用户在线状态回调](user_status_callback.html) 和发送后回调过滤规则设置。 +一般发送前回调是对用户发送的消息内容的处理,发送后回调还包括送达回执和已读回执、群组或聊天室操作、好友关系操作和用户状态变化等事件,详见发送后回调过滤规则设置。 设置消息内容回调的规则可以在环信即时通讯云控制台实现,如需单独设置特定类型不回调,请联系环信商务经理。 从处理角度看,回调分为以下两类: -- 发送前回调:回调的主要目的在于让 app 后台可以干预该事件的处理逻辑,环信 IM 服务器会根据回调返回码和返回值确定后续处理流程; +- 发送前回调:回调的主要目的在于让 app 后台可以干预该事件的处理逻辑,环信 IM 服务器会根据响应中的返回值确定后续处理流程; - 发送后回调:回调的主要目的在于让 app 后台实现必要的数据同步,环信 IM 服务器忽略回调返回码。 ## 1、发送前回调 @@ -19,10 +19,7 @@ **发送前回调只对客户端发送的消息有效,不包含 REST API 发送的消息。** -应用服务器可以通过发送前回调实时监控用户的聊天消息,包括: - -- 对聊天消息进行实时同步; -- 拦截用户的消息请求。可拦截所有类型的消息,包含文本、图片、自定义消息等; +应用服务器可以通过发送前回调实时监控用户的聊天消息,对消息进行处理,例如,拦截用户的消息请求。可拦截所有类型的消息,包含文本、图片、自定义消息等; ![](@static/images/server-side/im-callback.jpeg) @@ -37,7 +34,7 @@ - 回调的方向是环信 IM 服务器向应用服务器发起 HTTP/HTTPS POST 请求。 - 若同时设置了消息发送前和发送后两种回调,且消息发送前回调返回拒绝,则消息发送后回调将不会被触发。 - 对同一个 app,可以针对不同类型的消息(“TEXT”,“IMAGE”,“VIDEO”,“LOCATION”,“VOICE” 和 ”FILE”)做配置;规则支持选择两种以上消息类型同时回调至一个指定服务器地址,接收到消息后,你可以区分消息的类型以便进行分类处理。详见 [消息管理 REST API](message_single.html)。 -- 环信 IM 服务器执行发送前回调后,如果你的应用服务器没有返回 valid 状态或者返回其他错误码,该条消息会根据默认设置(console 后台发送前回调中 ”调用失败时默认策略”)处理,不会再重试;后续消息依然正常执行回调。 +- 环信 IM 服务器执行发送前回调后,如果你的应用服务器没有返回 valid 状态或者未收到应答包,该条消息会根据默认设置(console 后台发送前回调中 ”调用失败时默认策略”)处理,不会重试;后续消息依然正常执行回调。 - 消息发送到你的应用服务器后,应用服务器需返回 HTTP 响应码 200 和 valid 属性,根据 valid 状态决定是否进行下发。 ### 实现步骤 @@ -56,26 +53,28 @@ #### 请求 body -| 参数 | 类型 | -| :---------------- | :--------------------------------------------------------------------------------------------------------------------------------- | -| `callId` | `callId` 为 `{appkey}_{uuid}`,其中 `uuid` 为随机生成,作为每条回调的唯一标识。 | -| `timestamp` | 环信 IM 服务器接收到此消息的时间戳。 | -| `chat_type` | `chat` 单聊回调、`groupchat` 群聊回调包含了群组和聊天室的消息回调,默认全选。 | -| `group_id` | 回调消息所在的群组。群聊消息回调才有此参数。 | -| `from` | 消息的发送方。 | -| `to` | 消息的接收方。 | -| `msg_id` | 消息的 ID。 | -| `payload` | 消息内容,与通过 REST API 发送过来的一致,查看 [消息格式文档](message_historical.html#历史消息记录的内容)。 | -| `securityVersion` | 安全校验版本,目前为 1.0.0。忽略此参数,以后会改成 Console 后台做设置。 | +| 参数 | 类型 | +| :---------------- | :--------------------------------------- | +| `callId` | `callId` 为 `{appkey}_{uuid}`,其中 `uuid` 为随机生成,作为每条回调的唯一标识。 | +| `timestamp` | 环信 IM 服务器接收到此消息的时间戳。 | +| `chat_type` | `chat` 单聊回调、`groupchat` 群聊回调包含了群组和聊天室的消息回调,默认全选。| +| `group_id` | 回调消息所在的群组或聊天室。该参数仅对群组聊天或聊天室中的消息回调生效。 | +| `from` | 消息的发送方。 | +| `to` | 消息的接收方。该参数仅对单聊生效。 | +| `msg_id` | 消息的 ID。 | +| `payload` | 消息内容,与通过 REST API 发送过来的一致,查看 [消息格式文档](message_historical.html#历史消息记录的内容)。 | +| `securityVersion` | 安全校验版本,目前为 1.0.0。忽略此参数,以后会改成 Console 后台做设置。 | | `security` | 签名,格式如下: MD5(callId+Secret+timestamp)。Secret 见 [环信即时通讯云控制台](https://console.easemob.com/user/login)回调规则。 | #### 响应 body +响应内容不能超过 1,000 个字符,否则环信服务器会认为是攻击,导致回调失败。 + | 参数 | 类型 | 是否必需
| 描述 | -| :-------- | :----- | :--------------------------------------- | :------------------ | -| `valid` | bool | 是 | 根据开发者自己服务器设定的规则判断消息是否合法。 | -| `code` | String | 否 | 自定义信息,字符串类型。该内容会显示到客户端返回的 error 中,具体分为以下几种情况:
1. 返回的应答包内该 code 并且类型正确,error 会显示为你填写的内容;
2. 返回的应答包内 code 为空,error 显示为 `custom logic denied`;
3. 在指定时间内未响应,未收到应答包,按默认配置处理,则 error 显示为 `custom internal error`;
4. 如果返回的应答包出现错误,包括缺少必填字段、字段类型不符合约定类型,error 显示为 `custom internal error`。 | -| `payload` | Object | 否 | 若无需修改消息内容,**请勿传该参数**。
若需要更改消息内容可以回传修改后的内容,格式同传入的消息内容。目前仅支持文本的形式,并且消息大小不能超过 1K。 | +| :-------- | :----- | :----------------- | :----------- | +| `valid` | bool | 是 | 根据开发者自己服务器设定的规则判断消息是否合法。 | +| `code` | String | 否 | 客户端上报的自定义发送前回调错误。环信控制台上的**发送前回调**页面中的**消息拦截报错时显示**设置为**报错** 时,该 `code` 的内容为客户端提示的错误。错误分为以下几种情况:
- 若 `code` 的内容为字符串类型,客户端上的错误为该参数的内容;
- 响应中不包含 `code` 字段, 客户端提示 `custom logic denied`;
- 若 `code` 为空字符串,移动客户端提示 `Message blocked by external logic` 错误;
- 若在指定时间内未收到应答包,则按默认配置处理,客户端提示 `custom internal error` 错误;
- 如果返回的应答包出现错误,包括缺少必填字段 `valid` 或字段类型不符合约定类型,客户端提示 `custom internal error` 错误。| +| `payload` | Object | 否 | 修改后的消息内容。若无需修改消息内容,**请勿传该参数**。
若需要更改消息内容可以回传修改后的内容,格式同传入的消息内容。目前仅支持文本的形式,并且消息大小不能超过 1 KB。 | ### 示例 @@ -135,7 +134,7 @@ - 发送后回调范围,所有聊天消息有效(包含通过 SDK 和 REST API 发送的消息),包含单聊/群聊;如果 app 开通了反垃圾/敏感词过滤,被识别的消息会在服务器被拦截并禁止发送,将不会回调。 - 发送后回调接收延时,是指消息服务器接收到客户端聊天消息、再将消息成功回调至客户指定服务器地址的时间间隔。消息接收延时保障是 99.95% 的消息在 30s 内。 - 发送后回调对同一个 app 可以针对不同类型的消息(聊天消息、离线消息和通过 REST API 发送的消息)进行配置,如果 app 同时需要聊天消息和离线消息两种消息,建议区分回调地址。当然,规则也可以把这两种消息同时回调至一个指定服务器地址,在接收到消息后,可以对 eventType 做判断,区分消息的类型。 -- **发送后回调重试,当环信服务器执行发出回调后,响应状态码非 200,认为是指定服务器无网络、超过 10 秒或者其他因素导致失败,记录一次失败,然后立即重试,若再次失败,再记录一次失败;针对一条回调仅重试一次,重试失败后即丢弃。若开通了[补发回调存储信息功能](#补发回调存储信息接口描述),则将消息放入异常存储中。若 30 秒内累计 90 次失败,会封禁该 app 的回调规则,5 分钟后自动解封。重试失败以及封禁期间的回调不会自动补录,可以下载历史消息记录自行补充。** +- **发送后回调重试,当环信服务器执行发出回调后,响应状态码非 200,则认为回调失败,然后立即重试,若再次失败,再记录一次失败;针对一条回调仅重试一次,重试失败后即丢弃。若开通了[补发回调存储信息功能](#补发回调存储信息接口描述),则将消息放入异常存储中。若 30 秒内累计 90 次失败,会封禁该 app 的回调规则,5 分钟后自动解封。重试失败以及封禁期间的回调不会自动补录,可以下载历史消息记录自行补充。** - 指定服务器收到回调消息后,向消息服务器发出响应内容不能超过 1,000 字符长度,如果连续发送超长的响应内容,会导致回调规则封禁,只能手动解除,需要用户手动重新设置。 - 客户有特殊需求不能丢失回调消息的情况下,请联系环信商务经理开通回调异常缓存功能,并使用 [查询回调异常缓存](#查询回调储存详情接口描述) 和 [补发回调储存信息](#补发回调存储信息接口描述) 接口。 @@ -248,9 +247,9 @@ app 的响应内容不能超过 1,000 个字符,否则环信服务器会认为 | `duration` | long | 请求耗时,单位为毫秒。 | | `applicationName` | string | 你在环信 IM 管理后台注册的 App 名称。 | | `data` | object | 响应数据内容。包括以下三个参数:`date`、`size` 和 `retry`。 | -| `date` | String | 代表本次可以发送的补发的一个十分钟 date key,key 为十分钟的起点。 | -| `size` | Int | 本时段消息数量。 | -| `retry` | Int | 开发者已经重试补发的次数。考虑到补发也可能失败,服务器会继续存储。最开始是 0。 | +| - `date` | String | 当前的 date key,即每 10 分钟内的消息和事件。key 为 10 分钟的起点。 | +| - `size` | Int | 该 date key 内的消息数量。 | +| - `retry` | Int | 该 date key 内的数据已经重试补发的次数。未重试时值为 `0`。 | #### 请求示例 diff --git a/docs/document/server-side/callback_configurations.md b/docs/document/server-side/callback_configurations.md index fac7b8e15..47ffee0ba 100644 --- a/docs/document/server-side/callback_configurations.md +++ b/docs/document/server-side/callback_configurations.md @@ -350,8 +350,6 @@ payload 中字段含义: ### 群组和聊天室操作 -注意:目前 muc:create 仅在开通多设备服务后,才支持回调。 - | 事件 | payload 中类型 | 群聊触发事件 | 聊天室触发事件 | | :------------------------- | :------------------------------------- | :--------------------------------------------- | :--------------------- | | muc | - | 群聊操作所有事件 | 聊天室操作所有事件 | @@ -363,8 +361,8 @@ payload 中字段含义: | muc:invite_accept | {“operation”:“invite_accept”} | 受邀用户同意入群 | 不支持 | | muc:invite_decline | {“operation”:“invite_decline”} | 受邀用户拒绝入群 | 不支持 | | muc:kick | {“operation”:“kick”} | 踢出群 | 踢出聊天室 | -| muc:ban | {“operation”:“ban”} | 封禁群成员,即管理员将用户添加到群组黑名单 | 不支持 | -| muc:allow | {“operation”:“allow”} | 解除群成员封禁,即管理员将用户添加到群组黑名单 | 不支持 | +| muc:ban | {“operation”:“ban”} | 将用户添加到群组黑名单 | 不支持 | +| muc:allow | {“operation”:“allow”} | 将用户移出群组黑名单 | 不支持 | | muc:update | {“operation”:“update”} | 群信息修改 | 聊天室信息修改 | | muc:block | {“operation”:“block”} | 用户屏蔽群 | 不支持 | | muc:unblock | {“operation”:“unblock”} | 用户解除屏蔽群 | 不支持 | @@ -384,23 +382,26 @@ payload 中字段含义: | muc:add_user_white_list | {“operation”:“add_user_white_list”} | 将成员加入群白名单 | 将成员加入聊天室白名单 | | muc:remove_user_white_list | {“operation”:“remove_user_white_list”} | 将成员移除群白名单 | 将成员移除聊天室白名单 | | muc:ban_group | {“operation”:“ban_group”} | 群全局禁言 | 聊天室全局禁言 | -| muc:remove_ban_group | {“operation”:“remove_ban_group”} | 解除群全局禁言 | 解除聊天室全局禁言 | +| muc:remove_ban_group | {“operation”:“remove_ban_group”} | 解除群全局禁言 | 解除聊天室全局禁言 | +| muc:set_metadata | {“operation”:“set_metadata”} | 不支持 | 设置/更新聊天室自定义属性。| +| muc:delete_metadata | {“operation”:“delete_metadata”} | 不支持| 删除聊天室自定义属性。| +| muc:group_member_metadata_update | {“operation”:“group_member_metadata_update”} | 设置群成员的自定义属性 | 不支持 | -#### 创建群组或聊天室 +#### 创建群组 payload 字段含义: | 字段 | 数据类型 | 含义 | | :------------ | :------- | :----------------------------------------------------------- | -| `muc_id` | String | 该回调事件所在群组/聊天室在服务器的唯一标识,`{appkey}_{群/聊天室 ID}@conference.easemob.com`。 | +| `muc_id` | String | 该回调事件所在群组在服务器的唯一标识,`{appkey}_{群组 ID}@conference.easemob.com`。 | | `reason` | String | / | | `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | -| `operation` | String | `create` 创建群聊或聊天室。 | +| `operation` | String | `create` 创建群组。 | | `status` | object | 状态,包括 `description` 和 `error_code`。 | -| `description` | String | 创建群聊或聊天室失败的原因描述。 | +| `description` | String | 创建群组失败的原因描述。 | | `error_code` | String | 创建失败对应的错误码。 | -创建群聊回调请求示例: +创建群组回调请求示例: ```json { @@ -438,7 +439,7 @@ payload 字段含义: | `reason` | String | / | | `operation` | String | `destroy` 删除群/聊天室。 | | `status` | object | 状态,包括 `description` 和 `error_code`。 | -| `description` | String | 删除群聊或聊天室失败的原因描述。 | +| `description` | String | 删除群组或聊天室失败的原因描述。 | | `error_code` | String | 操作失败对应的错误码。 | 删除群聊回调请求示例: @@ -502,12 +503,12 @@ payload 字段含义: | 字段 | 数据类型 | 含义 | | :------------ | :------- | :----------------------------------------------------------- | -| `muc_id` | String | 该回调事件所在群组/聊天室在服务器的唯一标识,`{appkey}_{群/聊天室 ID}@conference.easemob.com`。 | +| `muc_id` | String | 该回调事件所在群组在服务器的唯一标识,`{appkey}_{群组 ID}@conference.easemob.com`。 | | `reason` | String | / | | `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | | `operation` | String | `apply`:申请加入群。 | | `status` | object | 状态,包括 `description` 和 `error_code`。 | -| `description` | String | 申请加入群聊或聊天室失败的原因描述。 | +| `description` | String | 申请加入群组失败的原因描述。 | | `error_code` | String | 失败对应的错误码。 | 回调请求示例: @@ -590,7 +591,7 @@ payload 字段含义: | `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | | `operation` | String | `invite`:邀请新成员加入群。 | | `status` | object | 状态,包括 `description` 和 `error_code`。 | -| `description` | String | 邀请新用户加入群聊失败的原因描述。 | +| `description` | String | 邀请新用户加入群组失败的原因描述。 | | `error_code` | String | 失败对应的错误码。 | 回调请求示例: @@ -713,7 +714,7 @@ payload 字段含义: | :------------ | :------- | :----------------------------------------------------------- | | `muc_id` | String | 该回调事件所在群组/聊天室在服务器的唯一标识,`{appkey}_{群/聊天室 ID}@conference.easemob.com`。 | | `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | -| `operation` | String | `kick`:将成员踢出群聊或聊天室。 | +| `operation` | String | `kick`:将成员踢出群组或聊天室。 | | `status` | object | 状态,包括 `description` 和 `error_code`。 | | `description` | String | 操作失败的原因描述。 | | `error_code` | String | 失败对应的错误码。 | @@ -772,7 +773,7 @@ payload 字段含义: } ``` -#### 添加成员至黑名单 +#### 添加成员至群组黑名单 payload 字段含义: @@ -786,7 +787,7 @@ payload 字段含义: | `description` | String | 操作失败的原因描述。 | | `error_code` | String | 失败对应的错误码。 | -封禁群成员(将群成员添加到黑名单)回调请求示例: +封禁群成员,即将群成员添加到黑名单的回调请求示例: ```json { @@ -814,7 +815,7 @@ payload 字段含义: } ``` -#### 将成员从黑名单中移除 +#### 将成员从群组黑名单中移除 payload 字段含义: @@ -924,7 +925,7 @@ payload 字段含义: } ``` -#### 屏蔽群组或聊天室消息 +#### 屏蔽群组 payload 字段含义: @@ -966,7 +967,7 @@ payload 字段含义: } ``` -#### 取消屏蔽群组或聊天室消息 +#### 解除屏蔽群组 payload 字段含义: @@ -975,7 +976,7 @@ payload 字段含义: | `muc_id` | String | 该回调事件所在群组在服务器的唯一标识,`{appkey}_{群 ID}@conference.easemob.com`。 | | `reason` | String | / | | `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | -| `operation` | String | `unblock`:用户屏蔽群/聊天室。 | +| `operation` | String | `unblock`:用户解除屏蔽群组。 | | `status` | object | 状态,包括 `description` 和 `error_code`。 | | `description` | String | 操作失败的原因描述。 | | `error_code` | String | 失败对应的错误码。 | @@ -2005,6 +2006,150 @@ payload 字段含义: } ``` +#### 设置/更新聊天室自定义属性 + +payload 字段含义: + +| 字段 | 数据类型 | 含义 | +| :------------ | :------- | :----------------------------------------------------------- | +| `muc_id` | String | 该回调事件所在聊天室在服务器的唯一标识,`{appkey}_{聊天室 ID}@conference.easemob.com`。 | +| `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | +| `event_info.ext` | String | 消息的扩展字段,包含聊天室的自定义属性内容。 | +| `event_info.type` | String | 聊天室自定义属性类型。 | +| `operation` | String | `set_metadata`:设置或更新聊天室自定义属性。 | +| `status` | object | 状态,包括 `description` 和 `error_code`。 | +| `description` | String | 操作失败的原因描述。| +| `error_code` | String | 失败对应的错误码。| + +此外,`from` 为聊天室 ID,`to` 为聊天室中成员的用户 ID。 + +设置/更新聊天室自定义属性回调请求示例: + +```json +{ + "chat_type": "muc", + "callId": "XXXX#XXXX_976432657191668068", + "security": "f8956ab6d6f78df93efb2dbca5f2eb83", + "payload": { + "muc_id": "XXXX#XXXX@conference.easemob.com", + "is_chatroom": true, + "event_info":{ + "ext":"{\"result\":{\"successKeys\": [\"key1\",\"key2\"],\"errorKeys\":{}},\"identify\":\"\",\"is_forced\":false,\"muc_name\":\"Take\",\"need_notify\":true, \"properties\":{\"key1\": \"value1\",\"key2\": \"value2 \"}, \"operator \": \"user1\"}", + "type":"event_none" + }, + "operation": "set_metadata", + "status": { + "description": "", + "error_code": "ok" + } + }, + "group_id": "662XXXX13", + "host": "XXXX", + "appkey": "XXXX#XXXX", + "from": "662XXXX13", + "to": "aaa111", + "eventType": "chat", + "msg_id": "976432657191668068", + "timestamp": 1644908244060 +} +``` + +#### 删除聊天室自定义属性 + +payload 字段含义: + +| 字段 | 数据类型 | 含义 | +| :------------ | :------- | :----------------------------------------------------------- | +| `muc_id` | String | 该回调事件所在聊天室在服务器的唯一标识,`{appkey}_{聊天室 ID}@conference.easemob.com`。 | +| `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | +| `event_info.ext` | String | 消息的扩展字段,包含聊天室的自定义属性内容。 | +| `event_info.type` | String | 聊天室自定义属性类型。 | +| `operation` | String | `delete_metadata`:删除聊天室自定义属性。 | +| `status` | object | 状态,包括 `description` 和 `error_code`。 | +| `description` | String | 操作失败的原因描述。| +| `error_code` | String | 失败对应的错误码。| + +此外,`from` 为聊天室 ID,`to` 为聊天室中成员的用户 ID。 + +删除聊天室自定义属性回调请求示例: + +```json +{ + "chat_type": "muc", + "callId": "XXXX#XXXX_976432657191668068", + "security": "f8956ab6d6f78df93efb2dbca5f2eb83", + "payload": { + "muc_id": "XXXX#XXXX@conference.easemob.com", + "is_chatroom": true, + "event_info":{ + "ext":"{\"result\":{\"successKeys\": [\"key1\",\"key2\"],\"errorKeys\":{}},\"identify\":\"\",\"is_forced\":false,\"muc_name\":\"Take\",\"need_notify\":true, \"properties\":{\"key1\": \"value1\",\"key2\": \"value2 \"}, \"operator \": \"user1\"}", + "type":"event_none" + }, + "operation": "delete_metadata", + "status": { + "description": "", + "error_code": "ok" + } + }, + "group_id": "662XXXX13", + "host": "XXXX", + "appkey": "XXXX#XXXX", + "from": "662XXXX13", + "to": "aaa111", + "eventType": "chat", + "msg_id": "976432657191668068", + "timestamp": 1644908244060 +} +``` + +#### 设置群成员的自定义属性 + +payload 字段含义: + +| 字段 | 数据类型 | 含义 | +| :------------ | :------- | :----------------------------------------------------------- | +| `muc_id` | String | 该回调事件所在聊天室在服务器的唯一标识,`{appkey}_{群组 ID}@conference.easemob.com`。 | +| `is_chatroom` | Bool | 是否是聊天室。
- `true`:是;
- `false`:否。 | +| `event_info.ext` | String | 消息的扩展字段,包含群组成员的自定义属性内容。 | +| `event_info.type` | String | 群组成员的自定义属性类型。 | +| `operation` | String | `group_member_metadata_update`:设置或更新群组成员的自定义属性。 | +| `status` | object | 状态,包括 `description` 和 `error_code`。 | +| `description` | String | 操作失败的原因描述。| +| `error_code` | String | 失败对应的错误码。| + +此外,`from` 为群组 ID,`to` 为群组成员的用户 ID。 + +设置群成员的自定义属性的回调请求示例: + +```json +{ + "chat_type": "muc", + "callId": "XXXX#XXXX_976432657191668068", + "security": "f8956ab6d6f78df93efb2dbca5f2eb83", + "payload": { + "muc_id": "XXXX#XXXX@conference.easemob.com", + "is_chatroom": false, + "event_info":{ + "ext":"{\"result\":{\"successKeys\": [\"key1\",\"key2\"],\"errorKeys\":{}},\"identify\":\"\",\"is_forced\":false,\"muc_name\":\"Take\",\"need_notify\":true, \"properties\":{\"key1\": \"value1\",\"key2\": \"value2 \"}, \"operator \": \"user1\"}", + "type":"event_none" + }, + "operation": "group_member_metadata_update", + "status": { + "description": "", + "error_code": "ok" + } + }, + "group_id": "632XXXX13", + "host": "XXXX", + "appkey": "XXXX#XXXX", + "from": "632XXXX13", + "to": "aaa111", + "eventType": "chat", + "msg_id": "976432657191668068", + "timestamp": 1644908244060 +} +``` + ### 好友关系操作 | 事件 | payload 中类型 | 触发事件 | @@ -2014,8 +2159,6 @@ payload 字段含义: | `roster:remove` | `{“operation”:“remove”}` | 删除好友 | | `roster:accept` | `{“operation”:“accept”}` | 同意好友申请。对方用户收到该事件。 | | `roster:decline` | `{“operation”:“decline”}` | 拒绝好友申请。对方用户收到该事件。 | -| `roster:remote_accept` | `{“operation”:“remote_accept”}` | 远程同意。申请人收到该事件。 | -| `roster:remote_decline` | `{“operation”:“remote_decline”}` | 远程拒绝。申请人收到该事件。 | | `roster:ban` | `{“operation”:“ban”}` | 拉黑好友 | | `roster:allow` | `{“operation”:“allow”}` | 解除拉黑好友 | @@ -2143,70 +2286,6 @@ payload 示例: } ``` -#### 远程同意 - -用户发送好友申请后,对方用户同意加好友后,申请方会收到服务器发送的该事件。 - -payload 字段含义: - -| 字段 | 数据类型 | 含义 | -| :----------- | :------- | :---------------------------------------------------------- | -| `roster_ver` | String | 好友列表的版本号。 | -| `operation` | String | `remote_accept`:远程同意。 | - -payload 示例: - -```json -{ - "chat_type": "roster", - "callId": "XXXX#XXXX_967182720616630320", - "security": "f4bc73eb6e7764e383521c2e88dc2729", - "payload": { - "roster_ver": "1BD5718E9C9D3F0C572A5157CFC711D4F6FA490F", - "operation": "remote_accept" - }, - "host": "XXXX", - "appkey": "XXXX#XXXX", - "from": "XXXX#XXXX_XXXX/android_XXXX", - "to": "2222", - "eventType": "chat", - "msg_id": "967182720616630320", - "timestamp": 1642754575382 - } -``` - -#### 远程拒绝 - -用户发送好友申请后,对方用户拒绝添加好友后,申请方会收到服务器发送的该事件。 - -payload 字段含义: - -| 字段 | 数据类型 | 含义 | -| :----------- | :------- | :----------------------------------------------------------- | -| `roster_ver` | String | 好友列表的版本号。 | -| `operation` | String | `remote_decline`:远程拒绝。 | - -payload 示例: - -```json -{ - "chat_type": "roster", - "callId": "XXXX#XXXX_967182895737210928", - "security": "27f5b919623380cc11d863ef957aa61b", - "payload": { - "roster_ver": "CFC06E0BA39E8B7FD493D102E2F8F3CAE678B380", - "operation": "remote_decline" - }, - "host": "XXXX", - "appkey": "XXXX#XXXX", - "from": "XXXX#XXXX/android_XXXX", - "to": "2222", - "eventType": "chat", - "msg_id": "967182895737210928", - "timestamp": 1642754616149 -} -``` - #### 拉黑好友 payload 字段含义: @@ -2240,6 +2319,7 @@ payload 示例: } ``` + #### 解除拉黑好友 payload 字段含义: @@ -2273,13 +2353,41 @@ payload 示例: } ``` -### ack 事件 +### 发送会话已读回执 -| 事件 | payload 中类型 | 触发事件 | -| :----------- | :------------- | :----------- | -| `read_ack` | 无 | 发送已读回执 | +回调请求主要字段含义: -#### 发送已读回执 +| 字段 | 数据类型 | 含义 | +| :------------ | :------- | :----------------------------------------------------------- | +| chat_type | String | 会话已读回执。 | +| payload.ack_message_id | String | 会话中消息的消息 ID。 | +| payload.type | 会话已读回执类型。 | | +| from | String | 发送已读回执的用户。| +| to | String | 接收已读回执的用户。 | +| msg_id | String | 已读回执消息的消息 ID。 | + +会话已读回执的回调请求示例: + +```json +{ +"callId": "easemob-demo#testy_1252106597610555348", +"eventType": "chat", +"chat_type": "channel_ack", +"security": "203e3c86710ebdbd776d8aa9cc057b2d", +"payload": { +"ack_message_id": "1252106100258375636", +"type": "channel_ack" +}, +"host": "easemob@hsb-im-msync0", +"appkey": "easemob-demo#testy", +"from": "wzy", +"to": "wzy1", +"msg_id": "1252106597610555348", +"timestamp": 1709093585046 +} +``` + +#### 发送消息已读回执 回调请求主要字段含义: @@ -2355,7 +2463,7 @@ app 用户状态分为在线和离线两种,即用户已连接到环信即时 | `ip` | String | 用户登录 IP。 | | `host` | String | 服务器名称。 | | `appkey` | String | 你在环信管理后台注册的应用唯一标识。 | -| `user` | String | 登录用户识别号,为 {App Key/设备类型_设备 ID}。 | +| `user` | String | 登录用户识别号,格式为 `{app key_username@easemob.com/device operating system_device ID}`,其中 `@easemob.com` 为固定字符串,`device ID` 由 SDK 随机生成。 | | `version` | String | SDK 版本号。 | | `timestamp` | long | 登录请求到环信 IM 服务器的 Unix 时间戳,单位为 ms。 | | `status` | String | `online`,在线。 | @@ -2371,7 +2479,7 @@ app 用户状态分为在线和离线两种,即用户已连接到环信即时 "ip":"XXXX", "host":"XXXX", "appkey":"XXXX#XXXX", - "user":"XXXX#XXXX_XXXX/ios_6d580737-db3a-d2b5-da18-b6045ffd195b", + "user":"XXXX#XXXX_XXXX@easemob.com/ios_6d580737-db3a-d2b5-da18-b6045ffd195b", "version":"3.8.9.1", "timestamp":1642585154644, "status":"online" @@ -2391,7 +2499,7 @@ app 用户状态分为在线和离线两种,即用户已连接到环信即时 | `ip` | String | 用户登录 IP。 | | `host` | String | 服务器名称。 | | `appkey` | String | 你在环信管理后台注册的应用唯一标识。 | -| `user` | String | 登录用户识别号,为 `{App Key/设备类型_设备 ID}`。 | +| `user` | String | 登录用户识别号,格式为 `{app key_username@easemob.com/device operating system_device ID}`,其中 `@easemob.com` 为固定字符串,`device ID` 由 SDK 随机生成。 | | `version` | String | SDK 版本号。 | | `timestamp` | long | 请求到环信 IM 服务器的 Unix 时间戳,单位为 ms。 | | `status` | String | `offline`,离线。 | @@ -2407,7 +2515,7 @@ app 用户状态分为在线和离线两种,即用户已连接到环信即时 "ip":"XXXX", "host":"XXXX", "appkey":"XXXX#XXXX", - "user":"XXXX#XXXX_XXXX/ios_6d580737-db3a-d2b5-da18-b6045ffd195b", + "user":"XXXX#XXXX_XXXX@easemob.com/ios_6d580737-db3a-d2b5-da18-b6045ffd195b", "version":"3.8.9.1", "timestamp":1642648914742, "status":"offline" @@ -2427,7 +2535,7 @@ app 用户状态分为在线和离线两种,即用户已连接到环信即时 | `ip` | String | 用户登录 IP。 | | `host` | String | 服务器名称。 | | `appkey` | String | 你在环信管理后台注册的应用唯一标识。 | -| `user` | String | 登录用户识别号,为 `{App Key/设备类型_设备 ID}`。 | +| `user` | String | 登录用户识别号,格式为 `{app key_username@easemob.com/device operating system_device ID}`,其中 `@easemob.com` 为固定字符串,`device ID` 由 SDK 随机生成。 | | `version` | String | SDK 版本号。 | | `timestamp` | long | 请求到环信 IM 服务器的 Unix 时间戳,单位为毫秒 。 | | `status` | String | `offline`,离线。 | @@ -2443,7 +2551,7 @@ app 用户状态分为在线和离线两种,即用户已连接到环信即时 "ip":"223.71.97.198:52709", "host":"msync@ebs-ali-beijing-msync40", "appkey":"XXXX#XXXX", - "user":"XXXX#XXXX_XXXX/ios_a5fa01fd-b5a4-84d5-ebeb-bf10e8950442", + "user":"XXXX#XXXX_XXXX@easemob.com/ios_a5fa01fd-b5a4-84d5-ebeb-bf10e8950442", "version":"3.8.9.1", "timestamp":1642648955563, "status":"offline" @@ -2452,14 +2560,95 @@ app 用户状态分为在线和离线两种,即用户已连接到环信即时 ### 敏感词监测 -| 事件 | payload 中类型 | 触发事件 | -| :------------------------- | :---------------------------- | :------------------- | -| `sensitiveWords` | - | 敏感词所有事件 | -| `sensitiveWords:intercepted` | `{“alertReason”:“intercepted”}` | 因为触发敏感词被拦截 | +回调请求主要字段含义: + +| 字段 | 数据类型 | 含义 | +| :---------- | :------- | :----------------------------------------------------------- | +| `callId` | String | `callId` 为 `{appkey}_{uuid}`,其中 `uuid` 为随机生成,作为每条回调的唯一标识。 | +| `alertReason` | String | 敏感词是否合规:
- `through`:表示敏感词为合规内容;
- `intercepted`:表示敏感词为违规词,包含敏感词的消息被拦截。
- `replaced`:表示敏感词为违规词,使用 *** 代替。 | +| `contentReceiver` | String | 内容接收方的用户 ID。 | +| `eventType` | String | 事件类型,用于标识为敏感词检测还是其他类型的事件。 | +| `sensitiveWords` | List | 敏感词内容。 | +| `contentOwner` | String | 内容发送方的用户 ID。 | +| `security` | String | 签名,格式如下: `MD5(callId+secret+timestamp)`。`secret` 详见 [Console 后台的回调规则配置](enable_and_configure_IM.html#配置回调规则)。 | +| `contentUri` | String | 消息唯一标识,格式为 msync:msgId。 | +| `host` | String | 服务器名称。 | +| `appkey` | String | 即时通讯服务分配给每个应用的唯一标识,由 `orgname` 和 `appname` 参数的值组成。 | +| `contentType` | String | 内容类型,目前为 `message`,表示为消息。 | +| `timestamp` | Long | 环信 IM 服务器接收到此消息的 Unix 时间戳,单位为毫秒。 | +| `chatType` | String | 会话类型,默认全选:
- `chat`:单聊回调;
- `groupchat`:群聊回调包含了群组和聊天室的消息回调;
- `notify`:通知回调包含了 Thread 和 Reaction 的回调,需要结合 payload 中的 `type` 字段确定具体类型。 | +| `status` | String | 对敏感词或消息的处理动作。
- `pass`:敏感词为合规内容,包含敏感词的消息通过审核。
- `refuse`:敏感词为违规词,对包含敏感词的消息进行拦截,不下发。
- `replace`:敏感词为违规词,由 `***` 替换。 | + +- 敏感词审核通过的回调请求示例: + +```json +{ + "callId": "XXXX#XXXX_0e1b4c8e-a95c-4db1-85f3-2cbf6197d73c", + "alertReason": "through", + "contentReceiver": "XXXX#XXXX_test1@easemob.com", + "eventType": "keyword_alert", + "sensitiveWords": [], + "contentOwner": "XXXX#XXXX_test2@easemob.com", + "security": "36e8e82243ce96e1ac3f530fb815cef8", + "contentUri": "msync:1218049757197370792", + "host": "msync@ebs-ali-beijing-msync62", + "appkey": "XXXX#XXXX", + "contentType": "message", + "timestamp": 1701164109042, + "chatType": "chat:user:text", + "status": "pass" +} +``` + +- 包含敏感词的消息被直接拦截的回调请求示例: + +```json +{ + "callId": "XXXX#XXXX_16396528-2a9c-4d96-8219-15723e436fd6", + "alertReason": "intercepted", + "contentReceiver": "XXXX#XXXX_test1@easemob.com", + "eventType": "keyword_alert", + "sensitiveWords": [ + "12" + ], + "contentOwner": "XXXX#XXXX_test2@easemob.com", + "security": "47ce006af8a8f9ad26acf125244093ab", + "contentUri": "msync:1232040174779635136", + "host": "msync@ebs-ali-beijing-msync68", + "appkey": "XXXX#XXXX", + "contentType": "message", + "timestamp": 1704421506954, + "chatType": "chat:user:text", + "status": "refuse" +} +``` + +- 敏感词使用 *** 替换的回调请求示例: + +```json +{ + "callId": "XXXX#XXXX_3a49331a-e554-48d2-bacb-797739020e2a", + "alertReason": "intercepted", + "contentReceiver": "XXXX#XXXX_test1@easemob.com", + "eventType": "keyword_alert", + "sensitiveWords": [ + "12" + ], + "contentOwner": "XXXX#XXXX_test2@easemob.com", + "security": "e8b50122636487eacb55ada441f8f3cb", + "contentUri": "msync:1218049329273505228", + "host": "msync@ebs-ali-beijing-msync71", + "appkey": "easemob-demo#restys", + "contentType": "message", + "timestamp": 1701164009349, + "chatType": "chat:user:text", + "status": "replace" +} +``` ### Reaction 回调事件 -响应体字段含义: +回调请求主要字段含义: | 字段 | 数据类型 | 含义 | |:---------------|:-------|:---------------| diff --git a/docs/document/server-side/chatroom.md b/docs/document/server-side/chatroom.md index d35424e57..8a24631cb 100644 --- a/docs/document/server-side/chatroom.md +++ b/docs/document/server-side/chatroom.md @@ -513,7 +513,7 @@ GET https://{host}/{org_name}/{app_name}/chatrooms/{chatroom_id} | `data.id` | String | 聊天室 ID,聊天室唯一标识符,由环信即时通讯 IM 服务器生成。 | | `data.name` | String | 聊天室名称。 | | `data.description` | String | 聊天室描述。 | -| `data.membersonly` | Bool | 加入聊天室是否需要群主或者群管理员审批:
- `true`:是。
- `false`:否。 | +| `data.membersonly` | Bool | 加入聊天室是否需要聊天室所有者或者聊天室管理员审批:
- `true`:是。
- `false`:否。 | | `data.allowinvites` | Bool | 是否允许聊天室成员邀请其他用户加入该聊天室:
- `true`:允许聊天室成员邀请他人加入该聊天室。
- `false`:仅聊天室所有者和管理员可邀请他人加入该聊天室。 | | `data.maxusers` | Int | 聊天室成员数上限,创建聊天室时设置。 | | `data.owner` | String | 聊天室所有者的用户 ID。例如:{“owner”: “user1”}。 | @@ -1151,7 +1151,7 @@ PUT https://{host}/{org_name}/{app_name}/metadata/chatroom/{chatroom_id}/user/{u | 参数 | 类型 | 是否必需 | 描述 | | :----------- | :----- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `metaData` | JSON | 是 | 聊天室的自定义属性,存储为键值对(key-value pair)集合,即 Map。该集合中最多可包含 10 个键值对,在每个键值对中,key 为属性名称,最多可包含 128 个字符;value 为属性值,不能超过 4086 个字符。每个聊天室最多可有 100 个自定义属性,每个应用的聊天室自定义属性总大小为 10 GB。
key 支持以下字符集:
• 26 个小写英文字母 a-z;
• 26 个大写英文字母 A-Z;
• 10 个数字 0-9;
• “\_”, “-”, “.”。 | +| `metaData` | JSON | 是 | 聊天室的自定义属性,存储为键值对(key-value pair)集合,即 Map。该集合中最多可包含 10 个键值对,在每个键值对中,key 为属性名称,最多可包含 128 个字符;value 为属性值,不能超过 4096 个字符。每个聊天室最多可有 100 个自定义属性,每个应用的聊天室自定义属性总大小为 10 GB。
key 支持以下字符集:
• 26 个小写英文字母 a-z;
• 26 个大写英文字母 A-Z;
• 10 个数字 0-9;
• “\_”, “-”, “.”。 | | `autoDelete` | String | 否 | 当前成员退出聊天室时是否自动删除该自定义属性。
• (默认)'DELETE':是;
• 'NO_DELETE':否。 | #### HTTP 响应 diff --git a/docs/document/server-side/error.md b/docs/document/server-side/error.md index 300e6a3b2..7e8d58eba 100644 --- a/docs/document/server-side/error.md +++ b/docs/document/server-side/error.md @@ -23,7 +23,7 @@ | :------------------------- | :----------------------------------------------------------- | | 400 | (错误请求)服务器不理解请求的语法。 | | 401 | (未授权)请求要求身份验证。对于需要 token 的接口,服务器可能返回此响应。 | -| 403 | (禁止)服务器拒绝请求。对于群组/聊天室服务,表示本次调用不符合群组/聊天室操作的正确逻辑,例如调用添加成员接口,添加已经在群组里的用户,或者移除聊天室中不存在的成员等操作。 | +| 403 | (禁止)服务器拒绝请求。对于群组/聊天室服务,在以下两种情况会报该错误:
- 本次调用不符合群组/聊天室操作的正确逻辑,例如调用添加成员接口,添加已经在群组里的用户,或者移除聊天室中不存在的成员等操作。
- 每秒发送的消息条数超过了[发送群组消息 API](message_group.html) 和[发送聊天室消息 API](message_chatroom.html) 的限制,即群组消息的每秒发送上限为 20,聊天室为 100。 | | 404 | (未找到)服务器找不到请求的接口。 | | 405 | (请求方式错误)请按照环信官网接口说明,正确的使用接口 GET,POST 等请求方式。 | | 408 | (请求超时)服务器等候请求时发生超时。 | @@ -77,6 +77,7 @@ | 403 | forbidden_op | "forbidden operation on group owner!" | 当前操作禁止对群主使用,如将群主加入黑名单。 | | 403 | forbidden_op | "can not join this group, reason:user %s has joined too many groups/chatroom!” | 用户加入的群组或聊天室数超过了限制。 | | 403 | forbidden_op | "this appKey has create too many groups/chatrooms!” | 加入群组或聊天室时,群组或聊天室人数已达到上限。 | +| 403 | forbidden_op | "Forbidden for url: [1111111567788/test/messages/chatgroups]" | 调用[发送群聊消息接口](message_group.html)时每秒发送的消息数量超过了 20 条。 | | 403 | exceed_limit | "Invitee's contact max count" | 好友请求的接收方已达好友数量上限。 | | 403 | exceed_limit | "Inviter's contact max count" | 好友请求的发送方已达好友数量上限。 | | 404 | organization_application_not_found | "Could not find application for hx/hxdeo2 from URI: hx/hxdeo2/token" | hx/hxdeo2 这个设置不正确或不存在,或 baseurl 集群设置错误(只针对 vip 集群的 AppKey),正确的是 orgname/appname,即 AppKey 的 “#” 换成 “/“。 | diff --git a/docs/document/server-side/group.md b/docs/document/server-side/group.md index 36afca261..7eee6fb4d 100644 --- a/docs/document/server-side/group.md +++ b/docs/document/server-side/group.md @@ -90,10 +90,10 @@ POST https://{host}/{org_name}/{app_name}/chatgroups | `groupname` | String | 否 | 群组名称,最大长度为 128 字符。| | `description` | String | 否 | 群组描述,最大长度为 512 字符。| | `public` | Bool | 是 | 是否是公开群。公开群可以被搜索到,用户可以申请加入公开群;私有群无法被搜索到,因此需要群主或群管理员添加,用户才可以加入。
- `true`:公开群;
- `false`:私有群。 | -| `scale` | String | 否 | 群组规模,取决于群成员总数 `maxusers` 参数。
- (默认)`normal`:普通群,即群成员总数不超过 3000。
- `large`:大型群,群成员总数超过 3000。

- 创建大型群时,该参数必传。;
- 大型群不支持离线推送。如需默认创建大型群,请联系环信商务。
| -| `maxusers` | Int | 否 | 群组最大成员数(包括群主)。对于普通群,该参数的默认值为 `200`,大型群为 `1000`。不同套餐支持的人数上限不同,详见 [产品价格](https://www.easemob.com/pricing/im)。 | +| `scale` | String | 否 | 群组规模,取决于群成员总数 `maxusers` 参数。
- (默认)`normal`:普通群,即群成员总数不超过 3000。
- `large`:大型群,群成员总数超过 3000。

- 创建大型群时,该参数必传;
- 大型群不支持离线推送。仅旗舰版支持创建大型群,如需该功能,请联系环信商务。
| +| `maxusers` | Int | 否 | 群组最大成员数(包括群主)。对于普通群,该参数的默认值为 `200`,大型群为 `1000`。不同套餐支持的人数上限不同,详见 [产品价格](/product/pricing.html#套餐包功能详情)。 | | `allowinvites` | Bool | 否 | 是否允许群成员邀请用户加入群组:
- `true`:群成员可拉人入群;
- (默认)`false`:只有群主或者管理员才可以拉人入群。
注:该参数仅对私有群有效,因为公开群不允许群成员邀请其他用户入群。 | -| `membersonly` | Bool | 否 | 用户申请入群是否需要群主或者群管理员审批。
- `true`:需要;
- (默认)`false`:不需要,用户直接进群。 | +| `membersonly` | Bool | 否 | 用户申请入群是否需要群主或者群管理员审批。
- `true`:需要;
- (默认)`false`:不需要,用户直接进群。
该参数仅对公开群生效,因为对于私有群,用户无法申请加入群组,只能通过群成员邀请加入群。 | | `invite_need_confirm` | Bool | 否 | 邀请用户入群时是否需要被邀用户同意。
- (默认)`true`:是;
- `false`:否。 | | `owner` | String | 是 | 群主的用户 ID。 | | `members` | Array | 否 | 群成员的用户 ID 数组,不包含群主的用户 ID。该数组可包含的元素数量不超过 `maxusers` 的值。 | @@ -310,7 +310,7 @@ PUT https://{host}/{org_name}/{app_name}/chatgroups/{group_id} | :-------------------- | :----- | :------- | :-------------------------------------------------------------------------------------------------------------------------------- | | `groupname` | String | 否 | 群组名称,最大长度为 128 字符。 | | `description` | String | 否 | 群组描述,最大长度为 512 字符。 | -| `maxusers` | Int | 否 | 群组成员最大数(包括群主),值为数值类型。 | +| `maxusers` | Int | 否 | 群组最大成员数(包括群主)。对于普通群,该参数的默认值为 `200`,大型群为 `1000`。不同套餐支持的人数上限不同,详见 [产品价格](/product/pricing.html#套餐包功能详情)。 | | `membersonly` | Bool | 否 | 加入群组是否需要群主或者群管理员审批:
- `true`:是;
- `false`:否。 | | `allowinvites` | Bool | 否 | 是否允许群成员邀请别人加入此群:
- `true`:允许群成员邀请人加入此群;
- `false`:只有群主或群管理员才可以邀请用户入群。 | | `invite_need_confirm` | Bool | 否 | 受邀人加入群组前是否需接受入群邀请:
- `true`:需受邀人确认入群邀请;
- `false`:受邀人直接加入群组,无需确认入群邀请。 | @@ -400,7 +400,7 @@ GET https://{host}/{org_name}/{app_name}/chatgroups?limit={N}&cursor={cursor} | 参数 | 类型 | 是否必需 | 描述 | | :------- | :----- | :------- | :---------------------------------------------------------- | | `limit` | Int | 否 | 每次期望返回的群组数量。取值范围为 [1,1000],默认值为 `10`。 | -| `cursor` | String | 否 | 数据查询的起始位置。 | +| `cursor` | String | 否 | 数据查询的起始位置。首次调用该接口,不传 `cursor`,服务器按群组创建时间倒序返回 `limit` 指定的群组数量。后续接口调用时,需要从上次调用的响应中获取 `cursor` 参数的值传入请求中的该参数。 | :::tip 若请求中均未设置 `limit` 和 `cursor` 参数,环信服务器按群组创建时间倒序返回前 10 个群组。 @@ -426,7 +426,7 @@ GET https://{host}/{org_name}/{app_name}/chatgroups?limit={N}&cursor={cursor} | - `groupid` | String | 群组 ID。 | | - `affiliations` | int | 群组现有成员数。 | | - `type` | String | “group” 群组类型。 | -| - `last_modified` | String | 最近一次修改的时间戳,单位为毫秒。 | +| - `lastModified` | String | 最近一次修改的时间戳,单位为毫秒。 | | - `groupname` | String | 群组名称。 | | `count` | Int | 实际获取的群组数量。 | | `cursor` | String | 查询游标,指定下次查询的起始位置。 | @@ -469,7 +469,7 @@ curl -X GET -H 'Accept: application/json' -H 'Authorization: Bearer - `true`:是;
- `false`:否。 | | - `allowinvites` | Bool | 是否允许群成员邀请其他用户加入此群。
- `true`:允许群成员邀请其他用户加入此群;
- `false`:只有群主可以邀请其他用户入群。
注:该参数仅对私有群有效,因为公开群不允许群成员邀请其他用户入群。 | | - `maxusers` | Int | 群组最大成员数,创建群组的时候设置,可修改。 | -| - `permission` | String | 群组成员角色:
- `owner`:群主;
- `member`:普通成员。 | +| - `affiliations` | Array | 群组成员列表及其对应角色:
- `owner`:群主;
- `member`:群组管理员和普通成员。 | | - `owner` | String | 群主的用户 ID。例如:{“owner”: “user1”}。 | | - `created` | Long | 创建该群组的 Unix 时间戳。 | | - `affiliations_count` | int | 群组现有成员总数。 | @@ -891,12 +891,18 @@ POST https://{host}/{org_name}/{app_name}/chatgroups/{group_id}/announcement ##### 请求 header -| 参数 | 类型 | 是否必需 | 描述 | -| :-------------- | :----- | :------- | :------------------------------------------------------------------------------------------------------------------- | +| 参数 | 类型 | 是否必需 | 描述 | +| :-------------- | :----- | :------- | :---------------- | | `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | | `Accept` | String | 是 | 内容类型。请填 `application/json`。 | | `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | +##### 请求 body + +| 参数 | 类型 | 是否必需 | 描述 | +| :-------------- | :----- | :------- | :---------------- | +| `announcement` | String | 是 | 群组通告内容。 | + #### HTTP 响应 ##### 响应 body @@ -1057,7 +1063,6 @@ POST https://{host}/{org_name}/{app_name}/chatgroups/{group_id}/share_files | `Accept` | String | 是 | 内容类型。请填 `application/json`。 | | `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | | `Content-Type` | String | 是 | 内容类型。请填 `multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW`。 | -| `restrict-access` | Bool | 否 | 是否仅群成员可见。
- `true`:是。
- `false`:否。 | | `file` | String | 是 | 待上传文件的本地路径。 | #### HTTP 响应 @@ -1086,7 +1091,7 @@ POST https://{host}/{org_name}/{app_name}/chatgroups/{group_id}/share_files ```shell # 将 替换为你在服务端生成的 App Token -curl -X POST 'https://XXXX/XXXX/XXXX/chatgroups/66021836783617/share_files' -H 'Accept: application/json' -H 'Authorization: Bearer ' -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' -H 'restrict-access: true' -F file=@/Users/test/image/IMG_3.JPG +curl -X POST 'https://XXXX/XXXX/XXXX/chatgroups/66021836783617/share_files' -H 'Accept: application/json' -H 'Authorization: Bearer ' -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' -F file=@/Users/test/image/IMG_3.JPG ``` ##### 响应示例 @@ -1138,18 +1143,7 @@ GET https://{host}/{org_name}/{app_name}/chatgroups/{group_id}/share_files/{file ##### 响应 body -如果返回的 HTTP 状态码为 `200`,表示请求成功,响应包体中包含以下字段: - -| 字段 | 类型 | 描述 | -| :--------------- | :----- | :--------------------------------------------------------- | -| `data.file_url` | String | 群组共享文件的 URL,在环信即时通讯 IM 服务器上保存的地址。 | -| `data.group_id` | String | 群组 ID。 | -| `data.file_name` | String | 群组共享文件的名称。 | -| `data.created` | Long | 上传群组共享文件的时间。 | -| `data.file_id` | String | 群组共享文件 ID。该参数在删除共享文件时需要提供。 | -| `data.file_size` | Long | 群组共享文件大小,单位为字节。 | - -其他字段及描述详见 [公共参数](#公共参数)。 +如果返回的 HTTP 状态码为 `200`,表示请求成功,响应体中为上传的文件的内容,例如,上传的文件内容为“Hello world”,响应中返回“Hello world”。 如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考 [响应状态码](error.html) 了解可能的原因。 @@ -1165,26 +1159,7 @@ curl -X GET -H 'Content-Type: application/json' -H 'Accept: application/json' -H ##### 响应示例 -```json -{ - "action": "post", - "application": "7fXXXXef", - "uri": "https://XXXX/XXXX/XXXX/chatgroups/6XXXX7/share_files", - "entities": [], - "data": { - "file_url": "https://XXXX/XXXX/XXXX/chatgroups/6XXXX7/share_files/c6XXXXc0", - "group_id": "6XXXX7", - "file_name": "img_3.jpg", - "created": 1599050554954, - "file_id": "c6XXXXc0", - "file_size": 13512 - }, - "timestamp": 1599050554978, - "duration": 0, - "organization": "XXXX", - "applicationName": "testapp" -} -``` +返回上传的文件的内容。例如,上传的文件内容为“Hello world”,响应中返回“Hello world”。 ### 删除群组共享文件 @@ -3001,8 +2976,7 @@ POST https://{host}/{org_name}/{app_name}/chatgroups/{group_id}/ban | 字段 | 类型 | 描述 | | :------------ | :--- | :-------------------------------------------------------------- | -| `data.result` | Bool | 操作结果:
- `true`:禁言成功;
- `false`:禁言失败。 | -| `data.expire` | Long | 禁言到期的时间。该时间为 Unix 时间戳,单位为毫秒。 | +| `data.mute` | Bool | 操作结果:
- `true`:禁言成功;
- `false`:禁言失败。 | 其他字段及描述详见 [公共参数](#公共参数)。 @@ -3372,9 +3346,11 @@ GET https://{host}/{org_name}/{app_name}/threads/chatgroups/{group_id}/user/{use ##### 响应 body -如果返回的 HTTP 状态码为 `200`,表示请求成功,响应包体中包含以下字段: +如果返回的 HTTP 状态码为 `200`,表示请求成功,响应包体中包含以下字段。 + +若为最后一页数据,响应中仍会返回 `cursor`,而且获取的子区数量小于请求中的 `limit` 的值;若响应中不再返回子区数据,表示你已经获取该群组下的所有子区数据。 -| 字段 | 描述 | 描述 | +| 字段 | 描述 | 描述 | | :------------------ | :----- | :-------------------------------------- | | `entities` | JSON Array | 响应数据。 | | - `name` | String | 子区名称。 | @@ -3788,7 +3764,7 @@ curl -X POST https://XXXX/XXXX/XXXX/thread/1XXXX7/users -d '{ #### HTTP 请求 ```http -DELETE https://{host}/{org_name}/{app_name}/threads/{thread_id}/users +DELETE https://{host}/{org_name}/{app_name}/thread/{thread_id}/users ``` ##### 路径参数 diff --git a/docs/document/server-side/java_server_sdk.md b/docs/document/server-side/java_server_sdk.md index 63aa05071..c317f1296 100644 --- a/docs/document/server-side/java_server_sdk.md +++ b/docs/document/server-side/java_server_sdk.md @@ -24,14 +24,14 @@ Server SDK 提供了用户、消息、群组、聊天室等资源的操作管理 com.easemob.im im-sdk-core - 0.7.5 + 0.8.2 ``` 如果你的项目使用 Gradle 构建,可以在 build.gradle 中添加下面代码: ```gradle -implementation 'com.easemob.im:im-sdk-core:0.7.3' +implementation 'com.easemob.im:im-sdk-core:0.8.1' ``` ### 使用 @@ -235,6 +235,49 @@ EMProperties properties = EMProperties.builder() ## 更新日志 +### V0.8.2 2024-01-11 + +1.增加发送聊天室全局广播功能。 +2.增加群组封禁&群组解禁的功能。 +以上更新内容请到 GroupApi & MessageApi 中查看。 + +### V0.8.1 2024-01-2 + +1. 增加创建大型群组功能。 +2. 删除向大型和小型聊天室发送消息的功能。 +3. 批量 添加群组成员 & 移除群组成员 去掉用户列表数量检查。 +4. 修改获取 用户 Token 功能的注释说明。 +以上更新内容请到 GroupApi & MessageApi & TokenApi 中查看。 + +### V0.8.0 2023-12-21 + +1. 增加 向聊天室发送定向消息 功能。 + +以上更新内容请到 MessageApi 中查看。 + + +### V0.7.9 2023-11-28 + +增加查看指定用户是否已加入群组的功能。 + +以上更新内容请到 GroupApi 中查看。 + +### V0.7.8 2023-11-03 + +增加指定群主用户发送消息的功能。 + +以上更新内容请到 MessageApi 中查看。 + +### V0.7.7 2023-10-18 + +修复下载历史消息文件失败的问题。 + +### V0.7.6 2023-08-30 + +增加获取多个聊天室详情的功能。 + +以上更新内容请到 RoomApi 中查看。 + ### V0.7.5 2023-08-24 - `EMProperties` 中增加对 `ConnectionProvider` 的配置项,用于解决 Netty 请求连接问题。 diff --git a/docs/document/server-side/message_chatroom.md b/docs/document/server-side/message_chatroom.md index a48aee62f..a2352274b 100644 --- a/docs/document/server-side/message_chatroom.md +++ b/docs/document/server-side/message_chatroom.md @@ -1,15 +1,19 @@ - -### 发送聊天室消息 +# 发送聊天室消息 本文展示如何调用环信 IM RESTful API 在服务端实现聊天室场景中全类型消息的发送与接收,包括文本消息、图片消息、语音消息、视频消息、透传消息和自定义消息。 聊天室场景下,发送各类型的消息调用需调用同一 RESTful API,不同类型的消息只是请求体中的 body 字段内容存在差异,发送方式与单聊类似,详见[发送单聊消息](message_single.html)。 -:::notice -接口调用过程中,请求体若超过 5 KB 会导致 413 错误,需要拆成几个较小的请求体重试。同时,请求体和扩展字段的总长度不能超过 3 KB。 +:::tip +1. 接口调用过程中,请求体和扩展字段的总长度不能超过 5 KB。 +2. 聊天室中发消息时,不会同步给发送方。 ::: -**发送频率**:通过 RESTful API 单个应用每秒最多可向聊天室发送 100 条消息,每次最多可向 10 个聊天室发送消息。例如,一次向 10 个聊天室发送消息,视为 10 条消息。 +**发送频率**:对于单个应用来说,调用该 API 每次最多可向 10 个聊天室发送消息,而且该 API 存在以下两个限制: + +- 每秒最多可发送 100 条消息:例如,你每次向 10 个聊天室发送消息,即发送了 10 条消息,你每秒最多可调用 10 次该接口。第 11 次调用时,则报 403 错误。 + +- 每秒最大可调用 20 次:例如,你每次调用该 API 向单个聊天室发送消息,可调用 20 次,第 21 次调用时会报 429 错误。 对于聊天室消息,环信即时通讯提供消息分级功能,将消息的优先级划分为高、普通和低三种级别,高优先级的消息会优先送达。你可以在创建消息时对指定聊天室消息类型或指定成员的消息设置为高优先级,确保这些消息优先送达。这种方式确保在聊天室内消息并发量很大或消息发送频率过高时,重要消息能够优先送达,从而提升重要消息的可靠性。 当服务器的负载较高时,会优先丢弃低优先级的消息,将资源留给高优先级的消息。不过,消息分级功能只确保消息优先到达,并不保证必达。服务器负载过高的情况下,即使是高优先级消息依然会被丢弃。 @@ -81,13 +85,11 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms | 参数 | 类型 | 是否必需 | 描述 | | :-------------- | :----- | :------- | :--------------- | -| `from` | String | 否 | 消息发送方的用户 ID。若不传入该字段,服务器默认设置为管理员,即 “admin”;若传入字段但值为空字符串 (“”),请求失败。 | -| `to` | Array | 是 | 消息接收方聊天室 ID 数组。每次最多可向 10 个聊天室发送消息。 | +| `from` | String | 否 | 消息发送方的用户 ID。若不传入该字段,服务器默认设置为 `admin`。1. 服务器不校验传入的用户 ID 是否存在,因此,如果你传入的用户 ID 不存在,服务器并不会提示,仍照常发送消息。
2. 若传入字段但值为空字符串 (“”),请求失败。
| +| `to` | Array | 是 | 消息接收方聊天室 ID 数组。每次最多可向 10 个聊天室发送消息。服务器不校验传入的聊天室 ID 是否存在,因此,如果你传入的聊天室 ID 不存在,服务器并不会提示,仍照常发送消息。 | | `chatroom_msg_level` | String | 否 | 聊天室消息优先级:
- `high`:高;
- (默认)`normal`:普通;
- `low`:低。 | | `type` | String | 是 | 消息类型:
- `txt`:文本消息;
- `img`:图片消息;
- `audio`:语音消息;
- `video`:视频消息;
- `file`:文件消息;
- `loc`:位置消息;
- `cmd`:透传消息;
- `custom`:自定义消息。 | | `body` | JSON | 是 | 消息内容。body 包含的字段见下表说明。 | -| `sync_device` | Bool | 否 | 消息发送成功后,是否将消息同步到发送方。
- `true`:是;
- (默认)`false`:否。 | -| `routetype` | String | 否 | 若传入该参数,其值为 `ROUTE_ONLINE`,表示接收方只有在线时才能收到消息,若接收方离线则无法收到消息。若不传入该参数,无论接收方在线还是离线都能收到消息。 | | `ext` | JSON | 否 | 消息支持扩展字段,可添加自定义信息。不能对该参数传入 `null`。同时,推送通知也支持自定义扩展字段,详见 [APNs 自定义显示](/document/ios/push.html#自定义显示) 和 [Android 推送字段说明](/document/android/push.html#自定义显示)。 | 请求体中的 `body` 字段说明详见下表。 @@ -114,8 +116,6 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms #### 请求示例 -发送给目标用户,消息无需同步给发送方: - ```bash # 将 替换为你在服务端生成的 App Token @@ -133,27 +133,6 @@ curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatrooms' \ }' ``` -仅发送给在线用户,消息同步给发送方: - -```bash -# 将 替换为你在服务端生成的 App Token - -curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatrooms' \ --H 'Content-Type: application/json' \ --H 'Accept: application/json' \ --H 'Authorization: Bearer ' \ --d '{ - "from": "user1", - "to": ["185145305923585"], - "type": "txt", - "body": { - "msg": "testmessages" - }, - "routetype":"ROUTE_ONLINE", - "sync_device":true -}' -``` - #### 响应示例 ```json @@ -200,7 +179,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :------- | -| `filename` | String | 是 | 图片名称。 | +| `filename` | String | 否 | 图片名称。建议传入该参数,否则客户端收到图片消息时无法显示图片名称。 | | `secret` | String | 否 | 图片的访问密钥,即成功上传图片后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果图片文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `size` | JSON | 否 | 图片尺寸,单位为像素,包含以下字段:
- `height`:图片高度;
- `width`:图片宽度。 | | `url` | String | 是 | 图片 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。其中 `file_uuid` 为文件 ID,成功上传图片文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -292,7 +271,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :---------- | -| `filename` | String | 是 | 语音文件的名称。 | +| `filename` | String | 否 | 语音文件的名称。建议传入该参数,否则客户端收到语音消息时无法显示语音文件名称。 | | `secret` | String | 否 | 语音文件访问密钥,即成功上传语音文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。 如果语音文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `Length` | Int | 否 | 语音时长,单位为秒。 | | `url` | String | 是 | 语音文件 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。`file_uuid` 为文件 ID,成功上传语音文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -313,7 +292,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -381,7 +360,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms | 参数 | 类型 | 是否必需 | 描述 | | :------------- | :----- | :------- | :---------------- | -| `filename` | String | 是 | 视频文件名称。| +| `filename` | String | 否 | 视频文件名称。建议传入该参数,否则客户端收到视频消息时无法显示视频文件名称。| | `thumb` | String | 否 | 视频缩略图 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。`file_uuid` 为视频缩略图唯一标识,成功上传缩略图文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | | `length` | Int | 否 | 视频时长,单位为秒。 | | `secret` | String | 否 | 视频文件访问密钥,即成功上传视频文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果视频文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | @@ -405,7 +384,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -473,7 +452,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :------------ | -| `filename` | String | 是 | 文件名称。 | +| `filename` | String | 否 | 文件名称。建议传入该参数,否则客户端收到文件消息时无法显示文件名称。 | | `secret` | String | 否 | 文件访问密钥,即成功上传文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `url` | String | 是 | 文件 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。其中 `file_uuid` 为文件 ID,成功上传视频文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -493,7 +472,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -579,7 +558,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -664,7 +643,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -748,7 +727,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -762,6 +741,9 @@ curl -X POST -i "https://XXXX/XXXX/XXXX/messages/chatrooms" \ "type": "custom", "body": { "customEvent": "custom_event" + "customExts":{ + "ext_key1":"ext_value1" + } } }' ``` @@ -821,7 +803,6 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms/users | `chatroom_msg_level` | String | 否 | 聊天室消息优先级:
- `high`:高;
- (默认)`normal`:普通;
- `low`:低。 | | `type` | String | 是 | 消息类型:
- `txt`:文本消息;
- `img`:图片消息;
- `audio`:语音消息;
- `video`:视频消息;
- `file`:文件消息;
- `loc`:位置消息;
- `cmd`:透传消息;
- `custom`:自定义消息。 | | `body` | JSON | 是 | 消息内容。body 包含的字段见下表说明。 | -| `sync_device` | Bool | 否 | 消息发送成功后,是否将消息同步到发送方。
- `true`:是;
- (默认)`false`:否。 | | `ext` | JSON | 否 | 消息支持扩展字段,可添加自定义信息。不能对该参数传入 `null`。同时,推送通知也支持自定义扩展字段,详见 [APNs 自定义显示](/document/ios/push.html#自定义显示) 和 [Android 推送字段说明](/document/android/push.html#自定义显示)。 | | `users` | Array | 是 | 接收消息的聊天室成员的用户 ID 数组。每次最多可传 20 个用户 ID。 | @@ -851,28 +832,6 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms/users #### 请求示例 -发送给目标用户,消息无需同步给发送方: - -```bash -# 将 替换为你在服务端生成的 App Token - -curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatrooms' \ --H 'Content-Type: application/json' \ --H 'Accept: application/json' \ --H 'Authorization: Bearer ' \ --d '{ - "from": "user1", - "to": ["185145305923585"], - "type": "txt", - "body": { - "msg": "testmessages" - }, - "users": ["user2", "user3"] -}' -``` - -仅发送给在线用户,消息同步给发送方: - ```bash # 将 替换为你在服务端生成的 App Token @@ -887,7 +846,6 @@ curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatrooms' \ "body": { "msg": "testmessages" }, - "sync_device": true, "users": ["user2", "user3"] }' ``` @@ -945,7 +903,6 @@ POST https://{host}/{org_name}/{app_name}/messages/chatrooms/broadcast | `msg.type` | String | 是 | 广播消息类型:
- `txt`:文本消息;
- `img`:图片消息;
- `audio`:语音消息;
- `video`:视频消息;
- `file`:文件消息;
- `loc`:位置消息;
- `cmd`:透传消息;
- `custom`:自定义消息。 | | `msg.msg` | String | 是 | 消息内容。 | | `ext` | JSON | 否 | 广播消息支持扩展字段,可添加自定义信息。不能对该参数传入 `null`。同时,推送通知也支持自定义扩展字段,详见 [APNs 自定义显示](/document/ios/push.html#自定义显示) 和 [Android 推送字段说明](/document/android/push.html#自定义显示)。 | -| `sync_device` | Bool | 否 | 广播消息发送成功后,是否将消息同步到发送方。
- `true`:是;
- (默认)`false`:否。 | 不同类型的消息的请求体只在 `msg` 字段有差别,其他参数相同。除了 `type` 字段,`msg` 字段中包含的参数与发送聊天室消息的请求体中的 `body` 字段含义相同,详见各类消息的参数说明。 - [发送图片消息](#发送图片消息) @@ -993,7 +950,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` @@ -1021,7 +977,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` @@ -1046,7 +1001,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` @@ -1073,7 +1027,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` @@ -1097,7 +1050,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` @@ -1121,7 +1073,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` @@ -1143,7 +1094,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` @@ -1165,7 +1115,6 @@ curl -L 'https://XXXX/XXXX/XXXX/messages/chatrooms/broadcast' \ "ext": { "extKey": "extValue" }, - "sync_device": false, "chatroom_msg_level": "low" }' ``` diff --git a/docs/document/server-side/message_download.md b/docs/document/server-side/message_download.md index 4913e7590..12f82b785 100644 --- a/docs/document/server-side/message_download.md +++ b/docs/document/server-side/message_download.md @@ -58,7 +58,7 @@ 同时,为了保证聊天文件的安全,我们的 API 保证了以下几点: - 上传文件的大小不能超过 10 MB,超过会上传失败。 -- 支持对上传的文件限制访问。该功能开启后,你需要通过密钥才能下载被限制访问的文件。消息回调(包含发送前回调和发送后回调)和获取历史消息涉及下载文件时,都需要在下载 URL 中拼接密钥,才能正常下载文件,拼接规则为:`{{url}}?share-secret={{secret}}`。 +- 支持对上传的文件限制访问。要使用该功能,请联系商务开通。该功能开启后,你需要从文件上传响应中返回的 `share-secret` 通过密钥才能下载被限制访问的文件。消息回调(包含发送前回调和发送后回调)和获取历史消息涉及下载文件时,都需要在下载 URL 中拼接密钥,才能正常下载文件,拼接规则为:`{{url}}?share-secret={{secret}}`。 ### HTTP 请求 @@ -76,7 +76,7 @@ POST https://{host}/{org_name}/{app_name}/chatfiles | :---------------- | :----- | :------- | :------------------------ | | `Content-Type` | String | 否 | 内容类型: `multipart/form-data`。上传文件会自动填充该请求头。 | | `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | -| `restrict-access` | Bool | 否 | 是否限制访问该文件:
- `true`:是。用户需要通过响应 body 中获取的文件访问密钥(`share-secret`)才能下载该文件。
- `false`:否。表示不限制访问。用户可以直接下载该文件。 | +| `restrict-access` | Bool | 否 | 是否限制访问该文件:
- `true`:是。用户需要通过响应 body 中获取的文件访问密钥(`share-secret`)才能下载该文件。
- `false`:否。表示不限制访问。用户可以直接下载该文件。
要使用文件访问限制功能,请联系商务开通。| #### 请求 body @@ -142,7 +142,7 @@ curl L -X POST 'https://XXXX/XXXX/XXXX/chatfiles' \ 你可利用该方法下载图片、语音、视频或其他类型的文件。 -:::notice +:::tip 如果上传文件时设置了文件访问限制(`restrict-access` 设置为 `true`),需要在下载请求头中包含文件上传响应中返回的 `share-secret` 和当前登录用户的 token 才能下载文件。 ::: diff --git a/docs/document/server-side/message_group.md b/docs/document/server-side/message_group.md index b25d85a48..82ffbacd6 100644 --- a/docs/document/server-side/message_group.md +++ b/docs/document/server-side/message_group.md @@ -6,11 +6,14 @@ 群组聊天场景下,发送各类型的消息调用需调用同一 RESTful API,不同类型的消息只是请求体中的 body 字段内容存在差异,发送方式与单聊类似,详见[发送单聊消息](message_single.html)。 -:::notice -接口调用过程中,请求体若超过 5 KB 会导致 413 错误,需要拆成几个较小的请求体重试。同时,请求体和扩展字段的总长度不能超过 3 KB。 +:::tip +1. 接口调用过程中,请求体和扩展字段的总长度不能超过 5 KB。 +2. 群组中发送的消息均同步给发送方。 ::: -**发送频率**:通过 RESTful API 单个应用每秒最多可发送 20 条消息,每次最多可向 3 个群组发送。例如,一次向 3 个群组发送消息,视为 3 条消息。 +**发送频率**:对于单个应用来说,调用该 API 每次最多向 3 个群组发送消息,而且该 API 存在以下两个限制: +- 每秒最多可发送 20 条消息:例如,你每次向 3 个群组发送消息,即发送了 3 条消息,你每秒最多可调用 7 次。第 8 次调用时,则报 403 错误。 +- 每秒最大可调用 20 次:例如,你每次调用该 API 向单个群组发送消息,可调用 20 次。第 21 次调用时会报 429 错误。 ## 前提条件 @@ -74,17 +77,16 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups 下表为发送各类消息的通用请求体,为 JSON 对象,是所有消息的外层结构。与单聊消息类似,不同类型的消息的请求体只是 `body` 字段内容存在差异。 -:::notice -群聊消息的通用请求体中的参数与[发送单聊消息](message_single.html)类似,唯一区别在于群聊中的 `to` 字段表示消息接收方群组 ID 数组。
+:::tip +1. 群聊消息的通用请求体中的参数与[发送单聊消息](message_single.html)类似,唯一区别在于群聊中的 `to` 字段表示消息接收方群组 ID 数组。
::: | 参数 | 类型 | 是否必需 | 描述 | | :-------------- | :----- | :------- | :--------------- | -| `from` | String | 否 | 消息发送方的用户 ID。若不传入该字段,服务器默认设置为管理员,即 “admin”;若传入字段但值为空字符串 (“”),请求失败。 | -| `to` | Array | 是 | 消息接收方群组 ID 数组。每次最多可向 3 个群组发送消息。 | +| `from` | String | 否 | 消息发送方的用户 ID。若不传入该字段,服务器默认设置为 `admin`。1. 服务器不校验传入的用户 ID 是否存在,因此,如果你传入的用户 ID 不存在,服务器并不会提示,仍照常发送消息。
2. 若传入字段但值为空字符串 (“”),请求失败。
| +| `to` | Array | 是 | 消息接收方群组 ID 数组。每次最多可向 3 个群组发送消息。服务器不校验传入的群组 ID 是否存在,因此,如果你传入的群组 ID 不存在,服务器并不会提示,仍照常发送消息。 | | `type` | String | 是 | 消息类型:
- `txt`:文本消息;
- `img`:图片消息;
- `audio`:语音消息;
- `video`:视频消息;
- `file`:文件消息;
- `loc`:位置消息;
- `cmd`:透传消息;
- `custom`:自定义消息。 | | `body` | JSON | 是 | 消息内容。body 包含的字段见下表说明。 | -| `sync_device` | Bool | 否 | 消息发送成功后,是否将消息同步到发送方。
- `true`:是;
- (默认)`false`:否。 | | `routetype` | String | 否 | 若传入该参数,其值为 `ROUTE_ONLINE`,表示接收方只有在线时才能收到消息,若接收方离线则无法收到消息。若不传入该参数,无论接收方在线还是离线都能收到消息。 | | `ext` | JSON | 否 | 消息支持扩展字段,可添加自定义信息。不能对该参数传入 `null`。同时,推送通知也支持自定义扩展字段,详见 [APNs 自定义显示](/document/ios/push.html#自定义显示) 和 [Android 推送字段说明](/document/android/push.html#自定义显示)。 | | `ext.em_ignore_notification` | Bool | 否 | 是否发送静默消息:
- `true`:是;
- (默认)`false`:否。
发送静默消息指用户离线时,环信即时通讯 IM 服务不会通过第三方厂商的消息推送服务向该用户的设备推送消息通知。因此,用户不会收到消息推送通知。当用户再次上线时,会收到离线期间的所有消息。发送静默消息和免打扰模式下均为不推送消息,区别在于发送静默消息为发送方设置不推送消息,而免打扰模式为接收方设置在指定时间段内不接收推送通知。| @@ -113,7 +115,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups #### 请求示例 -发送给目标用户,消息无需同步给发送方: +发送给群组内所有成员,不论这些成员是否在线: ```bash # 将 替换为你在服务端生成的 App Token @@ -135,7 +137,7 @@ curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatgroups' \ }' ``` -仅发送给在线用户,消息同步给发送方: +仅发送给在线用户,即 `routetype` 设置为 `ROUTE_ONLINE`: ```bash # 将 替换为你在服务端生成的 App Token @@ -154,8 +156,7 @@ curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatgroups' "ext": { "em_ignore_notification": true }, - "routetype":"ROUTE_ONLINE", - "sync_device":true + "routetype":"ROUTE_ONLINE" }' ``` @@ -205,7 +206,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :------- | -| `filename` | String | 是 | 图片名称。 | +| `filename` | String | 否 | 图片名称。建议传入该参数,否则客户端收到图片消息时无法显示图片名称。 | | `secret` | String | 否 | 图片的访问密钥,即成功上传图片后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果图片文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `size` | JSON | 否 | 图片尺寸,单位为像素,包含以下字段:
- `height`:图片高度;
- `width`:图片宽度。 | | `url` | String | 是 | 图片 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。其中 `file_uuid` 为文件 ID,成功上传图片文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -297,7 +298,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :---------- | -| `filename` | String | 是 | 语音文件的名称。 | +| `filename` | String | 否 | 语音文件的名称。建议传入该参数,否则客户端收到语音消息时无法显示语音文件名称。 | | `secret` | String | 否 | 语音文件访问密钥,即成功上传语音文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。 如果语音文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `Length` | Int | 否 | 语音时长,单位为秒。 | | `url` | String | 是 | 语音文件 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。`file_uuid` 为文件 ID,成功上传语音文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -318,7 +319,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -385,7 +386,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups | 参数 | 类型 | 是否必需 | 描述 | | :------------- | :----- | :------- | :---------------- | -| `filename` | String | 是 | 视频文件名称。| +| `filename` | String | 否 | 视频文件名称。建议传入该参数,否则客户端收到视频消息时无法显示视频文件名称。 | | `thumb` | String | 否 | 视频缩略图 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。`file_uuid` 为视频缩略图唯一标识,成功上传缩略图文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | | `length` | Int | 否 | 视频时长,单位为秒。 | | `secret` | String | 否 | 视频文件访问密钥,即成功上传视频文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果视频文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | @@ -409,7 +410,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -480,7 +481,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :------------ | -| `filename` | String | 是 | 文件名称。 | +| `filename` | String | 否 | 文件名称。 建议传入该参数,否则客户端收到文件消息时无法显示文件名称。 | | `secret` | String | 否 | 文件访问密钥,即成功上传文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `url` | String | 是 | 文件 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。其中 `file_uuid` 为文件 ID,成功上传视频文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -500,7 +501,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -586,7 +587,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -671,7 +672,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -755,7 +756,7 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups ### 示例 -##### 请求示例 +#### 请求示例 ```bash # 将 替换为你在服务端生成的 App Token @@ -770,6 +771,9 @@ curl -X POST -i "https://XXXX/XXXX/XXXX/messages/chatgroups" \ "type": "custom", "body": { "customEvent": "custom_event" + "customExts":{ + "ext_key1":"ext_value1" + } } }' ``` @@ -799,6 +803,7 @@ curl -X POST -i "https://XXXX/XXXX/XXXX/messages/chatgroups" \ :::notice 1. 定向消息不写入会话列表,不计入群组会话的未读消息数。 2. 定向消息不支持消息漫游功能,因此从服务器拉取漫游消息时,不包含定向消息。 +3. 群组中发送的定向消息均同步给发送方。 ::: **发送频率**:100 次/秒/App Key @@ -833,7 +838,6 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups/users | `to` | Array | 是 | 消息接收方所属的群组 ID。每次只能传 1 个群组。 | | `type` | String | 是 | 消息类型:
- `txt`:文本消息;
- `img`:图片消息;
- `audio`:语音消息;
- `video`:视频消息;
- `file`:文件消息;
- `loc`:位置消息;
- `cmd`:透传消息;
- `custom`:自定义消息。 | | `body` | JSON | 是 | 消息内容。body 包含的字段见下表说明。 | -| `sync_device` | Bool | 否 | 消息发送成功后,是否将消息同步到发送方。
- `true`:是;
- (默认)`false`:否。 | | `ext` | JSON | 否 | 消息支持扩展字段,可添加自定义信息。不能对该参数传入 `null`。同时,推送通知也支持自定义扩展字段,详见 [APNs 自定义显示](/document/ios/push.html#自定义显示) 和 [Android 推送字段说明](/document/android/push.html#自定义显示)。 | | `ext.em_ignore_notification` | Bool | 否 | 是否发送静默消息:
- `true`:是;
- (默认)`false`:否。
发送静默消息指用户离线时,环信即时通讯 IM 服务不会通过第三方厂商的消息推送服务向该用户的设备推送消息通知。因此,用户不会收到消息推送通知。当用户再次上线时,会收到离线期间的所有消息。发送静默消息和免打扰模式下均为不推送消息,区别在于发送静默消息为发送方设置不推送消息,而免打扰模式为接收方设置在指定时间段内不接收推送通知。| | `users` | Array | 是 | 接收消息的群成员的用户 ID 数组。每次最多可传 20 个用户 ID。 | @@ -865,8 +869,6 @@ POST https://{host}/{org_name}/{app_name}/messages/chatgroups/users #### 请求示例 -发送给目标用户,消息无需同步给发送方: - ```bash # 将 替换为你在服务端生成的 App Token @@ -888,27 +890,6 @@ curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatgroups/users' \ }' ``` -消息同步给发送方: - -```bash -# 将 替换为你在服务端生成的 App Token - -curl -X POST -i 'https://XXXX/XXXX/XXXX/messages/chatgroups/users' --H 'Content-Type: application/json' --H 'Accept: application/json' --H 'Authorization: Bearer ' --d '{ - "from": "user1", - "to": ["184524748161025"], - "type": "txt", - "body": { - "msg": "testmessages" - }, - "sync_device":true, - "users": ["user2", "user3"] -}' -``` - #### 响应示例 ```json diff --git a/docs/document/server-side/message_modify_text_custom.md b/docs/document/server-side/message_modify_text_custom.md new file mode 100644 index 000000000..96ce40734 --- /dev/null +++ b/docs/document/server-side/message_modify_text_custom.md @@ -0,0 +1,164 @@ +# 修改文本或自定义消息 + +本文展示如何调用环信 IM RESTful API 在服务端修改发送成功的文本消息或自定义消息。 + +**调用频率**:100 次/秒/App Key + +:::tip +若使用该功能,需联系环信商务开通。 +::: + +## 前提条件 + +要调用环信即时通讯 REST API,请确保满足以下要求: + +- 已在环信即时通讯控制台 [开通配置环信即时通讯 IM 服务](enable_and_configure_IM.html)。 +- 了解环信 IM REST API 的调用频率限制,详见 [接口频率限制](limitationapi.html)。 + +## 认证方式 + +环信即时通讯 REST API 要求 Bearer HTTP 认证。每次发送 HTTP 请求时,都必须在请求头部填入如下 `Authorization` 字段: + +`Authorization: Bearer YourAppToken` + +为提高项目的安全性,环信使用 Token(动态密钥)对即将登录即时通讯系统的用户进行鉴权。本文涉及的所有消息管理 REST API 都需要使用 App Token 的鉴权方式,详见 [使用 App Token 鉴权](easemob_app_token.html)。 + +## HTTP 请求 + +```http +PUT https://{host}/{org_name}/{app_name}/messages/rewrite/{msg_id} +``` + +### 路径参数 + +| 参数 | 类型 | 是否必需 | 描述 | +| :--------- | :----- | :------- | :----------------------- | +| `host` | String | 是 | 环信即时通讯 IM 分配的用于访问 RESTful API 的域名。详见 [获取环信即时通讯 IM 的信息](enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `org_name` | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见 [获取环信即时通讯 IM 的信息](enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `app_name` | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见 [获取环信即时通讯 IM 的信息](enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `msg_id` | String| 是 | 要修改的消息的 ID。| + +### 请求 header + +| 参数 | 类型 | 是否必需 | 描述 | +| :-------------- | :----- | :------- | :-------------- | +| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | +| `Accept` | String | 是 | 内容类型。请填 `application/json`。 | +| `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | + +### 请求 body + +| 参数 | 类型 | 是否必需 | 描述 | +| :-------------- | :----- | :------- | :--------------- | +| `user`| String | 否 | 修改消息的用户。| +| `new_msg` | JSON | 是 | 修改后的消息。| +| `new_msg.type` | String | 是 | 修改的消息类型:
- `txt`:文本消息;
- `custom`:自定义消息。| +| `new_msg.msg` | String | 是 | 修改后的消息内容。**该字段只对文本消息生效。**| +| `new_msg.customEvent` | String | 否 | 用户自定义的事件类型。该参数的值必须满足正则表达式 `[a-zA-Z0-9-_/\.]{1,32}`,长度为 1-32 个字符。**该字段只对自定义消息生效。** | +| `new_msg.customExts` | JSON | 否 | 用户自定义的事件属性,类型必须是 `Map`,最多可以包含 16 个元素。**该字段只对自定义消息生效。** | +| `new_ext` | JSON | 否 | 修改后的消息扩展信息。| +| `is_combine_ext` | Boolean | 否 | 修改后的消息扩展信息与原有扩展信息是合并还是替换。
- (默认)`true`:合并;
- `false`:替换。| + +## HTTP 响应 + +### 响应 body + +如果返回的 HTTP 状态码为 `200`,表示请求成功,响应 body 包含如下字段: + +| 参数 | 类型 | 描述 | +| :---------------- | :----- | :------------------------------- | +| `path` | String | 请求路径,属于请求 URL 的一部分,开发者无需关注。 | +| `uri` | String | 请求 URL。 | +| `timestamp` | Long | HTTP 响应的 Unix 时间戳,单位为毫秒。 | +| `organization` | String | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识,与请求参数 `org_name` 相同。 | +| `application` | String | 应用在系统内的唯一标识。该标识由系统生成,开发者无需关心。 | +| `action` | String | 请求方法。 | +| `data` | String | 值为 `success`,表示消息成功修改。| +| `duration` | Int | 从发送 HTTP 请求到响应的时长,单位为毫秒。 | +| `applicationName` | String | 你在环信即时通讯云控制台创建应用时填入的应用名称,与请求参数 `app_name` 相同。 | + +如果返回的 HTTP 状态码非 `200`,表示请求失败,常见的异常类型如下表所示。 + +| 异常类型 | HTTP 状态码 | 错误信息 | 错误描述 | +| :-------- | :----- | :------ |:----- | +| `UnsupportedMessageTypeException` | 400 | The message is of a type that is currently not supported for modification. | 不支持修改的消息类型。目前只支持修改文本消息和自定义消息。 | +| `InvalidMessageIdException` | 400 | The provided message ID is not a valid number. | 消息 ID 必须是数字。 | +| `RewriteMessageNotAuthorizedException` | 401 | You are not authorized to edit this message. | 修改的消息 ID 不属于当前app。 | +| `EditLimitExceededException` | 403 | The message has reached its edit limit and cannot be modified further. | 当前消息修改次数达到上限。目前,每条消息最多可修改 10 次。 | +| `EditFeatureNotEnabledException` | 403 | The edit message feature is not enabled for this user or system. | 消息修改功能未开通。使用该功能前,你需要联系环信商务开通。 | +| `MessageUnavailableException` | 404 | The message is unavailable or has expired. | 修改的消息不存在或者已经过期。 | +| `RewriteMessageInternalErrorException` | 500 | An unknown error occurred while processing the request. | 内部服务异常,修改消息失败。 | + +关于其他异常,你可以参考 [响应状态码](error.html) 了解可能的原因。 + +## 示例 + +### 请求示例 + +- 修改发送成功的文本消息: + +```bash +# 将 替换为你在服务端生成的 App Token + +curl -X PUT -i 'https://XXXX/XXXX/XXXX/messages/rewrite/1235807318835202004' \ +-H 'Content-Type: application/json' \ +-H 'Accept: application/json' \ +-H 'Authorization: Bearer ' \ +-d '{ + "user": "user1", + "new_msg": { + "type": "txt", + "msg": "update message content" + }, + "new_ext": { + "key": "value", + "old_key": "new_value" + }, + "is_combine_ext": true +}' +``` + +- 修改发送成功的自定义消息: + +```bash +# 将 替换为你在服务端生成的 App Token + +curl -X PUT -i 'https://XXXX/XXXX/XXXX/messages/rewrite/1235807318835202004' \ +-H 'Content-Type: application/json' \ +-H 'Accept: application/json' \ +-H 'Authorization: Bearer ' \ +-d '{ + "user": "user1", + "new_msg": { + "type": "custom", + "customEvent": "custom_event", + "customExts":{ + "ext_key1":"ext_value1" + } + }, + "new_ext": { + "key": "value", + "old_key": "new_value" + }, + "is_combine_ext": true +}' +``` + +### 响应示例 + +```json +{ + "path": "/messages/rewrite/1235807318835202004", + "uri": "https://XXXX/XXXX/XXXX/messages/rewrite/1235807318835202004", + "timestamp": 1705372388118, + "organization": "XXXX", + "application": "ff678832-XXXX-XXXX-8130-58ac38cb6c15", + "action": "put", + "data": "success", + "duration": 49, + "applicationName": "XXXX" +} +``` + + + diff --git a/docs/document/server-side/message_single.md b/docs/document/server-side/message_single.md index 67fdbd98e..59dea527b 100644 --- a/docs/document/server-side/message_single.md +++ b/docs/document/server-side/message_single.md @@ -1,4 +1,4 @@ -# 发送单聊消息 + # 发送单聊消息 @@ -28,7 +28,7 @@

1.发送消息时,可选的 `from` 字段用于指定发送方。

-

2. 消息支持扩展属性 `ext`,可添加自定义信息。同时,推送通知也支持自定义扩展字段,详见 APNs 自定义显示Android 推送字段说明

+

2. 消息支持扩展属性 `ext`,可添加自定义信息。同时,推送通知也支持自定义扩展字段,详见 APNs 自定义显示Android 推送字段说明

@@ -36,7 +36,7 @@

图片/语音/视频/文件消息

-

1. 调用文件上传方法上传图片、语音、视频或其他类型文件,并从响应 body 中获取文件 UUID。

+

1. 调用文件上传方法上传图片、语音、视频或其他类型文件,并从响应 body 中获取文件 UUID。

2. 调用发送消息方法,在请求 body 中传入该 UUID。

@@ -47,7 +47,7 @@ 单聊场景下,发送各类型的消息调用需调用同一 RESTful API,不同类型的消息只是请求体中的 body 字段内容存在差异。 :::notice -在接口调用过程中,请求体若超过 5 KB 会导致 413 错误,需要拆成几个较小的请求体重试。同时,请求体和扩展字段的总长度不能超过 3 KB。 +接口调用过程中,请求体和扩展字段的总长度不能超过 5 KB。 ::: **发送频率**:通过 RESTful API 单个应用每分钟最多可发送 6000 条消息,每次最多可向 600 人发送。例如,一次向 600 人发消息,视为 600 条消息。 @@ -117,8 +117,8 @@ POST https://{host}/{org_name}/{app_name}/messages/users | 参数 | 类型 | 是否必需 | 描述 | | :-------------- | :----- | :------- | :----------------------------------------------------- | -| `from` | String | 否 | 消息发送方的用户 ID。若不传入该字段,服务器默认设置为管理员,即 “admin”;若传入字段但值为空字符串 (“”),请求失败。 | -| `to` | List | 是 | 消息接收方的用户 ID 数组。每次最多可向 600 个用户发送消息。 | +| `from` | String | 否 | 消息发送方的用户 ID。若不传入该字段,服务器默认设置为 `admin`。 1. 服务器不校验传入的用户 ID 是否存在,因此,如果你传入的用户 ID 不存在,服务器并不会提示,仍照常发送消息。
2. 若传入字段但值为空字符串 (“”),请求失败。
| +| `to` | List | 是 | 消息接收方的用户 ID 数组。每次最多可向 600 个用户发送消息。服务器不校验传入的用户 ID 是否存在,因此,如果你传入的用户 ID 不存在,服务器并不会提示,仍照常发送消息。 | | `type` | String | 是 | 消息类型:
- `txt`:文本消息;
- `img`:图片消息;
- `audio`:语音消息;
- `video`:视频消息;
- `file`:文件消息;
- `loc`:位置消息;
- `cmd`:透传消息;
- `custom`:自定义消息。 | | `body` | JSON | 是 | 消息内容。body 包含的字段见下表说明。 | | `sync_device` | Bool | 否 | 消息发送成功后,是否将消息同步到发送方。
- `true`:是;
- (默认)`false`:否。 | @@ -241,7 +241,7 @@ POST https://{host}/{org_name}/{app_name}/messages/users | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :------- | -| `filename` | String | 是 | 图片名称。 | +| `filename` | String | 否 | 图片名称。建议传入该参数,否则客户端收到图片消息时无法显示图片名称。 | | `secret` | String | 否 | 图片的访问密钥,即成功上传图片后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果图片文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `size` | JSON | 否 | 图片尺寸,单位为像素,包含以下字段:
- `height`:图片高度;
- `width`:图片宽度。 | | `url` | String | 是 | 图片 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。其中 `file_uuid` 为文件 ID,成功上传图片文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -333,7 +333,7 @@ POST https://{host}/{org_name}/{app_name}/messages/users | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :---------- | -| `filename` | String | 是 | 语音文件的名称。 | +| `filename` | String | 否 | 语音文件的名称。建议传入该参数,否则客户端收到语音消息时无法显示语音文件名称。 | | `secret` | String | 否 | 语音文件访问密钥,即成功上传语音文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。 如果语音文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `Length` | Int | 否 | 语音时长,单位为秒。 | | `url` | String | 是 | 语音文件 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。`file_uuid` 为文件 ID,成功上传语音文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -422,7 +422,7 @@ POST https://{host}/{org_name}/{app_name}/messages/users | 参数 | 类型 | 是否必需 | 描述 | | :------------- | :----- | :------- | :---------------- | -| `filename` | String | 是 | 文件名称。 | +| `filename` | String | 否 | 文件名称。建议传入该参数,否则客户端收到视频消息时无法显示视频文件名称。 | | `thumb` | String | 否 | 视频缩略图 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。`file_uuid` 为视频缩略图唯一标识,成功上传缩略图文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | | `length` | Int | 否 | 视频时长,单位为秒。 | | `secret` | String | 否 | 视频文件访问密钥,即成功上传视频文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果视频文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | @@ -517,7 +517,7 @@ POST https://{host}/{org_name}/{app_name}/messages/users | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :------------ | -| `filename` | String | 是 | 文件名称。 | +| `filename` | String | 否 | 文件名称。建议传入该参数,否则客户端收到文件消息时无法显示文件名称。 | | `secret` | String | 否 | 文件访问密钥,即成功上传文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取的 `share-secret`。如果文件上传时设置了文件访问限制(`restrict-access`),则该字段为必填。 | | `url` | String | 是 | 文件 URL 地址:`https://{host}/{org_name}/{app_name}/chatfiles/{file_uuid}`。其中 `file_uuid` 为文件 ID,成功上传视频文件后,从 [文件上传](message_download.html#上传文件) 的响应 body 中获取。 | @@ -808,6 +808,9 @@ curl -X POST -i "https://XXXX/XXXX/XXXX/messages/users" \ "type": "custom", "body": { "customEvent": "custom_event" + "customExts":{ + "ext_key1":"ext_value1" + } } }' ``` diff --git a/docs/document/server-side/overview.md b/docs/document/server-side/overview.md index fe83cd8c7..ce8ca6074 100644 --- a/docs/document/server-side/overview.md +++ b/docs/document/server-side/overview.md @@ -100,7 +100,7 @@ | 查询当前用户的所有设备的推送绑定信息 | GET | /{org_name}/{app_name}/users/wzy/push/binding |查询用户设备与推送信息进行绑定和解绑。 | | 设置推送消息显示昵称 | PUT | /{org_name}/{app_name}/users/{username} | 设置用户离线推送消息显示的昵称。 | | 设置推送消息展示方式 | PUT | /{org_name}/{app_name}/users/{username} | 设置用户离线推送消息展示为仅通知还是详情可见。 | -| 设置免打扰 | PUT | /{org_name}/{app_name}/users/{username} | 设置用户离线推送是否开启免打扰模式,以及开启/关闭免打扰的时间。 | +| 接收方配置模板名称 | PUT | /{org_name}/{app_name}/users/{username}/notification/template | 接收方配置模板名称。 | ### 消息发送及文件下载 @@ -109,6 +109,7 @@ | 名称
| 方法 | 请求 | 描述 | | :--------------- | :--- | :------------------------------------------ | :----------------------------------------------------------- | | 发送消息 | POST | 三种请求场景如下:
- 单聊:/{org_name}/{app_name}/messages/users
- 群聊:/{org_name}/{app_name}/messages/chatgroups
- 聊天室:/{org_name}/{app_name}/messages/chatrooms | 聊天相关 API,一般是模拟系统管理员给用户、群组或聊天室发送消息,支持发送文本消息、图片消息、语音消息、视频消息,透传消息,扩展消息以及文件类型消息。 | +| 发送聊天室广播消息 | POST | /{org_name}/{app_name}/messages/chatrooms/broadcast | 向 app 下的所有活跃聊天室(聊天室至少存在一个成员,而且曾经至少发送过一条消息)发送广播消息。 | | 上传文件 | POST | /{org_name}/{app_name}/chatfiles | 上传语音和图片等文件。 | | 下载文件 | GET | /{org_name}/{app_name}/chatfiles/{file_uuid} | 下载语音和图片等文件。 | | 获取聊天记录文件 | GET | /{org_name}/{app_name}/chatmessages/${time} | 获取聊天记录文件。 | @@ -133,7 +134,9 @@ | :----------- | :----- | :----------------------------------------------------------- | :--------------------- | | 添加好友 | POST | /{org_name}/{app_name}/users/{owner_username}/contacts/users/{friend_username} | 添加为好友。 | | 移除好友 | DELETE | /{org_name}/{app_name}/users/{owner_username}/contacts/users/{friend_username} | 移除好友列表中的用户。 | -| 获取好友列表 | GET | /{org_name}/{app_name}/users/{owner_username}/contacts/users | 获取好友列表。 | +| 设置好友备注 | PUT | /{org_name}/{app_name}/user/{owner_username}/contacts/users/{friend_username} | 设置好有备注。 | +| 分页获取好友列表 | GET | /{org_name}/{app_name}/user/{username}/contacts?limit={N}&cursor={cursor}&needReturnRemark={true/false} | 100 次/秒/App Key | +| 一次性获取好友列表 | GET | /{org_name}/{app_name}/users/{owner_username}/contacts/users | 获取好友列表。 | | 获取黑名单列表 | GET | /{org_name}/{app_name}/users/{owner_username}/blocks/users | 获取黑名单。 | | 添加用户至黑名单 | POST | /{org_name}/{app_name}/users/{owner_username}/blocks/users | 添加用户至黑名单。 | | 将用户从黑名单移除 | DELETE | /{org_name}/{app_name}/users/{owner_username}/blocks/users/{blocked_username} | 移除黑名单中的用户。 | diff --git a/docs/document/server-side/presence.md b/docs/document/server-side/presence.md index 0aab7a5d5..2fc1a0d27 100644 --- a/docs/document/server-side/presence.md +++ b/docs/document/server-side/presence.md @@ -115,6 +115,7 @@ POST https://{host}/{org_name}/{app_name}/users/{username}/presence/{expiry} | 参数 | 类型 | 是否必需 | 描述 | | :------- | :----- | :---------------- | :------- | +| `username` | String | 是 | 为哪个用户订阅在线状态。| | `expiry` | String | 是 | 订阅时长,单位为秒,最大值为 `2,592,000`,即 30 天。 | 其他参数及描述详见 [公共参数](#公共参数)。 @@ -188,6 +189,10 @@ curl -X POST 'a1-test.easemob.com:8089/5101220107132865/test/users/wzy/presence/ 你一次可获取多个用户的在线状态信息。 +:::tip +默认情况下,若用户在 1 秒内进行多次登录和登出,服务器以最后一次操作为准向客户端 SDK 发送状态变更通知。 +::: + ### HTTP 请求 ```http @@ -196,6 +201,10 @@ POST https://{host}/{org_name}/{app_name}/users/{username}/presence #### 路径参数 +| 参数 | 类型 | 是否必需 | 描述 | +| :------- | :----- | :---------------- | :------- | +| `username` | String | 是 | 获取哪个用户订阅的在线状态。若传入的用户 ID 不存在或未订阅其他用户的在线状态,返回空列表。| + 参数及描述详见 [公共参数](#公共参数)。 #### 请求 header @@ -333,6 +342,10 @@ DELETE https://{host}/{org_name}/{app_name}/users/{username}/presence ### 路径参数 +| 参数 | 类型 | 是否必需 | 描述 | +| :------- | :----- | :---------------- | :------- | +| `username` | String | 是 | 为哪个用户取消订阅的在线状态。| + 参数及描述详见 [公共参数](#公共参数)。 ### 请求 header @@ -388,6 +401,10 @@ GET https://{host}/{org_name}/{app_name}/users/{username}/presence/sublist?pageN #### 路径参数 +| 参数 | 类型 | 是否必需 | 描述 | +| :------- | :----- | :---------------- | :------- | +| `username` | String | 是 | 查询哪个用户的订阅列表。若传入的用户 ID 不存在或未订阅其他用户的在线状态,返回空列表。| + 参数及描述详见 [公共参数](#公共参数)。 #### 查询参数 diff --git a/docs/document/server-side/push.md b/docs/document/server-side/push.md index 2e064d13c..73df6afaa 100644 --- a/docs/document/server-side/push.md +++ b/docs/document/server-side/push.md @@ -391,120 +391,6 @@ curl -X PUT -H "Authorization: Bearer " -i https://XXXX/XXXX/XXXX } ``` -## 设置免打扰模式 - -设置离线推送免打扰模式,在免打扰期间,用户将不会收到离线消息推送。 - -该 API 为旧版接口,推荐使用新版的[设置离线推送 API](#设置离线推送)。 - -### HTTP 请求 - -```http -PUT https://{host}/{org_name}/{app_name}/users/{username} -``` - -#### 路径参数 - -参数及说明详见 [公共参数](#公共参数)。 - -#### 请求 header - -| 参数 | 类型 | 描述 | 是否必需 | -| :-------------- | :----- | :--------- | :------- | -| `Content-Type` | String | 内容类型。请填 `application/json`。 | 是 | -| `Authorization` | String | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | 是 | - -#### 请求 body - -请求包体为 JSON Object 类型,包含以下字段: - -| 参数 | 类型 | 描述 | 是否必需
| -| :--------------------------------- | :------ | :----------------------------------------------------------------------------------------------- | :--------------------------------------- | -| `notification_no_disturbing` | Boolean | 是否设置为免打扰模式:
  • `true`:是;
  • `false`:否。
| 否 | -| `notification_no_disturbing_start` | String | 免打扰时间段的开始时间,精确到小时,取值范围为 [0,23]。例如 “8” 表示每日 8:00 开启免打扰模式。 | 否 | -| `notification_no_disturbing_end` | String | 免打扰时间段的结束时间,精确到小时,取值范围为 [0,23]。例如 “18” 表示每日 18:00 关闭免打扰模式。 | 否 | - -:::tip -免打扰时间段的设置,应注意以下几项: - -1. 开始时间和结束时间的设置立即生效,免打扰模式每天定时触发。例如,开始时间为 `8`,结束时间为 `10`,免打扰模式在每天的 8:00-10:00 内生效。若你在 11:00 设置开始时间为 `8`,结束时间为 `12`,则免打扰模式在当天的 11:00-12:00 生效,以后每天均在 8:00-12:00 生效。 -2. 若开始时间和结束时间相同,则全天免打扰。 -3. 若结束时间早于开始时间,则免打扰模式在每天的开始时间到次日的结束时间内生效。例如,开始时间为 `10`,结束时间为 `8`,则免打扰模式的在当天的 10:00 到次日的 8:00 生效。 - ::: - -### HTTP 响应 - -#### 响应 body - -如果返回的 HTTP 状态码为 200,表示请求成功,响应包体中包含以下字段: - -| 参数 | 类型 | 描述 | -| :------------------------------------------ | :------ | :------------------------------------- | -| `entities` | JSON Array | 用户的免打扰模式的相关信息。 | -| - `uuid` | String | 用户的 UUID。系统为该请求中的 app 或用户生成的唯一内部标识,用于生成用户权限 token。 | -| - `type` | String | 用户类型,即 `user`。 | -| - `created` | Long | 用户创建的 Unix 时间戳,单位为毫秒。 | -| - `modified` | Long | 最近一次修改用户信息的 Unix 时间戳,单位为毫秒。 | -| - `username` | String | 用户 ID。用户登录的唯一账号。 | -| - `activated` | Boolean | 用户是否为活跃状态:
  • `true`:用户为活跃状态。
  • `false`:用户为封禁状态。如要使用已被封禁的用户账户,你需要调用[解禁用户](/document/server-side/account_system.html#账号封禁)解除封禁。
| -| - `notification_no_disturbing` | Boolean | 是否设置为免打扰模式:
  • `true`:是;
  • `false`:否。
| -| - `notification_no_disturbing_start` | Int | 免打扰时间段的开始时间。 | -| - `notification_no_disturbing_end` | Int | 免打扰时间段的结束时间。 | -| - `notification_display_style` | Int | 离线推送通知的展示方式。 | -| - `nickname` | String | 离线推送通知收到时显示的昵称。 | -| - `notifier_name` | String | 推送证书名称。 | - -其他参数及说明详见 [公共参数](#公共参数)。 - -如果返回的 HTTP 状态码非 200,表示请求失败。你可以参考 [错误码](error.html) 了解可能的原因。 - -### 示例 - -#### 请求示例 - -**设置免打扰时间段** - -```bash -curl -X PUT -H "Authorization: Bearer " -i "https://XXXX/XXXX/XXXX/users/a " -d '{"notification_no_disturbing": true,"notification_no_disturbing_start": "1","notification_no_disturbing_end": "3"}' -``` - -**关闭免打扰模式** - -```bash -curl -X PUT -H "Authorization: Bearer " -i "https://XXXX/XXXX/XXXX/users/a " -d '{"notification_no_disturbing": false}' -``` - -#### 响应示例 - -```json -{ - "action": "put", - "application": "17d59e50-XXXX-XXXX-XXXX-0dc80c0f5e99", - "path": "/users", - "uri": "https://XXXX/XXXX/XXXX/users", - "entities": [ - { - "uuid": "3b8c9890-XXXX-XXXX-XXXX-f50bf55cafad", - "type": "user", - "created": 1530276298905, - "modified": 1534405429835, - "username": "User1", - "activated": true, - "notification_no_disturbing": true, - "notification_no_disturbing_start": 1, - "notification_no_disturbing_end": 3, - "notification_display_style": 0, - "nickname": "testuser", - "notifier_name": "2882303761517426801" - } - ], - "timestamp": 1534405429833, - "duration": 4, - "organization": "1112171214115068", - "applicationName": "testapp" -} -``` - ## 设置离线推送 你可以设置全局离线推送的通知方式和免打扰模式以及单个单聊或群聊会话的离线推送设置。 @@ -683,7 +569,7 @@ PUT https://{host}/{org}/{app}/users/{username}/notification/language #### 请求 header | 参数 | 类型 | 描述 -| :-------------- | :----- | :-------------- | :------- | +| :-------------- | :----- | :-------------- | | `Content-Type` | String | 内容类型。请填 `application/json`。 | 是 | | `Authorization` | String | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | 是 | @@ -798,38 +684,91 @@ curl -L -X GET '{url}/{org}/{app}/users/{username}/notification/language' \ } ``` -## 创建离线推送模板 +## 使用推送模板 -创建离线推送消息模板。 +你可以使用推送模板设置推送标题和内容。你可以调用以下 REST API 配置默认推送模板 `default` 和自定义推送模板。除此之外,你也可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)设置推送模板,详见[控制台文档](enable_and_configure_IM.html#配置推送模板)。 -### HTTP 请求 +使用推送模板有以下优势: + +1. 自定义修改环信服务端默认推送内容。 + +2. 接收方可以决定使用哪个模板。 + +3. 按优先级选择模板使用方式。 + +**推送通知栏内容设置的使用优先级** + +通知栏中显示的推送标题和内容可通过以下方式设置,优先级为由低到高: + +1. 发送消息时使用默认的推送标题和内容:设置推送通知的展示方式 `notification_display_style`。推送标题为“您有一条新消息”,推送内容为“请点击查看”。 +2. 发送消息时使用默认模板:若有默认模板 `default`,发消息时无需指定。 +3. 发送消息时使用扩展字段自定义要显示的推送标题和推送内容,即 `em_push_title` 和 `em_push_content`。 +4. 接收方设置了推送模板。 +5. 发送消息时通过消息扩展字段指定模板名称。 + +### 创建离线推送模板 + +创建离线推送消息模板,包括默认模板 `default` 和自定模板。你可以通过[环信即时通讯云控制台](https://console.easemob.com/user/login)创建推送模板,详见[控制台文档](enable_and_configure_IM.html#配置推送模板)。 + +若使用默认模板 **default**,消息推送时自动使用默认模板,创建消息时无需传入模板名称。 + +#### HTTP 请求 ```http POST https://{host}/{org_name}/{app_name}/notification/template ``` -#### 路径参数 +##### 路径参数 参数及说明详见 [公共参数](#公共参数)。 -#### 请求 header +##### 请求 header -| 参数 | 类型 | 描述 | 是否必需 | -| :-------------- | :----- | :------------------------------------------------------------------------------------------------------------------- | :------- | -| `Content-Type` | String | 内容类型。请填 `application/json`。 | 是 | -| `Authorization` | String | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | 是 | +| 参数 | 类型 | 描述 | 是否必需 | +| :-------------- | :----- | :---------------------------------- | :------- | +| `Content-Type` | String | 内容类型。请填 `application/json`。 | 是 | +| `Authorization` | String | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | 是 | -#### 请求 body +##### 请求 body | 参数 | 类型 | 描述 | 是否必需 | | :---------------- | :----- | :------------------------------------ | :------- | -| `name` | String | 要添加的推送模板的名称。 | 是 | +| `name` | String | 要添加的推送模板的名称。模板名称最多可包含 64 个字符,支持以下字符集:
- 26 个小写英文字母 a-z;
- 26 个大写英文字母 A-Z;
- 10 个数字 0-9。 | 是 | | `title_pattern` | String | 自定义推送标题,例如: 标题 {0}。 | 是 | | `content_pattern` | String | 自定义推送内容,例如:内容 {0}, {1}。 | 是 | -### HTTP 响应 - -#### 响应 body +`title_pattern` 和 `content_pattern` 的设置方式如下: +- 输入固定的内容,例如,标题为 “您好”,内容为“您有一条新消息”。 +- 内置参数填充: + - `{$dynamicFrom}`:按优先级从高到底的顺序填充好友备注、群昵称(仅限群消息)和推送昵称。 + - `{$fromNickname}`:推送昵称。 + - `{$msg}`:消息内容。 +- 自定义参数填充:模板输入数组索引占位符,格式为: {0} {1} {2} ... {n} + + 对于推送标题和内容来说,前两种设置方式在创建消息时无需传入该参数,服务器自动获取,第三种设置方式则需要通过扩展字段 `ext.em_push_template` 传入,JSON 结构如下: + + ```json + { + "ext":{ + "em_push_template":{ + "title_args":[ + "环信" + ], + "content_args":[ + "欢迎使用im-push", + "加油" + ] + } + } + } + + # title: {0} = "环信" + # content: {0} = "欢迎使用im-push" {1} = "加油" + ``` + +#### HTTP 响应 + +##### 响应 body 如果返回的 HTTP 状态码为 200,表示请求成功,响应包体中包含以下字段: @@ -844,22 +783,22 @@ POST https://{host}/{org_name}/{app_name}/notification/template 如果返回的 HTTP 状态码非 200,表示请求失败。你可以参考 [错误码](error.html) 了解可能的原因。 -### 示例 +#### 示例 -#### 请求示例 +##### 请求示例 ```bash curl -X POST '{url}/{org}/{app}/notification/template' \ -H 'Authorization: Bearer ' \ -H 'Content-Type: application/json' \ ---data-raw '{ +-d '{ "name": "test7", "title_pattern": "你好,{0}", "content_pattern": "推送测试,{0}" }' ``` -#### 响应示例 +##### 响应示例 ```json { @@ -880,17 +819,17 @@ curl -X POST '{url}/{org}/{app}/notification/template' \ } ``` -## 查询离线推送模板 +### 查询离线推送模板 查询离线推送消息使用的模板。 -### HTTP 请求 +#### HTTP 请求 ```http GET https://{host}/{org_name}/{app_name}/notification/template/{name} ``` -#### 路径参数 +##### 路径参数 | 参数 | 类型 | 描述 | 是否必需 | | :----- | :----- | :----------------------- | :------- | @@ -898,16 +837,16 @@ GET https://{host}/{org_name}/{app_name}/notification/template/{name} 其他参数及说明详见 [公共参数](#公共参数)。 -#### 请求 header +##### 请求 header | 参数 | 类型 | 描述 | 是否必需 | | :-------------- | :----- | :------------------------------------------------------------------------------------------------------------------- | :------- | | `Content-Type` | String | 内容类型。请填 `application/json`。 | 是 | | `Authorization` | String | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | 是 | -### HTTP 响应 +#### HTTP 响应 -#### 响应 body +##### 响应 body 如果返回的 HTTP 状态码为 200,表示请求成功,响应包体中包含以下字段: @@ -922,16 +861,16 @@ GET https://{host}/{org_name}/{app_name}/notification/template/{name} 如果返回的 HTTP 状态码非 200,表示请求失败。你可以参考 [错误码](error.html) 了解可能的原因。 -### 示例 +#### 示例 -#### 请求示例 +##### 请求示例 ```bash curl -X GET '{url}/{org}/{app}/notification/template/{name}' \ -H 'Authorization: Bearer ' ``` -#### 响应示例 +##### 响应示例 ```json { @@ -952,17 +891,146 @@ curl -X GET '{url}/{org}/{app}/notification/template/{name}' \ } ``` -## 删除离线推送模板 +### 接收方配置模板名称 + +接收方可以调用该 API 设置推送模板。 + +#### HTTP 请求 + +``` +PUT https://{host}/{org_name}/{app_name}/users/{username}/notification/template +``` + +##### 请求 Header + +| 参数 | 类型 | 是否必需 | 描述 | +| :-------------- | :----- | :------- | :----------------------------------------------------------- | +| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | +| `Authorization` | String | 是 | App User 鉴权 token,格式为 `Bearer YourUserToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 user token。 | + +其他参数及说明详见 [公共参数](#公共参数)。 + +##### 请求 body + +| 参数 | 类型 | 是否必需 | 描述 | +| :--------- | :----- | :------- | :-------------------------------------------- | +| `templateName` | String | 是 | 模板名称。| + +#### HTTP 响应 + +如果返回的 HTTP 状态码为 `200`,表示请求成功,响应 body 包含如下字段: + +| 参数 | 类型 | 描述 | +| :----- | :--- | :------------------------------------------------------ | +| `data` | JSON | 响应中的数据详情。`templateName` 为设置成功后的模板名称。 | + +其他参数及说明详见 [公共参数](#公共参数)。 + +#### 示例 + +##### 请求示例 + +```shell +curl -X PUT '{host}/{org}/{app}/users/{username}/notification/template' \ + -H 'Content-Type: application/json' \ + -H 'Authorization: Bearer ' \ + -d '{ + "templateName": "hxtest" + } +``` + +##### 响应示例 +```json +{ + "path": "/users", + "uri": "http://XXX/XXX/XXX/users/XXX/notification/template", + "timestamp": 1705470003984, + "organization": "XXX", + "application": "cc7380d5-099c-4d11-a93e-51d6d590b475", + "action": "put", + "data": { + "templateName": "hxtest" + }, + "duration": 43, + "applicationName": "XXX" +} +``` + +### 发消息时配置模板名称 + +发送消息时,可使用消息扩展参数 `ext.em_push_template.name` 指定推送模板名称。 + +若使用默认模板 **default**,消息推送时自动使用默认模板,创建消息时无需传入模板名称。 + +该扩展参数的 JSON 结构如下: + +```json +{ + "ext":{ + "em_push_template":{ + "name":"hxtest" + } + } +} +``` + +下面以发送单聊文本消息时使用自定义推送模板为例进行介绍: + +#### 请求示例 + +```shell +curl -L -X POST 'https://XXXX/XXXX/XXXX/messages/users' \ +-H 'Content-Type: application/json' \ +-H 'Authorization: Bearer ' \ +-d '{ + "from": "user1", + "to": [ + "user2" + ], + "type": "txt", + "body": { + "msg": "testmessages" + }, + "ext": { + "em_push_template": { + "name": "hxtest" + } + } +}' +``` + +#### 响应示例 + +```json +{ + "path": "/messages/users", + "uri": "https://XXXX/XXXX/XXXX/messages/users", + "timestamp": 1657254052191, + "organization": "XXXX", + "application": "e82bcc5f-XXXX-XXXX-a7c1-92de917ea2b0", + "action": "post", + "data": { + "user2": "1029457500870543736" + }, + "duration": 0, + "applicationName": "XXXX" +} +``` + +接口详情,请参见[发送文本消息](https://doc.easemob.com/document/server-side/message_single.html#发送文本消息)。 + +### 删除离线推送模板 + 删除离线消息推送模板。 -### HTTP 请求 +#### HTTP 请求 ```http DELETE https://{host}/{org_name}/{app_name}/notification/template/{name} ``` -#### 路径参数 +##### 路径参数 | 参数 | 类型 | 描述 | 是否必需 | | :----- | :----- | :----------------------- | :------- | @@ -970,16 +1038,16 @@ DELETE https://{host}/{org_name}/{app_name}/notification/template/{name} 其他参数及说明详见 [公共参数](#公共参数)。 -#### 请求 header +##### 请求 header | 参数 | 类型 | 描述 | 是否必需 | | :-------------- | :----- | :------------------------------------------------------------------------------------------------------------------- | :------- | | `Content-Type` | String | 内容类型。请填 `application/json`。 | 是 | | `Authorization` | String | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | 是 | -### HTTP 响应 +#### HTTP 响应 -#### 响应 body +##### 响应 body 如果返回的 HTTP 状态码为 200,表示请求成功,响应包体中包含以下字段: @@ -994,16 +1062,16 @@ DELETE https://{host}/{org_name}/{app_name}/notification/template/{name} 如果返回的 HTTP 状态码非 200,表示请求失败。你可以参考 [错误码](error.html) 了解可能的原因。 -### 示例 +#### 示例 -#### 请求示例 +##### 请求示例 ```bash curl -X DELETE '{url}/{org}/{app}/notification/template/{name}' \ -H 'Authorization: Bearer {YourAppToken}' ``` -#### 响应示例 +##### 响应示例 ```json { @@ -1023,3 +1091,5 @@ curl -X DELETE '{url}/{org}/{app}/notification/template/{name}' \ "applicationName": "hxdemo" } ``` + + diff --git a/docs/document/server-side/user_relationship.md b/docs/document/server-side/user_relationship.md index 140504478..45b01617a 100644 --- a/docs/document/server-side/user_relationship.md +++ b/docs/document/server-side/user_relationship.md @@ -24,7 +24,7 @@ ### 请求参数 | 参数 | 类型 | 是否必需 | 描述 | -| :--------- | :----- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------- | +| :--------- | :----- | :------- | :------------------------------------ | | `host` | String | 是 | 环信即时通讯 IM 分配的用于访问 RESTful API 的域名。详见 [获取环信即时通讯 IM 的信息](enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | | `org_name` | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见 [获取环信即时通讯 IM 的信息](enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | | `app_name` | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见 [获取环信即时通讯 IM 的信息](enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | @@ -89,13 +89,13 @@ POST https://{host}/{org_name}/{app_name}/users/{owner_username}/contacts/users/ | 字段 | 类型 | 描述 | | :------------------- | :--------- | :---------------------------------------------------------------------- | | `entities` | JSON Array | 添加的好友的详情。 | -| `entities.uuid` | String | 系统内为好友生成的系统内唯一标识,开发者无需关心。 | -| `entities.type` | String | 对象类型,值为 `user` 或 `group`。 | -| `entities.created` | Long | 用户创建时间,Unix 时间戳,单位为毫秒。 | -| `entities.modified` | Long | 好友的用户信息如密码或者昵称等最新修改时间,Unix 时间戳,单位为毫秒。 | -| `entities.username` | String | 添加的好友的用户 ID。 | -| `entities.activated` | Bool | 好友是否为正常状态:
• `true` 正常状态。
• `false` 已被封禁。 | -| `entities.nickname` | String | 好友的用户昵称。 | +| - `uuid` | String | 系统内为好友生成的系统内唯一标识,开发者无需关心。 | +| - `type` | String | 对象类型,值为 `user` 或 `group`。 | +| - `created` | Long | 用户创建时间,Unix 时间戳,单位为毫秒。 | +| - `modified` | Long | 好友的用户信息如密码或者昵称等最新修改时间,Unix 时间戳,单位为毫秒。 | +| - `username` | String | 添加的好友的用户 ID。 | +| - `activated` | Bool | 好友是否为正常状态:
• `true` 正常状态。
• `false` 已被封禁。 | +| - `nickname` | String | 好友的用户昵称。 | 其他字段及描述详见 [公共参数](#公共参数)。 @@ -220,9 +220,174 @@ curl -X DELETE -H 'Accept: application/json' -H 'Authorization: Bearer | 描述 | +| :-------------- | :----- | :--------------------------------------- | :------------------------ | +| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | +| `Accept` | String | 是 | 内容类型。请填 `application/json`。 | +| `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | + +#### 请求 body + +| 参数 | 类型 | 是否必需 | 描述 | +| :---------------- | :----- | :------- |:-------------| +| `remark` | String | 是 | 好友备注。好友备注的长度不能超过 100 个字符。 | + +### HTTP 响应 + +#### 响应 body + +如果返回的 HTTP 状态码为 `200`,表示请求成功,响应包体中包含以下字段: + +| 字段 | 类型 | 描述 | +| :------------------- |:-------|:--------------------------------------| +| `action` | String | 请求方法。 | +| `status` | String | 好友备注是否设置成功,`ok` 表示设置成功。 | +| `timestamp` | Long | HTTP 响应的 UNIX 时间戳,单位为毫秒。 | +| `uri` | Long | 请求 URL。 | + +其他字段及描述详见 [公共参数](#公共参数)。 + +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考 [响应状态码](error.html) 了解可能的原因。 + +### 示例 + +#### 请求示例 + +```shell +# 将 替换为你在服务端生成的 App Token +curl -X PUT 'https://{host}/{org_name}/{app_name}/user/{owner_username}/contacts/users/{friend_username}' \ +-H 'Content-Type: application/json' \ +-H 'Accept: application/json' \ +-H 'Authorization: Bearer ' \ +-d '{ + "remark": +}' +``` + +#### 响应示例 + +```json +{ + "action": "put", + "duration": 22, + "status": "ok", + "timestamp": 1700633088329, + "uri": "https://{host}/{org_name}/{app_name}/user/{owner_username}/contacts/users/{friend_username}" +} +``` + +## 分页获取好友列表 + +分页获取指定用户的好友列表。 + +### HTTP 请求 + +```http +GET https://{host}/{org_name}/{app_name}/user/{username}/contacts?limit={N}&cursor={cursor}&needReturnRemark={true/false} +``` + +#### 路径参数 + +| 参数 | 类型 | 是否必需 | 描述 | +| :---------------- | :----- | :------- |:-------------| +| `username` | String | 是 | 当前用户的用户 ID。 | + +其他参数及描述详见 [公共参数](#公共参数)。 + +#### 查询参数 + +| 参数 | 类型 | 是否必需 | 描述 | +|:--------|:--------|:-----|:-------------------------------------------------| +| `limit` | Int | 否 | 每次期望返回的好友的数量。取值范围为 [1,50]。该参数仅在分页获取时为必需,默认为 `10`。 | +| `cursor` | String | 否 | 数据查询的起始位置。该参数仅在分页获取时为必需。第一次调用该接口不传 `cursor`,获取 `limit` 指定的好友数量。| +| `needReturnRemark` | Boolean | 否 | 是否需要返回好友备注:
- `true`:返回;
- (默认)`false`:不返回。| + + +#### 请求 header + +| 参数 | 类型 | 是否必需
| 描述 | +| :-------------- | :----- | :--------------- | :-------------------- | +| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | +| `Accept` | String | 是 | 内容类型。请填 `application/json`。 | +| `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | + +### HTTP 响应 + +#### 响应 body + +如果返回的 HTTP 状态码为 `200`,表示请求成功,响应包体中包含以下字段: + +| 字段 | 类型 | 描述 | +|:-------------------------|:-------|:---------------| +| `count` | Int | 当前页的好友数量。 | +| `data` | Object | 返回的好友列表对象。 | +| `data.contacts` | Array | 返回的好友列表数据。 | +| `data.contacts.remark` | String | 好友备注。 | +| `data.contacts.username` | String | 好友的用户 ID。 | + +其他字段及描述详见 [公共参数](#公共参数)。 + +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考 [响应状态码](error.html) 了解可能的原因。 + +### 示例 + +#### 请求示例 + +```shell +# 将 替换为你在服务端生成的 App Token +curl --location 'https://{host}/{org_name}/{app_name}/user/{username}/contacts?limit=10&needReturnRemark=true' \ +-H 'Content-Type: application/json' \ +-H 'Accept: application/json' \ +-H 'Authorization: Bearer ' +``` + +#### 响应示例 + +```json +{ + "uri": "http://{host}/{org_name}/{app_name}/users/{username}/rostersByPage", + "timestamp": 1706238297509, + "entities": [], + "count": 1, + "action": "get", + "data": { + "contacts": [ + { + "remark": null, + "username": "username" + } + ] + }, + "duration": 27 +} +``` + +## 一次性获取好友列表 + +一次性获取指定用户的好友列表。 ### HTTP 请求 diff --git a/docs/document/server-side/userprofile.md b/docs/document/server-side/userprofile.md index 55d9533ee..0f9fe22e9 100644 --- a/docs/document/server-side/userprofile.md +++ b/docs/document/server-side/userprofile.md @@ -164,9 +164,9 @@ GET https://{host}/{org_name}/{app_name}/metadata/user/{username} #### 请求 header -| 参数 | 类型 | 是否必需 | 描述 | -| :-------------- | :----- | :------- | :------------------------------------------------------------------------------------------------------------------- | -| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | +| 参数 | 类型 | 是否必需 | 描述 | +| :-------------- | :----- | :------- | :---------- | +| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | | `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | ### HTTP 响应 @@ -225,15 +225,15 @@ POST https://{host}/{org_name}/{app_name}/metadata/user/get #### 请求 header -| 参数 | 类型 | 是否必需
| 描述 | -| :-------------- | :----- | :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------- | -| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | -| `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | +| 参数 | 类型 | 是否必需
| 描述 | +| :-------------- | :----- | :--------------------- | :--------------- | +| `Content-Type` | String | 是 | 内容类型。请填 `application/json`。 | +| `Authorization` | String | 是 | App 管理员的鉴权 token,格式为 `Bearer YourAppToken`,其中 `Bearer` 为固定字符,后面为英文空格和获取到的 app token。 | #### 请求 body | 参数 | 类型 | 是否必需 | 描述 | -| :----------- | :---- | :------- | :------------------------------------------------------------------------- | +| :----------- | :---- | :------- | :-------------------- | | `targets` | Array | 是 | 用户 ID 列表,最多可传 100 个用户 ID。 | | `properties` | Array | 是 | 属性名列表,查询结果只返回该列表中包含的属性,不在该列表中的属性将被忽略。 | @@ -258,7 +258,7 @@ POST https://{host}/{org_name}/{app_name}/metadata/user/get ```shell # 将 替换为你在服务端生成的 App Token -curl -X POST -H 'Content-Type: application/json' -H 'Authorization: Bearer ' -d '{ +curl -X POST -H 'Content-Type: application/json' -H 'Authorization: Bearer ' -d '{ "properties": [ "avatarurl", "ext", diff --git a/docs/document/unity/conversation_delete.md b/docs/document/unity/conversation_delete.md new file mode 100644 index 000000000..226dc7e4b --- /dev/null +++ b/docs/document/unity/conversation_delete.md @@ -0,0 +1,52 @@ +# 删除会话 + + + +删除好友或退出群组后,SDK 不会自动删除对应的单聊或群聊会话。你可以调用相应的接口从服务器和本地删除单个会话及其历史消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地删除单个会话及其历史消息,主要方法如下: + +- `DeleteConversationFromServer`:单向删除服务端的单个会话及其历史消息。 +- `DeleteConversation`:删除本地单个会话及其历史消息。 + +## 实现方法 + +### 单向删除服务端会话及其历史消息 + +你可以调用 `DeleteConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 + +```csharp +SDKClient.Instance.ChatManager.DeleteConversationFromServer(conversationId, conversationType, isDeleteServerMessages, new CallBack( + onSuccess: () => + { + }, + onError: (code, desc) => + { + } +)); +``` + +### 删除本地会话及历史消息 + +- 你可以调用 `DeleteConversation` 方法删除本地会话及其聊天消息: + +```csharp +//如需保留历史消息,传 `false`。 +SDKClient.Instance.ChatManager.DeleteConversation(conversationId, true); +``` + +- 你可以调用 `DeleteMessage` 方法删除指定会话中指定的一条历史消息。 + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.DeleteMessage(msgId); +``` diff --git a/docs/document/unity/conversation_list.md b/docs/document/unity/conversation_list.md new file mode 100644 index 000000000..db8603056 --- /dev/null +++ b/docs/document/unity/conversation_list.md @@ -0,0 +1,90 @@ +# 会话列表 + + + +对于单聊、群组聊天和聊天室会话,用户发消息时 SDK 会自动创建会话并将会话添加至用户的会话列表。 + +环信服务器和本地均存储会话,你可以获取会话列表。**服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地获取会话列表,主要方法如下: + +- `IChatManager#GetConversationsFromServerWithCursor`:从服务器获取会话列表。 +- `IChatManager#LoadAllConversations`:获取本地所有会话。 + +## 实现方法 + +### 从服务器分页获取会话列表 + +你可以调用 `GetConversationsFromServerWithCursor` 方法从服务端分页获取会话列表,包含单聊和群组聊天会话,不包含聊天室会话。通过设置该方法中的 `pinOnly` 参数确定是否只获取置顶会话列表: + +- 若 `pinOnly` 为 `false`,获取包括置顶和未置顶会话的列表。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 +- 若为 `true` 仅获取置顶会话列表,最多可拉取 50 个置顶会话。SDK 按照会话置顶时间的倒序返回。 + +:::tip +1. 若使用该方法,需将 SDK 升级至 1.2.0。 +2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `LoadAllConversations` 方法获取本地所有会话即可。 +3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +::: + +```csharp +// limit: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新活跃的会话开始查询。 +int limit = 10; +string cursor = ""; +bool pinOnly = false; // `false`:获取所有会话;`true`仅获取置顶会话列表。 +SDKClient.Instance.ChatManager.GetConversationsFromServerWithCursor(pinOnly, cursor, limit, new ValueCallBack>( + onSuccess: (result) => + { + // 遍历获取到的会话列表 + foreach (var conv in result.Data) + { + + } + // 下一次请求的 cursor + string nextCursor = result.Cursor; + }, + onError: (code, desc) => + { + + } +)); + +``` + +若不支持 `GetConversationsFromServerWithCursor` 方法,你可以调用 `GetConversationsFromServerWithPage` 方法从服务端分页获取会话列表。利用该接口,你总共可获取服务器最近 7 天内存储的 100 个会话。若提升这两个上限,需联系环信商务。 + +若使用该功能,需将 SDK 升级至 V1.1.0。 + +```csharp +SDKClient.Instance.ChatManager.GetConversationsFromServerWithPage(pageNum, pageSize, new ValueCallBack>( + //获取会话成功后的处理逻辑。 + //list 为 List 类型。 + onSuccess: (list) => + { + }, + onError: (code, desc) => + { + } +)); +``` + +### 获取本地所有会话 + +你可以调用 `LoadAllConversations` 方法根据会话 ID 和会话类型获取本地所有会话。SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 + +本地会话列表包含单聊和群组聊天会话,至于是否包含聊天室会话,取决于在 SDK 初始化时 `Options#DeleteMessagesAsExitRoom` 参数的设置。若设置为 `true`,即离开聊天室时删除该聊天室的所有本地消息,则本地会话列表中不包含聊天室会话。若设置为 `false`,即保留该聊天室的所有本地消息,则本地会话列表中包含聊天室会话。 + +示例代码如下: + +```csharp +Listlist = SDKClient.Instance.ChatManager.LoadAllConversations(); +``` \ No newline at end of file diff --git a/docs/document/unity/conversation_overview.md b/docs/document/unity/conversation_overview.md new file mode 100644 index 000000000..45cf62f78 --- /dev/null +++ b/docs/document/unity/conversation_overview.md @@ -0,0 +1,73 @@ +# 会话介绍 + + + +会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息、查看或清空历史消息等操作。 + +环信即时通讯 IM SDK 提供 `IChatManager` 和 `Conversation` 类以会话为单位对消息数据进行管理,如获取会话列表、置顶会话、添加会话标记、删除会话和管理未读消息等。 + +## 会话类 + +环信即时通讯 IM 提供会话类 `Conversation`。该类定义了以下内容: + +| 类/方法 | 描述 | +| :--------- | :------- | +| Id | 会话 ID,取决于会话类型。
- 单聊:会话 ID 为对方的用户 ID;
- 群聊:会话 ID 为群组 ID;
- 聊天室:会话 ID 为聊天室的 ID。 | +| Type | 会话类型。
- `Chat`:单聊会话;
- `Group`:群聊会话;
- `Room`:聊天室会话。
- `HelpDesk`:客服会话。 | +| IsThread | 判断该会话是否为子区会话。 | +| IsPinned | 判断该会话是否被置顶。 | +| PinnedTime | 会话置顶时间戳(毫秒)。如果 `IsPinned` 为 `false`,将返回 `0`。 | +| LastMessage | 获取指定会话的最新消息。该方法的调用不影响会话的未读消息数。 SDK 首先从内存中获取最新消息,若在内存中未找到,则从数据库中加载,然后将其存放在内存中。 | +| LastReceivedMessage | 获取指定会话中收到的最新消息。 | +| Ext | 获取指定会话的扩展信息。 | +| UnReadCount | 获取指定会话的未读消息数。 | +| MarkMessageAsRead | 设置指定消息为已读。 | +| MarkAllMessageAsRead | 将指定会话的所有未读消息设置为已读。 | +| InsertMessage | 在本地数据库的指定会话中插入一条消息。 | +| AppendMessage | 在本地数据库中指定会话的尾部插入一条消息。 | +| UpdateMessage | 更新本地数据库的指定消息。 | +| DeleteMessage | 删除本地数据库中的一条指定消息。 | +| DeleteMessages | 删除本地数据库中指定时间段的消息。 | +| DeleteAllMessages | 删除指定会话中所有消息。 | +| LoadMessage | 加载指定消息。SDK 首先在内存中查找消息,若在内存中未找到,SDK 会在本地数据库查询并加载。 | +| LoadMessagesWithMsgType | 加载特定类型的多条消息。SDK 首先在内存中查询消息,若在内存中未找到,SDK 会在本地数据库查询并加载。 | +| LoadMessages | 从指定消息 ID 开始加载消息。 | +| LoadMessagesWithKeyword | 根据关键字加载消息。SDK 首先在内存中查找消息,若在内存中未找到,SDK 会在本地数据库查询并加载。 | +| LoadMessagesWithTime | 加载指定时间段内的消息。 | +| MessagesCount | 获取 SDK 本地数据库中会话的全部消息数目。 | + + +## 会话事件 + +`IChatManagerDelegate` 中提供会话事件的监听接口。开发者可以通过设置此监听,获取会话事件,并做出相应处理。如果不再使用该监听,需要移除。 + +示例代码如下: + +```csharp +public class ChatManagerDelegate : IChatManagerDelegate { + // 收到会话已读的事件。该事件在以下场景中触发: + // 1. 当消息接收方调用 `SendConversationReadAck 方法,SDK 会执行此回调, + // 会将本地数据库中该会话中消息的 `isAcked` 属性置为 `true`。 + // 2. 多端多设备登录时,若一端发送会话已读回执(conversation ack), + // 服务器端会将会话的未读消息数置为 0, + // 同时其他端会回调此方法,并将本地数据库中该会话中消息的 `isRead` 属性置为 `true`。 + public void OnConversationRead(string from, string to) + { + + } +} + +// 注册会话监听回调。 +ChatManagerDelegate adelegate = new ChatManagerDelegate(); +SDKClient.Instance.ChatManager.AddChatManagerDelegate(adelegate); + +// 移除会话监听回调。 +SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); + +``` + + + + + + diff --git a/docs/document/unity/conversation_pin.md b/docs/document/unity/conversation_pin.md new file mode 100644 index 000000000..3eea29d93 --- /dev/null +++ b/docs/document/unity/conversation_pin.md @@ -0,0 +1,56 @@ +# 会话置顶 + + + +会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 + +**若使用会话置顶功能,需将 SDK 升级至 1.2.0,并[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 技术原理 + +环信即时通讯 IM 支持会话置顶,主要方法如下: + +- `IChatManager#PinConversation`:置顶会话。 +- `IChatManager#GetConversationsFromServerWithCursor`:获取服务端置顶会话列表。 + +## 实现方法 + +### 置顶会话 + +你可以调用 `PinConversation` 方法设置是否置顶会话。置顶状态会存储在服务器上,多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他登录设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。 + +你最多可以置顶 50 个会话。 + +示例代码如下: + +```csharp +SDKClient.Instance.ChatManager.PinConversation(convId, isPinned, new CallBack( + onSuccess: () => + { + + }, + onError: (code, desc) => + { + + } +)); +``` + +你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 + +### 获取服务端的置顶会话列表 + +你可以调用 `GetConversationsFromServerWithCursor` 方法从服务端分页获取置顶会话列表。如果将该方法中的 pinOnly 参数设置为 `true` 则只获取置顶会话列表。该接口详情,请参考[从服务器分页获取会话列表](conversation_list#从服务器分页获取会话列表)。 + +你最多可以拉取 50 个置顶会话。 + + + diff --git a/docs/document/unity/conversation_unread.md b/docs/document/unity/conversation_unread.md new file mode 100644 index 000000000..64af88cc5 --- /dev/null +++ b/docs/document/unity/conversation_unread.md @@ -0,0 +1,68 @@ +# 会话未读数 + + + +你可以查看本地所有会话或指定会话的未读消息数,并针对会话的未读消息数清零。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM SDK 通过 `IChatManager` 和 `Conversation` 类实现对本地会话的未读消息数的管理,其中核心方法如下: + +- `IChatManager#GetUnreadMessageCount`:获取本地所有会话的未读消息数。 +- `Conversation#UnReadCount`:获取本地指定会话的未读消息数。 +- `IChatManager#MarkAllConversationsAsRead`:将本地所有会话的未读消息数清零。 +- `IChatManager#MarkAllMessageAsRead`:对于本地指定会话的未读消息数清零。 +- `IChatManager#MarkMessageAsRead`:将指定会话的单条未读消息置为已读。 + +## 实现方法 + +### 获取所有会话的未读消息数 + +你可以调用 `GetUnreadMessageCount` 方法获取本地所有会话的未读消息数量,示例代码如下: + +```csharp +SDKClient.Instance.ChatManager.GetUnreadMessageCount(); +``` + +### 获取指定会话的未读消息数 + +你可以调用 `UnReadCount` 方法获取本地指定会话的未读消息数,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +int unread = conv.UnReadCount; +``` + +### 将所有会话的未读消息数清零 + +你可以调用 `MarkAllConversationsAsRead` 方法将本地所有会话的未读消息数清零,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +SDKClient.Instance.ChatManager.MarkAllConversationsAsRead(); +``` + +### 指定会话的未读消息数清零 + +你可以调用 `MarkAllMessageAsRead` 方法对指定会话的未读消息数清零,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.MarkAllMessageAsRead(); +``` + +### 将指定会话的单条未读消息置为已读 + +你可以调用 `markMessageAsRead` 方法将指定会话的单条未读消息置为已读。 + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.MarkMessageAsRead(msgId); +``` diff --git a/docs/document/unity/group_attributes.md b/docs/document/unity/group_attributes.md index de194840a..ee129f3aa 100644 --- a/docs/document/unity/group_attributes.md +++ b/docs/document/unity/group_attributes.md @@ -97,7 +97,7 @@ SDKClient.Instance.GroupManager.GetGroupAnnouncementFromServer(currentGroupId, n #### 上传共享文件 -所有群组成员均可以调用 `UploadGroupSharedFile` 方法上传共享文件至群组,群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `IGroupManagerDelegate#OnSharedFileAddedFromGroup` 回调。 +所有群组成员均可以调用 `UploadGroupSharedFile` 方法上传共享文件至群组,单个群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `IGroupManagerDelegate#OnSharedFileAddedFromGroup` 回调。 示例代码如下: diff --git a/docs/document/unity/group_manage.md b/docs/document/unity/group_manage.md index e1fd8e8de..0b38a6554 100644 --- a/docs/document/unity/group_manage.md +++ b/docs/document/unity/group_manage.md @@ -150,6 +150,10 @@ SDKClient.Instance.GroupManager.LeaveGroup(groupId, new CallBack( 群成员也可以调用 `GetGroupSpecificationFromServer` 方法从服务器获取群组详情。返回结果包括:群组 ID、群组名称、群组描述、群主、群组管理员列表、是否已屏蔽群组消息以及群组是否禁用等信息,不包括群成员列表。 +:::tip +对于公有群,用户即使不加入群也能获取群组详情,而对于私有群,用户只有加入了群组才能获取群详情。 +::: + 示例代码如下: ```csharp diff --git a/docs/document/unity/group_members.md b/docs/document/unity/group_members.md index f8ccad8b0..c89d7240d 100644 --- a/docs/document/unity/group_members.md +++ b/docs/document/unity/group_members.md @@ -48,17 +48,22 @@ SDKClient.Instance.GroupManager.AddGroupMembers(groupId, members, new CallBack( ### 群组踢人 -仅群主和群管理员可以调用 `DeleteGroupMembers` 方法将指定成员移出群组。被移出后,该成员收到 `IGroupManagerDelegate#OnUserRemovedFromGroup` 回调,其他群成员收到 `IGroupManagerDelegate#OnMemberExitedFromGroup` 回调。被移出群组后,该用户还可以再次加入群组。 +仅群主和群管理员可以调用 `DeleteGroupMembers` 方法将单个或多个成员移出群组。被移出后,该成员收到 `IGroupManagerDelegate#OnUserRemovedFromGroup` 回调,其他群成员收到 `IGroupManagerDelegate#OnMemberExitedFromGroup` 回调。被移出群组后,该用户还可以再次加入群组。 示例代码如下: ```csharp -SDKClient.Instance.GroupManager.DeleteGroupMembers(groupId, list, new CallBack ( - onSuccess: () => - { +List members = new List(); +members.Add("member1"); +members.Add("member2"); + +SDKClient.Instance.GroupManager.DeleteGroupMembers(groupId, members, callback: new CallBack( + onSuccess: () => { + Console.WriteLine($"DeleteGroupMembers success"); }, onError: (code, desc) => { + Console.WriteLine($"DeleteGroupMembers failed, code:{code}, desc:{desc}"); } )); ``` @@ -243,6 +248,7 @@ SDKClient.Instance.GroupManager.GetGroupBlockListFromServer(groupId, pageNum, pa 示例代码如下: ```csharp +// muteMilliseconds:禁言时间。若传 -1,表示永久禁言。 SDKClient.Instance.GroupManager.MuteGroupMembers(groupId, members, new CallBack( onSuccess: () => { @@ -290,7 +296,9 @@ SDKClient.Instance.GroupManager.GetGroupMuteListFromServer(groupId, callback: ne #### 开启群组全员禁言 -仅群主和群管理员可以调用 `MuteGroupAllMembers` 方法开启全员禁言。群组全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。 +仅群主和群管理员可以调用 `MuteGroupAllMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动取消禁言,需要调用 `UnMuteGroupAllMembers` 方法取消全员禁言。 + +群组全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。 示例代码如下: diff --git a/docs/document/unity/message_delete.md b/docs/document/unity/message_delete.md new file mode 100644 index 000000000..be8d258cb --- /dev/null +++ b/docs/document/unity/message_delete.md @@ -0,0 +1,104 @@ +# 删除消息 + + + +本文介绍用户如何单向删除服务端和本地的历史消息。 + +## 技术原理 + +使用环信即时通讯 IM SDK 可以通过 `ChatManager` 和 `Conversation` 类单向删除服务端和本地的历史消息,主要方法如下: + +- `ChatManager#RemoveMessagesFromServer`:单向删除服务端的历史消息。 +- `Conversation#DeleteAllMessages`:删除本地指定会话的所有消息。 +- `Conversation#DeleteMessages (long startTime, long endTime)`:删除本地单个会话在指定时间段的消息。 +- `Conversation#DeleteMessage (string messageId)`:删除本地单个会话的指定消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 单向删除服务端的历史消息 + +你可以调用 `RemoveMessagesFromServer` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。删除后,消息自动从设备本地移除且该用户无法从服务端拉取到该消息。其他用户不受该操作影响。 + +登录该账号的其他设备会收到 `IMultiDeviceDelegate` 中的 `OnRoamDeleteMultiDevicesEvent` 回调,已删除的消息自动从设备本地移除。 + +:::tip +若使用该功能,需将 SDK 升级至 V1.1.0 或以上版本并联系商务。 +::: + +```csharp +// 按时间删除历史消息 +SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, time, new CallBack( + onSuccess: () => + { + }, + onError: (code, desc) => + { + } +)); +// 按消息 ID 删除历史消息 +SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, msgList, new CallBack( + onSuccess: () => + { + }, + onError: (code, desc) => + { + } +)); +``` + +### 删除本地指定会话的所有消息 + +你可以删除本地指定会话的所有消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversionId, conversationType); + +if (conv.DeleteAllMessages()){ + //成功删除消息 +} +else{ + //删除消息失败 +} +``` + +### 删除本地单个会话在指定时间段的消息 + +你可以删除本地指定会话在一段时间内的本地消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversionId, conversationType); + +if (conv.DeleteMessages(startTime, endTime)) { + //成功删除消息 +} +else { + //删除消息失败 +} +``` + +### 删除本地单个会话的指定消息 + +你可以删除本地单个会话的指定消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversionId, conversationType); + +if (conv.DeleteMessage(msgid)){ + //成功删除消息 +} +else{ + //删除消息失败 +} +``` + + + + + diff --git a/docs/document/unity/message_deliver_only_online.md b/docs/document/unity/message_deliver_only_online.md new file mode 100644 index 000000000..f613d7e6e --- /dev/null +++ b/docs/document/unity/message_deliver_only_online.md @@ -0,0 +1,46 @@ +# 消息仅投递在线用户 + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **支持本地存储**:消息成功发送后,写入数据库。 +3. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 技术原理 + +环信即时通讯 IM 通过 `Message` 类支持只将消息投递给在线用户: + +- `DeliverOnlineOnly`:设置消息是否只投递给在线用户。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +要将消息只投递给在线用户,你需要在发送消息时将 `Message#DeliverOnlineOnly` 设置为 `true`。 + +下面以发送文本消息为例进行说明: + +```csharp +// 创建一条文本消息,`content` 为消息文字内容。 +// `conversationId` 为消息接收方,单聊时为对端用户 ID、群聊时为群组 ID。 +Message message = Message.CreateTextSendMessage(conversationId, content); +// 消息是否只投递在线用户。(默认)`false`:不论用户是否在线均投递;`true`:只投递给在线用户。若用户离线,消息不投递。 +message.DeliverOnlineOnly = true; +// 会话类型:单聊为 MessageType.Chat,群聊为 MessageType.Group,默认为单聊。 +message.MessageType = MessageType.Chat; +// 发送消息。 +SDKClient.Instance.ChatManager.SendMessage(ref message, new CallBack( + onSuccess: () => { + }, + onError: (code, desc) => { + } +)); +``` + diff --git a/docs/document/unity/message_import_insert.md b/docs/document/unity/message_import_insert.md new file mode 100644 index 000000000..2af695dfe --- /dev/null +++ b/docs/document/unity/message_import_insert.md @@ -0,0 +1,53 @@ +# 导入和插入消息 + + + +本文介绍环信即时通讯 IM SDK 如何在本地导入和插入消息。 + +## 技术原理 + +环信即时通讯 IM SDK 支持提供 `IChatManager` 和 `Conversation` 类支持在本地导入和插入消息,其中包含如下主要方法: + +- `IChatManager.ImportMessages` 批量导入消息到数据库。 +- `Conversation.InsertMessage` 在指定会话中插入消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 批量导入消息到数据库 + +如果你需要使用批量导入方式在本地会话中插入消息,可以调用 `ImportMessages` 方法,构造 `EMMessage` 对象,将消息导入本地数据库。 + +当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 + +推荐一次导入 1,000 条以内的数据。 + +示例代码如下: + +```csharp +SDKClient.Instance.ChatManager.ImportMessages(messages, new CallBack( + onSuccess: () => { + }, + onError: (code, desc) => + { + } +)); +``` + +### 插入消息 + +如果你想在当前对话中插入消息而不实际发送消息,请构造消息正文并调用 `InsertMessage` 方法用于发送通知消息,例如“XXX 撤回一条消息”、“XXX 入群” 和 “对方正在输入...”。 + +消息会根据消息中的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 + +```csharp +// 将消息插入到指定会话中。 +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.InsertMessage(message); +``` diff --git a/docs/document/unity/message_manage.md b/docs/document/unity/message_manage.md deleted file mode 100644 index 5595e77c9..000000000 --- a/docs/document/unity/message_manage.md +++ /dev/null @@ -1,219 +0,0 @@ -# 管理本地会话和消息 - - - -本文介绍即时通讯 IM SDK 如何管理本地会话和消息。 - -除了发送和接收消息外,环信即时通讯 IM SDK 还支持以会话为单位对本地的消息数据进行管理,如获取与管理未读消息、搜索和删除历史消息等。其中,会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息以及查看或清空历史消息。 - -本文介绍如何使用环信即时通讯 IM SDK 在 app 中实现这些功能。 - -## 技术原理 - -SQLCipher 用于加密存储本地消息的数据库。即时通讯 IM SDK 使用 `IChatManager` 和 `Conversation` 管理本地消息。以下是核心方法: - -- `IChatManager.LoadAllConversations` 获取本地所有会话; -- `Conversation.LoadMessages` 读取指定会话的消息; -- `Conversation.UnReadCount` 获取指定会话的未读消息数; -- `IChatManager.GetUnreadMessageCount` 获取所有会话的未读消息数; -- `IChatManager.MarkAllConversationsAsRead` 指定会话的未读消息数清零; -- `IChatManager.DeleteConversation` 删除本地会话及历史消息; -- `IChatManager.DeleteConversationFromServer` 删除服务端的会话及历史消息; -- `IChatManager.LoadMessage` 根据消息 ID 搜索消息; -- `Conversation.LoadMessagesWithMsgType` 获取指定会话中特定类型的消息; -- `Conversation.LoadMessagesWithTime` 获取指定会话中一定时间段内的消息; -- `IChatManager.SearchMsgFromDB` 根据关键字搜索会话消息; -- `IChatManager.ImportMessages` 批量导入消息到数据库; -- `Conversation.InsertMessage` 在指定会话中插入消息。 - -## 前提条件 - -开始前,请确保满足以下条件: - -- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 - -## 实现方法 - -### 获取本地所有会话 - -你可以调用 `LoadAllConversations` 方法可以根据会话 ID 和会话类型获取本地所有会话: - -```csharp -Listlist = SDKClient.Instance.ChatManager.LoadAllConversations(); - -``` -SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 - - -### 读取指定会话的消息 - -你可以从本地数据库中读取指定会话的消息,示例代码如下: - -```csharp -// 获取本地会话。 -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -// 该方法获取 `startMsgId` 之前的 `pagesize` 条消息。 -conv.LoadMessages(startMsgId, pagesize, callback:new ValueCallBack>( - onSuccess: (list) => { - Debug.Log($"获取到{list.Count}条消息"); - }, - onError:(code, desc) => { - Debug.Log($"获取会话消息失败,errCode={code}, errDesc={desc}"); - } -)); -``` - -### 获取指定会话的未读消息数 - -你可以调用接口获取特定会话的未读消息数,示例代码如下: - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -int unread = conv.UnReadCount; -``` - -### 获取所有会话的未读消息数 - -你可以通过接口获取所有会话的未读消息数量,示例代码如下: - -```csharp -SDKClient.Instance.ChatManager.GetUnreadMessageCount(); -``` - -### 指定会话的未读消息数清零 - -你可以调用接口对特定会话的未读消息数清零,示例代码如下: - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -// 指定会话的未读消息数清零。 -conv.MarkAllMessageAsRead(); - -// 将一条消息置为已读。 -conv.MarkMessageAsRead(msgId); - -// 将所有未读消息数清零。 -SDKClient.Instance.ChatManager.MarkAllConversationsAsRead(); -``` - -### 删除会话及历史消息 - -SDK 提供两个接口,分别可以删除本地会话和历史消息或者删除当前用户在服务器端的会话和聊天消息。 - -调用 `DeleteConversation` 和 `DeleteMessage` 删除本地会话和聊天消息,示例代码如下: - -```csharp -//删除和特定用户的会话,如需保留历史消息,传 `false`。 -SDKClient.Instance.ChatManager.DeleteConversation(conversationId, true); - -//删除当前会话中指定的一条历史消息。 -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -conv.DeleteMessage(msgId); -``` - -删除服务端的会话及其历史消息,详见 [删除服务端会话及其历史消息](message_retrieve.html#单向删除服务端会话及其历史消息)。 - -### 根据消息 ID 搜索消息 - -你可以调用 `LoadMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 - -```csharp -// msgId:要获取消息的消息 ID。 -Message msg = SDKClient.Instance.ChatManager.LoadMessage("msgId"); -``` - -### 获取指定会话中特定类型的消息 - -你可以调用 `LoadMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); -// type:消息类型;count:每次获取的消息数量,取值范围为 [1,400];direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -conv.LoadMessagesWithMsgType(type: MessageBodyType.TXT, count: 50, direction: MessageSearchDirection.UP, new ValueCallBack>( - onSuccess: (list) => { - // 遍历消息列表 - foreach(var it in list) - { - } - }, - onError: (code, desc) => { - } -)); -``` - -### 获取指定会话中一定时间段内的消息 - -你可以调用 `LoadMessagesWithTime` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。每次最多可获取 400 条消息。 - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); -// startTime:搜索的起始时间戳;endTime:搜索的结束时间戳;count:每次获取的消息数量,取值范围为 [1,400]。 -conv.LoadMessagesWithTime(startTime: startTime, endTime: endTime, count: 50, new ValueCallBack>( - onSuccess: (list) => { - // 遍历消息列表 - foreach (var it in list) - { - } - }, - onError: (code, desc) => { - } -)); -``` - -### 根据关键字搜索会话消息 - -你可以调用 `LoadMessagesWithKeyword` 方法以从本地数据库获取会话中的指定用户发送的包含特定关键字的消息,示例代码如下: - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); - -conv.LoadMessagesWithKeyword( - // 搜索关键字。 - "key", - // 消息发送方。 - sender: "tom", - // 搜索开始的 Unix 时间戳,单位为毫秒。 - timestamp: 1653971593000, - // 搜索的最大消息数。 - count: 10, - // 消息的搜索方向:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 - direction: MessageSearchDirection.UP, - // 回调处理 - new ValueCallBack>( - onSuccess: (list) => { - // 遍历消息列表 - foreach(var it in list) - { - } - }, - onError: (code, desc) => { - } -)); -``` - -### 批量导入消息到数据库 - -如果你需要使用批量导入方式在本地会话中插入消息,可以调用 `ImportMessages` 方法,构造 `EMMessage` 对象,将消息导入本地数据库。 - -示例代码如下: - -```csharp -SDKClient.Instance.ChatManager.ImportMessages(messages, new CallBack( - onSuccess: () => { - }, - onError: (code, desc) => - { - } -)); -``` - -### 插入消息 - -如果你想在当前对话中插入消息而不实际发送消息,请构造消息正文并调用 `InsertMessage` 方法用于发送通知消息,例如“XXX 撤回一条消息”、“XXX 入群” 和 “对方正在输入...”。 - -```csharp -// 将消息插入到指定会话中。 -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -conv.InsertMessage(message); -``` diff --git a/docs/document/unity/message_modify.md b/docs/document/unity/message_modify.md index b1061e6da..2219487be 100644 --- a/docs/document/unity/message_modify.md +++ b/docs/document/unity/message_modify.md @@ -1,6 +1,15 @@ # 修改消息 -对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。消息内容修改流程如下: +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。 + +:::tip +1. 若使用该功能,需将 SDK 升级至 1.2.0 或以上版本。 +2. 聊天室会话不支持消息修改功能。 +::: + +## 技术原理 + +消息内容修改流程如下: 1. 用户调用 SDK 的 API 修改一条消息。 2. 服务端存储的该条消息,修改成功后回调给 SDK。 @@ -13,10 +22,14 @@ - 对于单聊会话,只有消息发送方才能对消息进行修改。 - 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -:::notice -1. 若使用该功能,需将 SDK 升级至 1.2.0 或以上版本。 -2. 聊天室会话不支持消息修改功能。 -::: +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 你可以调用 `ChatManager#ModifyMessage` 方法修改已经发送成功的消息。一条消息默认最多可修改 10 次,若要提升修改次数,需联系商务。 diff --git a/docs/document/unity/message_recall.md b/docs/document/unity/message_recall.md new file mode 100644 index 000000000..54218d12a --- /dev/null +++ b/docs/document/unity/message_recall.md @@ -0,0 +1,54 @@ +# 撤回消息 + + + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能**页面设置消息撤回时长,该时长不超过 7 天。 + +:::tip +除了透传消息,其他各类型的消息都支持撤回。 +::: + +## 技术原理 + +环信即时通讯 IM 通过 `IChatManager` 和 `Message` 类支持你撤回一条发送成功的消息: + +- `RecallMessage`:撤回一条发送成功的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 撤回消息 + +你可以调用 `RecallMessage` 方法撤回一条发送成功的消息。 + +调用该方法后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `OnMessagesRecalled` 事件。 + +```csharp +SDKClient.Instance.ChatManager.RecallMessage("Message ID", new CallBack( + onSuccess: () => { + Debug.Log("回撤成功"); + }, + onProgress: (progress) => { + Debug.Log($"回撤进度 {progress}"); + }, + onError: (code, desc) => { + Debug.Log($"回撤失败,errCode={code}, errDesc={desc}"); + } + )); +``` + +### 设置消息撤回监听 + +你可以使用 `IChatManagerDelegate` 设置消息撤回监听,通过 `OnMessagesRecalled` 事件监听发送方对已接收的消息的撤回。 + +```csharp +void OnMessagesRecalled(List messages); +``` \ No newline at end of file diff --git a/docs/document/unity/message_receipt.md b/docs/document/unity/message_receipt.md index 15b4c3d41..74d439306 100644 --- a/docs/document/unity/message_receipt.md +++ b/docs/document/unity/message_receipt.md @@ -1,10 +1,10 @@ -# 管理消息回执 +# 实现消息回执 单聊会话支持消息送达回执、会话已读回执和消息已读回执,发送方发送消息后可及时了解接收方是否及时收到并阅读了信息,也可以了解整个会话是否已读。 -群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 本文介绍如何使用环信即时通讯 IM Unity SDK 实现单聊和群聊的消息回执功能。 @@ -41,7 +41,7 @@ - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html); - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html); -- 群消息已读回执功能仅在环信 IM 旗舰版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +- 群消息已读回执功能仅在环信 IM 专业版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 ## 实现方法 @@ -134,6 +134,8 @@ SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); ##### 消息已读回执 +单聊消息的已读回执有效期与消息在服务端的存储时间一致,即在服务器存储消息期间均可发送已读回执。消息在服务端的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + 参考如下步骤在单聊中实现消息已读回执。 1. 接收方发送已读回执消息。 @@ -223,7 +225,9 @@ SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); 对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。 -仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊已读回执的有效期为 3 天,即群组中的消息发送时间超过 3 天,服务器不记录阅读该条消息的群组成员,也不会发送已读回执。 + +仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 1. 群主或群管理员发送消息时若需已读回执,需设置 `Message` 的 `IsNeedGroupAck` 为 `true`。 diff --git a/docs/document/unity/message_retrieve.md b/docs/document/unity/message_retrieve.md index 99052a315..d14e73c05 100644 --- a/docs/document/unity/message_retrieve.md +++ b/docs/document/unity/message_retrieve.md @@ -1,23 +1,22 @@ -# 从服务器获取会话和消息 +# 获取历史消息 -环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。本文介绍用户如何从消息服务器获取和删除会话和消息。 +本文介绍环信即时通讯 IM SDK 如何从服务器和本地获取历史消息。 -:::tip -本文介绍的功能均为增值服务,需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 -::: +- 环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 + +- SDK 内部使用 SQLite 保存本地消息,你可以获取本地消息。 ## 实现原理 -使用环信即时通讯 IM SDK 可以通过 `IChatManager` 类的以下方法从服务器获取历史消息: +使用环信即时通讯 IM SDK 可以通过 `IChatManager` 和 `Conversation` 类的以下方法从服务器获取和删除历史消息: -- `GetConversationsFromServerWithPage` 分页获取服务器保存的会话列表; -- `GetConversationsFromServerWithCursor` 分页获取服务器保存的置顶会话列表; -- `PinConversation` 置顶会话。 -- `FetchHistoryMessagesFromServer` 获取服务器保存的指定会话中的消息; -- `RemoveMessagesFromServer` 单向删除服务端的历史消息; -- `DeleteConversationFromServer` 删除服务端的会话及其历史消息。 +- `IChatManager.FetchHistoryMessagesFromServer` 获取服务器保存的指定会话中的消息; +- `Conversation.LoadMessages` 读取本地指定会话的消息。 +- `IChatManager.LoadMessage` 根据消息 ID 获取消息。 +- `Conversation.LoadMessagesWithMsgType` 获取本地单个会话中特定类型的消息。 +- `Conversation.LoadMessagesWithTime` 获取本地单个会话中一定时间段内的消息。 ## 前提条件 @@ -28,152 +27,97 @@ ## 实现方法 -### 从服务器获取会话 +### 从服务器获取指定会话的消息 对于单聊或群聊,用户发消息时,会自动将对方添加到用户的会话列表。 -你可以调用 `GetConversationsFromServerWithCursor` 方法从服务端分页获取会话列表。通过设置该方法中的 `pinOnly` 参数确定是否只获取置顶会话列表: +你可以调用 `FetchHistoryMessagesFromServer` 方法从服务器分页获取指定会话的消息(消息漫游)。 -- 若 `pinOnly` 为 `false`,获取包括置顶和未置顶会话的列表。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。 -- 若为 `true` 仅获取置顶会话列表,最多可拉取 50 个置顶会话。SDK 按照会话置顶时间的倒序返回。 +为确保数据可靠,我们建议你多次调用该方法,且每次获取的消息数小于 50 条。获取到数据后,SDK 会自动将消息更新到本地数据库。 -:::notice -1. 若使用该方法,需将 SDK 升级至 1.2.0。 -2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `LoadAllConversations` 方法获取本地所有会话即可。 -3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +:::tip +1. 历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +2. 各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 ::: ```csharp -// limit: 每页返回的会话数。取值范围为 [1,50]。 -// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新活跃的会话开始查询。 -int limit = 10; -string cursor = ""; -bool pinOnly = false; // `false`:获取所有会话;`true`仅获取置顶会话列表。 -SDKClient.Instance.ChatManager.GetConversationsFromServerWithCursor(pinOnly, cursor, limit, new ValueCallBack>( - onSuccess: (result) => - { - // 遍历获取到的会话列表 - foreach (var conv in result.Data) - { - - } - // 下一次请求的 cursor - string nextCursor = result.Cursor; - }, - onError: (code, desc) => - { - - } -)); - -``` - -此外,你可以调用 `GetConversationsFromServerWithPage` 方法从服务端分页获取会话列表,每个会话包含最新一条历史消息。 - -若使用该功能,需将 SDK 升级至 V1.1.0。 - -```csharp -SDKClient.Instance.ChatManager.GetConversationsFromServerWithPage(pageNum, pageSize, new ValueCallBack>( - //获取会话成功后的处理逻辑。 - //list 为 List 类型。 - onSuccess: (list) => - { +SDKClient.Instance.ChatManager.FetchHistoryMessagesFromServer(conversationId, type, startId, pageSize, new ValueCallBack>( + // 获取历史消息成功。 + // result 为 CursorResult 类型。 + onSuccess: (result) => { }, - onError: (code, desc) => - { + + // 获取历史消息失败。 + onError:(code, desc) => { } )); ``` -### 置顶会话 +### 从本地读取指定会话的消息 -会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 - -置顶状态会存储在服务器上,多设备登录情况下,更新置顶状态会同步到其他登录设备。你最多可以置顶 50 个会话。 - -你可以调用 `PinConversation` 方法设置是否置顶会话。多设备登录情况下,会话置顶或取消置顶后,其他登录设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。 - -:::notice -若使用该功能,需将 SDK 升级至 1.2.0。 -::: - -示例代码如下: +你可以从本地数据库中读取指定会话的消息,示例代码如下: ```csharp -SDKClient.Instance.ChatManager.PinConversation(convId, isPinned, new CallBack( - onSuccess: () => - { - - }, - onError: (code, desc) => - { - - } +// 获取本地会话。 +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +// 该方法获取 `startMsgId` 之前的 `pagesize` 条消息。 +conv.LoadMessages(startMsgId, pagesize, callback:new ValueCallBack>( + onSuccess: (list) => { + Debug.Log($"获取到{list.Count}条消息"); + }, + onError:(code, desc) => { + Debug.Log($"获取会话消息失败,errCode={code}, errDesc={desc}"); + } )); ``` -你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 - - -### 分页获取指定会话的历史消息 - -你可以调用 `FetchHistoryMessagesFromServer` 方法从服务器分页获取指定会话的历史消息,实现消息漫游。该功能需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 +### 根据消息 ID 获取本地消息 -为确保数据可靠,我们建议你多次调用该方法,且每次获取的消息数小于 50 条。获取到数据后,SDK 会自动将消息更新到本地数据库。 +你可以调用 `LoadMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 ```csharp -SDKClient.Instance.ChatManager.FetchHistoryMessagesFromServer(conversationId, type, startId, pageSize, new ValueCallBack>( - // 获取历史消息成功。 - // result 为 CursorResult 类型。 - onSuccess: (result) => { - }, - - // 获取历史消息失败。 - onError:(code, desc) => { - } -)); +// msgId:要获取消息的消息 ID。 +Message msg = SDKClient.Instance.ChatManager.LoadMessage("msgId"); ``` -### 单向删除服务端的历史消息 +### 获取本地会话中特定类型的消息 -你可以调用 `RemoveMessagesFromServer` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息。其他用户不受该操作影响。已删除的消息自动从设备本地移除。 +你可以调用 `LoadMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。 -:::tip -若使用该功能,需将 SDK 升级至 V1.1.0 或以上版本并联系商务。 -::: +每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 ```csharp -// 按时间删除历史消息 -SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, time, new CallBack( - onSuccess: () => - { - }, - onError: (code, desc) => - { - } -)); -// 按消息 ID 删除历史消息 -SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, msgList, new CallBack( - onSuccess: () => - { +Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); +// type:消息类型;count:每次获取的消息数量,取值范围为 [1,400];direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +conv.LoadMessagesWithMsgType(type: MessageBodyType.TXT, count: 50, direction: MessageSearchDirection.UP, new ValueCallBack>( + onSuccess: (list) => { + // 遍历消息列表 + foreach(var it in list) + { + } }, - onError: (code, desc) => - { + onError: (code, desc) => { } )); ``` -### 单向删除服务端会话及其历史消息 +### 获取一定时间内本地会话的消息 + +你可以调用 `LoadMessagesWithTime` 方法从本地存储中搜索一定时间段内指定会话中发送和接收的消息。 -你可以调用 `DeleteConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 +每次最多可获取 400 条消息。 ```csharp -SDKClient.Instance.ChatManager.DeleteConversationFromServer(conversationId, conversationType, isDeleteServerMessages, new CallBack( - onSuccess: () => - { +Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); +// startTime:搜索的起始时间戳;endTime:搜索的结束时间戳;count:每次获取的消息数量,取值范围为 [1,400]。 +conv.LoadMessagesWithTime(startTime: startTime, endTime: endTime, count: 50, new ValueCallBack>( + onSuccess: (list) => { + // 遍历消息列表 + foreach (var it in list) + { + } }, - onError: (code, desc) => - { + onError: (code, desc) => { } )); -``` \ No newline at end of file +``` diff --git a/docs/document/unity/message_search.md b/docs/document/unity/message_search.md new file mode 100644 index 000000000..0794e510d --- /dev/null +++ b/docs/document/unity/message_search.md @@ -0,0 +1,51 @@ +# 搜索消息 + + + +本文介绍即时通讯 IM SDK 如何搜索本地消息。 + +## 技术原理 + +环信即时通讯 IM SDK 通过 `IChatManager` 类支持搜索用户设备上存储的消息数据,其中包含如下主要方法: + +- `LoadMessagesWithKeyword` 根据关键字搜索会话消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 根据关键字搜索会话消息 + +你可以调用 `LoadMessagesWithKeyword` 方法根据关键字搜索本地数据库中单个会话中指定用户发送的消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); + +conv.LoadMessagesWithKeyword( + // 搜索关键字。 + "key", + // 消息发送方。 + sender: "tom", + // 搜索开始的 Unix 时间戳,单位为毫秒。 + timestamp: 1653971593000, + // 搜索的最大消息数。 + count: 10, + // 消息的搜索方向:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 + direction: MessageSearchDirection.UP, + // 回调处理 + new ValueCallBack>( + onSuccess: (list) => { + // 遍历消息列表 + foreach(var it in list) + { + } + }, + onError: (code, desc) => { + } +)); +``` diff --git a/docs/document/unity/message_send_receive.md b/docs/document/unity/message_send_receive.md index ffc9b015c..b68fb525d 100644 --- a/docs/document/unity/message_send_receive.md +++ b/docs/document/unity/message_send_receive.md @@ -20,13 +20,21 @@ ## 技术原理 -环信即时通讯 IM Unity SDK 通过 `IChatManager` 和 `Message` 类实现消息的发送、接收与撤回。 +环信即时通讯 IM Unity SDK 通过 `IChatManager` 和 `Message` 类实现消息的发送和接收。 其中,发送和接收消息的逻辑如下: 1. 发送方调用相应 `Create` 方法创建文本、文件、附件等类型的消息; 2. 发送方调用 `SendMessage` 发送消息; -3. 接收方通过 `AddChatManagerDelegate` 方法监听消息回调事件。在收到 `OnMessageReceived` 后,即表示成功接收到消息。 +3. 接收方通过 `AddChatManagerDelegate` 方法监听消息回调事件。在收到 `OnMessagesReceived` 后,即表示成功接收到消息。 + +消息收发流程如下: + +1. 用户 A 发送一条消息到环信的消息服务器; +2. 单聊消息时,服务器投递消息给用户 B;对于群聊时消息,服务器投递给群内其他每一个成员; +3. 用户收到消息。 + +![img](@static/images/android/sendandreceivemsg.png) ## 前提条件 @@ -98,33 +106,6 @@ SDKClient.Instance.ChatManager.AddChatManagerDelegate(adelegate); SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); ``` -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `OnMessagesRecalled` 事件。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 - -```csharp -SDKClient.Instance.ChatManager.RecallMessage("Message ID", new CallBack( - onSuccess: () => { - Debug.Log("回撤成功"); - }, - onProgress: (progress) => { - Debug.Log($"回撤进度 {progress}"); - }, - onError: (code, desc) => { - Debug.Log($"回撤失败,errCode={code}, errDesc={desc}"); - } - )); -``` - -还可以使用 `IChatManagerDelegate` 设置消息撤回监听: - -```csharp -// 接收到消息被撤回时触发此回调(此回调位于 IChatManagerDelegate 中)。 -void OnMessagesRecalled(List messages); -``` - ### 发送和接收附件消息 除文本消息外,还有几种其他类型的消息,其中语音,图片,短视频,文件等消息,是通过先将附件上传到消息服务器的方式实现。收到语音时,会自动下载,而图片和视频会自动下载缩略图。文件消息不会自动下载附件,接收方需调用下载附件的 API,具体实现参考下文。 @@ -374,6 +355,10 @@ SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( 透传消息可视为命令消息,通过发送这条命令给对方,通知对方要进行的操作,收到消息可以自定义处理。(透传消息不会存入本地数据库中,所以在 UI 上不会显示)。具体功能可以根据自身业务需求自定义,例如实现头像、昵称的更新等。另外,以 “em_” 和 “easemob::” 开头的 action 为内部保留字段,注意不要使用。 +:::tip +透传消息发送后,不支持撤回。 +::: + ```csharp //`action` 可以自定义。 string action = "actionXXX"; @@ -426,7 +411,7 @@ SDKClient.Instance.ChatManager.AddChatManagerDelegate(adelegate); - 收到消息后,如果用户 B 与用户 A 的聊天页面处于打开状态,则显示用户 A 的输入指示器。 - 如果用户 B 在几秒后未收到用户 A 的输入,则自动取消输入指示器。 -:::notice +:::tip 用户 A 可根据需要设置透传消息发送间隔。 @@ -526,7 +511,7 @@ SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( | `messageList` | List | 合并消息的原始消息 ID 列表。该列表最多包含 300 个消息 ID。 | -:::notice +:::tip 1. 合并转发支持嵌套,最多支持 10 层嵌套,每层最多 300 条消息。 2. 不论 `Options#ServerTransfer` 设置为 `false` 或 `true`,SDK 都会将合并消息附件上传到环信服务器。 ::: @@ -579,7 +564,7 @@ SDKClient.Instance.ChatManager.FetchCombineMessageDetail(msg, new ValueCallBack< 该功能适用于文本消息、图片消息和音视频消息等全类型消息,最多可向群组或聊天室的 20 个成员发送定向消息。 -:::notice +:::tip 1. 仅 SDK 1.2.0 及以上版本支持。 2. 定向消息不写入服务端会话列表,不计入服务端会话的未读消息计数。 3. 定向消息不支持消息漫游功能,因此从服务器拉取漫游消息时,不包含定向消息。 diff --git a/docs/document/unity/message_update.md b/docs/document/unity/message_update.md new file mode 100644 index 000000000..fc8fc112b --- /dev/null +++ b/docs/document/unity/message_update.md @@ -0,0 +1,38 @@ +# 更新消息 + + + +本文介绍环信即时通讯 IM SDK 如何更新本地消息。 + +## 技术原理 + +环信即时通讯 IM SDK 使用 `IChatManager` 和 `Conversation` 支持更新本地数据库中的消息,其中包含如下主要方法: + +- `UpdateMessage`:更新 SDK 本地数据库中的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 更新消息到本地数据库 + +你可以通过以下方式更新本地数据库中的消息: + +- 直接调用 `UpdateMessage` 方法更新 SDK 本地数据库中的消息。 + +```csharp +SDKClient.Instance.ChatManager.UpdateMessage(message): +``` + +- 若正在使用 `Conversation` 类,可以先获取会话,再调用 `UpdateMessage` 方法更新 SDK 本地数据库会话中的消息。 + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, type); +conv.UpdateMessage(message); +``` + diff --git a/docs/document/unity/moderation.md b/docs/document/unity/moderation.md index f6241ebe4..73f3c2fe8 100644 --- a/docs/document/unity/moderation.md +++ b/docs/document/unity/moderation.md @@ -2,7 +2,14 @@ -即时通讯 IM SDK 提供消息举报接口。开发者可以在客户端调用该接口举报违规消息。当服务器端审核服务收到举报消息后,会将举报消息存储到数据库,并在 Console 展示。审核员可在 Console 查看举报记录,并进行相应处理。 +即时通讯 IM SDK 提供消息举报接口。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +:::tip +1. 使用前,你需要在[环信即时通讯云控制台](https://console.easemob.com/user/login) 开通该功能。 +2. 消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +关于如何开通消息举报和查看举报记录,详见[环信即时通讯云控制台文档说明](/product/enable_and_configure_IM.html#消息举报)。 ## 技术原理 @@ -13,7 +20,7 @@ 开始前,请确保满足以下条件: - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 开通消息审核服务,详见管理后台。 +- 已在 [环信即时通讯云控制台开通消息举报功能](/product/enable_and_configure_IM.html#消息举报)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 @@ -23,7 +30,7 @@ ```csharp // msgId:要举报的消息 ID。 // tag:非法消息的标签。你需要自定义标签,例如`涉政`或`广告`。该字段对应环信即时通讯云控制台的消息举报记录页面的`词条标记`字段。 -// reason:举报原因。你需要自行填写举报原因。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 +// reason:举报原因。你需要自行填写举报原因,最长不能超过 512 字节。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 SDKClient.Instance.ChatManager.ReportMessage(msgId, tag, reason, new CallBack( onSuccess: () => { diff --git a/docs/document/unity/multi_device.md b/docs/document/unity/multi_device.md index 69dac1038..b1d54a427 100644 --- a/docs/document/unity/multi_device.md +++ b/docs/document/unity/multi_device.md @@ -74,10 +74,10 @@ SDKClient.Instance.ContactManager.GetSelfIdsOnOtherPlatform(new ValueCallBack>( onSuccess: (list) => { - // 选择一个登录 ID 作为消息发送方。 + // 选择一个登录 ID 作为消息接收方。 string toChatUsername = list[0]; string content = "content"; - // 创建一条文本消息,content 为消息文字内容,toChatUsername 传入登录 ID 作为消息发送方。 + // 创建一条文本消息,content 为消息文字内容,toChatUsername 传入登录 ID 作为消息接收方。 Message msg = Message.CreateTextSendMessage(toChatUsername, content); // 发送消息。 SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( diff --git a/docs/document/unity/overview.md b/docs/document/unity/overview.md index d7dfbb63d..40ed7a1f6 100644 --- a/docs/document/unity/overview.md +++ b/docs/document/unity/overview.md @@ -245,4 +245,53 @@ SDKClient.Instance.DeleteConnectionDelegate(connectionDelegate); ## 输出信息到日志文件 -如果开启日志调试模式,会通过控制台输出日志。`DebugMode` 设置为 `true`。 +环信即时通讯 IM 日志记录 SDK 相关的信息和事件。环信技术支持团队帮你排查问题时可能会请你发送 SDK 日志。 + +默认情况下,SDK 最多可生成和保存三个文件,`easemob.log` 和两个 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件。这些文件为 UTF-8 编码,每个不超过 2 MB。SDK 会将最新的日志写入 `easemob.log` 文件,写满时则会将其重命名为对应时间点的 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件,若日志文件超过三个,则会删除最早的文件。 + +例如,SDK 在 2024 年 1 月 1 日上午 8:00:00 记录日志时会生成 `easemob.log` 文件,若在 8:30:00 将 `easemob.log` 文件写满则会将其重命名为 `easemob_2024-01-01_08-30-00.log` 文件,随后在 9:30:30 和 10:30:30 分别生成了 `easemob_2024-01-01_09-30-30.log` 和 `easemob_2024-01-01_10-30-30.log` 文件,则此时 `easemob_2024-01-01_08-30-00.log` 文件会被移除。 + +SDK 默认不输出调试信息(所有日志,包括调试信息、警告和错误),只需输出错误日志。若需调试信息,首先要开启调试模式。 + +```csharp +Options options = new Options("YourAppKey"); +options.DebugMode = true; +SDKClient.Instance.InitWithOptions(options); +``` + +### 获取本地日志 + +Unity 分为 4 个端:Unity Mac、Unity Windows、Unity iOS、Unity Android。 + +- Unity Mac + +日志路径: /Users/XXX/Library/Application Support/YYY/ZZZ/sdkdata/easemobLog 或者 /Users/XXX/Library/Application Support/com.YYY.ZZZ/sdkdata/easemobLog + +XXX: Mac 用户名; YYY: Unity 中设置的公司名称,如果没有设置则为 `DefaultCompany`,ZZZ 为 app 名称。 + +- Unity Windows + +日志路径:C:\Users\XXX\AppData\LocalLow\YYY\ZZZ\sdkdata\easemobLog + +XXX:Windows 用户名; YYY: Unity 中设置的公司名称,如果没有设置则为 `DefaultCompany`,ZZZ 为 app 名称。 + +- Unity iOS + +本地日志的获取与 iOS 的相同,详见 [iOS 本地日志的获取](/document/ios/overview.html#获取本地日志)。 + +日志路径:沙箱 Library/Application Support/HyphenateSDK/easemobLog。 + +以真机为例,获取本地日志过程如下: + +- 打开 Xcode,连接设备,选择 **Xcode** > **Window** > **Devices and Simulators**。 +- 进入 **Devices** 选项卡,在左侧选择目标设备,例如 Easemob IM,点击设置图标,然后选择 **Download Container**。 + +![img](@static/images/ios/overview_fetchlogfile.png) + +日志文件 `easemob.log` 文件在下载包的 AppData/Library/Application Support/HyphenateSDK/easemobLog 目录下。 + +- Unity Android + +在 Android Studio 中,选择 **View** > **Tool Windows** > **Device File Explorer**,然后浏览设备上的文件夹。 + +日志路径为 /data/data//sdkdata/easemobLog。 diff --git a/docs/document/unity/presence.md b/docs/document/unity/presence.md index d1c776212..77cdec6d0 100644 --- a/docs/document/unity/presence.md +++ b/docs/document/unity/presence.md @@ -6,10 +6,6 @@ 本文介绍如何在即时通讯应用中发布、订阅和查询用户的在线状态。 -:::notice -私有化版本不支持在线状态订阅。 -::: - ## 技术原理 环信 IM SDK 提供 `Presence`、`PresenceManager` 和 `IPresenceManagerDelegate` 类,用于管理在线状态订阅,包含如下核心方法: diff --git a/docs/document/unity/reaction.md b/docs/document/unity/reaction.md index 499761f0a..a80e251fe 100644 --- a/docs/document/unity/reaction.md +++ b/docs/document/unity/reaction.md @@ -6,9 +6,9 @@ :::notice -1. 目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 -2. 私有化版本不支持 Reaction 功能。 - ::: +目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 + +::: ## 技术原理 diff --git a/docs/document/unity/releasenote.md b/docs/document/unity/releasenote.md index 400b79517..6bbf0f2e4 100644 --- a/docs/document/unity/releasenote.md +++ b/docs/document/unity/releasenote.md @@ -25,7 +25,7 @@ - `SDKClient#GetLoggedInDevicesFromServerWithToken`:获取指定账号下登录的在线设备列表; - `SDKClient#KickDeviceWithToken`:将指定账号登录的指定设备踢下线; - `SDKClient#KickAllDevicesWithToken`:将指定账号登录的所有设备都踢下线。 -- [IM SDK] 新增[会话置顶功能](message_retrieve.html#置顶会话): +- [IM SDK] 新增[会话置顶功能](conversation_pin.html#置顶会话): - `Conversation#IsPinned`:判断该会话是否被置顶; - `Conversation#PinnedTime`:会话置顶时间戳。 - [IM SDK] 新增 `ChatManager#FetchHistoryMessagesFromServerBy` 方法根据消息拉取参数配置类 `FetchServerMessagesOption` 从服务器获取历史消息
@@ -37,7 +37,7 @@ - `FetchServerMessagesOption#MsgTypes`:要查询的消息类型列表; - `FetchServerMessagesOption#StartTime`:消息查询的起始时间; - `FetchServerMessagesOption#EndTime`:消息查询的结束时间。 -- [IM SDK] 新增 `GetConversationsFromServerWithCursor` 方法[从服务端分页获取会话列表](message_retrieve.html#从服务器获取会话)。 +- [IM SDK] 新增 `GetConversationsFromServerWithCursor` 方法[从服务端分页获取会话列表](conversation_list.html#从服务器分页获取会话列表)。 - [IM SDK] 新增[在群组或聊天室中发送定向消息功能](message_send_receive.html#发送和接收定向消息): - `Message#ReceiverList`:设置群组或聊天室消息接收列表。 - [IM SDK] 新增 `Conversation#DeleteMessages`方法删除本地数据库中指定时间段的消息。 @@ -84,7 +84,7 @@ ### 修复 -1. 修复 [`ChatManager#FetchHistoryMessageFromServer`](message_retrieve.html#从服务器获取会话) 方法在安卓环境下调用失败的问题。 +1. 修复 [`ChatManager#FetchHistoryMessageFromServer`](conversation_list.html#从服务器分页获取会话列表) 方法在安卓环境下调用失败的问题。 2. 修复在安卓环境下发送视频消息没有回调的问题。 ## 版本 V1.1.0 Dev 2023-2-25 @@ -213,7 +213,7 @@ - 消息表情回复; - 管理子区等。 -关于详细功能概述,请参见[产品概述](https://docs-im-beta.easemob.com/product/introduction.html)。 +关于详细功能概述,请参见[产品概述](https://doc.easemob.com/product/introduction.html)。 具体集成请参考以下文档: diff --git a/docs/document/unity/room_manage.md b/docs/document/unity/room_manage.md index de8dd6e1b..b92309087 100644 --- a/docs/document/unity/room_manage.md +++ b/docs/document/unity/room_manage.md @@ -38,7 +38,7 @@ 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 可以调用 `CreateRoom` 方法创建聊天室,并设置聊天室的名称、描述、最大成员数等信息。成功创建聊天室后,该超级管理员为该聊天室的所有者。 -你也可以直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 +建议直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 示例代码如下: @@ -129,7 +129,8 @@ Options options = new Options(); options. DeleteMessagesAsExitRoom = false; ``` -与群主无法退出群组不同,聊天室所有者可以离开聊天室,例如所有者从服务器下线则 2 分钟后自动离开聊天室。如果所有者重新进入聊天室仍是该聊天室的所有者。 +与群主无法退出群组不同,聊天室所有者可以离开聊天室,离开后重新进入聊天室仍是该聊天室的所有者。若 `Options#IsRoomOwnerLeaveAllowed +` 参数在初始化时设置为 `true` 时,聊天室所有者可以离开聊天室;若该参数设置为 `false`,聊天室所有者调用 `LeaveRoom` 方法离开聊天室时会提示错误 706。 ### 解散聊天室 diff --git a/docs/document/unity/room_members.md b/docs/document/unity/room_members.md index 1f283c661..715cbd928 100644 --- a/docs/document/unity/room_members.md +++ b/docs/document/unity/room_members.md @@ -46,7 +46,7 @@ SDKClient.Instance.RoomManager.FetchRoomMembers(roomId, cursor, pageSize, callba ### 将成员移出聊天室 -仅聊天室所有者和管理员可调用 `DeleteRoomMembers` 方法将指定成员移出聊天室。 +仅聊天室所有者和管理员可调用 `DeleteRoomMembers` 方法将单个或多个成员移出聊天室。 被移出后,该成员收到 `OnRemovedFromRoom` 回调,其他成员收到 `OnMemberExitedFromRoom` 回调。 @@ -55,10 +55,16 @@ SDKClient.Instance.RoomManager.FetchRoomMembers(roomId, cursor, pageSize, callba 示例代码如下: ```csharp +List members = new List(); +members.Add("member1"); +members.Add("member2"); + SDKClient.Instance.RoomManager.DeleteRoomMembers(roomId, members, new CallBack( onSuccess: () => { + Console.WriteLine($"DeleteRoomMembers success."); }, onError: (code, desc) => { + Console.WriteLine($"DeleteRoomMembers failed, code:{code}, desc:{desc}"); } )); ``` @@ -194,6 +200,7 @@ SDKClient.Instance.RoomManager.RemoveAllowListMembers(roomId, list, new CallBack 示例代码如下: ```csharp +// muteMilliseconds:禁言时间。若传 -1,表示永久禁言。 SDKClient.Instance.RoomManager.MuteRoomMembers(roomId, members, new CallBack( onSuccess: () => { }, @@ -204,7 +211,7 @@ SDKClient.Instance.RoomManager.MuteRoomMembers(roomId, members, new CallBack( #### 将成员移出聊天室禁言列表 -仅聊天室所有者和管理员可以调用 `UnMuteRoomMembers` 方法将成员移出聊天室禁言列表。被解除禁言后,其他成员收到 `OnMuteListRemovedFromRoom` 回调。 +仅聊天室所有者和管理员可以调用 `UnMuteRoomMembers` 方法将成员移出聊天室禁言列表。被移出的群成员及其他未操作的管理员或者群主将会收到群组事件 `OnMuteListRemovedFromRoom`。 :::notice 聊天室所有者可对聊天室所有成员解除禁言,聊天室管理员可对聊天室普通成员解除禁言。 @@ -215,7 +222,7 @@ SDKClient.Instance.RoomManager.MuteRoomMembers(roomId, members, new CallBack( ```csharp SDKClient.Instance.RoomManager.UnMuteRoomMembers(roomId, members, new CallBack( onSuccess: () => { - }, + }, onError: (code, desc) => { } )); @@ -242,7 +249,9 @@ SDKClient.Instance.RoomManager.FetchRoomMuteList(roomId, pageSize, pageNum, call #### 开启聊天室全员禁言 -仅聊天室所有者和管理员可以调用 `MuteAllRoomMembers` 方法开启全员禁言。全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `OnAllMemberMuteChangedFromChatroom` 回调。 +仅聊天室所有者和管理员可以调用 `MuteAllRoomMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动取消禁言,需要调用 `UnMuteAllRoomMembers` 方法取消全员禁言。 + +全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `OnAllMemberMuteChangedFromChatroom` 回调。 示例代码如下: diff --git a/docs/document/unity/thread.md b/docs/document/unity/thread.md index 8f1682ef9..7560d8c60 100644 --- a/docs/document/unity/thread.md +++ b/docs/document/unity/thread.md @@ -6,10 +6,6 @@ 如需查看消息相关内容,参见 [子区消息管理](thread_message.html)。 -:::notice -私有化版本不支持子区功能。 -::: - ## 技术原理 环信即时通讯 IM Unity SDK 提供 `IChatThreadManager`、`ChatThread`、`ChatThreadEvent` 和 `IChatThreadManagerDelegate` 类,用于管理子区,支持你通过调用 API 在项目中实现如下功能: diff --git a/docs/document/unity/thread_message.md b/docs/document/unity/thread_message.md index fd0fc4341..9a1d37829 100644 --- a/docs/document/unity/thread_message.md +++ b/docs/document/unity/thread_message.md @@ -94,7 +94,7 @@ SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); ### 撤回子区消息 -接收消息的具体逻辑,请参考[撤回消息](message_send_receive.html#撤回消息),此处只介绍子区消息和其他消息的区别。 +接收消息的具体逻辑,请参考[撤回消息](message_recall.html),此处只介绍子区消息和其他消息的区别。 子区有消息撤回时,子区所属群组的所有成员收到 `IChatThreadManagerDelegate#OnUpdateMyThread` 回调,子区成员收到 `IChatManagerDelegate#OnMessagesRecalled` 回调。 diff --git a/docs/document/unity/user_relationship.md b/docs/document/unity/user_relationship.md index e3e8cc7f5..1de5f1645 100644 --- a/docs/document/unity/user_relationship.md +++ b/docs/document/unity/user_relationship.md @@ -35,9 +35,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理 本节展示如何在项目中管理好友的添加移除和黑名单的添加移除。 -### 管理好友列表 - -#### 添加好友 +### 添加好友 好友请求部分主要功能是发送好友请求、接收好友请求、处理好友请求和好友请求处理结果回调等。 @@ -124,10 +122,12 @@ SDKClient.Instance.ContactManager.DeclineInvitation(username, callback: new Call 当你同意或者拒绝后,对方会通过好友事件回调,收到 `OnFriendRequestAccepted` 或者 `OnFriendRequestDeclined` 回调。 -#### 删除好友 +### 删除好友 调用 `DeleteContact` 删除指定联系人。被删除的用户收到 `OnContactDeleted` 回调。删除联系人时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 +删除好友后,对方会收到 `OnContactDeleted` 回调。 + ```csharp SDKClient.Instance.ContactManager.DeleteContact(username, callback: new CallBack( onSuccess: () => @@ -139,20 +139,11 @@ SDKClient.Instance.ContactManager.DeleteContact(username, callback: new CallBack )); ``` -调用 `DeleteContact` 删除好友后,对方会收到 `OnContactDeleted` 回调。 - -#### 获取好友列表 - -你可以从服务器获取好友列表,也可以从本地数据库获取保存的好友列表。 +### 从服务器获取好友列表 -:::notice -从服务器获取好友列表之后才能从本地数据库获取到好友列表。 -::: - -示例代码如下: +你可以调用 `GetAllContactsFromServer` 方法从服务器获取好友列表: ```csharp -//从服务器获取好友列表。 SDKClient.Instance.ContactManager.GetAllContactsFromServer(new ValueCallBack>( onSuccess: (list) => { @@ -161,19 +152,24 @@ SDKClient.Instance.ContactManager.GetAllContactsFromServer(new ValueCallBacklist = SDKClient.Instance.ContactManager.GetAllContactsFromDB(); ``` -### 管理黑名单 +### 添加用户到黑名单 黑名单是与好友无任何关系的独立体系。可以将任何用户加入黑名单,不论该用户与你是否是好友关系。 黑名单功能包括加入黑名单,从黑名单移出用户和获取黑名单列表。 -#### 添加用户到黑名单 - 你可以调用 `AddUserToBlockList` 添加用户到黑名单。用户被加入黑名单后,无法向你发送消息,也无法发送好友申请。 用户可以将任何其他用户添加到黑名单列表,无论该用户是否是好友。好友被加入黑名单后仍在好友列表上显示。 @@ -190,7 +186,7 @@ SDKClient.Instance.ContactManager.AddUserToBlockList(username, callback: new Cal )); ``` -#### 将用户从黑名单移除 +### 将用户从黑名单移除 你可以调用 `RemoveUserFromBlockList` 将用户从黑名单移除,用户发送消息等行为将恢复。 @@ -205,7 +201,7 @@ SDKClient.Instance.ContactManager.RemoveUserFromBlockList(username, callback: ne )); ``` -#### 从服务器获取黑名单列表 +### 从服务器获取黑名单列表 你可以调用 `GetBlockListFromServer` 从服务端获取黑名单列表。示例代码如下: diff --git a/docs/document/web/apireference.md b/docs/document/web/apireference.md index 8c2cfb9af..612c63430 100644 --- a/docs/document/web/apireference.md +++ b/docs/document/web/apireference.md @@ -2,4 +2,4 @@ -[4.X Web SDK 接口列表](https://docs-im-beta.easemob.com/jsdoc/index.html) +[4.X Web SDK 接口列表](https://doc.easemob.com/jsdoc/index.html) diff --git a/docs/document/web/conversation_delete.md b/docs/document/web/conversation_delete.md new file mode 100644 index 000000000..efb94910f --- /dev/null +++ b/docs/document/web/conversation_delete.md @@ -0,0 +1,43 @@ +# 删除会话 + + + +删除好友或退出群组后,SDK 不会自动删除对应的单聊或群聊会话。你可以调用相应的接口从服务器删除单个会话及其历史消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器删除单个会话及其历史消息,主要方法如下: + +`deleteConversation`:单向删除服务端的单个会话及其历史消息。 + +## 实现方法 + +### 单向删除服务器端会话及其对应的消息 + +你可以调用 `deleteConversation` 方法删除服务器端会话及其对应的消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,其他用户不受影响。 + +```javascript +let options = { + // 会话 ID:单聊为对方的用户 ID,群聊为群组 ID。 + channel: "channel", + // 会话类型:(默认) `singleChat`:单聊;`groupChat`:群聊。 + chatType: "singleChat", + // 删除会话时是否同时删除服务端漫游消息。 + deleteRoam: true, +}; +WebIM.conn + .deleteConversation(options) + .then((res) => { + console.log(res); + }) + .catch((e) => { + // 删除失败。 + }); +``` diff --git a/docs/document/web/conversation_list.md b/docs/document/web/conversation_list.md new file mode 100644 index 000000000..d17359e21 --- /dev/null +++ b/docs/document/web/conversation_list.md @@ -0,0 +1,58 @@ +# 会话列表 + + + +对于单聊和群组聊天会话,用户发消息时 SDK 会自动创建会话并将会话添加至用户的会话列表。 + +**环信服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。** 你可以获取会话列表。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器获取会话列表,主要方法如下: + +`getServerConversations`:从服务器分页获取会话列表。 + +## 实现方法 + +### 从服务器分页获取会话列表 + +你可以调用 `getServerConversations` 方法从服务端分页获取会话列表,包含单聊和群组聊天会话,不包含聊天室会话。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表。 + +:::tip +1. **若使用该功能,需在环信控制台开通,并将 SDK 升级至 4.1.7 或以上版本。而且,只有开通该功能,你才能使用置顶会话和会话标记功能。** +2. 登录用户的 ID 大小写混用会导致拉取会话列表时提示会话列表为空,因此建议用户 ID 使用小写字母。 +3. 服务端会话列表的更新存在延时,建议你仅在登录时调用该方法。 +4. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +::: + +示例代码如下: + +```javascript +// pageSize: 每页期望获取的会话数量。取值范围为 [1,50],默认为 `20`。 +// cursor:开始获取数据的游标位置。若传空字符串(''),SDK 从最新活跃的会话开始获取。 +connection.getServerConversations({pageSize:50, cursor: ''}).then((res)=>{ + console.log(res) +}) +``` +该方法的返回数据包含 `conversations` 和 `cursor` 参数: + +- conversations: 会话列表。`conversations` 为 `ConversationItem[]` 类型,`ConversationItem` 包含如下属性: + +| 属性名称 | 描述 | +| :--------- | :----- | +| `conversationId` | 会话 ID。 | +| `conversationType` | 会话类型。| +| `isPinned` | 是否置顶:
- `true`:置顶;
- `false`:不置顶。 | +| `pinnedTime`| 会话置顶的 UNIX 时间戳,单位为毫秒。未置顶时值为 `0` | +| `lastMessage` | 最新一条消息概况。 | +| `unReadCount` | 未读消息数。 | +| `marks` | 会话标记。| + +- cursor: 下次查询数据的游标位置。若 SDK 返回的数据条数小于请求中设置的数目,`cursor` 的值为空字符串(''),表示当前为最后一页数据。否则,SDK 返回具体的游标位置,指定开始获取数据的位置。 \ No newline at end of file diff --git a/docs/document/web/message_manage.md b/docs/document/web/conversation_local.md similarity index 76% rename from docs/document/web/message_manage.md rename to docs/document/web/conversation_local.md index bddf6b89a..5c56b0c5e 100644 --- a/docs/document/web/message_manage.md +++ b/docs/document/web/conversation_local.md @@ -30,13 +30,12 @@ miniCore.open({ 环信即时通讯 IM SDK 支持你通过调用 API 在项目中实现如下功能: -- 获取本地会话列表; -- 获取单个本地会话; -- 设置会话自定义字段; -- 从服务器拉取历史消息; -- 对会话的未读消息数清零; -- 删除单个本地会话; -- 同步服务端会话列表到本地数据库。 +- `getLocalConversations`:获取本地会话列表; +- `getLocalConversation`:获取单个本地会话; +- `setLocalConversationCustomField`:设置会话自定义字段; +- `clearConversationUnreadCount`:对会话的未读消息数清零; +- `removeLocalConversation`:删除单个本地会话; +- `getServerConversations`:同步服务端会话列表到本地数据库。 ## 前提条件 @@ -121,27 +120,6 @@ miniCore.localCache.setLocalConversationCustomField(options).then(()=>{ }) ``` -### 从服务器获取历史消息 - -你可以调用 `getHistoryMessages` 方法基于 `searchOptions` 参数对象允许用户按消息发送方、消息类型或时间段从服务器分页拉取单聊和群组聊天的历史消息。 - -对于群组聊天,你可以通过设置 `searchOptions` 对象中的 `from` 参数拉取群组中单个成员发送的历史消息。 - -```javascript -connection.getHistoryMessages({ - targetId: 'targetId', // 单聊为对端用户 ID,群组聊天为群组 ID。 - chatType: 'groupChat', // 会话类型:单聊和群组聊天分别为 `singleChat` 和 `groupChat`。 - pageSize: 20, // 每次获取的消息数量,取值范围为 [1,50],默认值为 `20`。 - searchDirection: 'down', // 消息搜索方向。`up` 表示按消息时间戳递减的方向获取,即先获取最新消息;`down` 表示按消息时间戳递增的方向获取,即先获取最老的消息。 - searchOptions: { - from: 'message sender userID', // 消息发送方的用户 ID。该参数仅用于群组聊天。 - msgTypes: ['txt'], // 要获取的消息类型的数组。若不传值,会获取所有类型的消息。 - startTime: new Date('2023,11,9').getTime(), // 查询的起始时间戳,单位为毫秒。 - endTime: new Date('2023,11,10').getTime(), // 查询的结束时间戳,单位为毫秒。 - }, -}); -``` - ### 对会话的未读消息数清零 你可以调用 `clearConversationUnreadCount` 方法对单个本地会话的未读消息数清零。示例代码如下: diff --git a/docs/document/web/conversation_mark.md b/docs/document/web/conversation_mark.md new file mode 100644 index 000000000..1f5456dfc --- /dev/null +++ b/docs/document/web/conversation_mark.md @@ -0,0 +1,103 @@ +# 会话标记 + + + +某些情况下,你可能需要对会话添加标记,例如会话标星或将会话标为已读或未读。即时通讯云 IM 支持对单聊和群聊会话添加标记,最大支持 20 个标记,所以一个会话最多可添加 20 个标记。 + +**如果要使用会话标记功能,你需要确保开通了[会话列表服务](conversation_list.html#从服务器分页获取会话列表)并将 SDK 版本升级至 4.4.0 或以上版本。** + +你需要自行维护会话标记与具体业务含义之间的映射,例如 [`MarkType.mark_0`](https://doc.easemob.com/jsdoc/enums/Types.ContactType.MarkType.html)表示待处理会话。 + +```javascript +const MarkMap = new Map(); +MarkMap.set(0, 'IMPORTANT'); +MarkMap.set(1, 'NORMAL'); +MarkMap.set(2, 'STAR'); +``` + +## 技术原理 + +环信即时通讯 IM 支持会话标记功能,主要方法如下: + +- `addConversationMark`:标记会话。 +- `removeConversationMark`:取消标记会话。 +- `getServerConversationsByFilter`:根据会话标记从服务器分页查询会话列表。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 实现方法 + +### 标记会话 + +你可以调用 `addConversationMark` 方法标记会话。调用该方法会为服务器端的会话添加标记。 + +添加会话标记后,若调用 `getServerConversations` 方法从服务器分页获取会话列表,返回的会话对象中包含会话标记,即 `ConversationItem#marks` 字段。若你已经达到了服务端会话列表长度限制(默认 100 个会话),服务端会根据会话的活跃度删除不活跃会话,这些会话的会话标记也随之删除。 + +:::tip +对会话添加标记,例如会话标星,并不影响会话的其他逻辑,例如会话的未读消息数。 +::: + + +```javascript +const options = { + conversations: [ + {conversationId: 'test', conversationType: 'singleChat'}, + {conversationId: 'groupId', conversationType: 'groupChat'} + ], + mark: 0, +} + +conn.addConversationMark(options).then(() => { + console.log('addConversationMark success') +}) +``` + +### 取消标记会话 + +你可以调用 `removeConversationMark` 方法删除会话标记。 + +调用该方法会同时移除本地和服务器端会话的标记。 + +```javascript +const options = { + conversations: [ + {conversationId: 'test', conversationType: 'singleChat'}, + {conversationId: 'groupId', conversationType: 'groupChat'} + ], + mark: 0, +} + +conn.removeConversationMark(options).then(() => { + console.log('removeConversationMark success') +}) +``` + +### 根据会话标记从服务器分页查询会话列表 + +你可以调用 `getServerConversationsByFilter` 方法根据会话标记从服务器分页获取会话列表。SDK 会按会话标记的时间的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)、未读消息数、会话标记以及最新一条消息。 + +```javascript +const options = { + pageSize: 10, + cursor: '', + filter: { + mark: 0 + } +} +conn.getServerConversationsByFilter().then((res) => { + console.log('getServerConversationsByFilter success', res) +}) +``` + + + + + + + diff --git a/docs/document/web/conversation_overview.md b/docs/document/web/conversation_overview.md new file mode 100644 index 000000000..582319857 --- /dev/null +++ b/docs/document/web/conversation_overview.md @@ -0,0 +1,48 @@ +# 会话介绍 + + + +会话包含单聊会话、群聊会话。用户可与在会话中发送消息、查看或清空历史消息等操作。 + +环信即时通讯 IM SDK 提供会话相关 API,如获取会话列表、置顶会话、添加会话标记、删除会话等。 + +## 会话 API + +环信即时通讯 IM 提供如下会话方法: + +| 方法 | 描述 | +| :--------- | :------- | +| getServerConversations | 分页获取服务器会话列表。 | +| pinConversation | 设置是否置顶会话。 | +| getServerPinnedConversations | 分页获取服务器端的置顶会话列表。 | +| deleteConversation | 删除会话。 | +| getLocalConversations | 获取本地会话列表。 | +| getLocalConversation | 获取单个本地会话。 | +| removeLocalConversation | 删除单个本地会话。 | +| setLocalConversationCustomField | 设置本地会话自定义字段。 | +| clearConversationUnreadCount | 对本地会话的未读消息数清零。 | + +## 会话事件 + +SDK 提供了会话已读事件 `onChannelMessage`,用户可以通过该事件,更新会话未读状态。 + +示例代码如下: + +```javascript +conn.addEventHandler("handlerId", { + onChannelMessage: (message) => { + // 收到会话已读的事件。该事件在以下场景中触发: + // 1. 当消息接收方调用 `send` 方法发送 `channel` 类型消息。SDK 会触发此回调。 + // 2. 多端多设备登录时,若一端发送会话已读回执(`send` 方法发送`channel`类型消息), + // 服务器端会将该会话的未读消息数置为 0,同时其他端会触发此回调。 + console.log("收到会话已读回执消息", message.from, message.to); + }, +}); + +``` + + + + + + diff --git a/docs/document/web/conversation_pin.md b/docs/document/web/conversation_pin.md new file mode 100644 index 000000000..dee1ffd2b --- /dev/null +++ b/docs/document/web/conversation_pin.md @@ -0,0 +1,51 @@ +# 会话置顶 + + + +会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 + +**若使用会话置顶功能,需将 SDK 升级至 4.1.7,并[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 技术原理 + +环信即时通讯 IM 支持会话置顶,主要方法如下: + +- `pinConversation`:置顶会话。 +- `getServerPinnedConversations`:获取服务端置顶会话列表。 + +## 实现方法 + +### 置顶会话 + +你可以调用 `pinConversation` 方法设置是否置顶会话。置顶状态会存储在服务器上,多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他登录设备会收到 `onMultiDeviceEvent` 事件,事件名分别为 `pinnedConversation` 和 `unpinnedConversation` 事件。 + +你最多可以置顶 50 个会话。 + +示例代码如下: + +```javascript +connection.pinConversation({conversationId:'conversationId', conversationType: 'singleChat', isPinned: true}) +``` + +### 获取服务端的置顶会话列表 + +你可以调用 `getServerPinnedConversations` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 + +你最多可以拉取 50 个置顶会话。 + +示例代码如下,返回数据类型参见[从服务器分页获取会话列表](conversation_list#从服务器分页获取会话列表)。 + +```javascript +// pageSize: 每页返回的会话数。取值范围为 [1,50]。 +// cursor:开始获取数据的游标位置。若传空字符串(''),SDK 从最新置顶的会话开始查询。 +connection.getServerPinnedConversations({pageSize:50, cursor: ''}) +``` + diff --git a/docs/document/web/demo_vue.md b/docs/document/web/demo_vue.md index a63796147..1192213d9 100644 --- a/docs/document/web/demo_vue.md +++ b/docs/document/web/demo_vue.md @@ -22,6 +22,7 @@ - Vue 2 下载源代码:[github 源码地址](https://github.com/easemob/webim-vue-demo/tree/dev-4.0) - Vue 3 下载源代码:[github 源码地址](https://github.com/easemob/webim-vue-demo/tree/demo-vue3) +- Vue 3(miniCore) 下载源码:[github 源码地址](https://github.com/easemob/webim-vue-demo/tree/vue3-miniCore) **miniCore 版本提供 WebIM SDK 按需引入示例以及本地会话使用方式示例,后续新功能将在此版本添加**。 欢迎大家提交 PR 改进和修复 Web IM 中的问题。 diff --git a/docs/document/web/group_attributes.md b/docs/document/web/group_attributes.md index 0bde21297..6f63bc2ab 100644 --- a/docs/document/web/group_attributes.md +++ b/docs/document/web/group_attributes.md @@ -72,7 +72,7 @@ conn.updateGroupAnnouncement(option).then(res => console.log(res)) #### 上传共享文件 -所有群组成员均可调用 `uploadGroupSharedFile` 方法上传共享文件至群组,群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `uploadFile` 事件。 +所有群组成员均可调用 `uploadGroupSharedFile` 方法上传共享文件至群组,单个群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `uploadFile` 事件。 ```javaScript let option = { diff --git a/docs/document/web/group_manage.md b/docs/document/web/group_manage.md index c05afa34a..cd225f7c1 100644 --- a/docs/document/web/group_manage.md +++ b/docs/document/web/group_manage.md @@ -44,7 +44,7 @@ | `approval` | Bool | 入群申请是否需群主或管理员审批:
- `true`:需要;
- `false`:不需要。
由于私有群不支持用户申请入群,只能通过邀请方式进群,因此该参数仅对公开群有效,即 `public` 设置为 `true` 时,对私有群无效。 | | `allowinvites` | Bool | 是否允许普通群成员邀请人入群:
- `true`:允许;
- `false`:不允许。只有群主和管理员才可以向群组添加用户。
该参数仅对私有群有效,即 `public` 设置为 `false` 时, 因为公开群(public:`true`)仅支持群主和群管理员邀请人入群,不支持普通群成员邀请人入群。 | | `inviteNeedConfirm` | Bool | 邀请加群时是否需要受邀用户确认:
- `true`:受邀用户需同意才会加入群组;
- `false`:受邀用户直接加入群组,无需确认。 | -| `maxusers` | Int | 群组最大成员数,默认为 `200`。不同套餐支持的人数上限不同,详见 [产品价格](https://www.easemob.com/pricing/im)。 | +| `maxusers` | Int | 群组最大成员数,默认为 `200`。不同套餐支持的人数上限不同,详见 [产品价格](/product/pricing.html#套餐包功能详情)。 | | `ext` | String | 群组扩展信息,例如可以给群组添加业务相关的标记,不要超过 1,024 字符。 | 创建群组的示例代码如下: @@ -114,13 +114,17 @@ conn.destroyGroup(option).then((res) => console.log(res)); ### 获取群组详情信息 -所有群成员均可调用 `getGroupInfo` 方法根据群组 ID 获取群组详情,包括群组 ID、群组名称、群组描述、群组基本属性、群主、群组管理员列表、、是否已屏蔽群组消息以及群组是否禁用。默认不包含群成员列表。 +所有群成员均可调用 `getGroupInfo` 方法根据群组 ID 获取单个或多个群组的详情,包括群组 ID、群组名称、群组描述、群组基本属性、群成员列表、是否已屏蔽群组消息以及群组是否禁用。 + +:::tip +对于公有群,用户即使不加入群也能获取群组详情,而对于私有群,用户只有加入了群组才能获取群详情。 +::: 示例代码如下: ```javascript let option = { - // 群组 ID 或群组 ID 数组。 + // 单个群组 ID 或群组 ID 数组。 groupId: "groupId", }; conn.getGroupInfo(option).then((res) => { diff --git a/docs/document/web/group_members.md b/docs/document/web/group_members.md index f3082c9f1..ecfe9657b 100644 --- a/docs/document/web/group_members.md +++ b/docs/document/web/group_members.md @@ -91,9 +91,9 @@ conn.leaveGroup(option).then(res => console.log(res)) #### 群成员被移出群组 -仅群主和群管理员可以调用 `removeGroupMember` 方法将指定成员移出群组。被踢出群组后,被踢群成员将会收到 `removeMember` 事件,其他成员会收到 `memberAbsence` 监听事件。被移出群组后,该用户还可以再次加入群组。 +仅群主和群管理员可以调用 `removeGroupMember` 或 `removeGroupMembers` 方法将指定的单个成员或多个成员移出群组。被踢出群组后,被踢群成员会收到 `removeMember` 事件,其他成员会收到 `memberAbsence` 监听事件。被移出群组后,用户还可以再次加入群组。 -示例代码如下: +- 移出单个群成员,示例代码如下: ```javascript let option = { @@ -103,6 +103,12 @@ let option = { conn.removeGroupMember(option).then(res => console.log(res)) ``` +- 批量移出群成员,示例代码如下: + +```javascript +connection.removeGroupMembers({groupId: 'groupId', users: ['user1', 'user2']}) +``` + ### 管理群成员自定义属性 群成员可设置自定义属性(key-value),例如在群组中的昵称和头像等。 @@ -360,7 +366,7 @@ conn.getGroupBlocklist(option).then(res => console.log(res)) let option = { groupId: "groupId", username: "user1" || ["user1", "user2"], - muteDuration: 886400000 // 禁言时长,单位为毫秒。 + muteDuration: 886400000 // 禁言时长,单位为毫秒,传 -1 表示永久禁言。 }; conn.muteGroupMember(option).then(res => console.log(res)) ``` @@ -394,7 +400,9 @@ conn.getGroupMutelist(option).then(res => console.log(res)) #### 开启群组全员禁言 -仅群主和群管理员可以调用 `disableSendGroupMsg` 方法开启群组全员禁言。群组全员开启禁言后,群成员将会收到 `muteAllMembers` 事件,除群组白名单中的成员,其他成员将不能发言。 +仅群主和群管理员可以调用 `disableSendGroupMsg` 方法开启群组全员禁言。全员禁言开启后不会在一段时间内自动取消禁言,需要调用 `enableSendGroupMsg` 方法取消全员禁言。 + +群组全员开启禁言后,群成员将会收到 `muteAllMembers` 事件,除群组白名单中的成员,其他成员将不能发言。 示例代码如下: diff --git a/docs/document/web/message_delete.md b/docs/document/web/message_delete.md new file mode 100644 index 000000000..05902e260 --- /dev/null +++ b/docs/document/web/message_delete.md @@ -0,0 +1,58 @@ +# 删除消息 + + + +本文介绍用户如何单向清空本地和服务端的聊天记录和单向删除服务端的历史消息。 + +## 技术原理 + +利用环信即时通讯 IM SDK 可从服务器单向删除历史消息,主要方法如下: + +- `removeHistoryMessages`:单向删除服务端的历史消息。 +- `deleteAllMessagesAndConversations`:单向清空服务端的聊天记录,本地若有会话和消息,也会被清除。 + +## 前提条件 + +开始前,请确保已完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 + +## 实现方法 + +### 清空聊天记录 + +你可以调用 `deleteAllMessagesAndConversations` 方法单向清空服务端的当前用户的聊天记录,包括消息和会话。 + +若存在本地会话和消息,也会被清除。 + +该操作对其他用户不受该操作影响。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.5.0 或以上版本。 +::: + +```javascript +conn.deleteAllMessagesAndConversations().then(() => { + // 清除全部会话和消息记录成功 +}) +``` + +### 单向删除服务端的历史消息 + +你可以调用 `removeHistoryMessages` 方法按照时间或消息 ID 单向删除服务端的历史消息。每次最多可删除 20 条消息。消息删除后,该账号无法从服务端拉取到该消息。其他用户不受该操作影响。 + +多端多设备登录时,删除成功后会触发 `onMultiDeviceEvent#deleteRoaming` 回调。 + +:::tip +若使用该功能,需将 SDK 升级至 V4.1.2 或以上版本并联系商务开通。 +::: + +示例代码如下: + +```javascript +// 按时间删除消息 +connection.removeHistoryMessages({targetId: 'userId', chatType: 'singleChat', beforeTimeStamp: Date.now()}) + +// 按消息 ID 删除消息 +connection.removeHistoryMessages({targetId: 'userId', chatType: 'singleChat', messageIds: ['messageId']}) +``` + + diff --git a/docs/document/web/message_deliver_only_online.md b/docs/document/web/message_deliver_only_online.md new file mode 100644 index 000000000..802da546e --- /dev/null +++ b/docs/document/web/message_deliver_only_online.md @@ -0,0 +1,53 @@ +# 消息仅投递在线用户 + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 技术原理 + +环信即时通讯 IM 通过 `Message` 类支持只将消息投递给在线用户: + +- `deliverOnlineOnly`:设置消息是否只投递给在线用户。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +要将消息只投递给在线用户,你需要在发送消息时将 `Message#deliverOnlineOnly` 设置为 `true`。 + +下面以发送文本消息为例进行说明: + +```javascript +// 发送文本消息。 +function sendTextMessage() { + let option = { + // 消息类型。 + type: "txt", + // 消息内容。 + msg: "message content", + // 消息接收方:单聊为对方用户 ID,群聊为群组 ID。 + to: "username", + // 会话类型:单聊和群聊分别为 `singleChat` 和 `groupChat`,默认为单聊。 + chatType: "singleChat", + // 消息是否只投递在线用户。(默认)`false`:不论用户是否在线均投递;`true`:只投递给在线用户。若用户离线,消息投递失败。 + deliverOnlineOnly: "true", + }; + // 创建文本消息。 + let msg = WebIM.message.create(option); + // 调用 `send` 方法发送该文本消息。 + conn.send(msg).then((res)=>{ + console.log("Send message success",res); + }).catch((e)=>{ + console.log("Send message fail",e); + }); +} +``` diff --git a/docs/document/web/message_modify.md b/docs/document/web/message_modify.md index b467f35f1..84ba7e907 100644 --- a/docs/document/web/message_modify.md +++ b/docs/document/web/message_modify.md @@ -1,6 +1,15 @@ # 修改消息 -对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。消息内容修改流程如下: +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。 + +:::tip +1. 若使用该功能,需将 SDK 升级至 4.2.0 或以上版本。 +2. 聊天室会话不支持消息修改功能。 +::: + +## 技术原理 + +消息内容修改流程如下: 1. 用户调用 SDK 的 API 修改一条消息。 2. 服务端存储的该条消息,修改成功后回调给 SDK。 @@ -13,10 +22,14 @@ - 对于单聊会话,只有消息发送方才能对消息进行修改。 - 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -:::notice -1. 若使用该功能,需将 SDK 升级至 4.2.0 或以上版本。 -2. 聊天室会话不支持消息修改功能。 -::: +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 你可以调用 `modifyMessage` 方法修改已经发送成功的消息。一条消息默认最多可修改 10 次,若要提升修改次数,需联系商务。 diff --git a/docs/document/web/message_overview.md b/docs/document/web/message_overview.md index 212331d86..80d590ec7 100644 --- a/docs/document/web/message_overview.md +++ b/docs/document/web/message_overview.md @@ -2,51 +2,106 @@ -## 功能描述 - 环信即时通讯 IM 支持多种消息类型,开发者可以方便地对本地会话、消息进行管理,可以从服务端获取历史会话和消息,提供送达回执和已读回执能力。 -消息:环信即时通讯 IM 中消息(Message)表示发送方给接收方发送的内容,消息包括多种类型,如:文本、图片、语音等。 +消息:环信即时通讯 IM 中消息表示发送方给接收方发送的内容,消息包括多种类型,如:文本、图片、语音等。 -会话:环信即时通讯 IM 中会话(Conversation)分为 3 种,单聊、群聊、聊天室会话。单聊是指 2 个用户建立的会话,双方可以在会话中收发消息。群聊会话是由群成员发送消息所组成的,群成员可以在群会话中收发消息。聊天室会话与群聊会话类似。 +会话:环信即时通讯 IM 中会话分为 3 种,单聊、群聊、聊天室会话。单聊是指 2 个用户建立的会话,双方可以在会话中收发消息。群聊会话是由群成员发送消息所组成的,群成员可以在群会话中收发消息。聊天室会话与群聊会话类似。 -### 消息类型 +## 消息类型 -| 类型
| 描述 | -| :------------- | :----------------------------------------------------------- | -| 文本消息 | 文本消息的内容是文本,可以包含超链接、emoji 表情符号等。表情消息是基于文本消息实现的。
文本消息大小限制为 3 KB。 | -| 图片消息 | 图片消息是附件消息,需要先将图片上传至消息服务器。接收方收到图片时自动下载图片缩略图。
图片消息大小限制为 10 MB。 | -| 语音消息 | 语音消息是附件消息,需要先将语音上传至消息服务器。接收方收到语音时自动下载语音。
语音消息大小限制为 10 MB。 | -| 视频消息 | 视频消息是附件消息,需要先将视频上传至消息服务器。接收方收到视频时自动下载视频缩略图,点击下载视频消息。
视频消息大小限制为 10 MB。 | -| 文件消息 | 文件消息是附件消息,需要先将文件上传至消息服务器。接收方收到文件时自动下载文件。
文件消息大小限制为 10 MB。 | +| 类型
| 描述 | +| :------------- | :------------------------- | +| 文本消息 | 文本消息的内容是文本,可以包含超链接、emoji 表情符号等。表情消息是基于文本消息实现的。
文本消息大小限制为 5 KB。 | +| 图片消息 | 图片消息是附件消息,需要先将图片上传至消息服务器。接收方收到图片时自动下载图片缩略图。
图片不能超过 10 MB,图片消息大小限制为 5 KB。 | +| 语音消息 | 语音消息是附件消息,需要先将语音上传至消息服务器。接收方收到语音时自动下载语音。
音频文件不能超过 10 MB,音频消息大小限制为 5 KB。 | +| 视频消息 | 视频消息是附件消息,需要先将视频上传至消息服务器。接收方收到视频时自动下载视频缩略图,点击下载视频消息。
视频文件不能超过 10 MB,视频消息大小限制为 5 KB。 | +| 文件消息 | 文件消息是附件消息,需要先将文件上传至消息服务器。接收方收到文件时自动下载文件。
附件大小不能超过 10 MB,文件消息大小限制为 5 KB。 | | 位置消息 | 位置消息需要第三方的地图服务提供经纬度信息。接收方接收到位置消息,通过经纬度信息可以在第三方的地图服务中显示位置。 | -| 透传消息 | 透传消息可视为命令消息,通过发送这条命令给对方,通知对方要执行的操作,对方收到消息后系统可以自定义处理。透传消息不会在 UI 上展示。
消息大小显示为 3 KB。
透传消息的使用场景:头像、昵称的更新、状态同步等。
透传消息不会存入本地数据库。 | +| 透传消息 | 透传消息可视为命令消息,通过发送这条命令给对方,通知对方要执行的操作,对方收到消息后系统可以自定义处理。透传消息不会在 UI 上展示。
消息大小限制为 5 KB。
透传消息的使用场景:头像、昵称的更新、状态同步等。
透传消息不会存入本地数据库。 | | 消息自定义扩展 | 当基础的消息类型不满足需求时,可以使用消息自定义扩展增强基础消息类型。
使用扩展后,消息大小不能超过原类型消息的大小。
消息自定义扩展的使用场景:消息中需要携带被回复的消息内容和图文消息等。 | -| 自定义消息 | 开发者自定义的消息类型。自定义消息支持设置类型名称,开发者可以添加多种自定义消息。
自定义消息大小限制为 3 KB。
自定义消息的使用场景:红包消息、模板消息等。 | +| 自定义消息 | 开发者自定义的消息类型。自定义消息支持设置类型名称,开发者可以添加多种自定义消息。
自定义消息大小限制为 5 KB。
自定义消息的使用场景:红包消息、模板消息等。 | + +## 消息功能 + +Web 和小程序端无本地消息存储,只支持管理服务端消息。 + +- 发送和接收消息; +- 获取历史消息; +- 撤回消息; +- 修改消息; +- 删除消息; +- 实现消息回执; +- 翻译消息。 + +### [发送和接收消息](message_send_receive.html) + +用户可以在单聊、群聊、聊天室中发送如下类型的消息: +- 文字消息,包含超链接和表情消息。 +- 附件消息,包含图片、语音、视频及文件消息。 +- 位置消息。 +- 透传消息。 +- 自定义消息。 +- 合并消息。 +- 定向消息(只适用于群组聊天和聊天室聊天)。 + +当目前消息类型不满足用户需求时,可以在扩展部分保存更多信息,例如消息中需要携带被回复的消息内容或者是图文消息等场景。 + +### [获取历史消息](message_retrieve.html) + +从服务器获取指定会话的历史消息。 + +### [撤回消息](message_recall.html) + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除。 -### 消息功能 +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的功能配置 > 功能配置总览 > 基础功能页面设置消息撤回时长,该时长不超过 7 天。 -#### 管理本地会话和消息 +### [修改消息](message_modify.html) -Web 端暂无相关功能。 +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。聊天室会话不支持消息修改功能。 -#### 从服务器获取消息 +对于修改后的消息,消息体中除了内容变化,还新增了修改者的用户 ID、修改时间和修改次数属性。除消息体外,该消息的其他信息(例如,消息发送方、接收方和扩展属性)均不会发生变化。 -环信即时通讯 IM 在消息服务器保存历史消息,方便用户在新设备上获取历史消息。 -历史消息存储时间与套餐版本相关:专业版 7 天,旗舰版版 90 天, 尊享版 180 天。 +- 对于单聊会话,只有消息发送方才能对消息进行修改。 +- 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -| 功能 | 描述 | -| :------------------------- | :----------------------------------- | -| 从服务器获取会话 | 从服务端获取会话。 | -| 分页获取指定会话的历史消息 | 从服务端分页获取会话的历史消息。 | +### [删除消息](message_delete.html) -#### 获取消息的已读回执和送达回执 +单向删除服务端的历史消息:删除后,消息自动从设备本地移除且该用户无法从服务端拉取到该消息。其他用户不受该操作影响。每次最多可删除 50 条消息。 -环信即时通讯 IM 消息投递成功会返回送达回执,而且提供消息已读功能,接收方查看消息后会返回已读回执。 +登录该账号的其他设备会收到漫游消息删除回调。 + +### [实现消息回执](message_receipt.html) + +即时通讯 IM 消息投递成功会返回送达回执,而且提供消息已读功能,接收方查看消息后会返回已读回执。 | 功能 | 描述 | | :--------------- | :------------------------------------- | | 单聊消息送达回执 | 消息下发成功后,返回消息送达回执。 | | 单聊消息已读回执 | 接收方查看消息后,返回消息已读回执。 | | 单聊会话已读回执 | 接收方查看单聊会话后,返回会话已读回执。 | -| 群组消息已读回执 | 提供群组消息已读回执能力。 | \ No newline at end of file +| 群组消息已读回执 | 提供群组消息已读回执能力。 | + +### [翻译消息](message_translation.html) + +环信即时通讯 IM SDK 集成了 Microsoft Azure Translation API,支持在发送或接收消息时对文本消息进行按需翻译或自动翻译: + +- 按需翻译:接收方在收到文本消息后,将消息内容翻译为目标语言。 +- 自动翻译:发送方发送消息时,SDK 根据发送方设置的目标语言自动翻译文本内容,然后将消息原文和译文一起发送给接收方。 + +### [只投在线用户](message_deliver_only_online.html) + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。 该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 消息重发机制 + +发送消息时如果 WebSocket 已经断开正在进行重连时,重新连接后会重新发送消息;若 WebSocket 断开时发送消息,SDK 会提示网络断开连接导致消息发送失败的错误,即错误码 510 `MESSAGE_WEBSOCKET_DISCONNECTED`。 + diff --git a/docs/document/web/message_recall.md b/docs/document/web/message_recall.md new file mode 100644 index 000000000..953873165 --- /dev/null +++ b/docs/document/web/message_recall.md @@ -0,0 +1,60 @@ +# 撤回消息 + + + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能**页面设置消息撤回时长,该时长不超过 7 天。 + +## 技术原理 + +环信即时通讯 IM 支持你撤回一条发送成功的消息: + +- `recallMessage`:撤回一条发送成功的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 撤回消息 + +你可以调用 `recallMessage` 方法撤回一条发送成功的消息。 + +调用该方法后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `onRecallMessage` 事件。 + +```javascript +let option = { + // 要撤回消息的消息 ID。 + mid: "msgId", + // 消息接收方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。 + to: "username", + // 会话类型:单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`。 + chatType: "singleChat", +}; +conn.recallMessage(option) + .then((res) => { + console.log("success", res); + }) + .catch((error) => { + // 消息撤回失败,原因可能是超过了撤销时限(超过 2 分钟)。 + console.log("fail", error); + }); +``` + +### 设置消息撤回监听 + +你可以设置消息撤回监听,通过 `onRecallMessage` 监听消息撤回状态。 + +```javascript +conn.addEventHandler('MESSAGES',{ + onRecallMessage: (msg) => { + // 这里需要在本地删除对应的消息,也可以插入一条消息:“XXX撤回一条消息”。 + console.log('Recalling the message success',msg) + } +}) +``` \ No newline at end of file diff --git a/docs/document/web/message_receipt.md b/docs/document/web/message_receipt.md index c0c913fc1..0d62bfce5 100644 --- a/docs/document/web/message_receipt.md +++ b/docs/document/web/message_receipt.md @@ -1,10 +1,10 @@ -# 消息回执 +# 实现消息回执 单聊会话支持消息送达回执、会话已读回执和消息已读回执,发送方发送消息后可及时了解接收方是否及时收到并阅读了信息,也可以了解整个会话是否已读。 -群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 本文介绍如何使用环信即时通讯 IM Web SDK 实现单聊和群聊的消息回执功能。 @@ -14,7 +14,7 @@ 单聊消息送达回执: -1. SDK 初始化时,用户将 [`Connection` 类中的 `delivery` 参数](https://docs-im-beta.easemob.com/jsdoc/classes/Connection.Connection-1.html)设置为 `true` 开启消息送达回执。 +1. SDK 初始化时,用户将 [`Connection` 类中的 `delivery` 参数](https://doc.easemob.com/jsdoc/classes/Connection.Connection-1.html)设置为 `true` 开启消息送达回执。 2. 发送方发送一条消息。 3. 接收方收到消息后,SDK 会自动向发送方发送送达回执。 4. 发送方通过监听 `onDeliveredMessage` 收到送达回执。 @@ -37,7 +37,7 @@ - 已经集成和初始化环信 IM SDK,并实现了注册账号和登录功能。详情请参见 [快速开始](quickstart.html)。 - 了解 [使用限制](/product/limitation.html) 中的 API 调用频率限制。 -- 群消息已读回执功能仅在环信 IM 旗舰版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +- 群消息已读回执功能仅在环信 IM 专业版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 ## 实现方法 @@ -104,6 +104,8 @@ conn.addEventHandler("customEvent", { ##### 消息已读回执 +单聊消息的已读回执有效期与消息在服务端的存储时间一致,即在服务器存储消息期间均可发送已读回执。消息在服务端的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + 参考如下步骤在单聊中实现消息已读回执。 1. 接收方发送消息已读回执。 @@ -147,7 +149,9 @@ conn.addEventHandler("customEvent", { 对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。 -仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊已读回执的有效期为 3 天,即群组中的消息发送时间超过 3 天,服务器不记录阅读该条消息的群组成员,也不会发送已读回执。 + +仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 1. 群主或群管理员发送消息时若需已读回执,需设置 `allowGroupAck` 为 `true`: diff --git a/docs/document/web/message_retrieve.md b/docs/document/web/message_retrieve.md index 7259cd408..46715eeb0 100644 --- a/docs/document/web/message_retrieve.md +++ b/docs/document/web/message_retrieve.md @@ -1,24 +1,16 @@ -# 管理服务端的会话和消息 +# 获取历史消息 -环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。本文介绍如何实现用户从消息服务器获取会话和消息。 +环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 -:::tip -本文介绍的功能均为增值服务,需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 - -::: +本文介绍环信即时通讯 IM SDK 如何从服务器获取历史消息。 ## 技术原理 -利用环信即时通讯 IM SDK 可从服务器获取会话和历史消息。 +利用环信即时通讯 IM SDK 可从服务器获取历史消息,主要方法如下: -- `getServerConversations` 分页获取会话列表以及会话中的最新一条消息; -- `getServerPinnedConversations` 获取服务端的置顶会话列表; -- `pinConversation` 设置是否置顶会话; -- `getHistoryMessages` 按服务器接收消息的时间顺序获取服务器上保存的指定会话中的消息; -- `removeHistoryMessages` 单向删除服务端的历史消息; -- `deleteConversation` 删除服务器端会话及其对应的消息。 +- `getHistoryMessages`:基于 `searchOptions` 参数对象从服务器获取指定会话的历史消息。 ## 前提条件 @@ -26,84 +18,34 @@ ## 实现方法 -### 从服务器分页获取会话列表 - -对于单聊或群聊,用户发消息时,会自动将对方添加到用户的会话列表。 - -你可以调用 `getServerConversations` 方法从服务端分页获取会话列表。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表。服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。 - -:::notice -1. 若使用该功能,需将 SDK 升级至 4.1.7 或以上版本。 -2. 登录用户的 ID 大小写混用会导致拉取会话列表时提示会话列表为空,因此建议用户 ID 使用小写字母。 -3. 服务端会话列表的更新存在延时,建议你仅在登录时调用该方法。 -4. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 -::: - -示例代码如下: - -```javascript -// pageSize: 每页期望获取的会话数量。取值范围为 [1,50],默认为 `20`。 -// cursor:开始获取数据的游标位置。若传空字符串(''),SDK从最新活跃的会话开始获取。 -connection.getServerConversations({pageSize:50, cursor: ''}).then((res)=>{ - console.log(res) -}) -``` -该方法的返回数据包含 `conversations` 和 `cursor` 参数: - -- conversations: 会话列表。`conversations` 为 `ConversationItem[]` 类型,`ConversationItem` 包含如下属性: - -| 属性名称 | 描述 | -| :--------- | :----- | -| `conversationId` | 会话 ID。 | -| `conversationType`| 会话类型。| -| `isPinned` | 是否置顶:
- `true`:置顶;
- `false`:不置顶。 | -| `pinnedTime`| 会话置顶的 UNIX 时间戳,单位为毫秒。未置顶时值为 `0` | -| `lastMessage` | 最新一条消息概况。 | -| `unReadCount` | 未读消息数。 | - -- cursor: 下次查询数据的游标位置。若 SDK 返回的数据条数小于请求中设置的数目,`cursor` 的值为空字符串(''),表示当前为最后一页数据。否则,SDK 返回具体的游标位置,指定开始获取数据的位置。 - -### 获取服务端的置顶会话列表 - -你可以调用 `getServerPinnedConversations` 方法从服务端分页获取置顶会话列表。SDK 按照会话置顶时间的倒序返回。 - -你最多可以拉取 50 个置顶会话。 - -:::notice -若使用该功能,需将 SDK 升级至 4.1.7 或以上版本。 -::: - -示例代码如下,返回数据类型参见getServerConversations: - -```javascript -// pageSize: 每页返回的会话数。取值范围为 [1,50]。 -// cursor:开始获取数据的游标位置。若传空字符串(''),SDK 从最新置顶的会话开始查询。 -connection.getServerPinnedConversations({pageSize:50, cursor: ''}) -``` - -该方法的返回数据与[获取服务端的会话列表](#从服务器分页获取会话列表)相同。 - -### 置顶会话 - -会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 +### 从服务器获取指定会话的历史消息 -置顶状态会存储在服务器上,多设备登录情况下,更新置顶状态会同步到其他登录设备。你最多可以置顶 50 个会话。 +你可以调用 `getHistoryMessages` 方法基于 `searchOptions` 参数对象允许用户按消息发送方、消息类型或时间段从服务器分页拉取单聊和群组聊天的历史消息。为确保数据可靠,我们建议你每次最多获取 50 条消息,可多次获取。 -你可以调用 `pinConversation` 方法设置是否置顶会话。多设备登录情况下,会话置顶或取消置顶后,其他登录设备会收到 `onMultiDeviceEvent` 事件,事件名分别为 `pinnedConversation` 和 `unpinnedConversation` 事件。 +对于群组聊天,你可以通过设置 `searchOptions` 对象中的 `from` 参数拉取群组中单个成员发送的历史消息。 -:::notice -若使用该功能,需将 SDK 升级至 4.1.7 或以上版本。 +:::tip +1. 若使用该 API,需将 SDK 版本升级至 V4.1.6 版本或以上。 +2. 历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +3. 各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 ::: -示例代码如下: - ```javascript -connection.pinConversation({conversationId:'conversationId', conversationType: 'singleChat', isPinned: true}) +connection.getHistoryMessages({ + targetId: 'targetId', // 单聊为对端用户 ID,群组聊天为群组 ID。 + chatType: 'groupChat', // 会话类型:单聊和群组聊天分别为 `singleChat` 和 `groupChat`。 + pageSize: 20, // 每次获取的消息数量,取值范围为 [1,50],默认值为 `20`。 + searchDirection: 'down', // 消息搜索方向。`up` 表示按消息时间戳递减的方向获取,即先获取最新消息;`down` 表示按消息时间戳递增的方向获取,即先获取最老的消息。 + searchOptions: { + from: 'message sender userID', // 消息发送方的用户 ID。该参数仅用于群组聊天。 + msgTypes: ['txt'], // 要获取的消息类型的数组。若不传值,会获取所有类型的消息。 + startTime: new Date('2023,11,9').getTime(), // 查询的起始时间戳,单位为毫秒。 + endTime: new Date('2023,11,10').getTime(), // 查询的结束时间戳,单位为毫秒。 + }, +}); ``` -### 从服务器获取指定会话的历史消息 - -你可以调用 `getHistoryMessages` 方法从服务器获取指定会话的消息(消息漫游)。你可以指定消息查询方向,即明确按时间顺序或逆序获取。为确保数据可靠,我们建议你每次最多获取 50 条消息,可多次获取。拉取后,SDK 会自动将消息更新到本地数据库。 +同时,你可以调用 `getHistoryMessages` 方法从服务器获取指定会话的历史消息。你可以指定消息查询方向,即明确按时间顺序或逆序获取。 ```javascript let options = { @@ -129,44 +71,4 @@ WebIM.conn }); ``` -### 单向删除服务端的历史消息 - -你可以调用 `removeHistoryMessages` 方法按照时间或消息 ID 单向删除服务端的历史消息。每次最多可删除 20 条消息。消息删除后,该账号无法从服务端拉取到该消息。其他用户不受该操作影响。多端多设备登录时,删除成功后会触发 `onMultiDeviceEvent#deleteRoaming` 回调。 - -:::tip -若使用该功能,需将 SDK 升级至 V4.1.2 或以上版本并联系商务开通。 -::: - -示例代码如下: - -```javascript -// 按时间删除消息 -connection.removeHistoryMessages({targetId: 'userId', chatType: 'singleChat', beforeTimeStamp: Date.now()}) - -// 按消息 ID 删除消息 -connection.removeHistoryMessages({targetId: 'userId', chatType: 'singleChat', messageIds: ['messageId']}) -``` - -### 删除服务器端会话及其对应的消息 -你可以调用 `deleteConversation` 方法删除服务器端会话及其对应的消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,其他用户不受影响。 - -```javascript - -let options = { - // 会话 ID:单聊为对方的用户 ID,群聊为群组 ID。 - channel: "channel", - // 会话类型:(默认) `singleChat`:单聊;`groupChat`:群聊。 - chatType: "singleChat", - // 删除会话时是否同时删除服务端漫游消息。 - deleteRoam: true, -}; -WebIM.conn - .deleteConversation(options) - .then((res) => { - console.log(res); - }) - .catch((e) => { - // 删除失败。 - }); -``` diff --git a/docs/document/web/message_send_receive.md b/docs/document/web/message_send_receive.md index f1fc53023..fd0618c93 100644 --- a/docs/document/web/message_send_receive.md +++ b/docs/document/web/message_send_receive.md @@ -23,7 +23,7 @@ ## 技术原理 -环信即时通讯 IM Web SDK 可以实现消息的发送、接收与撤回。 +环信即时通讯 IM Web SDK 可以实现消息的发送和接收。 发送和接收消息: @@ -100,13 +100,15 @@ function sendTextMessage() { } ``` +若初始化时打开了 `useReplacedMessageContents` 开关,发送文本消息时如果被内容审核(Moderation)进行了内容替换,发送方会收到替换后的内容。若该开关为关闭状态,则发送方不会收到替换后的内容。 + ### 接收消息 你可以通过 `addEventHandler` 注册监听器监听消息事件。你可以添加多个事件。当不再监听事件时,请确保删除监听器。 当消息到达时,接收方会收到 `onXXXMessage` 回调。每个回调包含一条或多条消息。你可以遍历消息列表,并可以解析和展示回调中的消息。 -对于聊天室消息,你可以通过消息的 `broadcast` 属性判断通过该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 +对于聊天室消息,你可以通过消息的 `broadcast` 属性判断该消息是否为[通过 REST API 发送的聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 ```javascript // 使用 `addEventHandler` 监听回调事件 @@ -164,55 +166,19 @@ conn.addEventHandler("eventName", { }); ``` -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)均会被移除,消息的接收方会收到 `onRecallMessage` 事件。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 - -```javascript -let option = { - // 要撤回消息的消息 ID。 - mid: "msgId", - // 消息接收方:单聊为对方用户 ID,群聊和聊天室分别为群组 ID 和聊天室 ID。 - to: "username", - // 会话类型:单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`。 - chatType: "singleChat", -}; -conn.recallMessage(option) - .then((res) => { - console.log("success", res); - }) - .catch((error) => { - // 消息撤回失败,原因可能是超过了撤销时限(超过 2 分钟)。 - console.log("fail", error); - }); -``` - -你还可以使用 `onRecallMessage` 监听消息撤回状态: - -```javascript -conn.addEventHandler('MESSAGES',{ - onRecallMessage: (msg) => { - // 这里需要在本地删除对应的消息,也可以插入一条消息:“XXX撤回一条消息”。 - console.log('Recalling the message success',msg) - } -}) -``` - ### 发送附件消息 语音、图片、视频和文件消息本质上是附件消息。发送和接收附件消息的流程如下: 1. 创建和发送附件类型消息。SDK 将附件上传到环信服务器,获取消息的基本信息以及服务器上附件文件的路径。 - 对于图片消息来说,环信服务器会自动生成图片缩略图;而对于视频消息来说,服务器不会生成视频缩略图。 + 对于图片消息来说,环信服务器会自动生成图片缩略图;而对于视频消息来说,视频的首帧为缩略图。 2. 接收附件消息。 接收方可以自行下载语音、图片、图片缩略图、视频和文件。 -#### 发送语音消息 +#### 发送和接收语音消息 发送语音消息前,你应该在 app 级别实现录音,提供录制的语音文件的 URI 和时长。 @@ -270,7 +236,21 @@ function sendPrivateAudio() { } ``` -#### 发送图片消息 +接收方收到 `onAudioMessage` 回调,根据消息 `url` 字段获取语音文件的服务器地址,从而获取语音文件。 + +```javascript +// 使用 `addEventHandler` 监听回调事件 +conn.addEventHandler("eventName", { + // 当前用户收到语音消息。 + onAudioMessage: function (message) { + // 语音文件在服务器的地址。 + console.log(message.url); + }, +}); + +``` + +#### 发送和接收图片消息 对于图片消息,服务器会根据用户设置的 `thumbnailHeight` 和 `thumbnailWidth` 参数自动生成图片的缩略图。若这两个参数未传,则图片的高度和宽度均默认为 170 像素。你也可以在 [环信即时通讯控制台](https://console.easemob.com/user/login)的 `服务概览` 页面的 `设置` 区域修改该默认值。 @@ -332,11 +312,27 @@ function sendPrivateImg() { } ``` +接收方收到 `onImageMessage` 回调,根据消息 `url` 字段获取图片文件的服务器地址,从而获取图片文件。 + +```javascript +// 使用 `addEventHandler` 监听回调事件 +conn.addEventHandler("eventName", { + // 当前用户收到图片消息。 + onImageMessage: function (message) { + // 图片文件在服务器的地址。 + console.log(message.url); + // 图片缩略图文件在服务器的地址。 + console.log(message.thumb); + }, +}); + +``` + #### 发送 URL 图片消息 你也可以将图片上传到自己的服务器,而不是环信服务器,然后调用 `sendPrivateUrlImg` 方法传入图片的 URL 发送图片消息。 -发送 URL 图片消息之前,确保在 SDK 初始化时将 [`Connection` 类中的 `useOwnUploadFun` 参数](https://docs-im-beta.easemob.com/jsdoc/classes/Connection.Connection-1.html)设置为 `true`。 +发送 URL 图片消息之前,确保在 SDK 初始化时将 [`Connection` 类中的 `useOwnUploadFun` 参数](https://doc.easemob.com/jsdoc/classes/Connection.Connection-1.html)设置为 `true`。 ```javascript function sendPrivateUrlImg() { @@ -356,7 +352,7 @@ function sendPrivateUrlImg() { } ``` -#### 发送视频消息 +#### 发送和接收视频消息 在发送视频消息之前,应在 app 级别实现视频捕获,获得捕获的视频文件的时长,单位为秒。 @@ -414,7 +410,23 @@ function sendPrivateVideo() { } ``` -#### 发送文件消息 +接收方收到 `onVideoMessage` 回调,根据消息 `url` 字段获取视频文件的服务器地址,从而获取视频文件。 + +```javascript +// 使用 `addEventHandler` 监听回调事件 +conn.addEventHandler("eventName", { + // 当前用户收到视频消息。 + onVideoMessage: function (message) { + // 视频文件在服务器的地址。 + console.log(message.url); + // 视频首帧缩略图文件在服务器的地址。 + console.log(message.thumb); + }, +}); + +``` + +#### 发送和接收文件消息 参考以下代码示例创建、发送和接收文件消息: @@ -473,6 +485,20 @@ function sendPrivateFile() { } ``` +接收方收到 `onFileMessage` 回调,根据消息 `url` 字段获取文件的服务器地址,从而获取文件。 + +```javascript +// 使用 `addEventHandler` 监听回调事件 +conn.addEventHandler("eventName", { + // 当前用户收到文件消息。 + onFileMessage: function (message) { + // 文件在服务器的地址。 + console.log(message.url); + }, +}); + +``` + ### 发送位置消息 当你需要发送位置时,需要集成第三方的地图服务,获取到位置点的经纬度信息。接收方接收到位置消息时,需要将该位置的经纬度,借由第三方的地图服务,将位置在地图上显示出来。 diff --git a/docs/document/web/message_translation.md b/docs/document/web/message_translation.md index eed726178..52034f891 100644 --- a/docs/document/web/message_translation.md +++ b/docs/document/web/message_translation.md @@ -38,7 +38,7 @@ conn.getSupportedLanguages().then(res => console.log(res)) 接收方调用 `translateMessage` 将接收到的消息翻译成目标语言。示例代码如下: ```javascript -conn.translateMessage('hello', ['zh']).then(res => console.log(res)) +conn.translateMessage({text: 'hello', languages: [zh-Hans]}) ``` ### 自动翻译 @@ -54,7 +54,7 @@ let option = { type: 'txt', to: 'userId', msg: 'hello', - msgConfig:{ languages: ['zh'] } // 设置目标语言。 + msgConfig:{ languages: ['zh-Hans'] } // 设置目标语言。 } let msg = WebIM.message.create(option); conn.send(msg) diff --git a/docs/document/web/moderation.md b/docs/document/web/moderation.md index 363e82b6b..0fcc4bec5 100644 --- a/docs/document/web/moderation.md +++ b/docs/document/web/moderation.md @@ -2,7 +2,14 @@ -即时通讯 IM SDK 提供消息举报接口。开发者可以在客户端调用该接口举报违规消息。当服务器端审核服务收到举报消息后,会将举报消息存储到数据库,并在 Console 展示。审核员可在 Console 查看举报记录,并进行相应处理。 +即时通讯 IM SDK 提供消息举报接口。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +:::tip +1. 使用前,你需要在[环信即时通讯云控制台](https://console.easemob.com/user/login) 开通该功能。 +2. 消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +关于如何开通消息举报和查看举报记录,详见[环信即时通讯云控制台文档说明](/product/enable_and_configure_IM.html#消息举报)。 ## 技术原理 @@ -13,7 +20,7 @@ 开始前,请确保满足以下条件: - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 已在 [环信即时通讯云控制台](https://console.easemob.com/user/login) 开通消息审核服务。 +- 已在 [环信即时通讯云控制台开通消息举报功能](/product/enable_and_configure_IM.html#消息举报)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 @@ -23,7 +30,7 @@ ```javascript connection.reportMessage({ reportType: 'report type', // 非法消息的标签。你需要自定义标签,例如`涉政`或`广告`。该字段对应环信即时通讯云控制台的消息举报记录页面的`词条标记`字段。 - reportReason: 'report reason', // 举报原因。你需要自行填写举报原因。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 + reportReason: 'report reason', // 举报原因。你需要自行填写举报原因,最长不能超过 512 字节。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 messageId: 'ID of the reported message' // 要举报的消息 ID。 }) ``` \ No newline at end of file diff --git a/docs/document/web/multi_device.md b/docs/document/web/multi_device.md index ada57983b..fdb84f66d 100644 --- a/docs/document/web/multi_device.md +++ b/docs/document/web/multi_device.md @@ -26,10 +26,33 @@ 即时通讯 IM Web SDK 在用户每次登录时会生成一个新的唯一的登录 ID,并将该 ID 发送到服务器。服务器会自动将新消息发送到用户登录的设备,可以自动监听到其他设备上进行的好友或群组操作。 -Web 端不存在用户获取其他登录设备的设备 ID 的 API,因此不支持查询其他同时登录的设备,也无法了解这些设备上进行的操作。 - ## 实现方法 +### 获取当前用户的其他登录设备的登录 ID 列表 + +你可以调用 `getSelfIdsOnOtherPlatform` 方法获取其他登录设备的登录 ID 列表。选择目标登录 ID 作为消息接收方发出消息,则这些设备上的同一登录账号可以收到消息,实现不同设备之间的消息同步。 + +```javascript +conn.getSelfIdsOnOtherPlatform().then((res) => { + console.log(res, '获取当前用户其他登录设备的登录 Id 列表成功'); + // 选择一个登录 ID 作为消息接收方。 + const toUserId = res.data[0]; + // toUserId 作为消息接收方。 + let option = { + type: "txt", + msg: "message content", + to: toUserId, + chatType: "singleChat", + }; + // 创建消息。 + const msg = WebIM.message.create(option); + // 发送消息。 + conn.send(msg); +}) +``` + +### 获取其他设备上的操作 + 你需要调用 `addEventHandler` 方法注册监听事件,监听其他设备上的操作。服务器同步信息之后,SDK 会回调这些事件,Web 端与其他端均会收到好友和群组相关操作的通知。 对于好友和群组的相关操作来说,多设备事件与单设备事件的名称相同,唯一区别在于事件中的 `from` 字段,即多端多设备事件中该字段的值为当前用户的用户 ID,而单设备事件中,该字段的值为操作方的用户 ID。详见[群组事件](group_manage.html#监听群组事件)和[用户关系事件](user_relationship.html#添加好友)。 @@ -61,20 +84,26 @@ conn.addEventHandler("handlerId", { //当前用户在其他设备上删除了服务端的会话。 break; case "memberAttributesUpdate": - // 群成员属性更新 + //当前用户在其他设备上更新了群成员属性。 break; case "deleteRoaming": - // 删除历史消息 + //当前用户在其他设备上删除历史消息。 break; case "deleteConversation": - // 删除会话 + //当前用户在其他设备上删除会话。 break; case "pinnedConversation": - // 置顶会话 + //当前用户在其他设备上置顶会话。 break; case "unpinnedConversation": - // 取消置顶会话 + //当前用户在其他设备上取消置顶会话。 + break; + case "markConversation": + //当前用户在其他设备上标记会话。 break; + case "unMarkConversation": + //当前用户在其他设备上取消标记会话。 + break; default: break; } diff --git a/docs/document/web/overview.md b/docs/document/web/overview.md index 3f79f82e0..e608a6d49 100644 --- a/docs/document/web/overview.md +++ b/docs/document/web/overview.md @@ -14,18 +14,50 @@ ## 引入 SDK -对于 JavaScript SDK,导入代码如下: +- 对于 JavaScript SDK,导入代码如下: ```javascript import EC from "easemob-websdk"; ``` -对于 TypeScript SDK,导入代码如下, EasemobChat 是 SDK 类型的命名空间。 +- 对于 TypeScript SDK,导入代码如下, EasemobChat 是 SDK 类型的命名空间。 ```javascript import EC, { EasemobChat } from "easemob-websdk"; ``` +- 对于服务端渲染框架, 如 Nuxt、Next 等,需要在客户端渲染阶段引入 SDK。 + +Nuxt 项目, 你可以在 mounted 生命周期动态导入 SDK: + +```javascript +export default { + mounted: () => { + import("easemob-websdk").then((res) => { + const EC = res.default; + console.log(EC, "easemob websdk"); + }); + } +}; +``` + +Next 项目, 要使用客户端组件,你可以在文件顶部的导入上方添加 `use client` 指令。 + +```tsx +'use client' + +import { useEffect } from 'react' + +export default function Home() { + useEffect(() => { + import('easemob-websdk').then((res)=>{ + const EC = res.default; + console.log(EC, "easemob websdk"); + }) + }, []) +} +``` + 如果对 SDK 大小有要求,可根据功能按需导入 SDK 文件。 | 功能 | 导入文件 | 使用方式 | diff --git a/docs/document/web/push.md b/docs/document/web/push.md index fcd6d3c84..91ea08e40 100644 --- a/docs/document/web/push.md +++ b/docs/document/web/push.md @@ -14,7 +14,7 @@ 环信 IM Web SDK 本身不支持离线推送,只支持对移动端离线推送进行如下配置: -- 设置推送通知,包含设置推送通知方式和免打扰模式。设置推送通知为推送的高级功能,使用前需要在环信控制台开启该功能。 +- 设置推送通知,包含设置推送通知方式和免打扰模式。设置推送通知为推送的高级功能,使用前需要在 [环信控制台](https://console.easemob.com/user/login)的**即时通讯 > 功能配置 > 功能配置总览**页面激活。如需关闭推送高级功能必须联系商务,因为该操作会删除所有相关配置。 - 设置推送翻译。 ## 技术原理 diff --git a/docs/document/web/reaction.md b/docs/document/web/reaction.md index 941f398d4..9834435cc 100644 --- a/docs/document/web/reaction.md +++ b/docs/document/web/reaction.md @@ -5,8 +5,7 @@ 环信即时通讯 IM 提供消息表情回复(下文统称 “Reaction”)功能。用户可以在单聊和群聊中对消息添加、删除表情。表情可以直观地表达情绪,利用 Reaction 可以提升用户的使用体验。同时在群组中,利用 Reaction 可以发起投票,根据不同表情的追加数量确认投票。 :::notice -1. 目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 -2. 私有化版本不支持 Reaction 功能。 +目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 ::: ## 技术原理 @@ -15,7 +14,7 @@ - `addReaction` 在消息上添加 Reaction; - `deleteReaction` 删除消息的 Reaction; -- `getReactionList` 获取消息的 Reaction 列表; +- `getReactionlist` 获取消息的 Reaction 列表; - `getReactionDetail` 获取 Reaction 详情; - `getHistoryMessages ` 获取漫游消息中的 Reaction。 @@ -77,11 +76,11 @@ conn.addEventHandler("REACTION", { ### 获取消息的 Reaction 列表 -调用 `getReactionList` 方法可以从服务器获取 Reaction 概览列表,列表内容包含 Reaction 内容,添加或移除 Reaction 的用户数量,以及添加或移除 Reaction 的前三个用户的用户 ID。示例代码如下: +调用 `getReactionlist` 方法可以从服务器获取 Reaction 概览列表,列表内容包含 Reaction 内容,添加或移除 Reaction 的用户数量,以及添加或移除 Reaction 的前三个用户的用户 ID。示例代码如下: ```javascript conn - .getReactionList({ chatType: "singleChat", messageId: "messageId" }) + .getReactionlist({ chatType: "singleChat", messageId: "messageId" }) .then((res) => { console.log(res); }); @@ -133,4 +132,4 @@ WebIM.conn // 获取失败。 }); -``` \ No newline at end of file +``` diff --git a/docs/document/web/releasenote.md b/docs/document/web/releasenote.md index 5dcbc5eed..9129d613a 100644 --- a/docs/document/web/releasenote.md +++ b/docs/document/web/releasenote.md @@ -2,11 +2,72 @@ -## 版本 V4.3.0 Dev 2023-11-17(开发版) +## 版本 V4.5.1 Dev 2024-02-22(开发版) + +### 优化 + +- [IM SDK] 统一消息附件的 URL 格式。 + +## 版本 V4.5.0 Dev 2024-01-30(开发版) + +### 新增特性 + +- [IM SDK] 聊天室和群组成员进出事件增加成员人数 `memberCount` 字段。 +- [IM SDK] 新增 [deleteAllMessagesAndConversations](message_delete.html#清空聊天记录) 方法,用于清空当前用户的聊天记录,包括消息和会话。 +- [IM SDK] 新增 [getSelfIdsOnOtherPlatform](multi_device.html#获取当前用户的其他登录设备的登录-id-列表) 方法,可以获取当前用户其他登录设备的登录 ID 列表,实现对指定设备发送消息。 +- [IM SDK] 新增 [useReplacedMessageContents](message_send_receive.html#发送文本消息) 开关。开启后,发送消息时如果被内容审核进行了内容替换,发送方可以获取替换后的内容。 + +### 优化 + +- [IM SDK] Web 本地数据库移除非必要唯一字段。 +- [IM SDK] 格式化会话列表中最近一条自定义消息的 `customExts` 字段。 +- [IM SDK] 重复拉消息问题。 + +### 修复 + +- [IM SDK] 修复 `onMessage` 回调消息顺序异常问题。 +- [IM SDK] 修复 vite electron 引入 MiniCore 插件报错。 +- [IM SDK] 修复 H5 引入微信 SDK 后,`updateOwnUserInfo` API 请求参数异常问题。 + +## 版本 V4.4.0 Dev 2023-12-22(开发版) + +### 新增特性 + +- [IM SDK] 新增[会话标记功能](conversation_mark.html)。 + - `addConversationMark`:[标记会话](conversation_mark.html#标记会话)。 + - `removeConversationMark`:[取消标记会话](conversation_mark.html#取消标记会话)。 + - `getServerConversationsByFilter`:[根据会话标记从服务器分页查询会话列表](conversation_mark.html#根据会话标记从服务器分页查询会话列表)。 + - `onMultiDeviceEvent#markConversation/unMarkConversation`:[多设备场景下的会话标记事件](multi_device.html#实现方法)。当前用户在一台登录设备上更新了会话标记,包括添加和移除会话标记,其他登录设备会收到该事件。 +- [IM SDK] 增加 `onMessage` 回调。在收到文本、图片、视频、语音、地理位置和文件等消息时,批量将消息回调给应用。 +- [IM SDK] 视频类型消息增加视频首帧缩略图, 通过 `videoMessage.thumb` 访问。 + +### 修复 + +- [IM SDK] SDK 类型修正。 +- [IM SDK] vite 引入 MiniCore SDK 报错。 +- [IM SDK] 优化附件类型消息发送时的附件上传,支持分片上传。 + +## 版本 V4.3.1 Dev 2023-12-13 + +### 新增特性 + +- [IM SDK] [发送消息方法 `Send`](message_send_receive.html#发送文本消息) 的成功回调参数 `SendMsgResult` 中新增 `message` 字段,用于返回成功发送的消息对象。 +- [IM SDK] MiniCore SDK 增加 logger 实例。 + +### 优化 + +- [IM SDK] 优化部分机型断网后 SDK 重连慢的问题。 + +### 修复 + +- [IM SDK] 修复 `isInGroupMutelist` API 调用时出现 404 的问题。 + +## 版本 V4.3.0 Dev 2023-11-17 ### 新增特性 -- [IM SDK] 新增[好友备注功能](user_relationship.html#设置好友备注)。 +- [IM SDK] 新增[设置好友备注功能](user_relationship.html#设置好友备注)。 +- [IM SDK] 新增 `getAllContacts` 和 `getContactsWithCursor` 方法分别用于[从服务器一次性和分页获取好友列表](user_relationship.html#获取好友列表),其中每个好友对象包含好友的用户 ID 和好友备注。 - [IM SDK] 消息结构新增 `broadcast` 字段, 用于判断该消息是否为聊天室全局广播消息。可通过[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 ### 优化 @@ -17,12 +78,11 @@ - [IM SDK] 修复会话列表最后一条消息中获取不到 `reaction` 的问题。 - -## 版本 V4.2.1 Dev 2023-09-27(开发版) +## 版本 V4.2.1 Dev 2023-09-27 ### 新增特性 -- [IM SDK] 新增 `LocalCache` 模块[实现本地会话数据管理](message_manage.html)。 +- [IM SDK] 新增 `LocalCache` 模块[实现本地会话数据管理](conversation_local.html)。 - [IM SDK] 用户申请加群被拒绝的回调 `joinPublicGroupDeclined` 中增加申请人的用户 ID。 ## 版本 V4.2.0 Dev 2023-07-27 @@ -40,9 +100,9 @@ ### 新增特性 -1. 新增 `pinConversation` 方法实现[会话置顶和取消置顶](message_retrieve.html#置顶会话)。 -2. 新增 `getServerPinnedConversations` 方法[分页获取服务器端的置顶会话列表](message_retrieve.html#获取服务端的置顶会话列表)。 -3. 新增 `getServerConversations` 方法[分页获取排序后的服务端会话列表](message_retrieve.html#从服务器分页获取会话列表)。 +1. 新增 `pinConversation` 方法实现[会话置顶和取消置顶](conversation_pin.html#置顶会话)。 +2. 新增 `getServerPinnedConversations` 方法[分页获取服务器端的置顶会话列表](conversation_pin.html#获取服务端的置顶会话列表)。 +3. 新增 `getServerConversations` 方法[分页获取排序后的服务端会话列表](conversation_list.html#从服务器分页获取会话列表)。原接口 `getConversationlist` 已废弃。 4. 新增[在群组或聊天室会话中发送定向消息](message_send_receive.html#发送定向消息)。通过在构建消息的方法 `create` 中添加 `receiverList` 参数实现该特性。 5. 在从服务器获取历史消息的方法 `getHistoryMessages` 的返回数据中新增 `isLast` 字段表示返回的是否为最后一页数据。 6. 在构建图片消息的方法 `create` 中新增 [`thumbnailWidth` 和 `thumbnailHeight`](message_send_receive.html#发送图片消息) 参数用于设置缩略图的宽度和高度。 @@ -61,7 +121,7 @@ ### 新增特性 -- [IM SDK] 新增 `searchOptions` 参数对象(包含 `from`、`msgTypes`、`startTime` 和 `endTime` 参数),允许用户调用 `getHistoryMessages` 方法时[按消息发送方、消息类型或时间段从服务端拉取历史消息](message_manage.html#在消息上添加-Reaction)。 +- [IM SDK] 新增 `searchOptions` 参数对象(包含 `from`、`msgTypes`、`startTime` 和 `endTime` 参数),允许用户调用 `getHistoryMessages` 方法时[按消息发送方、消息类型或时间段从服务端拉取历史消息](message_retrieve.html#从服务器获取指定会话的消息)。 - [IM SDK] 新增错误码 511,即 MESSAGE_SIZE_LIMIT,若[消息体大小超过限制](message_overview.html#消息类型)时提示用户。 ## 版本 V4.1.4 Dev 2023-03-16 @@ -85,7 +145,7 @@ #### 新增特性 -- [IM SDK] 在 `getConversationlist` 方法中新增分页参数 `pageNum` 和 `pageSize`,支持[分页方法获取会话列表](message_retrieve.html#从服务器分页获取会话列表)。 +- [IM SDK] 在 `getConversationlist` 方法中新增分页参数 `pageNum` 和 `pageSize`,支持[分页方法获取会话列表](conversation_list.html#从服务器分页获取会话列表)。 - [IM SDK] 新增[群组创建事件 `create`](group_manage.html#监听群组事件)。群组创建后,群主的其他设备会收到该事件。 #### 优化 @@ -163,7 +223,7 @@ ### 新增特性 -- [IM SDK] 新增群组事件回调 [onGroupEvent](https://docs-im-beta.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onGroupEvent) 和聊天室事件回调 [onChatroomEvent](https://docs-im-beta.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onChatroomEvent)。原回调可继续使用; +- [IM SDK] 新增群组事件回调 [onGroupEvent](https://doc.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onGroupEvent) 和聊天室事件回调 [onChatroomEvent](https://doc.easemob.com/jsdoc/interfaces/Types.EventHandlerType.EventHandlerType.html#onChatroomEvent)。原回调可继续使用; - [IM SDK] 新增群聊消息限流错误码 [MESSAGE_CURRENT_LIMITING](error.html) - [IM SDK] 邀请加入群聊回调 onGroupChange 返回中新增 群名称 参数值。 @@ -179,7 +239,7 @@ ### 新增特性: - [IM SDK] 新增消息子区(message thread)功能; -- [IM SDK] 新增 [getConversationlist](message_retrieve.html#从服务器获取消息) 方法解析会话中的最新一条消息; +- [IM SDK] 新增 [getConversationlist](conversation_list.html#从服务器分页获取会话列表) 方法解析会话中的最新一条消息; ### 优化: diff --git a/docs/document/web/room_manage.md b/docs/document/web/room_manage.md index 6aa4a94e8..e6db662a9 100644 --- a/docs/document/web/room_manage.md +++ b/docs/document/web/room_manage.md @@ -37,7 +37,7 @@ 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 可以调用 `createChatRoom` 方法创建聊天室,并设置聊天室的名称、描述、最大成员数等信息。成功创建聊天室后,该超级管理员为该聊天室的所有者。 -你也可以直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 +建议直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 示例代码如下: diff --git a/docs/document/web/room_members.md b/docs/document/web/room_members.md index 5817723cc..7e27c5765 100644 --- a/docs/document/web/room_members.md +++ b/docs/document/web/room_members.md @@ -44,7 +44,7 @@ conn.listChatRoomMembers(option).then(res => console.log(res)) #### 成员主动退出聊天室 -聊天室所有成员均可以调用 `leaveChatRoom` 退出当前聊天室。成员退出聊天室时,其他成员收到 `memberAbsence` 事件。与群主无法退出群组不同,聊天室所有者可以离开聊天室,如果所有者从服务器下线则 2 分钟后自动离开聊天室。如果所有者重新进入聊天室仍是该聊天室的所有者。 +聊天室所有成员均可以调用 `leaveChatRoom` 退出当前聊天室。成员退出聊天室时,其他成员收到 `memberAbsence` 事件。与群主无法退出群组不同,聊天室所有者可以离开聊天室,退出后重新进入仍是该聊天室的所有者。 示例代码如下: @@ -57,7 +57,7 @@ conn.leaveChatRoom(option).then(res => console.log(res)) #### 成员被移出聊天室 -仅聊天室所有者和聊天室管理员可以调用 `removeChatRoomMember` 方法将指定成员移出聊天室。被踢出聊天室后,被踢成员会收到 `removeMember` 事件,其他成员会收到 `memberAbsence` 事件。被移出聊天室后,该用户还可以再次加入聊天室。 +仅聊天室所有者和聊天室管理员可以调用 `removeChatRoomMember` 方法将指定的单个成员移出聊天室。被踢出聊天室后,被踢成员会收到 `removeMember` 事件,其他成员会收到 `memberAbsence` 事件。被移出聊天室后,该用户还可以再次加入聊天室。 示例代码如下: @@ -237,7 +237,10 @@ conn.unmuteChatRoomMember(option).then(res => console.log(res)) #### 开启全员禁言 -仅聊天室所有者和管理员可调用 `disableSendChatRoomMsg` 方法设置全员禁言。全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。调用成功后,聊天室成员会收到 `muteAllMembers` 事件。 +仅聊天室所有者和管理员可调用 `disableSendChatRoomMsg` 方法设置全员禁言。全员禁言开启后不会在一段时间内自动取消禁言,需要调用 `enableSendChatRoomMsg` 方法取消全员禁言。 + + +全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。调用成功后,聊天室成员会收到 `muteAllMembers` 事件。 示例代码如下: diff --git a/docs/document/web/thread.md b/docs/document/web/thread.md index ad3e45ecb..e9259a785 100644 --- a/docs/document/web/thread.md +++ b/docs/document/web/thread.md @@ -4,10 +4,6 @@ 子区是群组成员的子集,是支持多人沟通的即时通讯系统,本文介绍如何使用环信即时通讯 IM SDK 在实时互动 app 中创建和管理子区,并实现子区相关功能。 -:::notice -私有化版本不支持子区功能。 -::: - ## 技术原理 环信即时通讯 IM SDK 支持你通过调用 API 在项目中实现如下功能: diff --git a/docs/document/web/thread_message.md b/docs/document/web/thread_message.md index ecf271a27..ab8ccfc4e 100644 --- a/docs/document/web/thread_message.md +++ b/docs/document/web/thread_message.md @@ -92,7 +92,7 @@ connection.addEventHandler('THREADMESSAGE',{ ### 撤回子区消息 -撤回子区消息和撤回群组消息的方法基本一致,详情请参考 [撤回消息](message_send_receive.html#撤回消息)。唯一不同的是,撤回子区消息需要指定标记 `isChatThread` 为 `true`。 +撤回子区消息和撤回群组消息的方法基本一致,详情请参考 [撤回消息](message_recall.html)。唯一不同的是,撤回子区消息需要指定标记 `isChatThread` 为 `true`。 子区成员可以设置消息监听回调 `onRecallMessage` 对子区消息的撤回进行监听。 diff --git a/docs/document/web/user_relationship.md b/docs/document/web/user_relationship.md index 4bbc1225d..68bef4978 100644 --- a/docs/document/web/user_relationship.md +++ b/docs/document/web/user_relationship.md @@ -3,7 +3,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理: -- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请和删除好友等操作。 +- 好友列表管理:查询好友列表、申请添加好友、同意好友申请、拒绝好友申请、删除好友和设置好友备注等操作。 - 黑名单管理:查询黑名单列表、添加用户至黑名单以及将用户移出黑名单等操作。 ## 技术原理 @@ -24,9 +24,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理 ## 实现方法 -### 管理联系人列表 - -#### 添加好友 +### 添加好友 本节主要介绍发送好友请求、接收好友请求、处理好友请求和好友请求处理结果回调等。 @@ -75,7 +73,7 @@ conn.addContact("userId", "加个好友呗!"); conn.declineContactInvite("userId"); ``` -#### 删除好友 +### 删除好友 删除联系人时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 @@ -87,9 +85,9 @@ conn.deleteContact("userId"); 删除好友后,对方会收到 `onContactDeleted` 事件。 -#### 设置好友备注 +### 设置好友备注 -你可以调用 `setContactRemark` 方法设置单个好友的备注。 +自 4.3.0 版本开始,你可以调用 `setContactRemark` 方法设置单个好友的备注。 好友备注的长度不能超过 100 个字符。 @@ -107,12 +105,13 @@ conn }); ``` -#### 获取好友列表 +### 获取好友列表 + +自 4.3.0 版本,你可以调用 `getAllContacts` 或 `getContactsWithCursor` 方法一次性或分页获取好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 -调用以下两种方法返回好友列表,其中每个好友对象包含好友的用户 ID 和好友备注。 +- 一次性获取好友列表: ```javascript -// 一次性获取全部好友列表 conn .getAllContacts() .then((res) => { @@ -121,9 +120,11 @@ conn .catch((e) => { console.log(e, 'getAllContacts failed'); }); +``` +- 分页获取好友列表: -// 分页获取好友列表 +```javascript conn .getContactsWithCursor({ pageSize: 20, // 每页期望获取的联系人数量。取值范围为 [1,50],默认为 `20`。 @@ -137,7 +138,7 @@ conn }); ``` -你可以调用 `getContacts` 方法从服务端获取所有好友的列表,该列表只包含好友的用户 ID。 +此外,你可以调用 `getContacts` 方法从服务端一次性获取好友列表,该列表只包含好友的用户 ID。 ```javascript conn.getContacts().then((res) => { @@ -145,9 +146,7 @@ conn.getContacts().then((res) => { }) ``` -### 管理黑名单 - -#### 添加用户至黑名单 +### 添加用户至黑名单 你可以调用 `addUsersToBlocklist` 添加用户到黑名单。用户被加入黑名单后,无法向你发送消息,也无法发送好友申请。 @@ -160,7 +159,7 @@ conn.addUsersToBlocklist({ }); ``` -#### 将用户移出黑名单 +### 将用户移出黑名单 你可以调用 `removeUserFromBlocklist` 方法将用户移出黑名单,示例代码如下: @@ -171,7 +170,7 @@ conn.removeUserFromBlocklist({ }); ``` -#### 获取黑名单列表 +### 获取黑名单列表 你可以调用 `getBlocklist` 方法获取用户黑名单列表,示例代码如下: diff --git a/docs/document/windows/conversation_delete.md b/docs/document/windows/conversation_delete.md new file mode 100644 index 000000000..226dc7e4b --- /dev/null +++ b/docs/document/windows/conversation_delete.md @@ -0,0 +1,52 @@ +# 删除会话 + + + +删除好友或退出群组后,SDK 不会自动删除对应的单聊或群聊会话。你可以调用相应的接口从服务器和本地删除单个会话及其历史消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地删除单个会话及其历史消息,主要方法如下: + +- `DeleteConversationFromServer`:单向删除服务端的单个会话及其历史消息。 +- `DeleteConversation`:删除本地单个会话及其历史消息。 + +## 实现方法 + +### 单向删除服务端会话及其历史消息 + +你可以调用 `DeleteConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 + +```csharp +SDKClient.Instance.ChatManager.DeleteConversationFromServer(conversationId, conversationType, isDeleteServerMessages, new CallBack( + onSuccess: () => + { + }, + onError: (code, desc) => + { + } +)); +``` + +### 删除本地会话及历史消息 + +- 你可以调用 `DeleteConversation` 方法删除本地会话及其聊天消息: + +```csharp +//如需保留历史消息,传 `false`。 +SDKClient.Instance.ChatManager.DeleteConversation(conversationId, true); +``` + +- 你可以调用 `DeleteMessage` 方法删除指定会话中指定的一条历史消息。 + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.DeleteMessage(msgId); +``` diff --git a/docs/document/windows/conversation_list.md b/docs/document/windows/conversation_list.md new file mode 100644 index 000000000..db8603056 --- /dev/null +++ b/docs/document/windows/conversation_list.md @@ -0,0 +1,90 @@ +# 会话列表 + + + +对于单聊、群组聊天和聊天室会话,用户发消息时 SDK 会自动创建会话并将会话添加至用户的会话列表。 + +环信服务器和本地均存储会话,你可以获取会话列表。**服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM 支持从服务器和本地获取会话列表,主要方法如下: + +- `IChatManager#GetConversationsFromServerWithCursor`:从服务器获取会话列表。 +- `IChatManager#LoadAllConversations`:获取本地所有会话。 + +## 实现方法 + +### 从服务器分页获取会话列表 + +你可以调用 `GetConversationsFromServerWithCursor` 方法从服务端分页获取会话列表,包含单聊和群组聊天会话,不包含聊天室会话。通过设置该方法中的 `pinOnly` 参数确定是否只获取置顶会话列表: + +- 若 `pinOnly` 为 `false`,获取包括置顶和未置顶会话的列表。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。 +- 若为 `true` 仅获取置顶会话列表,最多可拉取 50 个置顶会话。SDK 按照会话置顶时间的倒序返回。 + +:::tip +1. 若使用该方法,需将 SDK 升级至 1.2.0。 +2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `LoadAllConversations` 方法获取本地所有会话即可。 +3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +::: + +```csharp +// limit: 每页返回的会话数。取值范围为 [1,50]。 +// cursor: 开始获取数据的游标位置。若获取数据时传 `null` 或者空字符串(""),SDK 从最新活跃的会话开始查询。 +int limit = 10; +string cursor = ""; +bool pinOnly = false; // `false`:获取所有会话;`true`仅获取置顶会话列表。 +SDKClient.Instance.ChatManager.GetConversationsFromServerWithCursor(pinOnly, cursor, limit, new ValueCallBack>( + onSuccess: (result) => + { + // 遍历获取到的会话列表 + foreach (var conv in result.Data) + { + + } + // 下一次请求的 cursor + string nextCursor = result.Cursor; + }, + onError: (code, desc) => + { + + } +)); + +``` + +若不支持 `GetConversationsFromServerWithCursor` 方法,你可以调用 `GetConversationsFromServerWithPage` 方法从服务端分页获取会话列表。利用该接口,你总共可获取服务器最近 7 天内存储的 100 个会话。若提升这两个上限,需联系环信商务。 + +若使用该功能,需将 SDK 升级至 V1.1.0。 + +```csharp +SDKClient.Instance.ChatManager.GetConversationsFromServerWithPage(pageNum, pageSize, new ValueCallBack>( + //获取会话成功后的处理逻辑。 + //list 为 List 类型。 + onSuccess: (list) => + { + }, + onError: (code, desc) => + { + } +)); +``` + +### 获取本地所有会话 + +你可以调用 `LoadAllConversations` 方法根据会话 ID 和会话类型获取本地所有会话。SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 + +本地会话列表包含单聊和群组聊天会话,至于是否包含聊天室会话,取决于在 SDK 初始化时 `Options#DeleteMessagesAsExitRoom` 参数的设置。若设置为 `true`,即离开聊天室时删除该聊天室的所有本地消息,则本地会话列表中不包含聊天室会话。若设置为 `false`,即保留该聊天室的所有本地消息,则本地会话列表中包含聊天室会话。 + +示例代码如下: + +```csharp +Listlist = SDKClient.Instance.ChatManager.LoadAllConversations(); +``` \ No newline at end of file diff --git a/docs/document/windows/conversation_overview.md b/docs/document/windows/conversation_overview.md new file mode 100644 index 000000000..87e8c4f00 --- /dev/null +++ b/docs/document/windows/conversation_overview.md @@ -0,0 +1,73 @@ +# 会话介绍 + + + +会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息、查看或清空历史消息等操作。 + +环信即时通讯 IM SDK 提供 `IChatManager` 和 `Conversation` 类以会话为单位对消息数据进行管理,如获取会话列表、置顶会话、添加会话标记、删除会话和管理未读消息等。 + +## 会话类 + +环信即时通讯 IM 提供会话类 `Conversation`。该类定义了以下内容: + +| 类/方法 | 描述 | +| :--------- | :------- | +| Id | 会话 ID,取决于会话类型。
- 单聊:会话 ID 为对方的用户 ID;
- 群聊:会话 ID 为群组 ID;
- 聊天室:会话 ID 为聊天室的 ID。 | +| Type | 会话类型。
- `Chat`:单聊会话;
- `Group`:群聊会话;
- `Room`:聊天室会话。
- `HelpDesk`:客服会话。 | +| IsThread | 判断该会话是否为子区会话。 | +| IsPinned | 判断该会话是否被置顶。 | +| PinnedTime | 会话置顶时间戳(毫秒)。如果 `IsPinned` 为 `false`,将返回 `0`。 | +| LastMessage | 获取指定会话的最新消息。该方法的调用不影响会话的未读消息数。 SDK 首先从内存中获取最新消息,若在内存中未找到,则从数据库中加载,然后将其存放在内存中。 | +| LastReceivedMessage | 获取指定会话中收到的最新消息。 | +| Ext | 获取指定会话的扩展信息。 | +| UnReadCount | 获取指定会话的未读消息数。 | +| MarkMessageAsRead | 设置指定消息为已读。 | +| MarkAllMessageAsRead | 将指定会话的所有未读消息设置为已读。 | +| InsertMessage | 在本地数据库的指定会话中插入一条消息。 | +| AppendMessage | 在本地数据库中指定会话的尾部插入一条消息。 | +| UpdateMessage | 更新本地数据库的指定消息。 | +| DeleteMessage | 删除本地数据库中的一条指定消息。 | +| DeleteMessages | 删除本地数据库中指定时间段的消息。 | +| DeleteAllMessages | 删除指定会话中所有消息。 | +| LoadMessage | 加载指定消息。SDK 首先在内存中查找消息,若在内存中未找到,SDK 会在本地数据库查询并加载。 | +| LoadMessagesWithMsgType | 加载特定类型的多条消息。SDK 首先在内存中查询消息,若在内存中未找到,SDK 会在本地数据库查询并加载。 | +| LoadMessages | 从指定消息 ID 开始加载消息。 | +| LoadMessagesWithKeyword | 根据关键字加载消息。SDK 首先在内存中查找消息,若在内存中未找到,SDK 会在本地数据库查询并加载。 | +| LoadMessagesWithTime | 加载指定时间段内的消息。 | +| MessagesCount | 获取 SDK 本地数据库中会话的全部消息数目。 | + + +## 会话事件 + +`IChatManagerDelegate` 中提供会话事件的监听接口。开发者可以通过设置此监听,获取会话事件,并做出相应处理。如果不再使用该监听,需要移除。 + +示例代码如下: + +```csharp +public class ChatManagerDelegate : IChatManagerDelegate { + // 收到会话已读的事件。该事件在以下场景中触发: + // 1. 当消息接收方调用 `SendConversationReadAck` 方法,SDK 会执行此回调, + // 会将本地数据库中该会话中消息的 `isAcked` 属性置为 `true`。 + // 2. 多端多设备登录时,若一端发送会话已读回执(conversation ack), + // 服务器端会将会话的未读消息数置为 0, + // 同时其他端会回调此方法,并将本地数据库中该会话中消息的 `isRead` 属性置为 `true`。 + public void OnConversationRead(string from, string to) + { + + } +} + +// 注册会话监听回调。 +ChatManagerDelegate adelegate = new ChatManagerDelegate(); +SDKClient.Instance.ChatManager.AddChatManagerDelegate(adelegate); + +// 移除会话监听回调。 +SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); + +``` + + + + + + diff --git a/docs/document/windows/conversation_pin.md b/docs/document/windows/conversation_pin.md new file mode 100644 index 000000000..3eea29d93 --- /dev/null +++ b/docs/document/windows/conversation_pin.md @@ -0,0 +1,56 @@ +# 会话置顶 + + + +会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 + +**若使用会话置顶功能,需将 SDK 升级至 1.2.0,并[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)。** + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 +- **[开通服务端会话列表功能](conversation_list#从服务器分页获取会话列表)**。 + +## 技术原理 + +环信即时通讯 IM 支持会话置顶,主要方法如下: + +- `IChatManager#PinConversation`:置顶会话。 +- `IChatManager#GetConversationsFromServerWithCursor`:获取服务端置顶会话列表。 + +## 实现方法 + +### 置顶会话 + +你可以调用 `PinConversation` 方法设置是否置顶会话。置顶状态会存储在服务器上,多设备登录情况下,更新的置顶状态会同步到其他登录设备,其他登录设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。 + +你最多可以置顶 50 个会话。 + +示例代码如下: + +```csharp +SDKClient.Instance.ChatManager.PinConversation(convId, isPinned, new CallBack( + onSuccess: () => + { + + }, + onError: (code, desc) => + { + + } +)); +``` + +你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 + +### 获取服务端的置顶会话列表 + +你可以调用 `GetConversationsFromServerWithCursor` 方法从服务端分页获取置顶会话列表。如果将该方法中的 pinOnly 参数设置为 `true` 则只获取置顶会话列表。该接口详情,请参考[从服务器分页获取会话列表](conversation_list#从服务器分页获取会话列表)。 + +你最多可以拉取 50 个置顶会话。 + + + diff --git a/docs/document/windows/conversation_unread.md b/docs/document/windows/conversation_unread.md new file mode 100644 index 000000000..64af88cc5 --- /dev/null +++ b/docs/document/windows/conversation_unread.md @@ -0,0 +1,68 @@ +# 会话未读数 + + + +你可以查看本地所有会话或指定会话的未读消息数,并针对会话的未读消息数清零。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 技术原理 + +环信即时通讯 IM SDK 通过 `IChatManager` 和 `Conversation` 类实现对本地会话的未读消息数的管理,其中核心方法如下: + +- `IChatManager#GetUnreadMessageCount`:获取本地所有会话的未读消息数。 +- `Conversation#UnReadCount`:获取本地指定会话的未读消息数。 +- `IChatManager#MarkAllConversationsAsRead`:将本地所有会话的未读消息数清零。 +- `IChatManager#MarkAllMessageAsRead`:对于本地指定会话的未读消息数清零。 +- `IChatManager#MarkMessageAsRead`:将指定会话的单条未读消息置为已读。 + +## 实现方法 + +### 获取所有会话的未读消息数 + +你可以调用 `GetUnreadMessageCount` 方法获取本地所有会话的未读消息数量,示例代码如下: + +```csharp +SDKClient.Instance.ChatManager.GetUnreadMessageCount(); +``` + +### 获取指定会话的未读消息数 + +你可以调用 `UnReadCount` 方法获取本地指定会话的未读消息数,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +int unread = conv.UnReadCount; +``` + +### 将所有会话的未读消息数清零 + +你可以调用 `MarkAllConversationsAsRead` 方法将本地所有会话的未读消息数清零,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +SDKClient.Instance.ChatManager.MarkAllConversationsAsRead(); +``` + +### 指定会话的未读消息数清零 + +你可以调用 `MarkAllMessageAsRead` 方法对指定会话的未读消息数清零,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.MarkAllMessageAsRead(); +``` + +### 将指定会话的单条未读消息置为已读 + +你可以调用 `markMessageAsRead` 方法将指定会话的单条未读消息置为已读。 + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.MarkMessageAsRead(msgId); +``` diff --git a/docs/document/windows/group_attributes.md b/docs/document/windows/group_attributes.md index de194840a..ee129f3aa 100644 --- a/docs/document/windows/group_attributes.md +++ b/docs/document/windows/group_attributes.md @@ -97,7 +97,7 @@ SDKClient.Instance.GroupManager.GetGroupAnnouncementFromServer(currentGroupId, n #### 上传共享文件 -所有群组成员均可以调用 `UploadGroupSharedFile` 方法上传共享文件至群组,群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `IGroupManagerDelegate#OnSharedFileAddedFromGroup` 回调。 +所有群组成员均可以调用 `UploadGroupSharedFile` 方法上传共享文件至群组,单个群共享文件大小限制为 10 MB。上传共享文件后,其他群成员收到 `IGroupManagerDelegate#OnSharedFileAddedFromGroup` 回调。 示例代码如下: diff --git a/docs/document/windows/group_manage.md b/docs/document/windows/group_manage.md index e1fd8e8de..0b38a6554 100644 --- a/docs/document/windows/group_manage.md +++ b/docs/document/windows/group_manage.md @@ -150,6 +150,10 @@ SDKClient.Instance.GroupManager.LeaveGroup(groupId, new CallBack( 群成员也可以调用 `GetGroupSpecificationFromServer` 方法从服务器获取群组详情。返回结果包括:群组 ID、群组名称、群组描述、群主、群组管理员列表、是否已屏蔽群组消息以及群组是否禁用等信息,不包括群成员列表。 +:::tip +对于公有群,用户即使不加入群也能获取群组详情,而对于私有群,用户只有加入了群组才能获取群详情。 +::: + 示例代码如下: ```csharp diff --git a/docs/document/windows/group_members.md b/docs/document/windows/group_members.md index f8ccad8b0..03c9db054 100644 --- a/docs/document/windows/group_members.md +++ b/docs/document/windows/group_members.md @@ -48,7 +48,7 @@ SDKClient.Instance.GroupManager.AddGroupMembers(groupId, members, new CallBack( ### 群组踢人 -仅群主和群管理员可以调用 `DeleteGroupMembers` 方法将指定成员移出群组。被移出后,该成员收到 `IGroupManagerDelegate#OnUserRemovedFromGroup` 回调,其他群成员收到 `IGroupManagerDelegate#OnMemberExitedFromGroup` 回调。被移出群组后,该用户还可以再次加入群组。 +仅群主和群管理员可以调用 `DeleteGroupMembers` 方法将单个或多个成员移出群组。被移出后,该成员收到 `IGroupManagerDelegate#OnUserRemovedFromGroup` 回调,其他群成员收到 `IGroupManagerDelegate#OnMemberExitedFromGroup` 回调。被移出群组后,该用户还可以再次加入群组。 示例代码如下: @@ -243,6 +243,7 @@ SDKClient.Instance.GroupManager.GetGroupBlockListFromServer(groupId, pageNum, pa 示例代码如下: ```csharp +// muteMilliseconds:禁言时间。若传 -1,表示永久禁言。 SDKClient.Instance.GroupManager.MuteGroupMembers(groupId, members, new CallBack( onSuccess: () => { @@ -290,7 +291,9 @@ SDKClient.Instance.GroupManager.GetGroupMuteListFromServer(groupId, callback: ne #### 开启群组全员禁言 -仅群主和群管理员可以调用 `MuteGroupAllMembers` 方法开启全员禁言。群组全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。 +仅群主和群管理员可以调用 `MuteGroupAllMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动取消禁言,需要调用 `UnMuteGroupAllMembers` 方法取消全员禁言。 + +群组全员禁言开启后,除了在白名单中的群成员,其他成员不能发言。 示例代码如下: diff --git a/docs/document/windows/message_delete.md b/docs/document/windows/message_delete.md new file mode 100644 index 000000000..458874e10 --- /dev/null +++ b/docs/document/windows/message_delete.md @@ -0,0 +1,102 @@ +# 删除消息 + + + +本文介绍用户如何单向删除服务端的历史消息。 + +## 技术原理 + +使用环信即时通讯 IM SDK 可以通过 `ChatManager` 和 `Conversation` 类单向删除服务端和本地的历史消息,主要方法如下: + +- `ChatManager#RemoveMessagesFromServer`:单向删除服务端的历史消息。 +- `Conversation#DeleteAllMessages`:删除本地指定会话的所有消息。 +- `Conversation#DeleteMessages (long startTime, long endTime)`:删除本地单个会话在指定时间段的消息。 +- `Conversation#DeleteMessage (string messageId)`:删除本地单个会话的指定消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 单向删除服务端的历史消息 + +你可以调用 `RemoveMessagesFromServer` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。删除后,消息自动从设备本地移除且该用户无法从服务端拉取到该消息。其他用户不受该操作影响。 + +登录该账号的其他设备会收到 `IMultiDeviceDelegate` 中的 `OnRoamDeleteMultiDevicesEvent` 回调,已删除的消息自动从设备本地移除。 + +:::tip +若使用该功能,需将 SDK 升级至 V1.1.0 或以上版本并联系商务。 +::: + +```csharp +// 按时间删除历史消息 +SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, time, new CallBack( + onSuccess: () => + { + }, + onError: (code, desc) => + { + } +)); +// 按消息 ID 删除历史消息 +SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, msgList, new CallBack( + onSuccess: () => + { + }, + onError: (code, desc) => + { + } +)); +``` + +### 删除本地指定会话的所有消息 + +你可以删除本地指定会话的所有消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversionId, conversationType); + +if (conv.DeleteAllMessages()){ + //成功删除消息 +} +else{ + //删除消息失败 +} +``` + +### 删除本地单个会话在指定时间段的消息 + +你可以删除本地指定会话在一段时间内的本地消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversionId, conversationType); + +if (conv.DeleteMessages(startTime, endTime)) { + //成功删除消息 +} +else { + //删除消息失败 +} +``` + +### 删除本地单个会话的指定消息 + +你可以删除本地单个会话的指定消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversionId, conversationType); + +if (conv.DeleteMessage(msgid)){ + //成功删除消息 +} +else{ + //删除消息失败 +} +``` + + + diff --git a/docs/document/windows/message_deliver_only_online.md b/docs/document/windows/message_deliver_only_online.md new file mode 100644 index 000000000..f613d7e6e --- /dev/null +++ b/docs/document/windows/message_deliver_only_online.md @@ -0,0 +1,46 @@ +# 消息仅投递在线用户 + +环信即时通讯 IM 支持只将消息投递给在线用户。若接收方不在线,则无法收到消息。该功能用于实现应用只需要向在线用户进行展示目的,例如,利用透传消息实现群投票的票数实时变化, 只有在线用户需要关注实时变化的动态, 离线用户只需要再次上线时获取最终状态。 + +各类型的消息均支持该功能,但该功能只支持单聊和群组聊天,**不适用于聊天室**。该类的消息与普通消息相比,存在如下差异: + +1. **不支持离线存储**:若发送消息时,接收方离线则无法收到消息,即使重新登录后也收不到消息。对于普通消息,当接收方在线时, 实时收到消息提醒;当接收方离线时,实时发送离线推送消息,接收方再次上线时, 由环信 IM 服务器主动推给客户端离线期间的消息。 +2. **支持本地存储**:消息成功发送后,写入数据库。 +3. **默认不支持漫游存储**:发送的消息默认不存储在环信消息服务器,用户在其他终端设备上无法获取到该消息。**如需开通在线消息的漫游存储,需联系环信商务。** + +## 技术原理 + +环信即时通讯 IM 通过 `Message` 类支持只将消息投递给在线用户: + +- `DeliverOnlineOnly`:设置消息是否只投递给在线用户。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +要将消息只投递给在线用户,你需要在发送消息时将 `Message#DeliverOnlineOnly` 设置为 `true`。 + +下面以发送文本消息为例进行说明: + +```csharp +// 创建一条文本消息,`content` 为消息文字内容。 +// `conversationId` 为消息接收方,单聊时为对端用户 ID、群聊时为群组 ID。 +Message message = Message.CreateTextSendMessage(conversationId, content); +// 消息是否只投递在线用户。(默认)`false`:不论用户是否在线均投递;`true`:只投递给在线用户。若用户离线,消息不投递。 +message.DeliverOnlineOnly = true; +// 会话类型:单聊为 MessageType.Chat,群聊为 MessageType.Group,默认为单聊。 +message.MessageType = MessageType.Chat; +// 发送消息。 +SDKClient.Instance.ChatManager.SendMessage(ref message, new CallBack( + onSuccess: () => { + }, + onError: (code, desc) => { + } +)); +``` + diff --git a/docs/document/windows/message_import_insert.md b/docs/document/windows/message_import_insert.md new file mode 100644 index 000000000..2af695dfe --- /dev/null +++ b/docs/document/windows/message_import_insert.md @@ -0,0 +1,53 @@ +# 导入和插入消息 + + + +本文介绍环信即时通讯 IM SDK 如何在本地导入和插入消息。 + +## 技术原理 + +环信即时通讯 IM SDK 支持提供 `IChatManager` 和 `Conversation` 类支持在本地导入和插入消息,其中包含如下主要方法: + +- `IChatManager.ImportMessages` 批量导入消息到数据库。 +- `Conversation.InsertMessage` 在指定会话中插入消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 批量导入消息到数据库 + +如果你需要使用批量导入方式在本地会话中插入消息,可以调用 `ImportMessages` 方法,构造 `EMMessage` 对象,将消息导入本地数据库。 + +当前用户只能导入自己发送或接收的消息。导入后,消息按照其包含的时间戳添加到对应的会话中。 + +推荐一次导入 1,000 条以内的数据。 + +示例代码如下: + +```csharp +SDKClient.Instance.ChatManager.ImportMessages(messages, new CallBack( + onSuccess: () => { + }, + onError: (code, desc) => + { + } +)); +``` + +### 插入消息 + +如果你想在当前对话中插入消息而不实际发送消息,请构造消息正文并调用 `InsertMessage` 方法用于发送通知消息,例如“XXX 撤回一条消息”、“XXX 入群” 和 “对方正在输入...”。 + +消息会根据消息中的 Unix 时间戳插入本地数据库,SDK 会更新会话的 `latestMessage` 等属性。 + +```csharp +// 将消息插入到指定会话中。 +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +conv.InsertMessage(message); +``` diff --git a/docs/document/windows/message_manage.md b/docs/document/windows/message_manage.md deleted file mode 100644 index 5595e77c9..000000000 --- a/docs/document/windows/message_manage.md +++ /dev/null @@ -1,219 +0,0 @@ -# 管理本地会话和消息 - - - -本文介绍即时通讯 IM SDK 如何管理本地会话和消息。 - -除了发送和接收消息外,环信即时通讯 IM SDK 还支持以会话为单位对本地的消息数据进行管理,如获取与管理未读消息、搜索和删除历史消息等。其中,会话是一个单聊、群聊或者聊天室所有消息的集合。用户需在会话中发送消息以及查看或清空历史消息。 - -本文介绍如何使用环信即时通讯 IM SDK 在 app 中实现这些功能。 - -## 技术原理 - -SQLCipher 用于加密存储本地消息的数据库。即时通讯 IM SDK 使用 `IChatManager` 和 `Conversation` 管理本地消息。以下是核心方法: - -- `IChatManager.LoadAllConversations` 获取本地所有会话; -- `Conversation.LoadMessages` 读取指定会话的消息; -- `Conversation.UnReadCount` 获取指定会话的未读消息数; -- `IChatManager.GetUnreadMessageCount` 获取所有会话的未读消息数; -- `IChatManager.MarkAllConversationsAsRead` 指定会话的未读消息数清零; -- `IChatManager.DeleteConversation` 删除本地会话及历史消息; -- `IChatManager.DeleteConversationFromServer` 删除服务端的会话及历史消息; -- `IChatManager.LoadMessage` 根据消息 ID 搜索消息; -- `Conversation.LoadMessagesWithMsgType` 获取指定会话中特定类型的消息; -- `Conversation.LoadMessagesWithTime` 获取指定会话中一定时间段内的消息; -- `IChatManager.SearchMsgFromDB` 根据关键字搜索会话消息; -- `IChatManager.ImportMessages` 批量导入消息到数据库; -- `Conversation.InsertMessage` 在指定会话中插入消息。 - -## 前提条件 - -开始前,请确保满足以下条件: - -- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 - -## 实现方法 - -### 获取本地所有会话 - -你可以调用 `LoadAllConversations` 方法可以根据会话 ID 和会话类型获取本地所有会话: - -```csharp -Listlist = SDKClient.Instance.ChatManager.LoadAllConversations(); - -``` -SDK 从内存中获取会话,若未从本地数据库中加载过,会先从数据库加载到内存中。获取会话后,SDK 按照会话活跃时间(最新一条消息的时间戳)的倒序返回会话,置顶会话在前,非置顶会话在后,会话列表为 `List` 结构。 - - -### 读取指定会话的消息 - -你可以从本地数据库中读取指定会话的消息,示例代码如下: - -```csharp -// 获取本地会话。 -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -// 该方法获取 `startMsgId` 之前的 `pagesize` 条消息。 -conv.LoadMessages(startMsgId, pagesize, callback:new ValueCallBack>( - onSuccess: (list) => { - Debug.Log($"获取到{list.Count}条消息"); - }, - onError:(code, desc) => { - Debug.Log($"获取会话消息失败,errCode={code}, errDesc={desc}"); - } -)); -``` - -### 获取指定会话的未读消息数 - -你可以调用接口获取特定会话的未读消息数,示例代码如下: - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -int unread = conv.UnReadCount; -``` - -### 获取所有会话的未读消息数 - -你可以通过接口获取所有会话的未读消息数量,示例代码如下: - -```csharp -SDKClient.Instance.ChatManager.GetUnreadMessageCount(); -``` - -### 指定会话的未读消息数清零 - -你可以调用接口对特定会话的未读消息数清零,示例代码如下: - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -// 指定会话的未读消息数清零。 -conv.MarkAllMessageAsRead(); - -// 将一条消息置为已读。 -conv.MarkMessageAsRead(msgId); - -// 将所有未读消息数清零。 -SDKClient.Instance.ChatManager.MarkAllConversationsAsRead(); -``` - -### 删除会话及历史消息 - -SDK 提供两个接口,分别可以删除本地会话和历史消息或者删除当前用户在服务器端的会话和聊天消息。 - -调用 `DeleteConversation` 和 `DeleteMessage` 删除本地会话和聊天消息,示例代码如下: - -```csharp -//删除和特定用户的会话,如需保留历史消息,传 `false`。 -SDKClient.Instance.ChatManager.DeleteConversation(conversationId, true); - -//删除当前会话中指定的一条历史消息。 -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -conv.DeleteMessage(msgId); -``` - -删除服务端的会话及其历史消息,详见 [删除服务端会话及其历史消息](message_retrieve.html#单向删除服务端会话及其历史消息)。 - -### 根据消息 ID 搜索消息 - -你可以调用 `LoadMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 - -```csharp -// msgId:要获取消息的消息 ID。 -Message msg = SDKClient.Instance.ChatManager.LoadMessage("msgId"); -``` - -### 获取指定会话中特定类型的消息 - -你可以调用 `LoadMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); -// type:消息类型;count:每次获取的消息数量,取值范围为 [1,400];direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 -conv.LoadMessagesWithMsgType(type: MessageBodyType.TXT, count: 50, direction: MessageSearchDirection.UP, new ValueCallBack>( - onSuccess: (list) => { - // 遍历消息列表 - foreach(var it in list) - { - } - }, - onError: (code, desc) => { - } -)); -``` - -### 获取指定会话中一定时间段内的消息 - -你可以调用 `LoadMessagesWithTime` 方法从本地存储中获取指定的单个会话中一定时间内发送和接收的消息。每次最多可获取 400 条消息。 - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); -// startTime:搜索的起始时间戳;endTime:搜索的结束时间戳;count:每次获取的消息数量,取值范围为 [1,400]。 -conv.LoadMessagesWithTime(startTime: startTime, endTime: endTime, count: 50, new ValueCallBack>( - onSuccess: (list) => { - // 遍历消息列表 - foreach (var it in list) - { - } - }, - onError: (code, desc) => { - } -)); -``` - -### 根据关键字搜索会话消息 - -你可以调用 `LoadMessagesWithKeyword` 方法以从本地数据库获取会话中的指定用户发送的包含特定关键字的消息,示例代码如下: - -```csharp -Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); - -conv.LoadMessagesWithKeyword( - // 搜索关键字。 - "key", - // 消息发送方。 - sender: "tom", - // 搜索开始的 Unix 时间戳,单位为毫秒。 - timestamp: 1653971593000, - // 搜索的最大消息数。 - count: 10, - // 消息的搜索方向:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 - direction: MessageSearchDirection.UP, - // 回调处理 - new ValueCallBack>( - onSuccess: (list) => { - // 遍历消息列表 - foreach(var it in list) - { - } - }, - onError: (code, desc) => { - } -)); -``` - -### 批量导入消息到数据库 - -如果你需要使用批量导入方式在本地会话中插入消息,可以调用 `ImportMessages` 方法,构造 `EMMessage` 对象,将消息导入本地数据库。 - -示例代码如下: - -```csharp -SDKClient.Instance.ChatManager.ImportMessages(messages, new CallBack( - onSuccess: () => { - }, - onError: (code, desc) => - { - } -)); -``` - -### 插入消息 - -如果你想在当前对话中插入消息而不实际发送消息,请构造消息正文并调用 `InsertMessage` 方法用于发送通知消息,例如“XXX 撤回一条消息”、“XXX 入群” 和 “对方正在输入...”。 - -```csharp -// 将消息插入到指定会话中。 -Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); -conv.InsertMessage(message); -``` diff --git a/docs/document/windows/message_modify.md b/docs/document/windows/message_modify.md index b1061e6da..2219487be 100644 --- a/docs/document/windows/message_modify.md +++ b/docs/document/windows/message_modify.md @@ -1,6 +1,15 @@ # 修改消息 -对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。消息内容修改流程如下: +对于单聊或群组聊天会话中已经发送成功的文本消息,SDK 支持对这些消息的内容进行修改。 + +:::tip +1. 若使用该功能,需将 SDK 升级至 1.2.0 或以上版本。 +2. 聊天室会话不支持消息修改功能。 +::: + +## 技术原理 + +消息内容修改流程如下: 1. 用户调用 SDK 的 API 修改一条消息。 2. 服务端存储的该条消息,修改成功后回调给 SDK。 @@ -13,10 +22,14 @@ - 对于单聊会话,只有消息发送方才能对消息进行修改。 - 对于群聊会话,普通群成员只能修改自己发送的消息。群主和群管理员除了可以修改自己发送的消息,还可以修改普通群成员发送的消息。这种情况下,消息的发送方不变,消息体中的修改者的用户 ID 属性为群主或群管理员的用户 ID。 -:::notice -1. 若使用该功能,需将 SDK 升级至 1.2.0 或以上版本。 -2. 聊天室会话不支持消息修改功能。 -::: +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html) 及 [SDK 集成概述](overview.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 你可以调用 `ChatManager#ModifyMessage` 方法修改已经发送成功的消息。一条消息默认最多可修改 10 次,若要提升修改次数,需联系商务。 diff --git a/docs/document/windows/message_recall.md b/docs/document/windows/message_recall.md new file mode 100644 index 000000000..54218d12a --- /dev/null +++ b/docs/document/windows/message_recall.md @@ -0,0 +1,54 @@ +# 撤回消息 + + + +发送方可以撤回一条发送成功的消息,包括已经发送的历史消息,离线消息或漫游消息。 + +默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能**页面设置消息撤回时长,该时长不超过 7 天。 + +:::tip +除了透传消息,其他各类型的消息都支持撤回。 +::: + +## 技术原理 + +环信即时通讯 IM 通过 `IChatManager` 和 `Message` 类支持你撤回一条发送成功的消息: + +- `RecallMessage`:撤回一条发送成功的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 撤回消息 + +你可以调用 `RecallMessage` 方法撤回一条发送成功的消息。 + +调用该方法后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除,消息的接收方会收到 `OnMessagesRecalled` 事件。 + +```csharp +SDKClient.Instance.ChatManager.RecallMessage("Message ID", new CallBack( + onSuccess: () => { + Debug.Log("回撤成功"); + }, + onProgress: (progress) => { + Debug.Log($"回撤进度 {progress}"); + }, + onError: (code, desc) => { + Debug.Log($"回撤失败,errCode={code}, errDesc={desc}"); + } + )); +``` + +### 设置消息撤回监听 + +你可以使用 `IChatManagerDelegate` 设置消息撤回监听,通过 `OnMessagesRecalled` 事件监听发送方对已接收的消息的撤回。 + +```csharp +void OnMessagesRecalled(List messages); +``` \ No newline at end of file diff --git a/docs/document/windows/message_receipt.md b/docs/document/windows/message_receipt.md index d44bd99ac..a8f194951 100644 --- a/docs/document/windows/message_receipt.md +++ b/docs/document/windows/message_receipt.md @@ -1,10 +1,10 @@ -# 管理消息回执 +# 实现消息回执 单聊会话支持消息送达回执、会话已读回执和消息已读回执,发送方发送消息后可及时了解接收方是否及时收到并阅读了信息,也可以了解整个会话是否已读。 -群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊会话只支持消息已读回执。群主和群管理员在发送消息时,可以设置该消息是否需要已读回执。仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 本文介绍如何使用环信即时通讯 IM Windows SDK 实现单聊和群聊的消息回执功能。 @@ -41,7 +41,7 @@ - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html); - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html); -- 群消息已读回执功能仅在环信 IM 旗舰版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +- 群消息已读回执功能仅在环信 IM 专业版及以上版本支持该功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 ## 实现方法 @@ -134,6 +134,8 @@ SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); ##### 消息已读回执 +单聊消息的已读回执有效期与消息在服务端的存储时间一致,即在服务器存储消息期间均可发送已读回执。消息在服务端的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 + 参考如下步骤在单聊中实现消息已读回执。 1. 接收方发送已读回执消息。 @@ -223,7 +225,9 @@ SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); 对于群聊,群主和群管理员发送消息时,可以设置该消息是否需要已读回执。若需要,每个群成员在阅读消息后,SDK 均会发送已读回执,即阅读该消息的群成员数量即为已读回执的数量。 -仅旗舰版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 +群聊已读回执的有效期为 3 天,即群组中的消息发送时间超过 3 天,服务器不记录阅读该条消息的群组成员,也不会发送已读回执。 + +仅专业版及以上版本支持群消息已读回执功能。若要使用该功能,需在[环信即时通讯云控制台](https://console.easemob.com/user/login)开通。 1. 群主或群管理员发送消息时若需已读回执,需设置 `Message` 的 `IsNeedGroupAck` 为 `true`。 diff --git a/docs/document/windows/message_retrieve.md b/docs/document/windows/message_retrieve.md index 7d7f7ab28..44c73c2fa 100644 --- a/docs/document/windows/message_retrieve.md +++ b/docs/document/windows/message_retrieve.md @@ -1,23 +1,22 @@ -# 从服务器获取会话和消息 +# 获取历史消息 -环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。本文介绍用户如何从消息服务器获取和删除会话和消息。 +本文介绍环信即时通讯 IM SDK 如何从服务器和本地获取历史消息。 -:::tip -本文介绍的功能均为增值服务,需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 -::: +- 环信即时通讯 IM 提供消息漫游功能,即将用户的所有会话的历史消息保存在消息服务器,用户在任何一个终端设备上都能获取到历史信息,使用户在多个设备切换使用的情况下也能保持一致的会话场景。 + +- SDK 内部使用 SQLite 保存本地消息,你可以获取本地消息。 ## 实现原理 -使用环信即时通讯 IM SDK 可以通过 `IChatManager` 类的以下方法从服务器获取历史消息: +使用环信即时通讯 IM SDK 可以通过 `IChatManager` 和 `Conversation` 类的以下方法从服务器获取和删除历史消息: -- `GetConversationsFromServerWithPage` 分页获取服务器保存的会话列表; -- `GetConversationsFromServerWithCursor` 分页获取服务器保存的置顶会话列表; -- `PinConversation` 置顶会话。 -- `FetchHistoryMessagesFromServer` 获取服务器保存的指定会话中的消息; -- `RemoveMessagesFromServer` 单向删除服务端的历史消息; -- `DeleteConversationFromServer` 删除服务端的会话及其历史消息。 +- `IChatManager.FetchHistoryMessagesFromServer` 获取服务器保存的指定会话中的消息; +- `Conversation.LoadMessages` 读取本地指定会话的消息。 +- `IChatManager.LoadMessage` 根据消息 ID 获取消息。 +- `Conversation.LoadMessagesWithMsgType` 获取本地单个会话中特定类型的消息。 +- `Conversation.LoadMessagesWithTime` 获取本地单个会话中一定时间段内的消息。 ## 前提条件 @@ -28,152 +27,97 @@ ## 实现方法 -### 从服务器获取会话 +### 从服务器获取指定会话的消息 对于单聊或群聊,用户发消息时,会自动将对方添加到用户的会话列表。 -你可以调用 `GetConversationsFromServerWithCursor` 方法从服务端分页获取会话列表。通过设置该方法中的 `pinOnly` 参数确定是否只获取置顶会话列表: +你可以调用 `FetchHistoryMessagesFromServer` 方法从服务器获取指定会话的消息(消息漫游)。 -- 若 `pinOnly` 为 `false`,获取包括置顶和未置顶会话的列表。SDK 按照会话活跃时间(会话的最新一条消息的时间戳)的倒序返回会话列表,每个会话对象中包含会话 ID、会话类型、是否为置顶状态、置顶时间(对于未置顶的会话,值为 `0`)以及最新一条消息。从服务端拉取会话列表后会更新本地会话列表。服务器默认存储 100 条会话,可存储 7 天。若提升这两个上限,需联系环信商务。 -- 若为 `true` 仅获取置顶会话列表,最多可拉取 50 个置顶会话。SDK 按照会话置顶时间的倒序返回。 +为确保数据可靠,我们建议你多次调用该方法,且每次获取的消息数小于 50 条。获取到数据后,SDK 会自动将消息更新到本地数据库。 -:::notice -1. 若使用该方法,需将 SDK 升级至 1.2.0。 -2. 建议你在首次下载、卸载后重装应用等本地数据库无数据情况下拉取服务端会话列表。其他情况下,调用 `LoadAllConversations` 方法获取本地所有会话即可。 -3. 通过 RESTful 接口发送的消息默认不创建或写入会话。若会话中的最新一条消息通过 RESTful 接口发送,获取会话列表时,该会话中的最新一条消息显示为通过非 RESTful 接口发送的最新消息。若要开通 RESTful 接口发送的消息写入会话列表的功能,需联系商务。 +:::tip +1. 历史消息和离线消息在服务器上的存储时间与你订阅的套餐包有关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 +2. 各类事件通知发送时,若接收的用户离线时,事件通知的存储时间与离线消息的存储时间一致,即也取决于你订阅的套餐包。 ::: ```csharp -// limit: 每页返回的会话数。取值范围为 [1,50]。 -// cursor:开始获取数据的游标位置。若传空字符串(''),SDK 则从最新活跃的会话开始获取。 -int limit = 10; -string cursor = ""; -bool pinOnly = false; // `false`:获取所有会话;`true`仅获取置顶会话列表。 -SDKClient.Instance.ChatManager.GetConversationsFromServerWithCursor(pinOnly, cursor, limit, new ValueCallBack>( - onSuccess: (result) => - { - // 遍历获取到的会话列表 - foreach (var conv in result.Data) - { - - } - // 下一次请求的 cursor - string nextCursor = result.Cursor; - }, - onError: (code, desc) => - { - - } -)); - -``` - -此外,你可以调用 `GetConversationsFromServerWithPage` 方法从服务端分页获取会话列表,每个会话包含最新一条历史消息。 - -若使用该功能,需将 SDK 升级至 V1.1.0。 - -```csharp -SDKClient.Instance.ChatManager.GetConversationsFromServerWithPage(pageNum, pageSize, new ValueCallBack>( - //获取会话成功后的处理逻辑。 - //list 为 List 类型。 - onSuccess: (list) => - { +SDKClient.Instance.ChatManager.FetchHistoryMessagesFromServer(conversationId, type, startId, pageSize, new ValueCallBack>( + // 获取历史消息成功。 + // result 为 CursorResult 类型。 + onSuccess: (result) => { }, - onError: (code, desc) => - { + + // 获取历史消息失败。 + onError:(code, desc) => { } )); ``` -### 置顶会话 +### 从本地读取指定会话的消息 -会话置顶指将单聊或群聊会话固定在会话列表的顶部,方便用户查找。例如,将重点会话置顶,可快速定位会话。 - -置顶状态会存储在服务器上,多设备登录情况下,更新置顶状态会同步到其他登录设备。你最多可以置顶 50 个会话。 - -你可以调用 `PinConversation` 方法设置是否置顶会话。多设备登录情况下,会话置顶或取消置顶后,其他登录设备分别会收到 `CONVERSATION_PINNED` 和 `CONVERSATION_UNPINNED` 事件。 - -:::notice -若使用该功能,需将 SDK 升级至 1.2.0。 -::: - -示例代码如下: +你可以从本地数据库中读取指定会话的消息,示例代码如下: ```csharp -SDKClient.Instance.ChatManager.PinConversation(convId, isPinned, new CallBack( - onSuccess: () => - { - - }, - onError: (code, desc) => - { - - } +// 获取本地会话。 +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, convType); +// 该方法获取 `startMsgId` 之前的 `pagesize` 条消息。 +conv.LoadMessages(startMsgId, pagesize, callback:new ValueCallBack>( + onSuccess: (list) => { + Debug.Log($"获取到{list.Count}条消息"); + }, + onError:(code, desc) => { + Debug.Log($"获取会话消息失败,errCode={code}, errDesc={desc}"); + } )); ``` -你可以通过 `EMConversation` 对象的 `isPinned` 字段检查会话是否为置顶状态,或者调用 `getPinnedTime` 方法获取会话置顶时间。 - - -### 分页获取指定会话的历史消息 - -你可以调用 `FetchHistoryMessagesFromServer` 方法从服务器分页获取指定会话的历史消息,实现消息漫游。该功能需在[环信即时通讯 IM 管理后台](https://console.easemob.com/user/login)开通。 +### 根据消息 ID 获取本地消息 -为确保数据可靠,我们建议你多次调用该方法,且每次获取的消息数小于 50 条。获取到数据后,SDK 会自动将消息更新到本地数据库。 +你可以调用 `LoadMessage` 方法根据消息 ID 获取本地存储的指定消息。如果消息不存在会返回空值。 ```csharp -SDKClient.Instance.ChatManager.FetchHistoryMessagesFromServer(conversationId, type, startId, pageSize, new ValueCallBack>( - // 获取历史消息成功。 - // result 为 CursorResult 类型。 - onSuccess: (result) => { - }, - - // 获取历史消息失败。 - onError:(code, desc) => { - } -)); +// msgId:要获取消息的消息 ID。 +Message msg = SDKClient.Instance.ChatManager.LoadMessage("msgId"); ``` -### 单向删除服务端的历史消息 +### 获取本地会话中特定类型的消息 -你可以调用 `RemoveMessagesFromServer` 方法单向删除服务端的历史消息,每次最多可删除 50 条消息。消息删除后,该用户无法从服务端拉取到该消息。其他用户不受该操作影响。已删除的消息自动从设备本地移除。 +你可以调用 `LoadMessagesWithMsgType` 方法从本地存储中获取指定会话中特定类型的消息。 -:::tip -若使用该功能,需将 SDK 升级至 V1.1.0 或以上版本并联系商务。 -::: +每次最多可获取 400 条消息。若未获取到任何消息,SDK 返回空列表。 ```csharp -// 按时间删除历史消息 -SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, time, new CallBack( - onSuccess: () => - { - }, - onError: (code, desc) => - { - } -)); -// 按消息 ID 删除历史消息 -SDKClient.Instance.ChatManager.RemoveMessagesFromServer(convId, ctype, msgList, new CallBack( - onSuccess: () => - { +Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); +// type:消息类型;count:每次获取的消息数量,取值范围为 [1,400];direction:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 +conv.LoadMessagesWithMsgType(type: MessageBodyType.TXT, count: 50, direction: MessageSearchDirection.UP, new ValueCallBack>( + onSuccess: (list) => { + // 遍历消息列表 + foreach(var it in list) + { + } }, - onError: (code, desc) => - { + onError: (code, desc) => { } )); ``` -### 单向删除服务端会话及其历史消息 +### 获取一定时间内本地会话的消息 + +你可以调用 `LoadMessagesWithTime` 方法从本地存储中搜索一定时间段内指定会话中发送和接收的消息。 -你可以调用 `DeleteConversationFromServer` 方法删除服务器端会话和历史消息。会话和消息删除后,当前用户无法从服务器获取该会话和消息,对本地的会话无影响,但会删除本地消息,而其他用户不受影响。 +每次最多可获取 400 条消息。 ```csharp -SDKClient.Instance.ChatManager.DeleteConversationFromServer(conversationId, conversationType, isDeleteServerMessages, new CallBack( - onSuccess: () => - { +Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); +// startTime:搜索的起始时间戳;endTime:搜索的结束时间戳;count:每次获取的消息数量,取值范围为 [1,400]。 +conv.LoadMessagesWithTime(startTime: startTime, endTime: endTime, count: 50, new ValueCallBack>( + onSuccess: (list) => { + // 遍历消息列表 + foreach (var it in list) + { + } }, - onError: (code, desc) => - { + onError: (code, desc) => { } )); -``` \ No newline at end of file +``` diff --git a/docs/document/windows/message_search.md b/docs/document/windows/message_search.md new file mode 100644 index 000000000..0794e510d --- /dev/null +++ b/docs/document/windows/message_search.md @@ -0,0 +1,51 @@ +# 搜索消息 + + + +本文介绍即时通讯 IM SDK 如何搜索本地消息。 + +## 技术原理 + +环信即时通讯 IM SDK 通过 `IChatManager` 类支持搜索用户设备上存储的消息数据,其中包含如下主要方法: + +- `LoadMessagesWithKeyword` 根据关键字搜索会话消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 根据关键字搜索会话消息 + +你可以调用 `LoadMessagesWithKeyword` 方法根据关键字搜索本地数据库中单个会话中指定用户发送的消息,示例代码如下: + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation("convId"); + +conv.LoadMessagesWithKeyword( + // 搜索关键字。 + "key", + // 消息发送方。 + sender: "tom", + // 搜索开始的 Unix 时间戳,单位为毫秒。 + timestamp: 1653971593000, + // 搜索的最大消息数。 + count: 10, + // 消息的搜索方向:消息搜索方向:(默认)`UP`:按消息时间戳的逆序搜索;`DOWN`:按消息时间戳的正序搜索。 + direction: MessageSearchDirection.UP, + // 回调处理 + new ValueCallBack>( + onSuccess: (list) => { + // 遍历消息列表 + foreach(var it in list) + { + } + }, + onError: (code, desc) => { + } +)); +``` diff --git a/docs/document/windows/message_send_receive.md b/docs/document/windows/message_send_receive.md index 576cfec2c..b68fb525d 100644 --- a/docs/document/windows/message_send_receive.md +++ b/docs/document/windows/message_send_receive.md @@ -20,13 +20,21 @@ ## 技术原理 -环信即时通讯 IM Windows SDK 通过 `IChatManager` 和 `Message` 类实现消息的发送、接收与撤回。 +环信即时通讯 IM Unity SDK 通过 `IChatManager` 和 `Message` 类实现消息的发送和接收。 其中,发送和接收消息的逻辑如下: 1. 发送方调用相应 `Create` 方法创建文本、文件、附件等类型的消息; 2. 发送方调用 `SendMessage` 发送消息; -3. 接收方通过 `AddChatManagerDelegate` 方法监听消息回调事件。在收到 `OnMessageReceived` 后,即表示成功接收到消息。 +3. 接收方通过 `AddChatManagerDelegate` 方法监听消息回调事件。在收到 `OnMessagesReceived` 后,即表示成功接收到消息。 + +消息收发流程如下: + +1. 用户 A 发送一条消息到环信的消息服务器; +2. 单聊消息时,服务器投递消息给用户 B;对于群聊时消息,服务器投递给群内其他每一个成员; +3. 用户收到消息。 + +![img](@static/images/android/sendandreceivemsg.png) ## 前提条件 @@ -51,7 +59,7 @@ Message msg = Message.CreateTextSendMessage(conversationId, content); //设置会话类型,即 `Message` 类的 `MessageType` 属性。 -//单聊、群聊和聊天室分别设置为 `Chat`、`Group` 和 `Room`,默认为单聊。 +//单聊、群聊和聊天室分别为 `Chat`、`Group` 和 `Room`,默认为单聊。 msg.MessageType = MessageType.Group; //对于聊天室消息,可设置消息优先级。 @@ -98,33 +106,6 @@ SDKClient.Instance.ChatManager.AddChatManagerDelegate(adelegate); SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); ``` -### 撤回消息 - -发送方可以撤回一条发送成功的消息。调用 API 撤回消息后,服务端的该条消息(历史消息,离线消息或漫游消息)以及消息发送方和接收方的内存和数据库中的消息均会被移除。 - -默认情况下,发送方可撤回发出 2 分钟内的消息。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**功能配置** > **功能配置总览** > **基础功能** 页面设置消息撤回时长,该时长不超过 7 天。 - -```csharp -SDKClient.Instance.ChatManager.RecallMessage("Message ID", new CallBack( - onSuccess: () => { - Debug.Log("回撤成功"); - }, - onProgress: (progress) => { - Debug.Log($"回撤进度 {progress}"); - }, - onError: (code, desc) => { - Debug.Log($"回撤失败,errCode={code}, errDesc={desc}"); - } - )); -``` - -还可以使用 `IChatManagerDelegate` 设置消息撤回监听: - -```csharp -// 接收到消息被撤回时触发此回调(此回调位于 IChatManagerDelegate 中)。 -void OnMessagesRecalled(List messages); -``` - ### 发送和接收附件消息 除文本消息外,还有几种其他类型的消息,其中语音,图片,短视频,文件等消息,是通过先将附件上传到消息服务器的方式实现。收到语音时,会自动下载,而图片和视频会自动下载缩略图。文件消息不会自动下载附件,接收方需调用下载附件的 API,具体实现参考下文。 @@ -374,6 +355,10 @@ SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( 透传消息可视为命令消息,通过发送这条命令给对方,通知对方要进行的操作,收到消息可以自定义处理。(透传消息不会存入本地数据库中,所以在 UI 上不会显示)。具体功能可以根据自身业务需求自定义,例如实现头像、昵称的更新等。另外,以 “em_” 和 “easemob::” 开头的 action 为内部保留字段,注意不要使用。 +:::tip +透传消息发送后,不支持撤回。 +::: + ```csharp //`action` 可以自定义。 string action = "actionXXX"; @@ -426,7 +411,7 @@ SDKClient.Instance.ChatManager.AddChatManagerDelegate(adelegate); - 收到消息后,如果用户 B 与用户 A 的聊天页面处于打开状态,则显示用户 A 的输入指示器。 - 如果用户 B 在几秒后未收到用户 A 的输入,则自动取消输入指示器。 -:::notice +:::tip 用户 A 可根据需要设置透传消息发送间隔。 @@ -511,7 +496,6 @@ SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( 2. 发送合并消息。 3. 对端收到合并消息后进行解析,获取原始消息列表。 - #### 创建和发送合并消息 你可以调用 `CreateCombineSendMessage` 方法创建一条合并消息,然后调用 `SendMessage` 方法发送该条消息。 @@ -527,7 +511,7 @@ SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( | `messageList` | List | 合并消息的原始消息 ID 列表。该列表最多包含 300 个消息 ID。 | -:::notice +:::tip 1. 合并转发支持嵌套,最多支持 10 层嵌套,每层最多 300 条消息。 2. 不论 `Options#ServerTransfer` 设置为 `false` 或 `true`,SDK 都会将合并消息附件上传到环信服务器。 ::: @@ -580,9 +564,9 @@ SDKClient.Instance.ChatManager.FetchCombineMessageDetail(msg, new ValueCallBack< 该功能适用于文本消息、图片消息和音视频消息等全类型消息,最多可向群组或聊天室的 20 个成员发送定向消息。 -:::notice +:::tip 1. 仅 SDK 1.2.0 及以上版本支持。 -2. 定向消息不写入服务端会话列表,不计入服务端会话的未读消息数。 +2. 定向消息不写入服务端会话列表,不计入服务端会话的未读消息计数。 3. 定向消息不支持消息漫游功能,因此从服务器拉取漫游消息时,不包含定向消息。 ::: diff --git a/docs/document/windows/message_update.md b/docs/document/windows/message_update.md new file mode 100644 index 000000000..fc8fc112b --- /dev/null +++ b/docs/document/windows/message_update.md @@ -0,0 +1,38 @@ +# 更新消息 + + + +本文介绍环信即时通讯 IM SDK 如何更新本地消息。 + +## 技术原理 + +环信即时通讯 IM SDK 使用 `IChatManager` 和 `Conversation` 支持更新本地数据库中的消息,其中包含如下主要方法: + +- `UpdateMessage`:更新 SDK 本地数据库中的消息。 + +## 前提条件 + +开始前,请确保满足以下条件: + +- 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 +- 了解环信即时通讯 IM API 的使用限制,详见 [使用限制](/product/limitation.html)。 + +## 实现方法 + +### 更新消息到本地数据库 + +你可以通过以下方式更新本地数据库中的消息: + +- 直接调用 `UpdateMessage` 方法更新 SDK 本地数据库中的消息。 + +```csharp +SDKClient.Instance.ChatManager.UpdateMessage(message): +``` + +- 若正在使用 `Conversation` 类,可以先获取会话,再调用 `UpdateMessage` 方法更新 SDK 本地数据库会话中的消息。 + +```csharp +Conversation conv = SDKClient.Instance.ChatManager.GetConversation(conversationId, type); +conv.UpdateMessage(message); +``` + diff --git a/docs/document/windows/moderation.md b/docs/document/windows/moderation.md index 43574d949..869989db4 100644 --- a/docs/document/windows/moderation.md +++ b/docs/document/windows/moderation.md @@ -2,7 +2,14 @@ -即时通讯 IM SDK 提供消息举报接口。开发者可以在客户端调用该接口举报违规消息。当服务器端审核服务收到举报消息后,会将举报消息存储到数据库,并在 Console 展示。审核员可在 Console 查看举报记录,并进行相应处理。 +即时通讯 IM SDK 提供消息举报接口。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +:::tip +1. 使用前,你需要在[环信即时通讯云控制台](https://console.easemob.com/user/login) 开通该功能。 +2. 消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +关于如何开通消息举报和查看举报记录,详见[环信即时通讯云控制台文档说明](/product/enable_and_configure_IM.html#消息举报)。 ## 技术原理 @@ -13,7 +20,7 @@ 开始前,请确保满足以下条件: - 完成 SDK 初始化,并连接到服务器,详见 [快速开始](quickstart.html)。 -- 开通消息审核服务,详见管理后台。 +- 已在 [环信即时通讯云控制台开通消息举报功能](/product/enable_and_configure_IM.html#消息举报)。 - 了解环信即时通讯 IM 的使用限制,详见 [使用限制](/product/limitation.html)。 ## 实现方法 @@ -23,7 +30,7 @@ ```csharp // msgId:要举报的消息 ID。 // tag:非法消息的标签。你需要自定义标签,例如`涉政`或`广告`。该字段对应环信即时通讯云控制台的消息举报记录页面的`词条标记`字段。 -// reason:举报原因。你需要自行填写举报原因。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 +// reason:举报原因。你需要自行填写举报原因,最长不能超过 512 字节。该字段对应环信即时通讯云控制台的消息举报记录页面的`举报原因`字段。 SDKClient.Instance.ChatManager.ReportMessage(msgId, tag, reason, new CallBack( onSuccess: () => { diff --git a/docs/document/windows/multi_device.md b/docs/document/windows/multi_device.md index a21209e6e..22e9f5ec7 100644 --- a/docs/document/windows/multi_device.md +++ b/docs/document/windows/multi_device.md @@ -74,10 +74,10 @@ SDKClient.Instance.ContactManager.GetSelfIdsOnOtherPlatform(new ValueCallBack>( onSuccess: (list) => { - // 选择一个登录 ID 作为消息发送方。 + // 选择一个登录 ID 作为消息接收方。 string toChatUsername = list[0]; string content = "content"; - // 创建一条文本消息,content 为消息文字内容,toChatUsername 传入登录 ID 作为消息发送方。 + // 创建一条文本消息,content 为消息文字内容,toChatUsername 传入登录 ID 作为消息接收方。 Message msg = Message.CreateTextSendMessage(toChatUsername, content); // 发送消息。 SDKClient.Instance.ChatManager.SendMessage(ref msg, new CallBack( diff --git a/docs/document/windows/overview.md b/docs/document/windows/overview.md index 8366fba77..569fda4d6 100644 --- a/docs/document/windows/overview.md +++ b/docs/document/windows/overview.md @@ -245,4 +245,20 @@ SDKClient.Instance.DeleteConnectionDelegate(connectionDelegate); ## 输出信息到日志文件 -如果开启日志调试模式,会通过控制台输出日志。`DebugMode` 设置为 `true`。 +环信即时通讯 IM 日志记录 SDK 相关的信息和事件。环信技术支持团队帮你排查问题时可能会请你发送 SDK 日志。 + +默认情况下,SDK 最多可生成和保存三个文件,`easemob.log` 和两个 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件。这些文件为 UTF-8 编码,每个不超过 2 MB。SDK 会将最新的日志写入 `easemob.log` 文件,写满时则会将其重命名为对应时间点的 `easemob_YYYY-MM-DD_HH-MM-SS.log` 文件,若日志文件超过三个,则会删除最早的文件。 + +例如,SDK 在 2024 年 1 月 1 日上午 8:00:00 记录日志时会生成 `easemob.log` 文件,若在 8:30:00 将 `easemob.log` 文件写满则会将其重命名为 `easemob_2024-01-01_08-30-00.log` 文件,随后在 9:30:30 和 10:30:30 分别生成了 `easemob_2024-01-01_09-30-30.log` 和 `easemob_2024-01-01_10-30-30.log` 文件,则此时 `easemob_2024-01-01_08-30-00.log` 文件会被移除。 + +SDK 默认不输出调试信息(所有日志,包括调试信息、警告和错误),只需输出错误日志。若需调试信息,首先要开启调试模式。 + +```csharp +Options options = new Options("YourAppKey"); +options.DebugMode = true; +SDKClient.Instance.InitWithOptions(options); +``` + +### 获取本地日志 + +Windows SDK 日志位于可执行程序同级目录下的 `sdkdata\easemobLog` 目录中。 \ No newline at end of file diff --git a/docs/document/windows/presence.md b/docs/document/windows/presence.md index 24535c2cb..49b812784 100644 --- a/docs/document/windows/presence.md +++ b/docs/document/windows/presence.md @@ -6,10 +6,6 @@ 本文介绍如何在即时通讯应用中发布、订阅和查询用户的在线状态。 -:::notice -私有化版本不支持在线状态订阅。 -::: - ## 技术原理 环信 IM SDK 提供 `Presence`、`PresenceManager` 和 `IPresenceManagerDelegate` 类,用于管理在线状态订阅,包含如下核心方法: diff --git a/docs/document/windows/reaction.md b/docs/document/windows/reaction.md index c44dffdab..fd6381503 100644 --- a/docs/document/windows/reaction.md +++ b/docs/document/windows/reaction.md @@ -6,9 +6,9 @@ :::notice -1. 目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 -2. 私有化版本不支持 Reaction 功能。 - ::: +目前 Reaction 仅适用于单聊和群组。聊天室暂不支持 Reaction 功能。 + +::: ## 技术原理 diff --git a/docs/document/windows/releasenote.md b/docs/document/windows/releasenote.md index 83590b44b..ed200003a 100644 --- a/docs/document/windows/releasenote.md +++ b/docs/document/windows/releasenote.md @@ -25,7 +25,7 @@ - `SDKClient#GetLoggedInDevicesFromServerWithToken`:获取指定账号下登录的在线设备列表; - `SDKClient#KickDeviceWithToken`:将指定账号登录的指定设备踢下线; - `SDKClient#KickAllDevicesWithToken`:将指定账号登录的所有设备都踢下线。 -- [IM SDK] 新增[会话置顶功能](message_retrieve.html#置顶会话): +- [IM SDK] 新增[会话置顶功能](conversation_pin.html#置顶会话): - `Conversation#IsPinned`:判断该会话是否被置顶; - `Conversation#PinnedTime`:会话置顶时间戳。 - [IM SDK] 新增 `ChatManager#FetchHistoryMessagesFromServerBy` 方法根据消息拉取参数配置类 `FetchServerMessagesOption` 从服务器获取历史消息。
@@ -38,7 +38,7 @@ - `FetchServerMessagesOption#MsgTypes`:要查询的消息类型列表; - `FetchServerMessagesOption#StartTime`:消息查询的起始时间; - `FetchServerMessagesOption#EndTime`:消息查询的结束时间。 -- [IM SDK] 新增 `GetConversationsFromServerWithCursor` 方法从[服务端分页获取会话列表](message_retrieve.html#从服务器获取会话)。 +- [IM SDK] 新增 `GetConversationsFromServerWithCursor` 方法从[服务端分页获取会话列表](conversation_list.html#从服务器分页获取会话列表)。 - [IM SDK] 新增[在群组或聊天室中发送定向消息功能](message_send_receive.html#发送和接收定向消息): - `Message#ReceiverList`:设置群组或聊天室消息接收列表。 - [IM SDK] 新增删除本地数据库中指定时间段的消息: diff --git a/docs/document/windows/room_manage.md b/docs/document/windows/room_manage.md index de8dd6e1b..56bcfc41f 100644 --- a/docs/document/windows/room_manage.md +++ b/docs/document/windows/room_manage.md @@ -38,7 +38,7 @@ 仅 [超级管理员](/document/server-side/chatroom.html#管理超级管理员) 可以调用 `CreateRoom` 方法创建聊天室,并设置聊天室的名称、描述、最大成员数等信息。成功创建聊天室后,该超级管理员为该聊天室的所有者。 -你也可以直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 +建议直接调用 REST API [从服务端创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 示例代码如下: @@ -129,7 +129,8 @@ Options options = new Options(); options. DeleteMessagesAsExitRoom = false; ``` -与群主无法退出群组不同,聊天室所有者可以离开聊天室,例如所有者从服务器下线则 2 分钟后自动离开聊天室。如果所有者重新进入聊天室仍是该聊天室的所有者。 +与群主无法退出群组不同,聊天室所有者可以离开聊天室,离开后重新进入仍是该聊天室的所有者。若 `Options#IsRoomOwnerLeaveAllowed +` 参数在初始化时设置为 `true` 时,聊天室所有者可以离开聊天室;若该参数设置为 `false`,聊天室所有者调用 `LeaveRoom` 方法离开聊天室时会提示错误 706。 ### 解散聊天室 diff --git a/docs/document/windows/room_members.md b/docs/document/windows/room_members.md index 1f283c661..3c4aa33c9 100644 --- a/docs/document/windows/room_members.md +++ b/docs/document/windows/room_members.md @@ -46,7 +46,7 @@ SDKClient.Instance.RoomManager.FetchRoomMembers(roomId, cursor, pageSize, callba ### 将成员移出聊天室 -仅聊天室所有者和管理员可调用 `DeleteRoomMembers` 方法将指定成员移出聊天室。 +仅聊天室所有者和管理员可调用 `DeleteRoomMembers` 方法将单个或多个成员移出聊天室。 被移出后,该成员收到 `OnRemovedFromRoom` 回调,其他成员收到 `OnMemberExitedFromRoom` 回调。 @@ -194,6 +194,7 @@ SDKClient.Instance.RoomManager.RemoveAllowListMembers(roomId, list, new CallBack 示例代码如下: ```csharp +// muteMilliseconds:禁言时间。若传 -1,表示永久禁言。 SDKClient.Instance.RoomManager.MuteRoomMembers(roomId, members, new CallBack( onSuccess: () => { }, @@ -242,7 +243,9 @@ SDKClient.Instance.RoomManager.FetchRoomMuteList(roomId, pageSize, pageNum, call #### 开启聊天室全员禁言 -仅聊天室所有者和管理员可以调用 `MuteAllRoomMembers` 方法开启全员禁言。全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `OnAllMemberMuteChangedFromChatroom` 回调。 +仅聊天室所有者和管理员可以调用 `MuteAllRoomMembers` 方法开启全员禁言。全员禁言开启后不会在一段时间内自动取消禁言,需要调用 `UnMuteAllRoomMembers` 方法取消全员禁言。 + +全员禁言开启后,除了在白名单中的成员,其他成员不能发言。调用成功后,聊天室成员会收到 `OnAllMemberMuteChangedFromChatroom` 回调。 示例代码如下: diff --git a/docs/document/windows/thread.md b/docs/document/windows/thread.md index 0d4813c3e..db597c762 100644 --- a/docs/document/windows/thread.md +++ b/docs/document/windows/thread.md @@ -6,10 +6,6 @@ 如需查看消息相关内容,参见 [子区消息管理](thread_message.html)。 -:::notice -私有化版本不支持子区功能。 -::: - ## 技术原理 环信即时通讯 IM Windows SDK 提供 `IChatThreadManager`、`ChatThread`、`ChatThreadEvent` 和 `IChatThreadManagerDelegate` 类,用于管理子区,支持你通过调用 API 在项目中实现如下功能: diff --git a/docs/document/windows/thread_message.md b/docs/document/windows/thread_message.md index c0dc074a8..b21e8b685 100644 --- a/docs/document/windows/thread_message.md +++ b/docs/document/windows/thread_message.md @@ -93,7 +93,7 @@ SDKClient.Instance.ChatManager.RemoveChatManagerDelegate(adelegate); ### 撤回子区消息 -接收消息的具体逻辑,请参考[撤回消息](message_send_receive.html#撤回消息),此处只介绍子区消息和其他消息的区别。 +接收消息的具体逻辑,请参考[撤回消息](message_recall.html),此处只介绍子区消息和其他消息的区别。 子区有消息撤回时,子区所属群组的所有成员收到 `IChatThreadManagerDelegate#OnUpdateMyThread` 回调,子区成员收到 `IChatManagerDelegate#OnMessagesRecalled` 回调。 diff --git a/docs/document/windows/user_relationship.md b/docs/document/windows/user_relationship.md index 00ab02db7..ac2bd1118 100644 --- a/docs/document/windows/user_relationship.md +++ b/docs/document/windows/user_relationship.md @@ -35,9 +35,7 @@ SDK 提供用户关系管理功能,包括好友列表管理和黑名单管理 本节展示如何在项目中管理好友的添加移除和黑名单的添加移除。 -### 管理好友列表 - -#### 添加好友 +### 添加好友 好友请求部分主要功能是发送好友请求、接收好友请求、处理好友请求和好友请求处理结果回调等。 @@ -124,7 +122,7 @@ SDKClient.Instance.ContactManager.DeclineInvitation(username, callback: new Call 当你同意或者拒绝后,对方会通过好友事件回调,收到 `OnFriendRequestAccepted` 或者 `OnFriendRequestDeclined` 回调。 -#### 删除好友 +### 删除好友 调用 `DeleteContact` 删除指定联系人。被删除的用户收到 `OnContactDeleted` 回调。删除联系人时会同时删除对方联系人列表中的该用户,建议执行双重确认,以免发生误删操作。删除操作不需要对方同意或者拒绝。 @@ -141,18 +139,9 @@ SDKClient.Instance.ContactManager.DeleteContact(username, callback: new CallBack 调用 `DeleteContact` 删除好友后,对方会收到 `OnContactDeleted` 回调。 -#### 获取好友列表 - -你可以从服务器获取好友列表,也可以从本地数据库获取保存的好友列表。 - -:::notice -从服务器获取好友列表之后才能从本地数据库获取到好友列表。 -::: - -示例代码如下: +### 从服务器获取好友列表 ```csharp -//从服务器获取好友列表。 SDKClient.Instance.ContactManager.GetAllContactsFromServer(new ValueCallBack>( onSuccess: (list) => { @@ -161,19 +150,24 @@ SDKClient.Instance.ContactManager.GetAllContactsFromServer(new ValueCallBacklist = SDKClient.Instance.ContactManager.GetAllContactsFromDB(); ``` -### 管理黑名单 +### 添加用户到黑名单 黑名单是与好友无任何关系的独立体系。可以将任何用户加入黑名单,不论该用户与你是否是好友关系。 黑名单功能包括加入黑名单,从黑名单移出用户和获取黑名单列表。 -#### 添加用户到黑名单 - 你可以调用 `AddUserToBlockList` 添加用户到黑名单。用户被加入黑名单后,无法向你发送消息,也无法发送好友申请。 用户可以将任何其他用户添加到黑名单列表,无论该用户是否是好友。好友被加入黑名单后仍在好友列表上显示。 @@ -190,7 +184,7 @@ SDKClient.Instance.ContactManager.AddUserToBlockList(username, callback: new Cal )); ``` -#### 将用户从黑名单移除 +### 将用户从黑名单移除 你可以调用 `RemoveUserFromBlockList` 将用户从黑名单移除,用户发送消息等行为将恢复。 @@ -205,7 +199,7 @@ SDKClient.Instance.ContactManager.RemoveUserFromBlockList(username, callback: ne )); ``` -#### 从服务器获取黑名单列表 +### 从服务器获取黑名单列表 你可以调用 `GetBlockListFromServer` 从服务端获取黑名单列表。示例代码如下: diff --git a/docs/private/im/uc_deploy.md b/docs/private/im/uc_deploy.md index 0a3a99f70..af70c4f0f 100644 --- a/docs/private/im/uc_deploy.md +++ b/docs/private/im/uc_deploy.md @@ -69,7 +69,7 @@ ## 3、集成测试 -当服务端验证完成后,可通过下载需要的客户端 SDK 及 Demo 进行集成体验。环信客户端 SDK 已对 IM 核心服务完成封装, 通过调用 SDK API 接口,即可快速获得消息收发 、会话管理 、群组 、好友 、聊天室等功能。目前客户端 SDK 已覆盖 Windows 、Linux 、MacOS 、Android 、iOS 、Web 、小程序等多种平台,服务器端 SDK 已覆盖 Java 、PHP 等平台,[下载私有化客户端 SDK](http://docs-im-beta.easemob.com/private/im/uc_private.html#私有化-sdk-下载)。 +当服务端验证完成后,可通过下载需要的客户端 SDK 及 Demo 进行集成体验。环信客户端 SDK 已对 IM 核心服务完成封装, 通过调用 SDK API 接口,即可快速获得消息收发 、会话管理 、群组 、好友 、聊天室等功能。目前客户端 SDK 已覆盖 Windows 、Linux 、MacOS 、Android 、iOS 、Web 、小程序等多种平台,服务器端 SDK 已覆盖 Java 、PHP 等平台,[下载私有化客户端 SDK](http://doc.easemob.com/private/im/uc_private.html#私有化-sdk-下载)。 示例一:以 Android 端 demo 体验为例 diff --git a/docs/private/im/uc_lowcode.md b/docs/private/im/uc_lowcode.md index 382be8910..a1e2742b5 100644 --- a/docs/private/im/uc_lowcode.md +++ b/docs/private/im/uc_lowcode.md @@ -93,5 +93,5 @@ | Android | [下载体验](https://www.pgyer.com/Bt7N) | | iOS | [下载体验](https://www.pgyer.com/lbTC)| --> -授权开源
+授权免费开源
通过签署授权协议,环信可提供个性化协同源码以帮助合作伙伴或最终客户降低开发成本,加速项目进程。请联系程先生 (Tel:17611319060)。 \ No newline at end of file diff --git a/docs/private/im/uc_overview.md b/docs/private/im/uc_overview.md index 072a7725a..121745c85 100644 --- a/docs/private/im/uc_overview.md +++ b/docs/private/im/uc_overview.md @@ -82,5 +82,5 @@ | Android | [下载体验](https://download-sdk.oss-cn-beijing.aliyuncs.com/mp/poc/android/app-release.apk) | | iOS | [下载体验](https://testflight.apple.com/join/j1ssvXm0)| -授权开源
+授权免费开源
通过签署授权协议,环信可提供环信通源码以帮助合作伙伴或最终客户降低开发成本,加速项目进程。请联系程先生 (Tel:17611319060)。 \ No newline at end of file diff --git a/docs/private/im/uc_private.md b/docs/private/im/uc_private.md index 468bb6df4..a67754ba6 100644 --- a/docs/private/im/uc_private.md +++ b/docs/private/im/uc_private.md @@ -73,13 +73,13 @@

Android

-

3.9.1

+

3.9.1

下载 SDK 及 Demo 体验 Demo

-

查看

+

查看

@@ -87,13 +87,13 @@

Web

-

4.0.4

+

4.0.4

• React: 下载 SDK 及 Demo 体验 Demo
• Vue 2: 下载 SDK 及 Demo
• Vue 3: 下载 SDK 及 Demo

-

查看

+

查看

@@ -101,13 +101,13 @@

iOS

-

3.9.1

+

3.9.1

下载 SDK 及 Demo 

-

查看

+

查看

@@ -129,13 +129,13 @@

Windows(C#)

-

1.0.2

+

1.0.2

下载 SDK

-

查看

+

查看

@@ -217,7 +217,7 @@

下载 SDK

-

查看

+

查看

@@ -235,7 +235,7 @@

下载 SDK

-

查看

+

查看

@@ -249,7 +249,7 @@

下载 SDK

-

查看

+

查看

diff --git a/docs/private/media/conference_android.md b/docs/private/media/conference_android.md index 316262041..4c57da8f4 100644 --- a/docs/private/media/conference_android.md +++ b/docs/private/media/conference_android.md @@ -255,8 +255,8 @@ EMConferenceListener listener = new EMConferenceListener() { ### 8. 加入会议 -在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://docs-im-beta.easemob.com/document/android/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。
-若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://docs-im-beta.easemob.com/document/android/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7)。
+在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://doc.easemob.com/document/android/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。
+若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://doc.easemob.com/document/android/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7)。
登录环信ID以后,可以加入会议了,通过 [EMConferenceManager#joinRoom](http://sdkdocs.easemob.com/apidoc/android/chat3.0/classcom_1_1hyphenate_1_1chat_1_1_e_m_conference_manager.html#a8940f54febf2086ccd978d75980c7763) API加入房间。
- 创建会议成功以后,默认超时时间为三分钟,超过三分钟没有人加入,会议会自动销毁; - 另外当会议中所有人离开2分钟后,会议也会被销毁; diff --git a/docs/private/media/conference_ios.md b/docs/private/media/conference_ios.md index 4bf4035f8..b808c1dbb 100644 --- a/docs/private/media/conference_ios.md +++ b/docs/private/media/conference_ios.md @@ -185,8 +185,8 @@ retOpt.enableConsoleLog = YES; ### 7. 环信ID注册、登录 -在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://docs-im-beta.easemob.com/document/android/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。
-若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://docs-im-beta.easemob.com/document/android/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7)。
+在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://doc.easemob.com/document/android/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。
+若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://doc.easemob.com/document/android/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7)。
### 8. 音视频功能初始化 diff --git a/docs/private/media/conference_web.md b/docs/private/media/conference_web.md index 56f54527d..393976085 100644 --- a/docs/private/media/conference_web.md +++ b/docs/private/media/conference_web.md @@ -86,8 +86,8 @@ emedia.config({ ### 5. 环信ID注册、登录 -在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://docs-im-beta.easemob.com/document/web/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。
-若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://docs-im-beta.easemob.com/document/web/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7)。
+在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://doc.easemob.com/document/web/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。
+若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://doc.easemob.com/document/web/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7)。
### 6. 进入会议 diff --git a/docs/private/media/one2one_android.md b/docs/private/media/one2one_android.md index d69970715..9930152c9 100644 --- a/docs/private/media/one2one_android.md +++ b/docs/private/media/one2one_android.md @@ -192,9 +192,9 @@ public void init(Context context) { ### 8. 环信ID注册登录 -在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://docs-im-beta.easemob.com/document/android/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。 +在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://doc.easemob.com/document/android/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。 -若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://docs-im-beta.easemob.com/document/android/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7) +若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://doc.easemob.com/document/android/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7) ### 9. 音视频功能初始化 diff --git a/docs/private/media/one2one_ios.md b/docs/private/media/one2one_ios.md index 4b2bcf299..010dc23e1 100644 --- a/docs/private/media/one2one_ios.md +++ b/docs/private/media/one2one_ios.md @@ -133,9 +133,9 @@ retOpt.enableConsoleLog = YES; ### 7. 环信ID注册、登录 -在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://docs-im-beta.easemob.com/document/ios/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。 +在进行音视频通话前,需要首先登录IM账户,登录过程参见[账号登录](http://doc.easemob.com/document/ios/overview.html#%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95)。 -若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://docs-im-beta.easemob.com/document/ios/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7) +若您还没有IM账户,需要先注册账户,注册过程参见[账号注册](http://doc.easemob.com/document/ios/overview.html#%E6%B3%A8%E5%86%8C%E7%94%A8%E6%88%B7) ### 8. 音视频功能初始化 diff --git a/docs/private/media/scenario_live.md b/docs/private/media/scenario_live.md index 03b9c034b..cb40a2305 100644 --- a/docs/private/media/scenario_live.md +++ b/docs/private/media/scenario_live.md @@ -56,15 +56,15 @@ 多人视频会议如果需要环信即时通讯云的文字聊天室实现IM沟通功能,请详见文档: -服务器端: [聊天室管理](http://docs-im-beta.easemob.com/document/server-side/chatroom.html) +服务器端: [聊天室管理](http://doc.easemob.com/document/server-side/chatroom.html) -Android: [聊天室管理](http://docs-im-beta.easemob.com/document/android/room_overview.html) +Android: [聊天室管理](http://doc.easemob.com/document/android/room_overview.html) -iOS: [聊天室管理](http://docs-im-beta.easemob.com/document/ios/room_overview.html) +iOS: [聊天室管理](http://doc.easemob.com/document/ios/room_overview.html) -web端: [聊天室管理](http://docs-im-beta.easemob.com/document/web/room_overview.html) +web端: [聊天室管理](http://doc.easemob.com/document/web/room_overview.html) -微信小程序: [聊天室管理](http://docs-im-beta.easemob.com/document/applet/room_overview.html) +微信小程序: [聊天室管理](http://doc.easemob.com/document/applet/room_overview.html) PC端: [聊天室管理](https://docs-im.easemob.com/im/pc/basics/chatroom) diff --git a/docs/private/media/scenario_meeting.md b/docs/private/media/scenario_meeting.md index 10d6a2bca..f9c8d2bf9 100644 --- a/docs/private/media/scenario_meeting.md +++ b/docs/private/media/scenario_meeting.md @@ -41,15 +41,15 @@ 2. 多人视频会议如果需要环信即时通讯云的文字聊天室实现IM沟通功能,请详见文档: -服务器端: [聊天室管理](http://docs-im-beta.easemob.com/document/server-side/chatroom.html) +服务器端: [聊天室管理](http://doc.easemob.com/document/server-side/chatroom.html) -Android: [聊天室管理](http://docs-im-beta.easemob.com/document/android/room_overview.html) +Android: [聊天室管理](http://doc.easemob.com/document/android/room_overview.html) -iOS: [聊天室管理](http://docs-im-beta.easemob.com/document/ios/room_overview.html) +iOS: [聊天室管理](http://doc.easemob.com/document/ios/room_overview.html) -web端: [聊天室管理](http://docs-im-beta.easemob.com/document/web/room_overview.html) +web端: [聊天室管理](http://doc.easemob.com/document/web/room_overview.html) -微信小程序: [聊天室管理](http://docs-im-beta.easemob.com/document/applet/room_overview.html) +微信小程序: [聊天室管理](http://doc.easemob.com/document/applet/room_overview.html) PC端: [聊天室管理](https://docs-im.easemob.com/im/pc/basics/chatroom) diff --git a/docs/private/media/scenario_one2one.md b/docs/private/media/scenario_one2one.md index c1c5d98d3..d16ec0f90 100644 --- a/docs/private/media/scenario_one2one.md +++ b/docs/private/media/scenario_one2one.md @@ -31,14 +31,14 @@ 2. 一对一音视频还需要用到环信即时通讯云的基础IM功能,请详见文档: -服务器端:[服务端集成](http://docs-im-beta.easemob.com/document/server-side/overview.html) +服务器端:[服务端集成](http://doc.easemob.com/document/server-side/overview.html) -Android:[Android SDK 介绍及导入](http://docs-im-beta.easemob.com/document/android/quickstart.html) +Android:[Android SDK 介绍及导入](http://doc.easemob.com/document/android/quickstart.html) -iOS:[iOS SDK 快速集成](http://docs-im-beta.easemob.com/document/ios/quickstart.html) +iOS:[iOS SDK 快速集成](http://doc.easemob.com/document/ios/quickstart.html) -web端: [Web IM 介绍](http://docs-im-beta.easemob.com/document/web/quickstart.html) +web端: [Web IM 介绍](http://doc.easemob.com/document/web/quickstart.html) -微信小程序: [微信小程序SDK简介](http://docs-im-beta.easemob.com/document/applet/wechat.html) +微信小程序: [微信小程序SDK简介](http://doc.easemob.com/document/applet/wechat.html) PC端: [桌面端集成说明](https://docs-im.easemob.com/im/pc/intro/integration) \ No newline at end of file diff --git a/docs/product/circle/api_reference_android.md b/docs/product/circle/api_reference_android.md index b62ac28da..6e434f9c4 100644 --- a/docs/product/circle/api_reference_android.md +++ b/docs/product/circle/api_reference_android.md @@ -1,6 +1,7 @@ ---- -{ - pageUri: "https://www.easemob.com/apidoc/Android/hyphenate-api-doc/html/annotated.html", - title: "环信超级社区 Android SDK API 参考" -} ---- \ No newline at end of file +# 环信超级社区 Android SDK API 参考 + + + +若要访问环信超级社区 Android SDK API 参考,请点击[这里](https://www.easemob.com/apidoc/Android/hyphenate-api-doc/html/annotated.html)。 + + diff --git a/docs/product/circle/api_reference_ios.md b/docs/product/circle/api_reference_ios.md index e78f934a8..3ab48bd8b 100644 --- a/docs/product/circle/api_reference_ios.md +++ b/docs/product/circle/api_reference_ios.md @@ -1,6 +1,5 @@ ---- -{ - pageUri: "https://www.easemob.com/apidoc/iOS/html_ch/annotated.html", - title: "环信超级社区 iOS SDK API 参考" -} ---- \ No newline at end of file +# 环信超级社区 iOS SDK API 参考 + + + +若要访问环信超级社区 iOS SDK API 参考,请点击[这里](https://www.easemob.com/apidoc/iOS/html_ch/annotated.html)。 \ No newline at end of file diff --git a/docs/product/circle/api_reference_web.md b/docs/product/circle/api_reference_web.md index 0cd659449..1dbe69268 100644 --- a/docs/product/circle/api_reference_web.md +++ b/docs/product/circle/api_reference_web.md @@ -1,6 +1,5 @@ ---- -{ - pageUri: "https://www.easemob.com/apidoc/Web/", - title: "环信超级社区 Web SDK API 参考" -} ---- \ No newline at end of file +# 环信超级社区 Web SDK API 参考 + + + +若要访问环信超级社区 Web SDK API 参考,请点击[这里](https://www.easemob.com/apidoc/Web/)。 \ No newline at end of file diff --git a/docs/product/circle/category_mgmt_android.md b/docs/product/circle/category_mgmt_android.md index 73407a293..0be996be8 100644 --- a/docs/product/circle/category_mgmt_android.md +++ b/docs/product/circle/category_mgmt_android.md @@ -1,5 +1,7 @@ # 管理频道分组 + + 环信超级社区(Circle)支持将多个频道归入一个频道分组,方便频道管理。例如,可将歌剧频道、民歌频道和流行歌曲频道划分为声乐频道分组。 社区创建时会创建默认的频道分组,包含默认频道。 diff --git a/docs/product/circle/category_mgmt_ios.md b/docs/product/circle/category_mgmt_ios.md index f3e221dcb..3c607d3a0 100644 --- a/docs/product/circle/category_mgmt_ios.md +++ b/docs/product/circle/category_mgmt_ios.md @@ -1,5 +1,7 @@ # 管理频道分组 + + 环信超级社区(Circle)支持将多个频道归入一个频道分组,方便频道管理。例如,可将歌剧频道、民歌频道和流行歌曲频道划分为声乐频道分组。 社区创建时会创建默认的频道分组,包含默认频道。 diff --git a/docs/product/circle/category_mgmt_rest.md b/docs/product/circle/category_mgmt_rest.md index e7e207128..82006ed20 100644 --- a/docs/product/circle/category_mgmt_rest.md +++ b/docs/product/circle/category_mgmt_rest.md @@ -1,5 +1,7 @@ # 管理社区频道分组 + + 环信超级社区(Circle)支持频道分组方便频道管理。例如,可将歌剧频道、民歌频道和流行歌曲频道划分为声乐频道分组。 社区创建时会创建默认的频道分组,包含默认频道。 diff --git a/docs/product/circle/category_mgmt_web.md b/docs/product/circle/category_mgmt_web.md index f0f740315..46762e3d8 100644 --- a/docs/product/circle/category_mgmt_web.md +++ b/docs/product/circle/category_mgmt_web.md @@ -1,5 +1,7 @@ # 管理频道分组 + + 环信超级社区(Circle)支持将多个频道归入一个频道分组,方便频道管理。例如,可将歌剧频道、民歌频道和流行歌曲频道划分为声乐频道分组。 社区创建时会创建默认的频道分组,包含默认频道。 diff --git a/docs/product/circle/channel_mgmt_android.md b/docs/product/circle/channel_mgmt_android.md index 3b748141f..1934ef975 100644 --- a/docs/product/circle/channel_mgmt_android.md +++ b/docs/product/circle/channel_mgmt_android.md @@ -1,5 +1,7 @@ # 管理频道 + + 频道(Channel)是一个社区下不同子话题的讨论分区,因此一个社区下可以有多个频道。社区创建时会自动创建默认频道,该频道中添加了所有社区成员,用于承载各种系统通知。从可见性角度看,频道社区分为公开和私密频道;从功能角度看,频道分为文字频道和语聊频道。社区创建者可以根据自己需求创建频道。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** diff --git a/docs/product/circle/channel_mgmt_ios.md b/docs/product/circle/channel_mgmt_ios.md index eacb28461..467d1d075 100644 --- a/docs/product/circle/channel_mgmt_ios.md +++ b/docs/product/circle/channel_mgmt_ios.md @@ -1,5 +1,7 @@ # 管理频道 + + 频道(Channel)是一个社区下不同子话题的讨论分区,因此一个社区下可以有多个频道。社区创建时会自动创建默认频道,该频道中添加了所有社区成员,用于承载各种系统通知。从可见性角度看,频道社区分为公开和私密频道;从功能角度看,频道分为文字频道和语聊频道。社区创建者可以根据自己需求创建频道。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** diff --git a/docs/product/circle/channel_mgmt_rest.md b/docs/product/circle/channel_mgmt_rest.md index ee47d5b65..5f729ae79 100644 --- a/docs/product/circle/channel_mgmt_rest.md +++ b/docs/product/circle/channel_mgmt_rest.md @@ -1,5 +1,7 @@ # 管理频道以及频道成员 + + 频道(Channel)是一个社区下不同子话题的讨论分区,因此一个社区下可以有多个频道。社区创建时会自动创建默认频道,该频道中添加了所有社区成员,用于承载各种系统通知。从可见性角度看,频道社区分为公开和私密频道;从功能角度看,频道分为文字频道和语聊频道。用户可以根据自己需求创建频道。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** @@ -13,8 +15,8 @@ 要调用环信即时通讯 RESTful API,请确保满足以下要求: -- 已在环信即时通讯控制台 [开通配置环信即时通讯 IM 服务](http://docs-im-beta.easemob.com/document/server-side/enable_and_configure_IM.html)。 -- 了解环信 IM RESTful API 的调用频率限制,详见 [接口频率限制](http://docs-im-beta.easemob.com/product/limitationapi.html)。 +- 已在环信即时通讯控制台 [开通配置环信即时通讯 IM 服务](http://doc.easemob.com/document/server-side/enable_and_configure_IM.html)。 +- 了解环信 IM RESTful API 的调用频率限制,详见 [接口频率限制](http://doc.easemob.com/product/limitationapi.html)。 ## 公共参数 @@ -22,9 +24,9 @@ | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :----------------------------------------------------------- | -| `host` | String | 是 | 环信即时通讯 IM 分配的用于访问 RESTful API 的域名。详见[获取环信即时通讯 IM 的信息](http://docs-im-beta.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | -| `org_name` | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见[获取环信即时通讯 IM 的信息](http://docs-im-beta.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | -| `app_name` | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见[获取环信即时通讯 IM 的信息](http://docs-im-beta.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `host` | String | 是 | 环信即时通讯 IM 分配的用于访问 RESTful API 的域名。详见[获取环信即时通讯 IM 的信息](http://doc.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `org_name` | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见[获取环信即时通讯 IM 的信息](http://doc.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `app_name` | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见[获取环信即时通讯 IM 的信息](http://doc.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | | `server_id` | String | 是 | 社区 ID。 | | `channel_id` | String | 是 | 频道 ID。 | | `user_id` | String | 是 | 用户 ID。 | @@ -112,7 +114,7 @@ POST https://{host}/{org_name}/{app_name}/circle/channel | `code` | Int | 环信超级社区的服务状态码。 | | `channel` | JSON | 频道详情。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -252,7 +254,7 @@ PUT https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}?serverId={s 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -330,7 +332,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}?serverId={s 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -433,7 +435,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/public?serverId={server_ 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -514,7 +516,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/user/{user_id}/created/c 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -596,7 +598,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/user/joined/list?userId= 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -677,7 +679,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/private?serverId={server 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -751,7 +753,7 @@ DELETE https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}?serverId | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -820,7 +822,7 @@ POST https://{host}/{org_name}/{app_name}/circle/reaction/user/{user_id} | `code` | Int | 环信超级社区的服务状态码。 | | `reaction_id` | String | Reaction ID。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -890,7 +892,7 @@ GET https://{host}/{org_name}/{app_name}/circle/reaction/user/{user_id}?msgIdLis | `reactionList.count` | Int | 向消息添加了该 Reaction 的用户数量。| | `reactionList.userList` | List | 添加了该 Reaction 的用户 ID 列表。| -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -965,7 +967,7 @@ DELETE https://{host}/{org_name}/{app_name}/circle/reaction/user/{user_id}?messa | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1027,7 +1029,7 @@ POST https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/join?userI 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1098,7 +1100,7 @@ POST https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/user/remov | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1161,7 +1163,7 @@ POST https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/users/remo | `data.user` | String | 被移除的频道成员的用户 ID。 | | `data.result` | Bool | 频道成员是否被成功移除:
- `true`:移除成功;
- `false`:移除失败。失败的原因可能是用户不在频道所属的社区中、用户不在频道中、用户为频道所有者等。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1240,7 +1242,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/user/{user_ | `code` | Int | 环信超级社区的服务状态码。 | | `result` | Boolean | 查询结果:
- `true`:用户在频道中;
- `false`:用户不在频道中。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1301,7 +1303,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/user/role?s 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1371,7 +1373,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/users?serve 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1444,7 +1446,7 @@ GET https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/user/mute/l | `mute_users.expire` | Long | 禁言的到期时间,Unix 时间戳,单位为毫秒。 | | `mute_users.user` | String | 被禁言的成员的用户 ID。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1514,7 +1516,7 @@ POST https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/user/mute | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1577,7 +1579,7 @@ DELETE https://{host}/{org_name}/{app_name}/circle/channel/{channel_id}/user/mut 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1640,7 +1642,7 @@ POST https://{host}/{org_name}/{app_name}/circle/thread | `code` | Int | 环信超级社区的服务状态码。 | | `thread_id` | String | 子区 ID。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1703,7 +1705,7 @@ PUT https://{host}/{org_name}/{app_name}/circle/thread/{thread_id} | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1815,7 +1817,7 @@ DELETE https://{host}/{org_name}/{app_name}/circle/thread/{thread_id} | :--- | :--- | :------------------ | | code | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1865,7 +1867,7 @@ POST https://{host}/{org_name}/{app_name}/circle/thread/{thread_id}/user/join?us | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -2063,7 +2065,7 @@ curl -X GET https://{host}/{org_name}/{app_name}/circle/thread/list?channelId={c | `threads.created` | Long | 子区创建时间,Unix 时间戳,单位为毫秒。 | | `cursor` | String | 游标,指定下次查询的开始位置。| -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -2139,7 +2141,7 @@ GET https://{host}/{org_name}/{app_name}/circle/thread/joined?userId={user_id}&c | `threads.created` | Long | 子区创建时间,Unix 时间戳,单位为毫秒。 | | `cursor` | String | 游标,指定下次查询的开始位置。| -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 diff --git a/docs/product/circle/channel_mgmt_web.md b/docs/product/circle/channel_mgmt_web.md index 093083555..50af48a05 100644 --- a/docs/product/circle/channel_mgmt_web.md +++ b/docs/product/circle/channel_mgmt_web.md @@ -1,5 +1,7 @@ # 管理频道 + + 频道(Channel)是一个社区下不同子话题的讨论分区,因此一个社区下可以有多个频道。社区创建时会自动创建默认频道,该频道中添加了所有社区成员,用于承载各种系统通知。从可见性角度看,频道社区分为公开和私密频道;从功能角度看,频道分为文字频道和语聊频道。社区创建者可以根据自己需求创建频道。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** diff --git a/docs/product/circle/circle_overview.md b/docs/product/circle/circle_overview.md index 94aace2a3..5c26af7b9 100644 --- a/docs/product/circle/circle_overview.md +++ b/docs/product/circle/circle_overview.md @@ -1,5 +1,7 @@ # 环信超级社区概述 + + 环信超级社区(Circle)是一款基于环信 IM 打造的类 Discord 实时社区应用场景方案,支持社区(Server)、频道(Channel) 和子区(Thread) 三层结构。一个 App 下可以有多个社区,同时支持陌生人/好友单聊。用户可创建和管理自己的社区,在社区中设置和管理频道将一个话题下的子话题进行分区,在频道中根据感兴趣的某条消息发起子区讨论,实现万人实时群聊,满足超大规模用户的顺畅沟通需求。 ## 社区、频道和子区介绍 diff --git a/docs/product/circle/circle_quickstart_android.md b/docs/product/circle/circle_quickstart_android.md index d23cb6a7f..d3f5fe2f8 100644 --- a/docs/product/circle/circle_quickstart_android.md +++ b/docs/product/circle/circle_quickstart_android.md @@ -1,5 +1,7 @@ # 环信超级社区(Circle)快速开始 + + ## 集成准备 使用 Circle 之前,确保你已经集成环信即时通讯 IM Android SDK 3.9.9.2,详见 [环信即时通讯 IM Android 快速开始](/document/android/quickstart.html)。 diff --git a/docs/product/circle/circle_quickstart_ios.md b/docs/product/circle/circle_quickstart_ios.md index 9de6b070a..ef9696553 100644 --- a/docs/product/circle/circle_quickstart_ios.md +++ b/docs/product/circle/circle_quickstart_ios.md @@ -1,5 +1,7 @@ # 环信超级社区(Circle)快速开始 + + ## 集成准备 使用 Circle 之前,确保你已经集成环信即时通讯 IM iOS SDK 3.9.9.1,详见 [环信即时通讯 IM iOS 快速开始](/document/ios/quickstart.html)。 diff --git a/docs/product/circle/circle_quickstart_web.md b/docs/product/circle/circle_quickstart_web.md index bf36a8636..e82b7a2de 100644 --- a/docs/product/circle/circle_quickstart_web.md +++ b/docs/product/circle/circle_quickstart_web.md @@ -1,5 +1,7 @@ # 环信超级社区 (Circle) 快速开始 + + ## 集成准备 使用 Circle 前,确保你已经集成环信即时通讯 IM Web SDK 4.1.4-beta,详见 [环信即时通讯 IM Web 快速开始](/document/web/quickstart.html)。 diff --git a/docs/product/circle/server_mgmt_android.md b/docs/product/circle/server_mgmt_android.md index 1a6045ac0..169f5deab 100644 --- a/docs/product/circle/server_mgmt_android.md +++ b/docs/product/circle/server_mgmt_android.md @@ -1,5 +1,7 @@ # 管理社区 + + 社区(Server)是一群有着共同兴趣爱好的人的专属天地,也可以是同学朋友的社交圈子。社区是环信圈子三层基础架构的最上层,各种消息事件均发生在社区内。社区分为公开社区和私密社区。对于公开社区,任何用户均可查询社区列表,可自由加入或退出社区,无需审批;对于私密社区,用户无法查询社区列表,只能通过社区成员邀请加入社区,无法申请加入社区。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** diff --git a/docs/product/circle/server_mgmt_ios.md b/docs/product/circle/server_mgmt_ios.md index cda642c5a..013b7fd4d 100644 --- a/docs/product/circle/server_mgmt_ios.md +++ b/docs/product/circle/server_mgmt_ios.md @@ -1,5 +1,7 @@ # 管理社区 + + 社区(Server)是一群有着共同兴趣爱好的人的专属天地,也可以是同学朋友的社交圈子。社区是环信圈子三层基础架构的最上层,各种消息事件均发生在社区内。社区分为公开社区和私密社区。对于公开社区,任何用户均可查询社区列表,可自由加入或退出社区,无需审批;对于私密社区,用户无法查询社区列表,只能通过社区成员邀请加入社区,无法申请加入社区。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** diff --git a/docs/product/circle/server_mgmt_rest.md b/docs/product/circle/server_mgmt_rest.md index 6a1913407..76614fce9 100644 --- a/docs/product/circle/server_mgmt_rest.md +++ b/docs/product/circle/server_mgmt_rest.md @@ -1,5 +1,7 @@ # 管理社区及其成员 + + 社区(Server)是一群有着共同兴趣爱好的人的专属天地,也可以是同学朋友的社交圈子。社区是环信圈子三层基础架构的最上层,各种消息事件均发生在社区内。社区分为公开社区和私密社区。用户可查询公开社区列表,但无法查询私密社区列表。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** @@ -13,8 +15,8 @@ 要调用环信即时通讯 RESTful API,请确保满足以下要求: -- 已在环信即时通讯控制台 [开通配置环信即时通讯 IM 服务](http://docs-im-beta.easemob.com/document/server-side/enable_and_configure_IM.html)。 -- 了解环信 IM RESTful API 的调用频率限制,详见 [接口频率限制](http://docs-im-beta.easemob.com/product/limitationapi.html)。 +- 已在环信即时通讯控制台 [开通配置环信即时通讯 IM 服务](http://doc.easemob.com/document/server-side/enable_and_configure_IM.html)。 +- 了解环信 IM RESTful API 的调用频率限制,详见 [接口频率限制](http://doc.easemob.com/product/limitationapi.html)。 ## 公共参数 @@ -22,9 +24,9 @@ | 参数 | 类型 | 是否必需 | 描述 | | :--------- | :----- | :------- | :----------------------------------------------------------- | -| `host` | String | 是 | 环信即时通讯 IM 分配的用于访问 RESTful API 的域名。详见[获取环信即时通讯 IM 的信息](http://docs-im-beta.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | -| `org_name` | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见[获取环信即时通讯 IM 的信息](http://docs-im-beta.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | -| `app_name` | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见[获取环信即时通讯 IM 的信息](http://docs-im-beta.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `host` | String | 是 | 环信即时通讯 IM 分配的用于访问 RESTful API 的域名。详见[获取环信即时通讯 IM 的信息](http://doc.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `org_name` | String | 是 | 环信即时通讯 IM 为每个公司(组织)分配的唯一标识。详见[获取环信即时通讯 IM 的信息](http://doc.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | +| `app_name` | String | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。详见[获取环信即时通讯 IM 的信息](http://doc.easemob.com/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 | | `server_id` | String | 是 | 社区 ID。 | | `channel_id` | String | 是 | 频道 ID。 | | `user_id` | String | 是 | 用户 ID。 | @@ -60,7 +62,7 @@ Authorization:`Bearer ${YourAppToken}` -为提高项目的安全性,环信使用 App Token(动态密钥)对即将登录即时通讯系统的用户进行鉴权。即时通讯 RESTful API 需使用 App Token 的鉴权方式,详见 [使用环信 App Token 鉴权](http://docs-im-beta.easemob.com/product/easemob_app_token.html)。 +为提高项目的安全性,环信使用 App Token(动态密钥)对即将登录即时通讯系统的用户进行鉴权。即时通讯 RESTful API 需使用 App Token 的鉴权方式,详见 [使用环信 App Token 鉴权](http://doc.easemob.com/product/easemob_app_token.html)。 ### 查询环信超级社区用户是否存在 @@ -94,7 +96,7 @@ GET https://{host}/{org_name_}/{app_name}/circle/user/{user_id} | `code` | Int | 环信超级社区的服务状态码。 | | `result` | Boolean | 查询结果:
- `true`:用户存在;
- `false`:用户不存在。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -157,7 +159,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/list/by-app?limit={limit} 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/channelapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -243,7 +245,7 @@ POST https://{host}/{org_name}/{app_name}/circle/server | `code` | Int | 环信超级社区的服务状态码。 | | `server_id` | String | 社区 ID。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -320,7 +322,7 @@ PUT https://{host}/{org_name}/{app_name}/circle/server/{server_id} 其他字段及描述详见 [公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考 [响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考 [响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -404,7 +406,7 @@ POST https://{host}/{org_name}/{app_name}/circle/server/{server_id}/tag/add 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -466,7 +468,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/{server_id}/tag 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -530,7 +532,7 @@ POST https://{host}/{org_name}/{app_name}/circle/server/{server_id}/tag/remove | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -598,7 +600,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/search/{name}?type=0&limi 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -667,7 +669,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/{server_id}/by-id 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -741,7 +743,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/recommend/list 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -827,7 +829,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/list?userId={user_id}&lim 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -900,7 +902,7 @@ DELETE https://{host}/{org_name}/{app_name}/circle/server/{server_id} | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -964,7 +966,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/{server_id}/users?limit={ 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1025,7 +1027,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/{server_id}/users/count 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1088,7 +1090,7 @@ POST https://{host}/{org_name}/{app_name}/circle/server/{server_id}/join?userId= 其他字段及描述详见[公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1217,7 +1219,7 @@ GET https://{host}/{org_name}/{app_name}/circle/server/{server_id}/user/role?use 其他字段及描述详见 [公共参数](https://docs-im.easemob.com/ccim/circle/rest/serverapi#公共参数)。 -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1275,7 +1277,7 @@ PUT https://{host}/{org_name}/{app_name}/circle/server/{server_id}/user/role?use | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 @@ -1331,7 +1333,7 @@ POST https://{host}/{org_name}/{app_name}/circle/server/{server_id}/user/remove? | :--- | :--- | :------------------ | | `code` | Int | 环信超级社区的服务状态码。 | -如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://docs-im-beta.easemob.com/document/server-side/error.html)了解可能的原因。 +如果返回的 HTTP 状态码非 `200`,表示请求失败。你可以参考[响应状态码](http://doc.easemob.com/document/server-side/error.html)了解可能的原因。 #### 示例 diff --git a/docs/product/circle/server_mgmt_web.md b/docs/product/circle/server_mgmt_web.md index e1d75f18d..73f329fbf 100644 --- a/docs/product/circle/server_mgmt_web.md +++ b/docs/product/circle/server_mgmt_web.md @@ -1,5 +1,7 @@ # 管理社区 + + 社区(Server)是一群有着共同兴趣爱好的人的专属天地,也可以是同学朋友的社交圈子。社区是环信圈子三层基础架构的最上层,各种消息事件均发生在社区内。社区分为公开社区和私密社区。对于公开社区,任何用户均可查询社区列表,可自由加入或退出社区,无需审批;对于私密社区,用户无法查询社区列表,只能通过社区成员邀请加入社区,无法申请加入社区。 **超级社区中的频道基于即时通讯 IM 的群组或聊天室(频道 ID 为群组 ID 或聊天室 ID)创建,删除群组或聊天室时需注意以下几点:** diff --git a/docs/product/enable_and_configure_IM.md b/docs/product/enable_and_configure_IM.md index 0c1a5da3b..b9e171733 100644 --- a/docs/product/enable_and_configure_IM.md +++ b/docs/product/enable_and_configure_IM.md @@ -51,7 +51,7 @@ | 参数项 | 描述 | | :----------------------- | :-------------------------------------------- | | 选择要开通服务的 Appkey | 请确认 App Key 是否选择正确,购买后无法修改。 | -| 请选择服务版本 | 服务版本的选择如下:
- 当 App Key 为免费版时,可购买专业版、旗舰版或尊享版,不可单独购买增值服务。
- 当 App Key 为专业版时,可购买旗舰版、尊享版或单独购买增值服务。
- 当 App Key 为旗舰版时,可购买尊享版或单独购买增值服务。
- 当 App Key 为尊享版时,仅支持单独购买增值服务。| +| 请选择服务版本 | 服务版本的选择如下:
- 当 App Key 为免费版时,可购买专业版或旗舰版,不可单独购买增值服务。
- 当 App Key 为专业版时,可购买旗舰版或单独购买增值服务。| | 可选增值服务 | 请根据实际需求选择增值功能:
- 单个群成员数上限和单个用户可加入群组数上限:不支持叠加购买;以单个群成员数上限举例说明,如果旗舰版购买了 8000 人/群的增值服务,则表示单个群成员上限配置提升至 8000 人/群。
- 消息云存储时长和 REST API 接口调用频率上限:支持可叠加购买,即支持多倍购买;以消息云存储时长举例说明,如购买时选择了 10 份,则表示消息云存储时长延长 300 天(30 天*10)。 | :::notice @@ -109,24 +109,97 @@ 1. 在环信即时通讯云控制台首页的**应用列表**中,在目标应用的 **操作** 栏中,点击 **查看**。 -![img](@static/images/product/credentials.png) +![img](@static/images/product/push/push_app_list.png) 2. 在左侧导航栏,选择 **即时通讯** > **功能配置** > **消息推送** > **证书管理**,进入 **证书管理** 页面。 -![img](@static/images/product/push-settings.png) +![img](@static/images/product/push/push_settings.png) 3. 点击 **添加推送证书** 按钮,打开 **添加推送证书** 对话框。 -![img](@static/images/product/push-settings-window.png) +![img](@static/images/product/push/push_settings_window.png) 4. 在 **添加推送证书** 对话框中,填写各厂商平台的相关推送信息,点击 **保存** 按钮,完成证书配置。 -![img](@static/images/product/push-settings-form.png) +![img](@static/images/product/push/push_settings_form.png) + + +## 配置推送模板 + +若使用推送模板,你首先要在环信即时通讯云控制台选择 **即时通讯** > **功能配置** > **功能配置总览** 开启离线推送高级功能。 + +开启后,你可以配置默认推送模板和自定义推送模板。 + +![img](@static/images/product/push/enable_advanced_function.png) + +### 使用默认推送模板 + +默认推送模板主要用于服务器提供的默认配置不满足你的需求时,可使你设置全局范围的推送标题和推送内容。例如,服务器提供的默认设置为中文和英文的推送标题和内容,你若需要使用韩语或日语的推送标题和内容,则可以设置对应语言的推送模板。 + +要使用默认模板,你需要在环信即时通讯云控制台或[调用 RESTful 接口](/document/server-side/push.html#创建离线推送模板)创建默认推送模板,模板名称为 **default**。设置完毕,消息推送时自动使用默认模板,创建消息时无需传入模板名称。 + +按照以下步骤创建默认推送模板: + +1. 在环信即时通讯云控制台首页的**应用列表**中,在目标应用的 **操作** 栏中,点击 **查看**。 + +![img](@static/images/product/push/push_app_list.png) + +2. 在左侧导航栏,选择 **即时通讯** > **功能配置** > **消息推送** > **模板管理**,进入 **模板管理** 页面。 + +![img](@static/images/product/push/push_template.png) + +3. 点击 **添加推送模板**,在弹出的窗口中配置**模板名称**、**标题**和**内容**。 + +- **模板名称**:推送模板名称,String 类型,默认模板为 **default**。该参数必须填写。模板名称最多可包含 64 个字符,支持以下字符集: + - 26 个小写英文字母 a-z; + - 26 个大写英文字母 A-Z; + - 10 个数字 0-9。 +- **标题**/**内容**:推送标题/内容。Array 类型,该参数必须填写。这两个参数的设置方式如下: + - 输入固定的推送标题,例如,标题为 “您好”,内容为“您有一条新消息”。 + - 内置参数填充: + - `{$dynamicFrom}`:按优先级从高到底的顺序填充好友备注、群昵称(仅限群消息)和推送昵称。 + - `{$fromNickname}`:推送昵称。 + - `{$msg}`:消息内容。 + - 自定义参数填充:模板输入数组索引占位符,格式为: {0} {1} {2} ... {n} + + 对于推送标题和内容来说,前两种设置方式在创建消息时无需传入该参数,第三种设置方式则需要通过扩展字段传入。 + + 推送模板参数在消息扩展 `ext.em_push_template` 中。推送模板参数的 JSON 结构如下: + + ```json + { + "ext":{ + "em_push_template":{ + "title_args":[ + "环信" + ], + "content_args":[ + "欢迎使用im-push", + "加油" + ] + } + } + } + + # title: {0} = "环信" + # content: {0} = "欢迎使用im-push" {1} = "加油" + ``` + + ![img](@static/images/product/push/push_template_add.png) + +### 使用自定义推送模板 + +自定义推送模板,即名称为 `default` 之外的推送模板。你可以参考以下步骤使用自定义推送模板: + +1. 若使用自定义推送模板,你需要在环信即时通讯云控制台或[调用 RESTful 接口](/document/server-side/push.html#创建离线推送模板)创建自定义推送模板。**添加推送模板** 对话框中参数的描述,详见[使用默认推送模板](#使用默认推送模板)。使用自定义模板时,**标题** 和 **内容** 参数无论通过哪种方式设置,创建消息时均需通过扩展字段传入。 + +2. 创建消息时需通过使用扩展字段传入模板名称、推送标题和推送内容,通知栏中的推送标题和内容分别使用模板中的格式。 ## 配置消息回调 +环信即时通讯 IM 提供消息回调服务。**旗舰版 IM 服务包含回调服务,而专业版 IM 服务不包含回调服务,需要按以下步骤单独购买**。 -环信即时通讯 IM 提供消息回调服务。旗舰版 IM 服务包含回调服务,而专业版 IM 服务不包含回调服务,需要按以下步骤单独购买。 +### 开通消息回调 1. 在环信即时通讯云控制台首页的**应用列表**中,在目标应用的 **操作** 栏中点击 **查看**。 @@ -140,25 +213,23 @@ ![img](@static/images/callback/callback_purchase.png) -4. 在支付页面,点击**立即支付**支付费用后即可使用 +4. 在支付页面,点击**立即支付**支付费用后即可使用。 ![img](@static/images/callback/callback_payment.png) -你可以下步骤添加消息回调规则,最多可以配置 4 条发送前和发送后回调规则。配置回调后,应用服务器会收到所选类型的消息和事件。 +### 配置回调规则 + +你可以按照以下步骤添加消息回调规则,最多可以配置 4 条发送前和发送后回调规则。配置回调规则后,环信服务器会自动为该规则生成 secret,向你的 app server 发送数据时会基于该 secret 生成签名(即请求中的 `security` 参数),作为你的服务器识别环信服务器的依据。若要使用自定义密钥,可以联系环信商务经理。 1. 在左侧导航栏,选择 **即时通讯** > **功能配置** > **消息回调**,进入 **消息回调** 页面。 ![img](@static/images/product/push-callback.png) -2. 点击 **添加回调地址** 按钮,打开回调配置对话框。 - -![img](@static/images/product/push-callback-window.png) - -3. 在回调配置对话框中,填写回调相关配置信息,点击 **保存** 按钮,完成回调配置。 +2. 点击 **添加回调地址** 按钮,打开回调配置对话框,填写回调相关配置信息,点击 **保存** 按钮,完成回调配置。 - 配置发送前回调规则 -![img](@static/images/product/pre_delivery_rule_add.png) +![img](@static/images/callback/pre_delivery_rule_add.png) 在**发送前回调**对话框中配置以下参数: @@ -184,17 +255,49 @@ | 规则名称 | 是 | 唯一的规则名称,只支持字母、数字和下划线,不支持中文字符,且长度不超过 32 字符。 | | 回调地址 | 是 |环信 IM 服务器会将消息推送到指定的 URL 地址,支持针对不同类型的消息配置不同的 HTTP 和 HTTPS 回调地址。 | | 启用状态 | 是 |是否启用该规则。| -| 回调类型 | 是 |回调类型。你可以选择对各种类型的单聊、群聊、和聊天室消息以及各种事件进行回调。| +| 回调类型 | 是 |回调类型。你可以选择对各种类型的单聊、群聊、和聊天室消息以及各种事件进行回调,详见[回调事件](/document/server-side/callback_configurations.html)。对于表情回复 Reaction 和子区 Thread,如要获取回调事件,无需单独配置,只需选择对应的消息类型即可。例如,如果需要单聊文本消息的 Reaction,你需要选中 **单聊消息 > 文本消息**,服务器发送回调事件时即会返回 Reaction 信息。| | 消息类型 | 是 |需要回调的类型:
- **聊天消息**:发送成功的消息,包括通过客户端和 REST API 发送的消息。这些消息与通过 REST 导出的聊天记录查询到的消息一致。例如,用户 u1 向用户 u2 发送消息,则会产生一条聊天消息,与接收方是否在线无关。收到的消息中 `from` 为 u1,`to` 为 u2。用户 u1 在群组 g1 中发送消息,则会产生一条聊天消息,收到的消息中 `from` 为 u1,`to` 为 g1,且返回值包含 `group_id` 字段。
- **离线消息**:消息发送时接收方为离线的消息。例如:单聊中发送消息,若对端用户不在线,则会产生一条离线消息;在群聊中发送消息,若有几个群成员不在线,则会产生几条离线消息,这些离线消息的 `to` 参数为接收消息用户的 ID,并不是群组 ID。App 可以通过推送服务对这些消息进行个性化推送。| | REST 消息是否需要回调 | 是 | 通过 REST API 发送的消息是否需要回调:
- **是**:需要;
- **否**:不需要。 | -| From ID | 否 |消息发送方或操作执行者的用户 ID。每行输入一个用户 ID,一次最多输入 50 条。设置该参数后,环信服务器只针对该用户发送的消息及执行的操作(例如好友、群组或聊天室相关操作)进行回调。若不指定该参数,规则对消息发送方不限制。 | -| To ID | 否 | 消息接收方:
- 单聊:接收方的用户 ID。环信服务器只针对该用户接收的消息或事件通知进行回调。
- 群组聊天:群组 ID。环信服务器只针对该群组中接收的消息或事件通知进行回调。
- 聊天室:聊天室 ID。环信服务器只针对该聊天室中接收的消息或事件进行回调。
每行输入一个接收方 ID,一次最多输入 50 条。若不指定该参数,规则则对消息接收方不限制。| -| 群组/聊天室 ID | 否 | 群组或聊天室 ID。每行输入一个群组 ID 或聊天室 ID,一次最多输入 50 条。设置该参数后,环信服务器只针对该群组中的消息或事件进行回调。若不指定该参数,规则则对群组和聊天室不限制。| +| From ID | 否 |消息发送方或操作者的用户 ID。每行输入一个用户 ID,一次最多输入 50 条。设置该参数后,环信服务器只针对该用户发送的消息及执行的操作(例如好友、群组或聊天室相关操作)进行回调。若不指定该参数,规则对发送方或操作者不限制。 | +| To ID | 否 | 单聊的消息或事件接收方的用户 ID。每行输入一个用户 ID,一次最多输入 50 条。若不指定该参数,规则对接收方不限制。| +| 群组/聊天室 ID | 否 | 群组或聊天室 ID。每行输入一个群组 ID 或聊天室 ID,一次最多输入 50 条。设置该参数后,环信服务器只针对该群组中的消息或事件进行回调。若不指定该参数,规则对群组和聊天室不限制。| | 扩展字段中的 Key | 否 | 消息扩展字段中的属性 key。每行输入一个 key,一次最多输入 50 条。设置该参数后,只针对包含该属性 Key 的消息进行回调。若不指定该参数,规则对消息扩展字段不限制。| -回调规则配置后,环信服务器会自动为该规则生成 secret。环信服务器向你的 app server 发送数据时会基于该 secret 生成签名(即请求中的 `security` 参数),作为你的服务器识别环信服务器的依据。若要使用自定义密钥,可以联系环信商务经理。 +其中,**From ID**、**To ID**、**群组/聊天室 ID** 和**扩展字段中的 Key** 为配置发送后回调规则时需指定的高级筛选条件,配置示例如下: -![img](@static/images/callback/post_delivery_addsuccess.png) +- 仅对单聊的回调:仅设置 **From ID** 和 **To ID**。指定的发送方向接收方发单聊消息或对该好友进行操作(如删除好友)时收到回调消息。例如,**From ID** 设置为 test 1,**To ID** 设置为 test 2,test 1 向 test 2 发单聊消息时收到回调。 + +- 仅对群组或聊天室的回调:仅设置**群组/聊天室 ID** 参数。这种情况下,只有在指定的群组或聊天室中发送消息或进行操作时收到回调。例如,**群组/聊天室 ID** 设置为群组 ID 228978,则仅在该群组中发送消息时收到回调。 + +- 仅对群聊中某个用户的回调:仅设置 **From ID** 和 **群组/聊天室 ID**。这种情况下,只有群组或聊天室中的指定用户发送消息或执行操作时收到回调。例如,**From ID** 设置为 test 1,**群组/聊天室 ID** 设置为群组 ID 228978,仅 test 1 用户在群组中发送消息时收到回调。 + +:::tip + +若 **From ID**、 **To ID** 和**群组/聊天室 ID** 同时设置,发送方向接收方发送单聊、群聊消息时不会收到回调。 + +::: + +## 消息举报 + +环信即时通讯 IM 提供消息举报功能。你的用户可以在客户端举报违规消息。当服务器收到举报消息后,会将举报消息存储到数据库,并在[环信即时通讯云控制台](https://console.easemob.com/user/login)展示。你可在环信即时通讯云控制台查看举报记录,并进行相应处理。 + +1. 开通消息举报功能。 + +在环信即时通讯云的左侧导航栏中,选择 **即时通讯** > **功能配置** > **功能配置总览**。在 **功能配置总览** 页面的 **基础功能** 页签中搜索找到 **消息举报**,进行开通。 + +对于专业版,消息举报为增值服务,你需要点击 **增值服务** 单独付费开通,如下图所示。 + +对于旗舰版,该功能免费提供,你只需要点击 **免费开通**,开通即可使用。 + +:::tip +消息举报功能与内容审核功能为两个独立的功能,没有任何关联,因此使用该功能无需提前开通内容审核功能。 +::: + +![img](@static/images/product/enable_and_configure/message_report_enable.png) + +2. 查看消息举报记录。 + +消息举报服务开通后,你可以在环信即时通讯云控制台的左侧导航栏中选择 **内容审核 > 消息举报** 查看消息举报记录。 ## 敏感词设置 @@ -266,6 +369,26 @@ 要添加聊天室成员,选择 **查看聊天室成员**,在弹出的对话框中,输入用户 ID,点击 **添加成员**。成员添加后会显示在下方的成员列表中,你可以移除该成员。 +## IM 用户设备日志 + +环信即时通讯云控制台支持查询用户设备端的日志,或将设备端的日志上传到环信日志服务器。目前,仅支持使用了高于 3.3.2 的 Android/iOS SDK 的设备。 + +![img](@static/images/product/enable_and_configure/user_device_log.png) + +### 上传设备日志到环信日志服务器 + +输入用户 ID 后,点击**下发上传log指令**,服务端将对指定用户设备下发指令: + +- 如果当前用户在线,则会开始上传设备日志,正常情况预计 5s 内可完成上传。 + +- 如果当前用户不在线,则需要等用户下次上线时开始上传设备日志,日志保留时间为 7 天。 + +上传指令和日志保留时间为 7 天,即如果下发指令后 7 天内用户均未上线,则 7 天后指令失效,不会触发上传日志。 + +### 查询用户设备端日志 + +输入用户 ID 后,点击**查询**,查询用户设备端的日志。若设备已上传日志,则会查询到;若设备未上传过日志,则查询不到。 + ## 账户中心 登录环信即时通讯云控制台,选择 **费用中心** > **账户中心**,可查看你当前的账户余额和支出明细。 diff --git a/docs/product/faq_quality_issues.md b/docs/product/faq_quality_issues.md index dc103b1de..4b42fde1c 100644 --- a/docs/product/faq_quality_issues.md +++ b/docs/product/faq_quality_issues.md @@ -80,7 +80,7 @@ ### 如何判断用户是否在线 -在使用环信即时通讯 IM 基础聊天业务的场景下,处理特定业务需求时需知晓某些用户是否在线。为此,环信即时通讯 IM 提供单个用户以及批量用户是否在线状态的查询,详见 [用户在线状态回调](/document/server-side/user_status_callback.html)。 +在使用环信即时通讯 IM 基础聊天业务的场景下,处理特定业务需求时需知晓某些用户是否在线。为此,环信即时通讯 IM 提供单个用户以及批量用户是否在线状态的查询,详见 [用户在线状态回调](/document/server-side/callback_configurations.html#用户登入登出)。 除此之外,可以在 [环信即时通讯云控制台](https://console.easemob.com/user/login) 上查询用户连接状态,具体操作如下: diff --git a/docs/product/glossary.md b/docs/product/glossary.md index b44eee5b5..d77208a96 100644 --- a/docs/product/glossary.md +++ b/docs/product/glossary.md @@ -22,6 +22,10 @@ CallKit 提供应用内聊天中音视频通话的页面和 UI 组件,帮助 环信即时通讯 IM 示例开源项目,目前支持 Android、iOS 和 Web 平台。 +## 日活用户 + +日活用户(DAU),指日活跃用户数,即一个自然日内与环信服务器进行业务行为交互(包含但不局限于登录、收发消息)的用户总数。 + ## 会话和消息 ### 会话 diff --git a/docs/product/limitation.md b/docs/product/limitation.md index 3632005de..575516612 100644 --- a/docs/product/limitation.md +++ b/docs/product/limitation.md @@ -29,6 +29,13 @@ - 群组扩展信息,例如可以给群组添加业务相关的标记,最大长度为 1,024 字符。 - 单个群成员的自定义属性(key-value)总长度不能超过 4 KB。对于单个自定义属性,属性 key 不能超过 16 字节,value 不能超过 512 个字节。 +群组共享文件的限制如下: +- 单个群组共享文件大小上限默认 10 MB。如果需要提升限制,请联系商务。 + 该限制与消息附件的相同。如果消息附件的长度进行了上调,群组共享文件大小也会随之自动调整,反之亦然。 +- 单个群组最多上传 10,000 个共享文件。 +- 群组共享文件在服务器的存储时间与消息附件相同,即默认为 7 天。如果需要提升限制,请联系商务。 + 如果消息附件在服务器上的存储时间进行了上调,群组共享文件的存储时间也会随之自动调整,反之亦然。 + ## 聊天室限制 不同套餐版本支持的聊天室总数,详见[套餐包功能详情](pricing.html#套餐包功能详情)。 @@ -61,13 +68,13 @@ | 消息类型 | 消息长度限制 | | :------------- | :----------------------------------- | -| 文本消息 | 3 KB | -| 图片消息 | 图片不能超过 10 MB,图片消息大小限制为 3 KB。 | -| 语音消息 | 音频文件不能超过 10 MB,语音消息大小限制为 3 KB。 | -| 视频消息 | 视频文件不能超过 10 MB,视频消息大小限制为 3 KB。 | -| 文件消息 | 附件大小不能超过 10 MB,文件消息大小限制为 3 KB。 | -| 透传消息 | 3 KB | -| 自定义消息 | 3 KB | +| 文本消息 | 5 KB | +| 图片消息 | 图片不能超过 10 MB,图片消息大小限制为 5 KB。 | +| 语音消息 | 音频文件不能超过 10 MB,语音消息大小限制为 5 KB。 | +| 视频消息 | 视频文件不能超过 10 MB,视频消息大小限制为 5 KB。 | +| 文件消息 | 附件大小不能超过 10 MB,文件消息大小限制为 5 KB。 | +| 透传消息 | 5 KB | +| 自定义消息 | 5 KB | ## 用户属性大小限制 diff --git a/docs/product/limitationapi.md b/docs/product/limitationapi.md index bb5ab9955..195d49970 100644 --- a/docs/product/limitationapi.md +++ b/docs/product/limitationapi.md @@ -14,12 +14,11 @@ | 批量注册用户 | POST | /{org_name}/{app_name}/users | | 设置推送消息显示昵称 | PUT | /{org_name}/{app_name}/users/{username} | | 设置推送消息展示方式 | PUT | /{org_name}/{app_name}/users/{username} | -| 设置免打扰 | PUT | /{org_name}/{app_name}/users/{username} | | 绑定和解绑推送信息 | PUT | /{org_name}/{app_name}/users/wzy/push/binding | | 查询当前用户的所有设备的推送绑定信息 | GET | /{org_name}/{app_name}/users/wzy/push/binding | | 获取指定账号的在线登录设备列表 | GET | /{org_name}/{app_name}/users/{username}/resources | -以上八个接口的总调用频率(默认值)为 100 次/秒/App Key。 +以上七个接口的总调用频率(默认值)为 100 次/秒/App Key。 | RESTful API 接口 |方法 | 接口 URL| 接口最高调用频率(默认值) | | :----------- | :----- | :------------------- | :------------- | @@ -48,6 +47,7 @@ | 创建离线推送模板 | POST | /{org_name}/{app_name}/notification/template | 10 次/秒/App Key | | 查询离线推送模板 | GET | /{org_name}/{app_name}/notification/template/{name} | 10 次/秒/App Key | | 删除离线推送模板 | DELETE | /{org_name}/{app_name}/notification/template/{name} | 10 次/秒/App Key | +| 接收方配置模板名称 | PUT | /{org_name}/{app_name}/users/{username}/notification/template | 100 次/秒/App Key。 | ## 消息管理 @@ -56,14 +56,13 @@ | 发送单聊消息 | POST | /{org_name}/{app_name}/messages/users | 6000 条/分钟/App Key | | 发送群聊消息 | POST | /{org_name}/{app_name}/messages/chatgroups | 20 条/秒/App Key | | 发送聊天室消息 | POST | /{org_name}/{app_name}/messages/chatrooms | 100 条/秒/App Key | +| 发送聊天室广播消息 | POST | /{org_name}/{app_name}/messages/chatrooms/broadcast | 每分钟最多可发 10 次,而且每天最多可发 100 次广播消息。 | | 上传文件 | POST | /{org_name}/{app_name}/chatfiles | 100 次/秒/App Key | | 下载文件 | GET | /{org_name}/{app_name}/chatfiles/{file_uuid} | 100 次/秒/App Key | | 获取历史消息(聊天记录)文件 | GET | /{org_name}/{app_name}/chatmessages/${time} | 10 次/分钟/App Key | | 服务端消息撤回 | POST | /{org_name}/{app_name}/messages/recall | 100 次/秒/App Key | | 服务端单向删除会话 | DELETE | /{org_name}/{app_name}/users/{userName}/user_channel | 5 次/分钟/单用户 ID,100 次/秒/App Key | | 拉取会话列表 | GET | /{org_name}/{app_name}/user/{username}/user_channels | 5 次/分钟/单用户 ID,100 次/秒/App Key | -| 发送聊天室全局广播消息 | GET | /{org_name}/{app_name}/messages/chatrooms/broadcast | 1 条/秒 | - ## 用户属性 @@ -79,12 +78,14 @@ | RESTful API 接口 |方法 | 接口 URL| 接口最高调用频率 | | :------------- | :----- | :---------------- | :-------------- | -| 添加好友 | POST | /{org_name}/{app_name}/users/{owner_username}/contacts/users/{friend_username} | 100 次/秒/App Key | -| 移除好友 | DELETE | /{org_name}/{app_name}/users/{owner_username}/contacts/users/{friend_username} | 100 次/秒/App Key | -| 获取好友列表 | GET | /{org_name}/{app_name}/users/{owner_username}/contacts/users | 100 次/秒/App Key | -| 获取黑名单列表 | GET | /{org_name}/{app_name}/users/{owner_username}/blocks/users | 50 次/秒/App Key | -| 添加用户至黑名单 | POST | /{org_name}/{app_name}/users/{owner_username}/blocks/users | 50 次/秒/App Key | -| 从黑名单移除用户 | DELETE | /{org_name}/{app_name}/users/{owner_username}/blocks/users/{blocked_username} | 50 次/秒/App Key | +| 添加好友 | POST | /{org_name}/{app_name}/users/{owner_username}/contacts/users/{friend_username} | 100 次/秒/App Key | +| 移除好友 | DELETE | /{org_name}/{app_name}/users/{owner_username}/contacts/users/{friend_username} | 100 次/秒/App Key | +| 设置好友备注 | PUT | /{org_name}/{app_name}/user/{owner_username}/contacts/users/{friend_username} | 100 次/秒/App Key | +| 分页获取好友列表 | GET | /{org_name}/{app_name}/user/{username}/contacts?limit={N}&cursor={cursor}&needReturnRemark={true/false} | 100 次/秒/App Key | +| 一次性获取好友列表 | GET | /{org_name}/{app_name}/users/{owner_username}/contacts/users | 100 次/秒/App Key | +| 获取黑名单列表 | GET | /{org_name}/{app_name}/users/{owner_username}/blocks/users | 50 次/秒/App Key | +| 添加用户至黑名单 | POST | /{org_name}/{app_name}/users/{owner_username}/blocks/users | 50 次/秒/App Key | +| 从黑名单移除用户 | DELETE | /{org_name}/{app_name}/users/{owner_username}/blocks/users/{blocked_username} | 50 次/秒/App Key | ## 群组管理 diff --git a/docs/product/migrate_to_easemob.md b/docs/product/migrate_to_easemob.md index 908622e81..0f7c6b2c6 100644 --- a/docs/product/migrate_to_easemob.md +++ b/docs/product/migrate_to_easemob.md @@ -56,9 +56,9 @@ 具体可以参考: -[Android 导入消息至本地数据库](/document/android/message_manage.html#批量导入消息到数据库) +[Android 导入消息至本地数据库](/document/android/message_import_insert.html#批量导入消息到数据库) -[iOS 导入消息至本地数据库](/document/ios/message_manage.html#批量导入消息到数据库) +[iOS 导入消息至本地数据库](/document/ios/message_import_insert.html#批量导入消息到数据库) ## 新老兼容的平滑迁移 diff --git a/docs/product/moderation/moderation_record_callback.md b/docs/product/moderation/moderation_record_callback.md index d38509946..d0ecb05b3 100644 --- a/docs/product/moderation/moderation_record_callback.md +++ b/docs/product/moderation/moderation_record_callback.md @@ -24,20 +24,24 @@ 审核结果回调的示例代码如下所示: ```json -{ -"callId": "100220419126072#demo_54ae7e93-xxxx-xxxx-92f5-323e33187243", -"moderationResult": "PASS", -"providerResult": "PASS", -"security": "1f4857f120b2789b7d0abcd372c4f9e8", -"messageType": "txt", -"messageId": "1F4MX6iSdI7VFnN7Hm0vrcr3Uwr", -"targetType": "chat", -"appkey": "100220419126072#lydemo", -"source": { - -}, -"eventType": "moderation", -"timestamp": 1668766253245 + { + "callId": "100220419126072#demo_54ae7e93-xxxx-xxxx-92f5-323e33187243", + "moderationResult": "PASS", + "providerResult": "PASS", + "security": "1f4857f120b2789b7d0abcd372c4f9e8", + "messageType": "txt", + "messageId": "1F4MX6iSdI7VFnN7Hm0vrcr3Uwr", + "targetType": "chat", + "appkey": "100220419126072#lydemo", + "source": { + + }, + "eventType": "moderation", + "from": "qa2", + "to": "qa1", + "url": "", + "msg": "你好", + "timestamp": 1668766253245 } ``` @@ -52,4 +56,8 @@ | targetType | String | 会话类型。
- `chat`:单聊;
- `groupchat`:群聊;
- `chatroom`:聊天室。 | | appkey | String | 你的 App Key。 | | eventType | String | 事件类型,审核服务为 `moderation`。| +| from | String | 消息发送方。 | +| to | String | 消息接收方:
- 单聊为对端用户 ID;
- 群聊时为群组 ID;
- 聊天室聊天为聊天室 ID。 | +| msg | String | 文本消息的内容。该参数仅在 `messageType` 为 `txt` 时存在。| +| url | String | 音频消息、视频消息、图片消息中附件 URL。该参数仅在 `messageType` 为 `img`、`audio` 或 `video` 时存在。 | | timestamp | Long | 环信 IM 服务器接收到此消息的 Unix 时间戳,单位为毫秒。 | \ No newline at end of file diff --git a/docs/product/product_dynamics.md b/docs/product/product_dynamics.md index f7d663efd..0b87782b1 100644 --- a/docs/product/product_dynamics.md +++ b/docs/product/product_dynamics.md @@ -1,10 +1,23 @@ # 产品动态 +## 2024-01 + +| 动态名称 | 动态描述 | 发布时间 | 相关文档 | +| :----- | :------- | :---------------- | :---------------- | +| SDK 4.4.0 开发版发布 | **新增特性**:
- 客户端可[清空聊天记录](/document/android/message_delete.html#清空聊天记录):单个用户包含本地或服务端记录。
- 客户端发送消息时如果被内容审核进行了内容替换,你可以通过[设置开关](/document/android/message_send_receive.html#发送文本消息)决定发送方是否可以获取替换后的内容。
- 移动端的[本地消息搜索可选择搜索范围](/document/android/message_search.html#根据搜索范围搜索当前会话中的消息),如只搜索消息内容、只搜索消息扩展信息以及同时搜索消息内容以及扩展信息。
- 移动端接收消息的回调支持通过[设置开关](/document/android/message_send_receive.html#接收消息)设置是否返回发送成功的消息。
- [Web 端支持向指定设备发消息](/document/web/multi_device.html#获取当前用户的其他登录设备的登录-id-列表),例如,电脑端给手机端发消息,登录同一账号的多个设备均会收到消息。
- Web 端聊天室和群组成员进出事件增加成员人数 `memberCount` 字段。
**优化**:
- 移动端群组全员禁言状态存储到本地数据库,下次登录时可以直接从本地获取到。
- 移动端转发合并消息时导致的附件重复上传问题。| 2024-01-30 |
- [Android 4.4.0 更新日志](/document/android/releasenote.html#版本-v4-4-0-dev-2024-01-30-开发版)
- [iOS 4.4.0 更新日志](/document/ios/releasenote.html#版本-v4-4-0-dev-2024-01-30-开发版)
- [Web 4.5.0 更新日志](/document/web/releasenote.html#版本-v4-5-0-dev-2024-01-30-开发版)
- [小程序 4.5.0 更新日志](/document/applet/releasenote.html#版本-v4-5-0-dev-2024-01-30-开发版)。 | + +## 2023-12 + +| 动态名称 | 动态描述 | 发布时间 | 相关文档 | +| :----- | :------- | :---------------- | :---------------- | +| SDK 4.3.0 开发版发布 | **新增特性**:
- [会话标记功能](/document/android/conversation_mark.html):支持标记会话,并按照标记获取会话。
**优化**
- 对于原生平台,优化附件类型消息发送时的附件上传,支持分片上传。
- 移动端移除 FPA 功能,减小 SDK 体积。
- 移动端单个日志文件大小由 2 MB 提升到 5 MB。
- Web 端增加 `onMessage` 回调。在收到文本、图片、视频、语音、地理位置和文件等消息时,批量将消息回调给应用。
- Web 端视频类型消息增加视频首帧缩略图, 通过 videoMessage.thumb 访问。 | 2023-12-22 |
- [Android 4.3.0 更新日志](/document/android/releasenote.html#版本-v4-3-0-dev-2023-12-22-开发版)
- [iOS 4.3.0 更新日志](/document/ios/releasenote.html#版本-v4-3-0-dev-2023-12-22-开发版)
- [Web 4.4.0 更新日志](/document/web/releasenote.html#版本-v4-4-0-dev-2023-12-22-开发版)
- [小程序 4.4.0 更新日志](/document/applet/releasenote.html#版本-v4-4-0-dev-2023-12-22-开发版)。 | + ## 2023-11 | 动态名称 | 动态描述 | 发布时间 | 相关文档 | | :----- | :------- | :---------------- | :---------------- | -| SDK 4.2.0 开发版发布 | **新增特性**:
- 客户端支持[好友备注功能](/document/android/releasenote.html)。
- 客户端新增消息属性用于判断消息是否为聊天室全局广播消息。
- 移动端新增 API 用于[从服务器获取当前用户已加入的群组数量](/document/android/group_manage.html#查询当前用户已加入的群组数量)。
- 移动端的申请入群被拒绝的回调中添加申请者和拒绝者的用户 ID。
- 移动端新增错误码 706,表示聊天室所有者不允许离开聊天室。若初始化时,将是否允许聊天室所有者离开聊天室的参数设置为否时,聊天室所有者在移动端调用离开聊天室的方法时会提示该错误。
- 移动端在 `EMOptions` 类中新增属性用于在初始化时配置获取会话列表时是否返回空会话。
**优化**
- 客户端统一 Agora Token 和 EaseMob Token 登录方式,新增 EaseMob Token 即将过期及已过期的回调。
- 移动端优化发消息时重试的逻辑。
- 移动端优化数据库升级逻辑。| 2023-11-17 |
- [Android 4.2.1 更新日志](/document/android/releasenote.html)
- [iOS 4.2.1 更新日志](/document/ios/releasenote.html)
- [Web 4.3.0 更新日志](/document/web/releasenote.html)。 | +| SDK 4.2.0 开发版发布 | **新增特性**:
- 客户端支持[好友备注功能](/document/android/releasenote.html)。
- 客户端支持聊天室全局广播消息,可根据消息属性判断。
- 移动端可以[从服务器获取当前用户已加入的群组数量](/document/android/group_manage.html#查询当前用户已加入的群组数量)。
- 移动端在申请入群被拒绝时,返回的回调中增加了申请者和拒绝者。
- 移动端在初始化时可配置获取会话列表时是否返回空会话。
**优化**
- 客户端统一 Agora Token 和 EaseMob Token 登录方式,新增 EaseMob Token 即将过期及已过期的回调。
- 移动端优化发消息时重试的逻辑。
- 移动端优化数据库升级逻辑。| 2023-11-17 |
- [Android 4.2.1 更新日志](/document/android/releasenote.html)
- [iOS 4.2.1 更新日志](/document/ios/releasenote.html)
- [Web 4.3.0 更新日志](/document/web/releasenote.html)
- [小程序 4.3.0 更新日志](/document/applet/releasenote.html)。 | | REST API | 支持[通过 REST API 向 app 下的所有活跃聊天室发送全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息) 。活跃聊天室指聊天室至少存在一个成员,而且至少发送过一条消息。| 2023-11-17 | 详见[发送聊天室广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 | -| IM Demo | 好友详情页面可添加和修改好友备注。 | 2023-11-17 |
- [Android 4.2.1 Demo](https://www.easemob.com/download/demo)
- [iOS 4.2.0 Demo](https://www.easemob.com/download/demo) | \ No newline at end of file +| IM Demo | 好友详情页面可添加和修改好友备注。 | 2023-11-17 |
- [Android 4.2.1 Demo](https://www.easemob.com/download/demo)
- [iOS 4.2.0 Demo](https://www.easemob.com/download/demo) | + diff --git a/docs/product/security_best_practices.md b/docs/product/security_best_practices.md index 6be1b23b1..a73c3df5c 100644 --- a/docs/product/security_best_practices.md +++ b/docs/product/security_best_practices.md @@ -38,7 +38,7 @@ | 数据类型 | 数据分类 | 存储时间 | |:-----------------------------------------|:---------|:--------------------------------------------------------------------------------------| | Console 注册数据 | 客户信息 | 直至客户删除账号或服务停用 6 个月。 | -| 消息(包括历史消息、漫游消息、离线消息) | 用户信息 | 根据消息云存储时长进行保存。
专业版 7 天、旗舰版 90 天、尊享版 180 天。 | +| 消息(包括历史消息、漫游消息、离线消息) | 用户信息 | 消息的云存储时长与套餐版本相关,详见[产品价格](/product/pricing.html#套餐包功能详情)。 | | 消息附件 | 用户信息 | 7 天。 | | 消息回调 | 用户信息 | 3 天。 | | 用户资料托管 | 用户信息 | 直到客户删除或服务停用 6 个月。 | diff --git a/docs/product/uc_deploy.md b/docs/product/uc_deploy.md index cdcb51cc6..9250e6b55 100644 --- a/docs/product/uc_deploy.md +++ b/docs/product/uc_deploy.md @@ -58,7 +58,7 @@ ## 3、集成测试 -当服务端验证完成后,可通过下载需要的客户端 SDK 及 Demo 进行集成体验。环信客户端 SDK 已对 IM 核心服务完成封装, 通过调用 SDK API 接口,即可快速获得消息收发 、会话管理 、群组 、好友 、聊天室等功能。目前客户端 SDK 已覆盖 Windows 、Linux 、MacOS 、Android 、iOS 、Web 、小程序等多种平台,服务器端 SDK 已覆盖 Java 、PHP 等平台,[下载私有化客户端 SDK](http://docs-im-beta.easemob.com/product/uc_private.html#私有化-sdk-下载)。 +当服务端验证完成后,可通过下载需要的客户端 SDK 及 Demo 进行集成体验。环信客户端 SDK 已对 IM 核心服务完成封装, 通过调用 SDK API 接口,即可快速获得消息收发 、会话管理 、群组 、好友 、聊天室等功能。目前客户端 SDK 已覆盖 Windows 、Linux 、MacOS 、Android 、iOS 、Web 、小程序等多种平台,服务器端 SDK 已覆盖 Java 、PHP 等平台,[下载私有化客户端 SDK](http://doc.easemob.com/product/uc_private.html#私有化-sdk-下载)。 示例一:以 Android 端 demo 体验为例 diff --git a/docs/product/uc_private.md b/docs/product/uc_private.md index 9a771a182..03f0c8adb 100644 --- a/docs/product/uc_private.md +++ b/docs/product/uc_private.md @@ -71,13 +71,13 @@

Android

-

3.9.1

+

3.9.1

下载 SDK 及 Demo 体验 Demo

-

查看

+

查看

@@ -85,13 +85,13 @@

Web

-

4.0.4

+

4.0.4

• React: 下载 SDK 及 Demo 体验 Demo
• Vue 2: 下载 SDK 及 Demo
• Vue 3: 下载 SDK 及 Demo

-

查看

+

查看

@@ -99,13 +99,13 @@

iOS

-

3.9.1

+

3.9.1

下载 SDK 及 Demo 

-

查看

+

查看

@@ -127,13 +127,13 @@

Windows(C#)

-

1.0.2

+

1.0.2

下载 SDK

-

查看

+

查看

@@ -215,7 +215,7 @@

下载 SDK

-

查看

+

查看

@@ -233,7 +233,7 @@

下载 SDK

-

查看

+

查看

@@ -247,7 +247,7 @@

下载 SDK

-

查看

+

查看

diff --git a/docs/product/voiceroom/client_implementation_ios.md b/docs/product/voiceroom/client_implementation_ios.md index c01d0e7e0..8d214f6b1 100644 --- a/docs/product/voiceroom/client_implementation_ios.md +++ b/docs/product/voiceroom/client_implementation_ios.md @@ -180,7 +180,7 @@ ### 初始化设置 -加入语聊房前,进行[环信 IM SDK 初始化](http://docs-im-beta.easemob.com/document/android/quickstart.html#实现单聊)和 [Agora Audio 初始化](https://docportal.shengwang.cn/cn/voice-call-4.x/start_call_audio_ios_ng?platform=iOS#实现语音通话逻辑)设置。 +加入语聊房前,进行[环信 IM SDK 初始化](http://doc.easemob.com/document/android/quickstart.html#实现单聊)和 [Agora Audio 初始化](https://docportal.shengwang.cn/cn/voice-call-4.x/start_call_audio_ios_ng?platform=iOS#实现语音通话逻辑)设置。 ### 加入/离开环信 IM 聊天室或者声网 RTC 频道 diff --git a/docs/push/push_androidvendor_statistics.md b/docs/push/push_androidvendor_statistics.md index 9a6054342..c08de7417 100644 --- a/docs/push/push_androidvendor_statistics.md +++ b/docs/push/push_androidvendor_statistics.md @@ -57,7 +57,27 @@ 填写回执配置,测试回执通过后进行提交。 -![img](@static/images/instantpush/push_huawei_callbackconfig.png) +![img](@static/images/instantpush/huawei_report_v1.png) + +如果您有多个回执地址,且环信回执地址并非默认选项,则需要指定回执配置ID,详情见 [华为配置推送通知receiptId ](push_notification_config.html#华为推送说明) + +![img](@static/images/instantpush/huawei_receipt_id.png) + +示例: + +```json +{ + "pushMessage":{ + "huawei":{ + "message":{ + "android":{ + "receiptId":"RCP78C959D4" + } + } + } + } +} +``` ##### 2.4.1、回调地址 @@ -67,14 +87,6 @@ ![img](@static/images/instantpush/push_domain_name.png) -##### 2.4.2、证书内容 - -[easemob.txt.zip](https://docs-im.easemob.com/_media/playground/push/apppush/easemob.txt.zip) - -:::notice -证书内容在2023年3月4日过期,环信将在2023年2月进行更新,届时您需要同步更新。 -::: - ### 3、FCM 客户端处理上报 继承`FirebaseMessagingService`的`Service`里去实现`handleIntent`方法,添加上报送达事件的代码 diff --git a/docs/push/push_api_call_limitation.md b/docs/push/push_api_call_limitation.md new file mode 100644 index 000000000..42b69a934 --- /dev/null +++ b/docs/push/push_api_call_limitation.md @@ -0,0 +1,30 @@ +# 即时推送 RESTful API 调用频率限制 + +本文介绍即时推送 RESTful API 的调用频率限制,包括推送标签管理和发送推送通知相关的 API 的调用频率限制。 + + + +## 推送标签管理 + +| RESTful API 接口 |方法 | 接口 URL| 接口最高调用频率(默认值) | +| :----------- | :----- | :------------------- | :------------- | +| [创建推送标签](push_by_tag.html#创建推送标签) | POST | /{org_name}/{app_name}/push/label | 10 次/秒/App Key | +| [查询指定的推送标签](push_by_tag.html#查询指定的推送标签) | GET | /{org_name}/{app_name}/push/label/{labelname} | 10 次/秒/App Key | +| [分页查询推送标签](push_by_tag.html#分页查询推送标签) | GET | /{org_name}/{app_name}/push/label | 10 次/秒/App Key | +| [删除指定的推送标签](push_by_tag.html#删除指定的推送标签) | DELETE | /{org_name}/{app_name}/push/label/{labelname} | 10 次/秒/App Key | +| [在推送标签下添加用户](push_by_tag.html#在推送标签下添加用户) | POST | /{org_name}/{app_name}/push/label/{labelname}/user | 30 次/秒/App Key | +| [查询指定标签下的指定用户](push_by_tag.html#查询指定标签下的指定用户) | GET | /{org_name}/{app_name}/push/label/{labelname}/user/{username} | 30 次/秒/App Key | +| [分页查询指定标签下的用户](push_by_tag.html#分页查询指定标签下的用户) | GET | /{org_name}/{app_name}/push/label/{labelname}/user | 30 次/秒/App Key | +| [批量移出指定推送标签下的用户](push_by_tag.html#批量移出指定推送标签下的用户) | DELETE | /{org_name}/{app_name}/push/label/{labelname}/user | 30 次/秒/App Key | + +## 发送推送通知 + +| RESTful API 接口 |方法 | 接口 URL| 接口最高调用频率(默认值) | +| :----------- | :----- | :------------------- | :------------- | +| [以同步方式发送推送通知](push_send_notification.html#以同步方式发送推送通知) | POST | /{org_name}/{app_name}/push/sync/{target} | 1 次/秒/App Key | +| [以异步方式批量发送推送通知](push_send_notification.html#以异步方式批量发送推送通知) | POST | /{org_name}/{app_name}/push/single | 10 次/秒/App Key | +| [使用标签推送接口发送推送通知](push_send_notification.html#使用标签推送接口发送推送通知) | POST | /{org_name}/{app_name}/push/list/label | 10 次/秒/App Key | +| [创建全量推送任务](push_send_notification.html#创建全量推送任务) | POST | /{org_name}/{app_name}/push/task | 1 次/秒/App Key | +| [创建推送通知](push_send_notification.html#创建推送通知) | POST | /{org_name}/{app_name}/push/message | 1 次/秒/App Key | +| [查询推送通知](push_send_notification.html#查询推送通知) | POST| /{org_name}/{app_name}/push/message/{messageId} | 1 次/秒/App Key| +| [创建全量推送任务](push_send_notification.html#创建全量推送任务-1)| POST | /{org_name}/{app_name}/push/task/broadcast |1 次/秒/App Key | \ No newline at end of file diff --git a/docs/push/push_notification_config.md b/docs/push/push_notification_config.md index d52bbdfd5..e5d44e3f2 100644 --- a/docs/push/push_notification_config.md +++ b/docs/push/push_notification_config.md @@ -44,7 +44,7 @@ | `content` | String | 通知栏展示的通知内容。默认为“请及时查看”。该字段长度不能超过 100 个字符(一个汉字相当于两个字符)。 | iOS & Android | 是 | | `ext` | Object | 推送自定义扩展信息,为自定义 key-value 键值对。键值对个数不能超过 10 且长度不能超过 1024 个字符。 | iOS & Android | 否 | | `config` | Object | 与用户点击通知相关的操作。以及角标的配置,包含 `clickAction` 和 `badge` 字段。 | iOS & Android | 否 | -| `config.clickAction` | Object | 在通知栏中点击触发的动作,均为字符串类型:
- `url`:打开自定义的 URL;
- `action`:打开应用的指定页面;
- `activity`:打开应用包名或 Activity 组件路径。若不传该字段,默认打开应用的首页。 | Android | 否 | +| `config.clickAction` | Object | 在通知栏中点击触发的动作,均为字符串类型:
- `url`:打开自定义的 URL;
- `action`:打开应用的指定页面;
- `activity`:打开应用包名或 Activity 组件路径。若不传该字段,默认打开应用的首页。
环信 iOS 推送通道只支持设置为 `url`。 | Android | 否 | | `config.badge` | Object | 推送角标,包含以下三个字段:
- `addNum`:整型,表示推送通知到达设备时,角标数字累加的值。
- `setNum`:整型,表示推送通知到达设备时,角标数字显示的值。
- `activity`:字符串类型,入口类(华为角标需要配置)。 | Android | 否 | ## 各厂商推送配置 @@ -87,7 +87,7 @@ "channelName": "消息", "channelLevel": 3, "autoCancel": 1, - "expiresTime": 3600000, + "expiresTime": 1650859482843, "sound": 0, "vibrate": 0, "style": 2, @@ -108,12 +108,12 @@ | `needNotification` | boolean | 是否弹出通知:
- (默认)`true`:通知消息;
- `false`:透传消息。 | iOS & Android | | `badge` | Object | 推送角标。详见 [基本推送配置](#基本推送配置)中的角标说明。 | iOS & Android | | `operation` | Object | 在通知栏中点击触发的动作。 | iOS & Android | -| `operation.type` | Int | 在通知栏中点击触发的动作类型。
- (默认)`0`:启动应用。
- `1`:打开自定义的 URL。需设置 `openUrl` 字段为自定义的 URL,若不设置,点击无效果。
- `2`:打开应用的指定页面。需设置 `openAction` 为打开的应用页面的地址。若不设置,点击无效果。 | iOS & Android | +| `operation.type` | Int | 在通知栏中点击触发的动作类型。
- (默认)`0`:启动应用。
- `1`:打开自定义的 URL。需设置 `openUrl` 字段为自定义的 URL,若不设置,点击无效果。
- `2`:打开应用的指定页面。需设置 `openAction` 为打开的应用页面的地址。若不设置,点击无效果。
环信 iOS 推送通道只支持启动应用和打开自定义 URL,因此只能设置为 `0` 和 `1`。| iOS & Android | | `channelId` | String | 通知渠道 ID,默认为 `chat`。客户端渠道存在则通知。若客户端渠道不存在,则结合 channelName,channelLevel 创建新通道。 | Android | | `channelName` | String | 通知渠道名称,默认为 `消息`。只有第一次创建通道时使用。 | Android | | `channelLevel` | Int | 通知级别,只有第一次创建通道时使用。
- `0`:最低;
- `3`:默认;
- `4`:高。 | Android | | `autoCancel` | Int | 点击通知后是否自动关闭通知栏。
- `0`:否;
- (默认)`1`:是。 | Android | -| `expiresTime` | Long | 通知展示的过期时间,为 Unix 时间戳,单位为毫秒。 | iOS & Android | +| `expiresTime` | Long | 通知展示过期的 Unix 时间戳,单位为毫秒,例如 `1650859482843` 表示的时间为 2022-04-25 12:04:42。
计算公式:当前时间戳 + 保留时间。 | iOS & Android | | `sound` | Int | 声音提醒。
- (默认)`0`:无声音;
- `1`:声音提醒。 | iOS & Android | | `vibrate` | Int | 振动提醒。
- (默认)`0`:无振动;
- `1`:振动提醒。 | iOS & Android | | `style` | Int | 展示样式。
-(默认)`0`:普通样式;
- `1`:大文本样式;
- `2`:大图片样式。 | iOS & Android | @@ -323,6 +323,8 @@ | `extra` | Object | [推送回调](#vivo-推送回调)。 | | `category` | String | 二级分类,字段的值详见[二级分类标准 中category说明](https://dev.vivo.com.cn/documentCenter/doc/359)。 1. 填写`category` 后,可以不设置 `classification` 参数,但若设置 `classification`,需保证 `category` 与 `classification` 是正确对应关系,否则推送失败。 2. 该参数请按照消息分类规则填写,且必须大写;若传入无效的值,则推送失败。 | | `notifyId` | Int | 通知 ID,即通知的唯一标识。若多个消息的通知 ID 相同,到达设备的新消息会覆盖旧消息显示在设备通知栏中。取值范围为:1-2147483647。 | +| `profileId` | String| 关联终端设备登录用户标识,最大长度为 64 字符。| +| `sendOnline` | Bool| 是否在线直推,设置为 `true` 表示是在线直推,`false` 表示非直推。在线直推功能推送时在设备在线下发一次,设备离线直接丢弃。| #### vivo 推送回调 @@ -451,6 +453,8 @@ | `fastAppTargetType` | Int | 快应用发送透传消息时,指定小程序的模式类型。
- `1`:开发态;
- (默认)`2`:生产态。 | | `data` | String | 自定义消息负载,此处如果设置了 data,则会覆盖 `message.data` 字段。 | | `notification` | Object | [安卓通知栏消息结构体](#安卓通知栏消息结构体)。 | +| `receiptId` | String| 输入一个唯一的回执 ID 指定本次下行消息的回执地址及配置,该回执 ID 可以在回执参数配置中查看。| +| `targetUserType` | Int |
- `0`:普通消息(默认值);
- `1`:测试消息。每个应用每日可发送该测试消息 500 条且不受每日单设备推送数量上限要求。| ##### 安卓通知栏消息结构体 diff --git a/docs/uikit/chatroomuikit/README.md b/docs/uikit/chatroomuikit/README.md new file mode 100644 index 000000000..18796e855 --- /dev/null +++ b/docs/uikit/chatroomuikit/README.md @@ -0,0 +1,3 @@ +--- +title: 聊天室 UIKit +--- diff --git a/docs/uikit/chatroomuikit/android/design_guide.md b/docs/uikit/chatroomuikit/android/design_guide.md new file mode 100644 index 000000000..29ca49719 --- /dev/null +++ b/docs/uikit/chatroomuikit/android/design_guide.md @@ -0,0 +1,705 @@ +# 直播聊天室人机交互界面工具包设计指南 (V1.0.0) + + + +![img](@static/images/uikit/chatroomdesign/crukcover_ease.png) + +## 0.总的设计原则 + +### 0.1.功能与行为上确保通用、普遍、一般 + +### 0.2.风格上易于自定义 + +### 0.3.在业务形态上尽量不替用户做决定 + +## 1.全局样式(Style) + +### 1.1.UIkit 色彩规范 + +#### 1.1.1.颜色配置说明: + +##### 1.1.1.1.颜色类(Color Class) + +一般颜色类分为八类: +主题色(Theme Color):Primary、 Secondary、Error 三类; +渐变主题色(Primary Gradient)一类(含 8 种); +透明色(Alpha Color):On Light、On Dark 两类; +中性色(Neutral Colors):Neutral、Neutral Special 两类; + +##### 1.1.1.2.颜色模式(Hsla Model) + +颜色模式为比较直观的 hsla 模式: +整个模型是一个圆柱体,圆柱体底面周长划分为 360°,对应不同的色相(Hue); +圆柱体的半径为饱和度(Saturation),圆心为 0(最灰),半径值为 100(最艳); +圆柱体的高为亮度(Lightness),起始点为 0(纯黑色),中心点是 50(标准色,),结束点为 100(纯白色)。 + +##### 1.1.1.3.模型概览: + +![img](@static/images/uikit/chatroomdesign/cruk1113.png) + +#### 1.1.2.三种主题色(Theme Color)的色彩规范: + +##### 1.1.2.1.关于用户可配项(Hue value): + +用户可设定颜色类的可配项 Hue(0-360)为任意数值,修改后每类颜色的色相会发生变化,以贴合用户场景所需要的主题颜色。 +Hue 值(0-360)与色相的对应关系大致如以下图示所例: + +![img](@static/images/uikit/chatroomdesign/cruk11211.png) + +用户可依据自身产品的品牌色指定色相数值(Hue),从而确认主题色 Primary(主要用于 UI 组件中关键操作与重要文本展示,如推荐的 action、高亮显示的文本等),以及用于积极提示的 Secondary,和表示警示提示的 Error。 + +![img](@static/images/uikit/chatroomdesign/cruk11212.png) + +##### 1.1.2.2.关于饱和度(Saturation value): + +饱和度(Saturation)不开放给用户设置,三种主题色 Primary、 Secondary、Error 默认饱和度为 100%,Neutral 默认为 8%,Neutral Special 默认为 36% + +![img](@static/images/uikit/chatroomdesign/cruk1122.png) + +##### 1.1.2.3.关于亮度级别(Lightness level): + +亮度(Lightness)百分比用户不可随意设置,每个颜色类提供:0(0%) / 1(10%) / 2(20%) / 3(30%) / 4(40%) / 5(50%) / 6(60%) / 7(70%) / 8(80%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)十三个级别供用户可选; + +![img](@static/images/uikit/chatroomdesign/cruk1123.png) + +##### 1.1.2.4.示例: + +如指定主题色 Primary 色相(Hue)为 203,成功色 Secondary 色相(Hue)为 155,警示色 Error 色相(Hue)为 350,则会生成如下 39 种主题色可供用户在指定 UI 件块(View)颜色时使用: + +![img](@static/images/uikit/chatroomdesign/cruk1124.png) + +其中,主题色 Primary 的 L5 为亮色模式下的基色(Key Color),L6 为暗色模式下的基色(Key Color)。所有的颜色体系都是依照基色生成。 + +#### 1.1.3.关于渐变主题色(Primary Gradient)的规范: + +渐变主题色是由 Primary 色派生出的渐变色,为线性渐变(Linear Gradient),渐变方向依图示坐标系分为 8 类: + +![img](@static/images/uikit/chatroomdesign/cruk113.png) + +##### 1.1.3.1.关于渐变色的起始色(Start Color): + +渐变色中 Start Color 规则和 Primary 类的色值保持一致; + +![img](@static/images/uikit/chatroomdesign/cruk1131.png) + +##### 1.1.3.2.关于渐变色的结束色(End Color): + +End Color 用户可配置色相(Hue),亮度以 0(20%) / 1(30%) / 2(40%) / 3(50%) / 4(60%) / 5(70%) / 6(75%) / 7(80%) / 8(85%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)(对应 Primary 的 13 级亮度梯度值)为固定梯度值 + +以下以 Hue:233 为例,按照 End Color 颜色公式依旧得到 13 级颜色: + +![img](@static/images/uikit/chatroomdesign/cruk11321.png) + +起始色和结束色结合,得到相应的渐变结果 + +![img](@static/images/uikit/chatroomdesign/cruk11322.png) + +##### 1.1.3.3.关于渐变主题色可配项(End Color Hue Value): + +用户仅可配置渐变色中 End Color 的色相(Hue)以达成与用户业务场景符合的渐变颜色效果; + +##### 1.1.3.4.举个例子吧: + +用户设置 End Color Hue = 233,选择渐变方向为“↓”,则可得到如下效果: + +![img](@static/images/uikit/chatroomdesign/cruk11341.png) + +如使用渐变主题色,那么它将替代掉所有应用于背景色的 Primary 色 + +![img](@static/images/uikit/chatroomdesign/cruk11342.png) + +但一般不替代 UI 件块的前景色,因为没有什么意义,且有干扰文字阅读的可能性 + +![img](@static/images/uikit/chatroomdesign/cruk11343.png) + +#### 1.1.4.关于透明色(Alpha)的规范: + +##### 1.1.4.1.透明色(Alpha Color): + +在本案内带有透明度的组件仅有弹幕消息背景色、礼物消息背景色、模态背景色、轻提示背景色四种,应用范围有限,所以单独定义两个特殊的颜色类用于以上四种组件:Alpha onlight(hsl0, 0%, 0%) 和 Alpha ondark(hsl0, 0%, 100%),Alpha 值被指定为 0(0.0) / 1(0.1) / 2(0.2) / 3(0.3) / 4(0.4) / 5(0.5) / 6(0.6) / 7(0.7) / 8(0.8) / 9(0.9) / 95(0.95) / 98(0.98) / 100(1.0) 十三个梯度值,共 26 种颜色用例,以调整组件的背景色透明度。 + +![img](@static/images/uikit/chatroomdesign/cruk1141.png) + +Alpha onlight 和 Alpha ondark 均为默认值,无任何可配置项。 + +### 1.1.5.关于中性色(Neutral Colors): + +#### 1.1.5.1.中性色(Neutral) + +中性色(Neutral)仅有一个可配项:色相(Hue),饱和度(Saturation)固定值为 8,亮度级别(Lightness level)也和主题色相同,分为 0(0%) / 1(10%) / 2(20%) / 3(30%) / 4(40%) / 5(50%) / 6(60%) / 7(70%) / 8(80%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)十三个级别供用户可选; + +![img](@static/images/uikit/chatroomdesign/cruk1151.png) + +Neutral 和 Primary 的默认 Hue 值(色相)相同,也建议用户设置和主题色相同的 Hue 值已达成主题颜色和无彩色系的配套。但这仅仅是建议; + +#### 1.1.5.2.示例: + +如指定主题色 Primary 色相(Hue)为 203,饱和度(Saturation)固定值为 100%,中性色(Neutral)则也指定色相(Hue)为 203,饱和度(Saturation)固定值为 8%,则得到以下色列可供用户选择使用: + +![img](@static/images/uikit/chatroomdesign/cruk11521.png) + +其中,L98 为亮色模式下背景色的主色,L1 为亮色模式下前景色的主色;L1 为暗色模式下背景色的主色,L98 为暗色模式下前景色的主色。 + +![img](@static/images/uikit/chatroomdesign/cruk11522.png) + +### 1.1.6.关于特殊中性色(Neutral Special): + +特殊中性色 Neutral Special 主要用于级别低于 Primary 和 Secondary 的强调信息,如当前页面状态、消息发送者的昵称等。 +Neutral Special 和 Primary 的默认 Hue 值(色相)类似,为近似色,也建议用户设置和主题色近似的 Hue 值已达成主题色和无彩色系的配套。但这仅仅是建议; + +![img](@static/images/uikit/chatroomdesign/cruk116a.png) + +![img](@static/images/uikit/chatroomdesign/cruk116b.png) + +#### 1.1.6.1.示例: + +如指定主题色 Primary 色相(Hue)为 203,特殊中性色(Neutral)通过相似色原理(正负 30 度内)指定色相(Hue)为 220,饱和度(Saturation)固定值为 36%,则得到以下色列可供用户选择使用: + +![img](@static/images/uikit/chatroomdesign/cruk1161.png) + +## 1.2.主题 + +本期主题分为 2 种,每种分明亮(Light mode)和黑暗(Dark)两类。 + +### 1.2.1.圆润主题 + +组件一般采用较大的圆角,柔和轻盈 + +![img](@static/images/uikit/chatroomdesign/cruk121.png) + +### 1.2.2.硬朗主题 + +组件一般避免比较大的圆,硬朗实在 + +![img](@static/images/uikit/chatroomdesign/cruk122.png) + +以上两种主题可通过应用渐变主题色(Primary Gradient)得到两外两种渐变色主题。 +至于业务相关的主题,如“社交”、“游戏”、“教育”、“商务”等主题分类,因违反本案的最基本设计原则“在业务形态上尽量不替用户做决定”,所以不在本期考虑范围内。 + +## 1.3.图标(Icon) + +### 1.3.1.图标模板(Template) + +图标参照 Material Icon Font 的模板 ,以 24 为基本栅格,须在安全区域(20x20 的中心区域)内绘制,基本描边控制为 1.5 栅格。 + +![img](@static/images/uikit/chatroomdesign/cruk131.png) + +### 1.3.2 图标命名(Name) + +为防止将图标语意固定,icon 命名需要尽力避免定义操作行为,而是以“看见什么就是什么“进行命名,方便相同图标在不同操作行为下的复用。 +如 + +![img](@static/images/uikit/chatroomdesign/cruk132.png) + +## 1.4.字体(Typography) + +### 1.4.1.字族(Font Family) + +#### 1.4.1.1.iOS 字族 + +默认 SF Pro 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 SF Arabic、SF Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认苹方(PingFang SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +#### 1.4.1.2.Android 字族 + +默认 Roboto 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 Noto Sans Arabic、Noto Sans Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认思源黑体(Noto Sans SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +#### 1.4.1.3.Web 字族 + +默认 Roboto 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 Noto Sans Arabic、Noto Sans Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认思源黑体(Noto Sans SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +### 1.4.2.字号(Font Size) + +#### 1.4.2.1.最小字号 + +移动端最小字号为:11;web 端最小字号为:12 + +#### 1.4.2.2.字号规则 + +除移动端最小字号外,字号以 2 为梯度递增: +11,12,14,16,18,20 + +### 1.4.3.字重(Font Weight) + +字重分为标准(Regular, 400)、中等(Medium,510)、加粗(semibold,590)三种; +在一些跨平台框架中,如遇不支持设置非百位整数字重,则取近似值百位整数; +如字族没有 semibold,则以 bold 替换。 + +### 1.4.4.行高(Line height) + +行高依照以下固定值(字号/行高): +11/14,12/16,14/20,16/22,18/26,20/28。 + +### 1.4.5.字体角色(Font Role) + +字体角色分为 3 类: +大标题 Headline、标题 Title、标签 Label、正文 Body +需要注意的是,这些角色只是推荐的角色指示,并不具有完全的指定性,具体使用什么角色的字体需依照所使用的组件的实际情况(组件内信息的层级重要性,越重要的越大越重)而使用。 + +### 1.4.6.字体 Token + +依照依照 4.1-4.5 规则,设定以下西文字体排版 token, + + + +简体中文字体 token 示意 + + + +## 1.5.效果(Effects) + +所应用的效果主要分为两种:背景模糊(Background Blur)和阴影(Shadow) + +### 1.5.1.背景模糊(Background Blur) + +背景模糊主要应用于组件背景色使用 Alpha color 时,如组件背景色的透明度会造成组件前后层级干扰的话,则推荐使用背景模糊解决,比如: + +![img](@static/images/uikit/chatroomdesign/cruk151.png) + +也应用于模态显示的弹出层的背景虚化; +背景模糊的模糊半径值默认为 20 + +``` +/* bg_blur_modal */ backdrop-filter: blur(20); +``` + +### 1.5.2.阴影(Shadow) + +阴影应用于弹窗(Alert)、浮层(pop)、抽屉(Drawer)等,为区分层级,凸显聚焦的组件。 + +#### 1.5.2.1.阴影型号(Size) + +阴影分为小(small)、中(medium)、大(Large)三种型号,应用于不同尺寸的组件中,总体原则为:越小的组件越推荐使用小的阴影、反之越大的组件推荐使用大的阴影;圆角越小的组件越推荐使用小的阴影、反之亦然。 + +#### 1.5.2.2.阴影 token + +为保证阴影效果自然柔和,每个阴影都有两层不同偏移、不同模糊度、不同透明度的值。同时针对亮色/暗色模式有两套不同颜色的阴影。 + +**Shadow on Light:** + +``` +/* shadow/onlight/large */ +box-shadow: x0 y24 blur36 color(Neutral3) Alpha0.15, x8 y0 blur24 color(Neutral1) Alpha0.1 + +/* shadow/onlight/medium */ +box-shadow: x0 y4 blur4 color(Neutral3) Alpha0.15, x2 y0 blur8 color(Neutral1) Alpha0.1 + +/* shadow/onlight/small */ +box-shadow: x0 y1 blur3 color(Neutral3) Alpha0.15, x1 y0 blur2 color(Neutral1) Alpha0.1 +``` + +![img](@static/images/uikit/chatroomdesign/cruk1522a.png) + +**Shadow on Dark:** + +``` +/* shadow/onlight/large */ +box-shadow: x0 y24 blur36 color(Neutral4) Alpha0.15, x8 y0 blur24 color(Neutral1) Alpha0.1 + +/* shadow/onlight/medium */ +box-shadow: x0 y4 blur4 color(Neutral4) Alpha0.15, x2 y0 blur8 color(Neutral1) Alpha0.1 + +/* shadow/onlight/small */ +box-shadow: x0 y1 blur3 color(Neutral4) Alpha0.15, x1 y0 blur2 color(Neutral1) Alpha0.1 +``` + +![img](@static/images/uikit/chatroomdesign/cruk1522b.png) + +## 1.6.圆角(Radius) + +### 1.6.1.一般圆角 + +一般圆角分为 None(r=0)、Extra Small(r=4)、Small(r=8)、Medium(r=12)、Large(r=16)、Extra Large(r=½ Height)六个枚举值, +一般情况下组件的四个圆角为同一值 + +![img](@static/images/uikit/chatroomdesign/cruk161.png) + +#### 1.6.1.1.Extra Small(r=4) + +通常适用于如下组件 +Button(Small Radius) +Input(Small Radius) +Float(Small Radius) +Message Bubble(Small Radius) +Avatar(Small Radius) +Popover +Global Broadcast(Small Radius) + +#### 1.6.1.2.Small(r=8) + +通常适用于如下组件 +Alert(Small Radius) +Drawer(Small Radius) + +#### 1.6.1.3.Medium(r=12) + +通常适用于如下组件 +本案暂不涉及 + +#### 1.6.1.4.Large(r=16) + +通常适用于如下组件 +Input Area(Large Radius) +Alert(Large Radius) +Drawer(Large Radius) +Float(Large Radius) + +#### 1.6.1.5. Extra Large(r=½ Height) + +通常适用于如下组件 +Input Area(Large Radius) +Alert(Large Radius) +Drawer(Large Radius) +Message Bubble(Large Radius) + +### 1.6.2.特殊圆角 + +特殊圆角应用于有背景色的 IM 聊天消息组件: +Message Bubble(Large Radius) + + + +本案不涉及。 + +# 2.基础组件(Widgets) + +## 2.1.按钮组件(Button) + +按钮组件分为普通按钮、文本按钮、图标按钮三种,每种包含的状态有 Enabled、Hovered(限 web 端) 、Pressed、Loading、Pressed 五种状态,同时分为大、中、小三种按钮尺寸以贴合不同容器的使用。 + +### 2.1.1.普通按钮(Normal) + +普通按钮分主要操作(Primary)和次要操作(Secondary)两种类型。 + +#### 2.1.1.1.主要操作(Primary) + +主要操作用于推荐行为,一般背景色为主题色(Primary5\Primary6)或者渐变主题色,被禁用时置灰显示,圆角可配,依据需要可增加左侧或右侧 icon + +![img](@static/images/uikit/chatroomdesign/cruk2111.png) + +#### 2.1.1.2.次要操作(Secondary) + +次要操作用于辅助主要操作,一般不单独出现,一般背景色为亮色(Neutral98)或者暗色(Neutral1),同时有描边,被禁用时置灰显示,圆角可配 +依据需要可增加左侧或右侧 icon + +![img](@static/images/uikit/chatroomdesign/cruk2112.png) + +### 2.1.2.文字按钮(Text) + +文字按钮仅有前景色,也分为主要操作和次要操作,一般用于更频繁的常规操作(如表单填写的下一步、取消,消息的显示、隐藏等)或者在页面有普通按钮(主要操作)时作为更次一级操作出现 + +![img](@static/images/uikit/chatroomdesign/cruk212.png) + +### 2.1.3.图标按钮(Icon) + +图标按钮为组件位置局促又必须出现按钮时的补充形式,如输入条的键盘切换、顶部条的更多操作、表单填写时的推荐操作、输入框的清空和下拉操作等。 + +![img](@static/images/uikit/chatroomdesign/cruk213.png) + +需要注意的是,在 web 端,如非特殊说明,图标按钮必须搭配 Popover 使用,以交代清楚按钮的具体操作行为。如: + +![img](@static/images/uikit/chatroomdesign/cruk213b.png) + +## 2.2.输入框组件(Input) + +输入框为需要输入较少文字时使用的组件。 +也按照所放组件的大小分为大中小三种尺寸可配项,样式上,背景色和描边颜色可开关,圆角可配,状态上分为失焦未填写、失焦填写、聚焦未填写、聚焦填写、禁用填写、禁用未填写六种。 + + + +## 2.3.输入域组件(Input Area) + +输入框为需要输入较多文字时使用的组件。 +在用于输入器的文本输入,和表单中、发布内容时需要填写较多文本时使用,样式上,背景色和描边颜色可开关,圆角可配,可显示最大输入字符数分数。状态上分为失焦未填写、失焦填写、聚焦未填写、聚焦填写、禁用填写、禁用未填写六种。 + + + +## 2.4.头像组件(Avatar) + +头像组件是一类信息数据展示的组件,如用户、某个操作项的头像展示,常放置于个人信息页、与用户相关的列表项中 +头像圆角有两个枚举值:Extra Small(r=4)、Extra Large(r=½ Height)以配合不同主题的使用 +头像的尺寸可以依据所属组件的大小自由配置,但需要注意的是,头像的比例永远是 1:1 + +### 2.4.1.图片头像 + +能读取用户头像信息时展示图片头像。 + +![img](@static/images/uikit/chatroomdesign/cruk241.png) + +### 2.4.2.字符头像 + +用户未上传头像时显示字符头像,字符头像分为单字符和双字符两种 + +![img](@static/images/uikit/chatroomdesign/cruk242.png) + +### 2.4.3.组合头像 + +组合头像用于用户未上传数据时的群组聊天自动生成头像 +本案不涉及 + +![img](@static/images/uikit/chatroomdesign/cruk243.png) + +### 2.4.4.图标头像 + +图标头像用于获取不到用户头像信息的空状态以及表单单项有 icon 时的头像。 + +![img](@static/images/uikit/chatroomdesign/cruk244.png) + +### 2.4.5.头像徽章 + +头像可配置徽章(Badge)以体现用户的在离线等状态,徽章位置分两种:右下和右上 +本案不涉及 + + + + +## 2.5.操作表单(Action Sheet) + +操作表单是以模态形式展示的多操作项表单,单个操作项分为 Enabled、Pressed、Disabled、Destructive 四种状态,以及 Cancel 特殊类型。同时可配置是否显示 icon、是否有分割线(stroke) +此组件仅限移动端 + + + +## 2.6.浮层菜单(PopMenu) + +浮层菜单是以浮层形式展示的多操作项菜单,单个操作项分为 Enabled、Hovered、Pressed、Focused、Disabled、Destructive 六种状态,同时可配置是否显示 icon、是否有字段 2(Body),样式上可配置单项圆角、是否有分割线(Stroke)。 +此组件仅限 web 端 + +![img](@static/images/uikit/chatroomdesign/cruk26.png) + +## 2.7.弹窗通知(Alert) + +弹窗通知是一类模态提示,会提示用户正在进行的操作所需的关键信息,如警告等,或需要用户填写关键信息(通过输入框),需用户做出主要操作或次要操作。 +内容上,description 可配、输入框可配、操作项支持最多三个。 +样式上,弹窗的圆角可配,需要注意的是,组件内部的输入框和操作按钮圆角需要同弹窗按钮的圆角适配,以达成风格的一致性。 + +![img](@static/images/uikit/chatroomdesign/cruk27.png) + +## 2.8.浮层提示(Popover) + +浮层提示为 web 端的非常驻提示信息。仅在鼠标 Hoverd 相关组件时展示,最多支持两个字段(Title 和 Subtitle),因为是浮层提示,背景色需和底色有极大反差,具体表现为:亮色模式上用深色(Neutral1)、暗色模式上用亮色(Neutral98) +且依据需提示内容在页面上的实际位置,分为 10 个方向(上左、上、上右、右上、右、右下、下右、下、下左、左下、左、左上)。 + +![img](@static/images/uikit/chatroomdesign/cruk28.png) + +## 2.9.表情符号(Emoji) + +### 2.9.1.Twemoji [↗](https://github.com/twitter/twemoji) + +表情使用开源可免费商用的 Twemoji 作为基本表情,默认提供 52 个表情作为内置的表情,用户可根据自己的产品规划从 twemoji 提供的 3,245 个表情中进行替换增减; + +![img](@static/images/uikit/chatroomdesign/cruk291.png) + +### 2.9.2.表情模版(Emoji Template) + +如用户需替换 Twemoji,或者需要自己创作表情,需依照以下模板进行替换或绘制; + +![img](@static/images/uikit/chatroomdesign/cruk292.png) + +### 2.9.3.表情组件状态(State) + +表情组件的状态分为以下 4 种: +启用 Enabled、悬停 Hovered(仅限 web 端)、按下 Pressed、聚焦 Focused(本案不涉及) +悬停时,背景色递增一级;按下时,背景色递减一级;聚焦时,背景色转换为 Key Color。 + +![img](@static/images/uikit/chatroomdesign/cruk293.png) + +# 3.业务组件(Components) + +## 3.1.消息组件(Message) + +本案支持发送文本(含 Emoji)、语音(本期不涉及)、礼物消息、全局广播等消息类型 +样式上所有的配置项都是为要保障消息文本的可阅读性。 + +### 3.1.1.文本消息(Text Message) + +文本消息为用户发送的文字消息展示样式 +样式可配项有:背景色(Alpha0-100)、前景色(Neutral0-100)、圆角、字体的大小(Body Large、Body Medium、Body small)、消息气泡的 Pedding +可增减的显示内容项有:Label、Badge、Avatar,Title 和 Description 为必要内容,显示内容的顺序是不可修改的。 + + + +### 3.1.2.语音消息(Audio Message) + +本期不涉及 + +### 3.1.3.礼物消息(Gift Message) + +礼物消息依据国内国外使用场景的不同,分为两种样式 + +#### 3.1.3.1.非常驻礼物消息样式 + +为国内直播场景常见的样式,可设为 Large、Small 两个尺寸, +默认驻留时间为 3 秒(可配置),事件并发时排队展示,可同时最多展示 2 条礼物消息 + + + +消息气泡的样式可配项有:背景色、前景色、头像圆角(需要注意的是,消息背景圆角和头像圆角配套以达成风格的一致)、背景模糊(防止在语聊房场景下组件重叠带来的阅读困难)。 + +#### 3.1.3.2.常驻礼物消息样式 + + + +样式可配项和信息可配项与文本消息相同,只是增加了消息末尾的贴纸展示。 + +### 3.1.4.消息列(Massage List) + +为消息按照时间顺序组合后浮动在直播流上的组件样式,依据国内外用户习惯不同,分为两类样式 + +#### 3.1.4.1.礼物消息和文本消息分开展示的样式 + + + +此组件默认消息之间的间距为 4(用户可自行配置),文本消息区域整体高度占屏幕比例用户可自行配置。礼物非常驻消息一直显示在区域顶侧。消息列右侧需留出给用户放置自定义消息组件的区域,所以此处消息的左右间距不可配置,固定左侧 16,右侧 78。 + +#### 3.1.4.2.礼物消息和文本消息合并展示的样式 + + + +此组件默认消息之间的间距为 4(用户可自行配置),文本消息区域整体高度占屏幕比例用户可自行配置。消息列右侧需留出给用户放置自定义消息组件的区域,所以此处消息的左右间距不可配置,固定左侧 16,右侧 78。 + +### 3.1.5.消息操作(Message Action) + + + +长按消息弹起 action sheet 显示消息相关操作项,操作列表顶部标题栏显示所操作消息的详情。 + +#### 3.1.5.1.消息的举报表单(Report From) + +举报表单为消息操作的次级别页面,提供选择举报原因的单选项,选项数目可增减,选择后可提交举报。 + + + +### 3.1.6.全局广播(Global Message) + +全局广播为超级管理员发送的所有直播间同时可见的非常驻消息,分为三种类型(具体类型需开发者自行定义)通过左侧图标和背景色示以区分。样式的可配项有:圆角、背景色、前景色,信息展示的可配项有左侧 icon(有或无),以及用户可以在自定义广播类型时修改 icon 资源图。消息仅支持单排显示,广播内容超过一屏显示范围为字幕滚动展示,滚动速率可配。 + + + +此消息在移动端一般出现在视频流的顶部;在 web 端出现在聊天窗的顶部,为浮层展示。 + + + +## 3.2.底部条(Footer Bar) + +底部条为移动端的底部操作项展示区域 +样式上的可配项支持背景色、前景色、圆角、图标可替换,是否添加背景模糊效果 +发送消息 action 为必要项,礼物消息 action 为可选项,另最多支持 4 个用户可定义的 action。 + + + +## 3.3.输入条(Input Bar)和语音发送器(Audio Input) + +输入条为键入文本、发送语音和扩展消息的组件。在移动端点击底部条的发送消息操作触发,和键盘搭配使用;在 web 端为在消息窗内底部常驻显示。 +样式上,输入条支持配置分割线、内部的输入框和按钮支持圆角配置 + +### 3.3.1.文本输入条(Input Bar) + +#### 3.3.1.1.移动端文本输入条(Input Bar) + +移动端文本输入条包含文字输入和至多 4 个的键盘切换操作(包括表情键盘、发送语音两个可配项以及另外两个用户可自定义项),可选配文本或者图标形式的发送按钮。 + + + +文本输入条内的文本输入区域为输入区域组件,当单行文本放不下时,文字可在输入区域内折行,对应的输入区域会累积行高,至多支持 4 行文本区域,输入文本超过 4 行后,文本分页展示,用户可滚动查看所键入的文本。 + + + +样式上支持配置分割线(Stroke)、内部输入区域和发送按钮的圆角、描边(Stroke)、前/背景色。 + + + +#### 3.3.1.2.网页端文本输入条(Input Bar) + +网页端文本输入条包含文字输入和至多 4 个的键盘切换操作(包括表情键盘、发送语音、发送礼物三个可配项以及另外一个用户可自定义项),可选配图标形式的发送按钮。 + + + +文本输入条内的文本输入区域为输入区域组件,当单行文本放不下时,文字可在输入区域内折行,对应的输入区域会累积行高,至多支持 4 行文本区域,输入文本超过 4 行后,文本分页展示,用户可滚动查看所键入的文本。 + + + +### 3.3.2.语音发送器(Audio Input) + +本期不涉及 + +## 3.4.表情键盘(Emoji Pick) + +表情键盘是发送 app 内自建表情的键盘,内容上支持表情个数的增减,底部发送和退格按钮支持修改圆角。同时应满足接入第三方表情/贴纸库。 + +![img](@static/images/uikit/chatroomdesign/cruk34.png) + +本键盘不同于系统自带的 emoji 输入键盘,通过此组件输入的 emoji 不会同步为系统的 emoji,而是在任何平台同一 app 内均显示 app 内自建的表情符号。为满足版权方面的法律要求,请勿使用非申明开源可免费商用的表情符号(不限资源图或者源码)在 App 中(如:集成苹果表情符号在自己的 app 内,这样或许会导致 App 无法上架苹果应用商店) + +## 3.5.贴纸键盘(Stickers Pick) + +### 3.5.1.单个贴纸(Sticker) + +单个贴纸用以展示单个礼物消息样式,展示的信息有:礼物图片、礼物名称(Title)、礼物价值(Subtitle)。 +礼物图片未读到时显示默认图,礼物价值可配置价值图标。 +单个贴纸状态有 Enabled、Disabled(主要用于慢速发送,需要用户自行实现)、Focused 三种,Focused 时显示发送按钮。 + + + +### 3.5.2.贴纸键盘(Stickers Pick) + +贴纸键盘在本案内主要应用于发送礼物消息。内容上支持礼物类别(横向滑动切换礼物类别)/类别内礼物个数(上下滑动查看更多礼物)的增减。 + + + +## 3.6.成员列表(Member List) + +### 3.6.1.列表筛选(Tab) + +成员列表顶部支持成员类别筛选,可通过点击 tab 或者左右滑动整个列表切换,至少支持一个 tab, tab 超过四个时支持左右滑动 + + + +### 3.6.2.搜索条(Search Bar) + +搜索条一般位于列表顶端,分为 Enabled n‘ unfilled、Enabled n‘ filled、Focused n‘ unfilled、Focused n‘ filled 四种状态,依据所在列表组件性质的不同可配置左侧返回按钮和右侧 action 按钮,样式上可配置分割线、输入框圆角大小、输入框背景色和描边的增减。 + +![img](@static/images/uikit/chatroomdesign/cruk362.png) + +### 3.6.3.成员列表项(Member Item) + +列表项展示当前成员信息,可展示的信息有徽章(Badge)、头像(Avatar)、用户名(Title)、用户详情(Subtitle),用户名为必要项,其他信息可配置。列表项目右侧支持 action btn,同时列表项支持点击/长按等事件 + + + +样式上,列表项可配置分割线(Stroke),头像支持圆角可配。 + + + +### 3.6.4.列表(Member List) + +将 3.6.1.-3.6.3.组合起来即为整个列表项 + +#### 3.6.4.1.列表整体加载 + + + +#### 3.6.4.2.空列表 + + + +#### 3.6.4.3.列表拉取失败 + + + +#### 3.6.4.4.列表上滑加载 + + + +#### 3.6.4.5.列表展开全屏 + + + +# 4.UI 设计资源 + +设计资源详见 [figma 链接](https://www.figma.com/community/file/1322495388317476706/chatroom-uikit)。 diff --git a/docs/uikit/chatroomuikit/android/roomfeature_common.md b/docs/uikit/chatroomuikit/android/roomfeature_common.md new file mode 100644 index 000000000..93859dcec --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomfeature_common.md @@ -0,0 +1,85 @@ +# ChatroomUIKit 通用特性 + + + +## 创建聊天室 + +ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的 REST API 创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + +![img](@static/images/uikit/chatroomfeature/chatroom_create.png =500x500) + +## 离开聊天室 + +ChatroomUIKit 提供离开聊天室功能。聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + +## 销毁聊天室 + +ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的 REST API 销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + +![img](@static/images/uikit/chatroomfeature/chatroom_destroy.png =500x500) + +## 发送弹幕 + +用户在聊天室中向其他成员发送文字和表情的消息。发送消息在聊天室中是沟通和交流的基本行为,它使参与者能够分享信息、表达观点、提问、分享内容或与其他人建立联系。 + +在 UIKit 中,用户通过点击输入框,触发键盘以编辑文本信息,也可以通过点击表情按钮切换键盘,编辑表情信息,然后点击**发送**按钮发送消息。 + +用户可以根据业务需要选择显示或隐藏消息发送时间(HH:MM 格式)、用户标识和用户头像。 + +![img](@static/images/uikit/chatroomfeature/barrage_send.png =500x500) + +## 打赏 + +用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持的行为。当用户认为某个用户或内容值得赞赏时,可以选择打赏的方式给予对方代表着特定金额的虚拟礼物。 + +打赏不仅可以作为对其他用户的鼓励和支持,对于主播和直播平台而言,打赏也成为主要收入来源之一。 + +在 UIKit 中,默认提供了 12 种不同的虚拟礼物。同时,用户可以自定义虚拟礼物的样式、名称和金额。 + +![img](@static/images/uikit/chatroomfeature/gift.png =500x500) + +## 全局广播 + +全局广播即向 App 内所有聊天室中的所有用户发送消息或通知,可用于传达重要信息、公告、提醒或紧急通知等。 + +全局广播通常会使用明显的标识或格式以区别于普通聊天消息,确保用户能够快速识别全局广播。 + +你也可以[调用 REST API 发送聊天室全局广播消息](/document/server-side/message_chatroom.html#发送聊天室全局广播消息)。 + +在 UIKit 中,用户可以自定义全局广播的标识以及发送内容。全局广播消息的默认展示策略如下: + +- 若内容未超过一屏宽,无需滚动,停留 3 秒后消失; +- 若内容超过一屏宽,则需要滚动,先停留 2 秒展示开头部分,然后以每秒 10 个字符的速度进行滚动,滚动完成后再停留 2 秒。 +- 若同时有多条全局广播消息,则按消息发送的时间顺序播放,一条消息滚动完成后再播放下一条。 + +![img](@static/images/uikit/chatroomfeature/global_broadcast.png =600x500) + +## 未读消息数 + +聊天室未读消息数指在一个聊天室中用户尚未读取的消息数量。在 UIKit 中,当用户滑动屏幕回看消息时,消息区域定位将会变更,此时产生的新消息会被标记为未读消息。同时,在消息区域的右下方会出现未读消息按钮。该按钮展示未读消息数,用户点击后直接定位到最新消息位置(通常为消息区域的最底部),确保不错过未读信息。 + +若未读消息的数量不超过 99,则未读消息数显示实际的数量,若达到 100 及以上则显示 99+。 + +![img](@static/images/uikit/chatroomfeature/message_unread.png =300x600) + +## 已禁言列表 + +记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。被禁言的成员无法在聊天室中发送消息,但仍留在聊天室,可以查看消息。 + +在 UIKit 中,默认通过点击聊天室界面右上角的成员按钮,触发已禁言列表。用户在列表中查看聊天室被禁言的所有成员,包括成员的身份、头像和昵称,同时可以通过点击成员右端的管理功能按钮,触发解除禁言选项,实现取消禁言的操作。 + +![img](@static/images/uikit/chatroomfeature/mute_list.png =300x700) + +## 暗黑模式 + +暗黑模式是一种界面设计选择,旨在提供更低对比度和更多暗色调的视觉外观。用户可以根据需要启用或禁用暗黑模式,以实现最佳的使用体验。 + +UIKit 支持暗黑模式的一键切换。UIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 + +![img](@static/images/uikit/chatroomfeature/dark_mode.png) + + + + + + diff --git a/docs/uikit/chatroomuikit/android/roomfeature_member.md b/docs/uikit/chatroomuikit/android/roomfeature_member.md new file mode 100644 index 000000000..7f23e80ce --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomfeature_member.md @@ -0,0 +1,41 @@ +# 成员管理 + + + +聊天室中的成员角色分为聊天室所有者和普通成员。普通成员可以发送和查看聊天室中的消息、进行消息翻译、举报和撤回、以及查看成员列表和搜索成员等操作。聊天室所有者除了具备普通成员的权限,还可以禁言成员和移除成员。 + +## 查看成员列表 + +聊天室中的所有成员的列表。聊天室成员列表显示了该聊天室中的当前在线用户。通过查看成员列表,用户可以看到聊天室中有哪些成员正在参与对话,也可以对于成员采取一些操作。 + +在 UIKit 中,默认通过点击聊天室界面右上角的成员按钮,触发成员列表弹窗。在成员列表中,用户可以查看聊天室当前在线成员,包括成员的身份、头像和昵称,同时可以点击每位成员右侧的按钮,触发禁言和移除的操作。 + +![img](@static/images/uikit/chatroomfeature/member_list.png =500x500) + +## 搜索成员 + +在聊天室中查找指定成员的功能,支持本地搜索和模糊匹配。 + +UIKit 中的成员搜索功能放置在[成员列表](#查看成员列表)中。当聊天室中的成员较多时,用户可以在成员列表搜索框中输入成员昵称快速找到指定成员。 + +![img](@static/images/uikit/chatroomfeature/member_search.png =300x600) + +## 禁言成员 + +聊天室所有者可以在聊天室中对某个特定的成员禁言。禁言通常是对违反聊天室规则、发表不当言论或不断干扰聊天室秩序的成员所采取的一种惩罚。 + +在 UIKit 的成员列表中,通过点击单个成员的管理功能按钮,触发禁言成员的选项,实现对指定成员的禁言惩罚。你也可以通过长按聊天室中的单条消息,触发[禁言选项](roomfeature_message#禁言成员),实现对发送该条消息的成员的禁言惩罚。成员被禁言后,会被加入[已禁言列表](roomfeature_common#已禁言列表),无法在聊天室中发送消息,但仍留在聊天室,可以查看消息。 + +此外,在聊天室消息区域,你可以长按单条消息,对发送该条消息的成员的进行禁言。 + +如果用户想要取消禁言成员,需要在已禁言列表中找到该成员,点击成员右端的管理功能按钮,触发解除禁言选项,实现取消禁言的操作。 + +![img](@static/images/uikit/chatroomfeature/member_mute.png =500x500) + +## 移除成员 + +从聊天室中将某个成员踢出的行为。通常,当某成员违反了聊天室规则或发表了不当言论,聊天室所有者会对该成员进行移除。 + +在 UIKit 的成员列表中,聊天室所有者通过点击单个成员的管理功能按钮,触发移除成员的选项,实现对指定成员的踢出操作。 + +![img](@static/images/uikit/chatroomfeature/member_mute.png =500x500) \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/android/roomfeature_message.md b/docs/uikit/chatroomuikit/android/roomfeature_message.md new file mode 100644 index 000000000..5c452cc4c --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomfeature_message.md @@ -0,0 +1,41 @@ +# 消息扩展特性 + + + +除了在聊天室中发送和查看消息,还可以长按一条消息进行消息举报、翻译、撤回和禁言成员。 + +## 消息举报 + +在聊天室中,当用户发现其他人发布了可能违反聊天室规则或道德准则的消息时,可以举报该消息,促使聊天室所有者采取适当的行动。 + +在 UIKit 中,默认通过长按单条消息,触发举报选项,实现消息举报。用户可以选择举报原因,如色情内容、恶意攻击、仇恨言论、垃圾广告等。你也可以根据业务需要,修改举报原因选项。 + +![img](@static/images/uikit/chatroomfeature/msg_report.png =600x400) + +## 消息翻译 + +将聊天室中的单条消息从一种语言转换成另一种语言。翻译特性可以帮助聊天室中的成员克服语言障碍,促进跨语言沟通和交流。 + +在 UIKit 中,默认通过长按单条消息,触发翻译选项,实现消息翻译。默认翻译后的语言与用户设备的系统设置保持一致,例如,若你的手机系统语言为中文,则消息翻译的目标语言也是中文。翻译后的消息显示在原消息的位置,替换原消息。 + +![img](@static/images/uikit/chatroomfeature/msg_translate.png =500x500) + +## 消息撤回 + +在聊天室中撤销已经发送的消息。当用户发送一条消息后,可能会发现消息内容有误或不妥当,可以使用消息撤回功能将消息从聊天室的聊天窗口中删除,使其他用户无法再看到该消息。在 UIKit 中,默认通过长按单条消息,触发撤回选项,实现对该条消息的撤回。撤回的默认限制是 2 分钟,超时则无法撤回。时间限制可[通过环信控制台的进行调整](/product/enable_and_configure_IM.html#设置消息撤回-rest-客户端),最长为 7 天。 + +:::tip +所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 +::: + +![img](@static/images/uikit/chatroomfeature/msg_recall.png =800x600) + +## 禁言成员 + +在聊天室中对指定成员采取禁止发言的措施。禁言通常是对违反聊天室规则、发表不当言论或不断干扰聊天室秩序的成员所采取的一种惩罚。 + +在 UIKit 中,默认通过长按单条消息,触发禁言选项,实现对发送该条消息的成员的禁言惩罚。此外,用户也可以通过[成员列表](roomfeature_member#查看成员列表)对指定成员直接进行禁言惩罚。 + +当成员被禁言后,将会被加入[已禁言列表](roomfeature_common#已禁言列表)。如果用户想要取消禁言成员,需要在已禁言列表中找到该成员,点击成员右端的管理功能按钮,触发解除禁言选项,实现取消禁言的操作。 + +![img](@static/images/uikit/chatroomfeature/msg_mute.png =500x500) diff --git a/docs/uikit/chatroomuikit/android/roomuikit_best_practice.md b/docs/uikit/chatroomuikit/android/roomuikit_best_practice.md new file mode 100644 index 000000000..cf4d33f83 --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_best_practice.md @@ -0,0 +1,68 @@ +# 最佳实践 + + + +## 初始化 ChatroomUIKit + +初始化是使用 ChatroomUIKit 的必要步骤,需在所有接口方法调用前完成。 + +初始化 ChatroomUIKit 时,你可以传入 `option` 参数,设置各种选项。 + +```kotlin + val chatroomUIKitOptions = ChatroomUIKitOptions( + chatOptions = ChatSDKOptions(enableDebug = true), + uiOptions = UiOptions( + targetLanguageList = listOf(currentLanguage), + useGiftsInList = false, + ) + ) +``` + +## 登录 ChatroomUIKit + +你可以通过使用工程中的用户对象并遵守 `UserInfoProtocol` 协议登录 ChatroomUIKit,示例代码如下: + +```kotlin +class YourAppUser: UserInfoProtocol { + var userId: String = "your application user id" + + var nickName: String = "you user nick name" + + var avatarURL: String = "you user avatar url" + + var gender: Int = 1 + + var identity: String = "you user level symbol url" + +} +ChatroomUIKitClient.getInstance().login(YourAppUser, token, onSuccess = {}, onError = {code,error ->}) +``` + +## 初始化聊天室视图 + +1. 获取聊天室列表,加入指定的聊天室。除此之外,你还可以在环信即时通讯云控制台上[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室),获取聊天室 ID。 + +2. 加载聊天室视图 `ComposeChatroom`,传入的参数包括聊天室 ID、布局参数、聊天室所有者的用户 ID 及一些选项。 + +```kotlin +class ChatroomActivity : ComponentActivity(){ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + ComposeChatroom(roomId = roomId,roomOwner = ownerInfo) + } + } +} +``` + +## 监听 ChatroomUIKit 事件和错误 + +你可以调用 `registerRoomResultListener` 方法添加监听器用于监听 ChatroomUIKit 事件和错误。 + +```kotlin +ChatroomUIKitClient.getInstance().registerRoomResultListener(this) +``` + +## 参考 + +若要了解以上最佳实践的详情,请访问 [GitHub 仓库](https://github.com/easemob/ChatroomDemo/tree/dev/Android/ChatroomDemo)。 \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/android/roomuikit_config_item.md b/docs/uikit/chatroomuikit/android/roomuikit_config_item.md new file mode 100644 index 000000000..3c602d35c --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_config_item.md @@ -0,0 +1,29 @@ +# 可配置项 + + + +- 修改 `UiOptions` 中的可配置项。例如,你可以修改 `UiOptions` 中的 `useGiftsInList` 配置消息列表上是否显示礼物。 + +```kotlin +val chatroomUIKitOptions = ChatroomUIKitOptions( + uiOptions = UiOptions( + targetLanguageList = listOf(GlobalConfig.targetLanguage.code), + useGiftsInList = false, + ) +) +``` + +- 修改 `ViewModel` 中的可配置项。例如,你可以修改 `MessageListViewModel` 中的可配项,配置是否显示时间和头像。 + +```kotlin +class MessageListViewModel( + private val isDarkTheme: Boolean? = false, + private val showDateSeparators: Boolean = true, + private val showLabel: Boolean = true, + private val showAvatar: Boolean = true, + private val roomId: String, + private val chatService: UIChatroomService, + private val composeChatListController: ComposeChatListController +) +``` + diff --git a/docs/uikit/chatroomuikit/android/roomuikit_integrated.md b/docs/uikit/chatroomuikit/android/roomuikit_integrated.md new file mode 100644 index 000000000..18f1701b4 --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_integrated.md @@ -0,0 +1,33 @@ +# 集成 ChatroomUIKit + + + +使用 ChatroomUIKit 之前,你需要将 ChatroomUIKit 集成到你的应用中。 + +## 前提条件 + +要集成 ChatroomUIKit,你的开发环境需要满足以下需求: + +- Android Studio Arctic Fox (2020.3.1) 或以上版本; +- Android API 级别 21 或以上版本; +- 使用 Kotlin 语言开发,1.5.21 或以上版本; +- JDK 1.8 或以上版本; +- Gradle 7.0.0 或以上版本。 + +## 添加 ChatroomUIKit 模块本地依赖 + +找到下载的 **ChatroomUIKit** 模块添加为本地依赖。将 [ChatroomUIKit](https://github.com/easemob/UIKit_Chatroom_android/tree/dev/ChatroomUIKit) 和 [ChatroomService](https://github.com/easemob/UIKit_Chatroom_android/tree/dev/ChatroomService) 模块导入到项目中。 + +```kotlin +// settings.gradle +include ':ChatroomUIKit' +include ':ChatroomService' +project(':ChatroomUIKit').projectDir = new File('../ChatroomUIKit/ChatroomUIKit') +project(':ChatroomService').projectDir = new File('../ChatroomUIKit/ChatroomService') + +// app/build.gradle +dependencies { + implementation(project(mapOf("path" to ":ChatroomUIKit"))) +} +``` + diff --git a/docs/uikit/chatroomuikit/android/roomuikit_overview.md b/docs/uikit/chatroomuikit/android/roomuikit_overview.md new file mode 100644 index 000000000..a11e34c11 --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_overview.md @@ -0,0 +1,44 @@ +# 概述 + + + +环信 ChatroomUIKit 提供 UIKit 的各种组件帮助开发者根据实际业务需求快速搭建聊天室应用。通过该 UIKit,聊天室中的用户可实时交互,发送普通弹幕消息、打赏消息和全局广播等功能。 + +- 若要访问源码,请点击[这里](https://github.com/easemob/UIKit_Chatroom_android)。 + +- 你可以扫描以下二维码体验环信聊天室 UIKit Demo: + +![img](@static/images/uikit/chatroomandroid/demo.png) + +## 功能 + +ChatroomUIKit 提供以下功能: + +- **通用特性** +| 功能 | 描述 | + |--|:--| + | 创建聊天室 | ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 | + | 销毁聊天室 | ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 | + | 离开聊天室 | 聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 | + | 发送弹幕消息 | 用户在聊天室中向其他参与者发送文字和表情的消息。 | + | 打赏 | 用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 | + | 全局广播 | 向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 | + | 未读消息数 | 在一个聊天室中用户尚未读取的消息数量。 | + | 已禁言列表 | 记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 | + | 暗黑模式 | ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 | + +- **消息扩展** +| 功能 | 描述 | + |--|:--| + | 消息举报 | 在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。| + | 消息翻译 | 将聊天室中的单条消息从一种语言转换成另一种语言。| + | 消息撤回 | 在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。| + | 禁言成员 | 聊天室所有者对聊天室中的成员禁止发言。| + +- **成员管理** +| 功能 | 描述 | + |--|:--| + | 查看成员列表 | 聊天室成员列表显示了该聊天室中的当前在线用户 | + | 搜索成员 | 在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 | + | 禁言成员 | 聊天室所有者可以在聊天室中对某个特定的成员禁言。 | + | 移除成员 | 聊天室所有者将指定成员从聊天室中踢出。 | diff --git a/docs/uikit/chatroomuikit/android/roomuikit_quickstart.md b/docs/uikit/chatroomuikit/android/roomuikit_quickstart.md new file mode 100644 index 000000000..c4a427c54 --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_quickstart.md @@ -0,0 +1,101 @@ +# 快速开始 + + + +利用 ChatroomUIKit,你可以轻松实现聊天室内的用户交互。本文介绍如何实现在聊天室中发送消息。 + +## 前提条件 + +- Android Studio Arctic Fox (2020.3.1) 或以上版本; +- Android API 级别 21 或以上; +- 使用 Kotlin 语言开发,1.5.21 或以上版本; +- JDK 1.8 或以上版本; +- Gradle 7.0.0 或以上版本; +- 已在[环信即时通讯云控制台](https://console.easemob.com/user/login)创建了有效的环信即时通讯 IM 开发者账号,并[获取了 App Key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 +- 如果你的网络环境部署了防火墙,请联系环信技术支持设置白名单。 + +## 创建项目引入 ChatroomUIKit 模块 + +1. 在 Android Studio 中创建一个 Android 平台下的 App 或者打开自己现有项目。 + +2. 选择 **File** > **import Module**。 + +3. 模块本地依赖。 + +找到下载的 **ChatroomUIKit** 模块添加为本地依赖。将 [ChatroomUIKit](https://github.com/easemob/UIKit_Chatroom_android/tree/dev/ChatroomUIKit) 和 [ChatroomService](https://github.com/easemob/UIKit_Chatroom_android/tree/dev/ChatroomService) 模块导入到项目中。 + +```kotlin +// settings.gradle +include ':ChatroomUIKit' +include ':ChatroomService' +project(':ChatroomUIKit').projectDir = new File('../ChatroomUIKit/ChatroomUIKit') +project(':ChatroomService').projectDir = new File('../ChatroomUIKit/ChatroomService') + +// app/build.gradle +dependencies { + implementation(project(mapOf("path" to ":ChatroomUIKit"))) +} +``` + +### 第一步 初始化 ChatroomUIKit + +你可以在应用加载时或使用 ChatroomUIKit 之前对其进行初始化。 + +初始化时,需传入 App Key。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**应用详情**页面查看 App Key。 + +```kotlin +// 初始化 ChatroomUIKit +class ChatroomApplication : Application() { + + override fun onCreate() { + super.onCreate() + + ChatroomUIKitClient.getInstance().setUp(this, "Your AppKey") + + } +} +``` + +### 第二步 登录 ChatroomUIKit + +使用用户 ID 和用户 Token 登录 ChatroomUIKit。 + +:::tip +若你已集成了 IM SDK,SDK 的所有用户 ID 均可用于登录 ChatroomUIKit。 +::: + +为了方便快速体验,你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**应用概览** > **用户认证**页面创建用户并查看用户 token。**用户认证**页面中的用户仅用于快速体验或调试目的。 + +在开发环境中,你需要在环信控制台[创建 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户),从你的 App Server 获取用户 token,详见[使用环信用户 token 鉴权](/product/easemob_user_token.html) 。 + + +```kotlin + ChatroomUIKitClient.getInstance().login("userId", "token") +``` + +### 第三步 创建聊天室视图 + +创建聊天室视图的步骤如下: + +1. 获取聊天室列表,加入指定的聊天室。除此之外,你还可以在环信即时通讯云控制台上[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室),获取聊天室 ID。 + +2. 加载聊天室视图 `ComposeChatroom`,传入的参数包括聊天室 ID 和聊天室所有者的用户 ID。 + +```kotlin +class ChatroomActivity : ComponentActivity(){ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + ComposeChatroom(roomId = roomId,roomOwner = ownerInfo) + } + } +} +``` + +3. [添加聊天室成员](https://doc.easemob.com/product/enable_and_configure_IM.html#创建聊天室)。 + +### 第四步 发送消息 + +在屏幕下方输入消息内容,点击 **发送** 按钮,发送消息。 + +![img](@static/images/uikit/chatroomandroid/click_chat.png =500x500) \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/android/roomuikit_releasenote.md b/docs/uikit/chatroomuikit/android/roomuikit_releasenote.md new file mode 100644 index 000000000..1ef4a279a --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_releasenote.md @@ -0,0 +1,31 @@ +# 聊天室 UIKit 更新日志 + + + +## 版本 V1.0.0 2023-12-29 + +### 新增特性 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - [创建聊天室](roomfeature_common.html#创建聊天室):ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - [销毁聊天室](roomfeature_common.html#销毁聊天室):ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - [离开聊天室](roomfeature_common.html#离开聊天室):聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - [发送弹幕消息](roomfeature_common.html#发送弹幕):用户在聊天室中向其他参与者发送文字和表情的消息。 + - [打赏](roomfeature_common.html#打赏):用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - [全局广播](roomfeature_common.html#全局广播):向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - [未读消息数](roomfeature_common.html#未读消息数):在一个聊天室中用户尚未读取的消息数量。 + - [已禁言列表](roomfeature_common.html#已禁言列表):记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - [暗黑模式](roomfeature_common.html#暗黑模式):ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展**(长按一条消息可进行的操作) + - [消息举报](roomfeature_message.html#消息举报):在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - [消息翻译](roomfeature_message.html#消息翻译):将聊天室中的单条消息从一种语言转换成另一种语言。 + - [消息撤回](roomfeature_message.html#消息撤回):在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - [禁言成员](roomfeature_message.html#禁言成员):聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - [查看成员列表](roomfeature_member.html#查看成员列表):聊天室成员列表显示了该聊天室中的当前在线用户。 + - [搜索成员](roomfeature_member.html#搜索成员):在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - [禁言成员](roomfeature_member.html#禁言成员):聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - [移除成员](roomfeature_member.html#移除成员):聊天室所有者将指定成员从聊天室中踢出。 + diff --git a/docs/uikit/chatroomuikit/android/roomuikit_run.md b/docs/uikit/chatroomuikit/android/roomuikit_run.md new file mode 100644 index 000000000..c984cfb94 --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_run.md @@ -0,0 +1,91 @@ +# 跑通示例项目 + + + +环信提供一个开源的 ChatroomUIKit 示例项目,演示了如何使用该 UIKit 快速搭建聊天室页面,实现完整业务。 + +本文展示如何编译并运行 Android 平台的聊天室 UIKit 示例项目。 + +## 前提条件 + +开始前,确保你的开发环境满足如下条件: + +- Android Studio Arctic Fox (2020.3.1) 或以上版本; +- Android API 级别 21 或以上; +- 使用 Kotlin 语言开发,1.5.21 或以上版本; +- JDK 1.8 或以上版本; +- Gradle 7.0.0 或以上版本。 + +## 操作步骤 + +### 第一步 下载 ChatroomUIKit 示例代码 + +点击 [github源码](https://github.com/easemob/UIKit_Chatroom_android),将示例代码下载到本地设备。 + +### 第二步 添加 ChatroomUIKit 模块依赖 + +1. 在 Android Studio 中打开你的项目。 + +2. 选择 **File** > **import Module**。 + +3. 添加模块本地依赖。 + +找到下载的 **ChatroomUIKit** 模块添加为本地依赖。将 [ChatroomUIKit](https://github.com/easemob/UIKit_Chatroom_android/tree/dev/ChatroomUIKit) 和 [ChatroomService](https://github.com/easemob/UIKit_Chatroom_android/tree/dev/ChatroomService) 模块导入到项目中。 + +```kotlin +// settings.gradle +include ':ChatroomUIKit' +include ':ChatroomService' +project(':ChatroomUIKit').projectDir = new File('../ChatroomUIKit/ChatroomUIKit') +project(':ChatroomService').projectDir = new File('../ChatroomUIKit/ChatroomService') + +// app/build.gradle +dependencies { + implementation(project(mapOf("path" to ":ChatroomUIKit"))) +} +``` + +### 第三步 编译 + +编译时,需要传入 App Key、用户 ID 和用户 token。因此,编译前,你需要在[环信控制台](https://console.easemob.com/user/login)上创建有效的环信即时通讯 IM 开发者账号,并获取 App Key,[创建环信 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户)。此外,还需[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室)。 + +1. 初始化 ChatroomUIKit。 + +```kotlin +class ChatroomApplication : Application() { + + override fun onCreate() { + super.onCreate() + + ChatroomUIKitClient.getInstance().setUp(this, "Your AppKey") + + } +} +``` + +2. 登录 ChatroomUIKit。 + +```kotlin + ChatroomUIKitClient.getInstance().login("userId", "token") +``` + +3. 加载 ComposeChatroom 视图,传入 `roomId` 和聊天室所有者的 `UserEntity` 对象。 + +```kotlin +class ChatroomActivity : ComponentActivity(){ + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + ComposeChatroom(roomId = roomId,roomOwner = ownerInfo) + } + } +} +``` + +### 第四步 体验项目 + +运行并体验该项目。 + +## 注意事项 + +示例工程仅用于快速跑通流程,暂时未提供多成员交互测试。 diff --git a/docs/uikit/chatroomuikit/android/roomuikit_theme.md b/docs/uikit/chatroomuikit/android/roomuikit_theme.md new file mode 100644 index 000000000..7fa2692ea --- /dev/null +++ b/docs/uikit/chatroomuikit/android/roomuikit_theme.md @@ -0,0 +1,38 @@ +# 主题 + + + +ChatroomUIkit 内置浅色和深色主题,默认为浅色主题。 + +- 浅色主题 + +![img](@static/images/uikit/chatroomandroid/light_mode.png) + +- 深色主题 + +![img](@static/images/uikit/chatroomandroid/dark_mode.png) + +## 自定义主题 + +你可以通过更新主题相关的配置项自定义主题。若对任何配置项不做修改,可以使用默认主题。 + +```kotlin +@Composable +fun ChatroomUIKitTheme( + isDarkTheme: Boolean = isSystemInDarkTheme(), + colors: UIColors = if (!isDarkTheme) UIColors.defaultColors() else UIColors.defaultDarkColors(), + shapes: UIShapes = UIShapes.defaultShapes(), + dimens: UIDimens = UIDimens.defaultDimens(), + typography: UITypography = UITypography.defaultTypography(), + content: @Composable () -> Unit +) +``` + +## 设计指南 + +如果你对主题颜色,设计指南和细节有任何疑问,您可以在 Figma 设计稿中添加评论并提及我们的设计师 Stevie Jiang。 + +- [UI 设计资源](https://www.figma.com/community/file/1322495388317476706/chatroom-uikit)。 + +- [UI 设计指南](design_guide.html)。 + diff --git a/docs/uikit/chatroomuikit/flutter/design_guide.md b/docs/uikit/chatroomuikit/flutter/design_guide.md new file mode 100644 index 000000000..52ba5431a --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/design_guide.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/design_guide.html", + title: "设计指南" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/flutter/roomfeature_common.md b/docs/uikit/chatroomuikit/flutter/roomfeature_common.md new file mode 100644 index 000000000..fb695c37a --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomfeature_common.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_common.html", + title: "通用" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/flutter/roomfeature_member.md b/docs/uikit/chatroomuikit/flutter/roomfeature_member.md new file mode 100644 index 000000000..703fa2f8b --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomfeature_member.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_member.html", + title: "成员管理" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/flutter/roomfeature_message.md b/docs/uikit/chatroomuikit/flutter/roomfeature_message.md new file mode 100644 index 000000000..e76f080fa --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomfeature_message.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_message.html", + title: "消息扩展" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_best_practice.md b/docs/uikit/chatroomuikit/flutter/roomuikit_best_practice.md new file mode 100644 index 000000000..6dbbaceb2 --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_best_practice.md @@ -0,0 +1,149 @@ +# 最佳实践 + + + +## 初始化 chatroom_uikit + +初始化是使用 `chatroom_uikit` 的必要步骤,需在所有接口方法调用前完成。 + +```dart +void main() async { + assert(appKey.isNotEmpty, 'appKey is empty'); + await ChatroomUIKitClient.instance.initWithAppkey( + appKey, + ); + runApp(const MyApp()); +} +``` + +## 登录 chatroom_uikit + +你可以通过使用项目中的用户对象并遵守 `UserInfoProtocol` 协议登录。chatroom_uikit 提供了默认的 `UserEntity` 实现,如果需要自己添加属性,可以继承 `UserEntity`: + +- 使用用户 ID `userId` 和密码 `password` 登录: + +```dart +// ... +//设置当前用户的头像和昵称。 + UserEntity user = UserEntity(userId, nickname: nickname, avatarURL: avatarURL); +try { + // 通过密码登录。 + await ChatroomUIKitClient.instance.loginWithPassword( + userId: userId!, + password: password, + userInfo: user, + ); + +} on ChatError catch (e) { + // error. +} +``` + +- 使用用户 ID `userId` 和 token 登录: + +```dart +//设置当前用户的头像和昵称。 + UserEntity user = UserEntity(userId, nickname: nickname, avatarURL: avatarURL); +try { + await ChatroomUIKitClient.instance.loginWithToken( + userId: userId, + token: token!, + userInfo: user, + ); + +} on ChatError catch (e) { + // error. +} +``` + +## 初始化聊天室视图 + +1. 使用聊天室视图,需要先配置主题,确保聊天室能正常加载到主题, + +```dart + +@override + Widget build(BuildContext context) { + return MaterialApp( + builder: (context, child) { + return ChatUIKitTheme(child: child!); + }, + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ... + ); + } +``` + +2. 获取聊天室列表,加入指定的聊天室。除此之外,你还可以在环信即时通讯云控制台上[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室),获取聊天室 ID。 + +3. 使用 `chatroom_uikit` 前,需要先创建 `ChatroomController`, 并使 `ChatRoomUIKit` 作为当前页面的根节点,并将其他组件作为 `ChatRoomUIKit` 的子节点。 + +```dart +// roomId: 需要加入的聊天室 ID。 +// ownerId: 聊天室所有者的用户 ID。 +ChatroomController controller = ChatroomController(roomId: roomId, ownerId: ownerId); + +@override +Widget build(BuildContext context) { + Widget content = Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar(), + body: ChatRoomUIKit( + controller: controller, + child: (context) { + // 在子组件中构建页面,比如 礼物弹窗,消息列表等。 + return ...; + }, + ), + ); + + return content; +} +``` + +## 监听聊天室的事件和错误 + +你可以在初始化 `ChatroomController` 时设置聊天室事件的监听器 `ChatroomEventListener`, 当前聊天室的相关事件会通过该回调返回。 + +```dart +controller = ChatroomController( + listener: ChatroomEventListener((type, error) { + // catch errors. + }), + roomId: widget.room.id, + ownerId: widget.room.ownerId, +); +``` + +如果需要监听全局事件,可以使用 `ChatroomResponse` 和 `ChatroomEventResponse` + +```dart + +class _ChatroomViewState extends State + with ChatroomResponse, ChatroomEventResponse { + @override + void initState() { + super.initState(); + + ChatroomUIKitClient.instance.roomService.bindResponse(this); + ChatroomUIKitClient.instance.bindRoomEventResponse(this); + } + + @override + void dispose() { + ChatroomUIKitClient.instance.roomService.unbindResponse(this); + ChatroomUIKitClient.instance.unbindRoomEventResponse(this); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} + +``` + +## 参考 + +若要了解以上最佳实践的详情,请访问 [GitHub 仓库](https://github.com/easemob/ChatroomDemo/tree/dev/flutter/chatroom_uikit_demo)。 \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_config_item.md b/docs/uikit/chatroomuikit/flutter/roomuikit_config_item.md new file mode 100644 index 000000000..8e0c897a4 --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_config_item.md @@ -0,0 +1,358 @@ +# 可配置项 + + + +`chatroom_uikit` 的组件中包含各种属性,你可以根据需求进行设置。 + + `chatroom_uikit` 主要包括如下组件: + +| 组件名称 | 组件介绍 | +| --------------- | ---------------------------- | +| [ChatroomLocal 组件](#chatroomlocal-组件) | 可以设置 `UIKit` 所有 UI 组件的语言。 | +| [ChatRoomUIKit 组件](#chatroomuikit-组件) | 提供基础的聊天室页面。 | +| [ChatroomMessageListView 组件](#chatroommessagelistview-组件) | 聊天室消息区域组件,用于显示发送或者接收到的消息。 | +| [ChatroomParticipantsListView 组件](#chatroomparticipantslistview-组件) | 聊天室成员列表组件,包括聊天室成员和禁言成员的管理。 | +| [ChatroomGiftMessageListView 组件](#chatroomgiftmessagelistview-组件) | 聊天室打赏消息区域组件,用于显示打赏的礼物。 | +| [ChatroomGlobalBroadcastView 组件](#chatroomglobalbroadcastview-组件) | 聊天室全局广播组件,用于向 app 下的所有聊天室发送消息。 | +| [ChatInputBar 组件](#chatinputbar-组件) | 聊天室底部工具栏区域,可以与消息输入组件互相切换,支持添加自定义按钮。 | +| [ChatRoomGiftListView 组件](#chatroomgiftlistview-组件) | 发送礼物组件,用于发送礼物,礼物来源由开发者指定。 | +| [ChatroomReportListView 组件](#chatroomreportlistview-组件) | 聊天室举报组件。 | + +## ChatroomLocal 组件 + +UIKit 支持多国语言切换,目前内置中文和英文,可以扩展其他语言。 + +例如:若要 UIKit 使用英文显示,可以如下设置: + +```dart +final FlutterLocalization _localization = FlutterLocalization.instance; +_localization.init(mapLocales: [ + const MapLocale('zh', ChatroomLocal.zh), + const MapLocale('en', ChatroomLocal.en), +], initLanguageCode: 'zh'); + +... + +return MaterialApp( + title: 'Flutter Demo', + supportedLocales: _localization.supportedLocales, + localizationsDelegates: _localization.localizationsDelegates, + ... +); + +``` + +## ChatRoomUIKit 组件 + +ChatRoomUIKit 组件为聊天室组件,可以用来快速提供聊天室页面,并提供了聊天室事件监听和输入组件的自定义。 + +示例如下: + +```dart +ChatroomController controller = + ChatroomController(roomId: widget.roomId, ownerId: widget.ownerId); +... + +@override +Widget build(BuildContext context) { + return ChatRoomUIKit( + controller: controller, + inputBar: ChatInputBar( // 自定义你需要的输入样式 + actions: [ + InkWell( + onTap: () => controller.showGiftSelectPages(), + child: Padding( + padding: const EdgeInsets.all(3), + child: Image.asset('images/send_gift.png'), + ), + ), + ], + ), + child: (context) { + // 返回你的 widget + return Container(); + }, + ); +} + +``` + +## ChatroomMessageListView 组件 + +聊天室消息区域组件 `ChatroomMessageListView` 提供消息的显示,聊天室接收到的文本消息、表情消息、礼物消息以及发送成功的消息会显示在该区域。 + +可以在消息区域中对消息进行操作,例如,翻译文本消息为目标语言、撤销消息和消息上报等。你可以通过长按消息列表项弹出菜单进行相应操作。 + +数据上报组件支持自定义选项,可以自定义选项上报不同内容。 + +示例代码如下: + +```dart +ChatroomController controller = + ChatroomController(roomId: widget.roomId, ownerId: widget.ownerId); +... + +@override +Widget build(BuildContext context) { + return ChatRoomUIKit( + controller: controller, + inputBar: ChatInputBar( // 自定义你需要的输入样式 + actions: [ + InkWell( + onTap: () => controller.showGiftSelectPages(), + child: Padding( + padding: const EdgeInsets.all(3), + child: Image.asset('images/send_gift.png'), + ), + ), + ], + ), + child: (context) { + return Stack( + children: [ + const Positioned( + left: 16, + right: 78, + height: 204, + bottom: 90, + child: ChatroomMessageListView(), // 添加消息列表并设置位置 + ) + ], + ); + }, + ); +} +``` + +`ChatroomMessageListView` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ------------------------ | -------- | ----------------------------------------------- | +| onTap | 否 | 消息列表点击事件。 | +| onLongPress | 否 | 消息列表长按事件。 | +| itemBuilder | 否 | 消息列表项 build,可以用于自定义显示样式。 +| reportController | 否 | `ChatReportController` 用于自定义举报内容,默认使用 `DefaultReportController`。 | +| controller | 否 | `ChatroomMessageListController`, 用于配置默认长按事件,默认使用 `DefaultMessageListController`。 | + +## ChatroomParticipantsListView 组件 + +聊天室成员组件可以显示和管理聊天室成员,聊天室所有者、禁言列表以及管理权限。 + +聊天室所有者可以修改成员状态,例如,对成员禁言或踢出聊天室。 + +:::tip +该组件不支持自定义。 +::: + +## ChatroomGiftMessageListView 组件 + +聊天室打赏消息区域组件 `ChatroomGiftMessageListView` 用于展示发送的礼物效果,礼物消息可以显示在消息列表,也可以显示在该组件单独对礼物进行显示。 + +示例代码如下: + +```dart +ChatroomController controller = + ChatroomController(roomId: widget.roomId, ownerId: widget.ownerId); +... + +@override +Widget build(BuildContext context) { + return ChatRoomUIKit( + controller: controller, + inputBar: ChatInputBar( // 自定义你需要的输入样式 + actions: [ + InkWell( + onTap: () => controller.showGiftSelectPages(), + child: Padding( + padding: const EdgeInsets.all(3), + child: Image.asset('images/send_gift.png'), + ), + ), + ], + ), + child: (context) { + return Stack( + children: [ + const Positioned( + left: 16, + right: 100, + height: 84, + bottom: 300, + child: ChatroomGiftMessageListView(), // 设置礼物展示区域 + ), + const Positioned( + left: 16, + right: 78, + height: 204, + bottom: 90, + child: ChatroomMessageListView(), // 添加消息列表并设置位置 + ) + ], + ); + }, + ); +} +``` + +`ChatroomGiftMessageListView` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ----------------------- | -------- | ---------------------------------------------- | +| giftWidgetBuilder | 否 | 单个礼物展示的 builder。 | +| placeholder | 否 | 默认图片占位符,当礼物图片下载成功之前用于占位。 | + +## ChatroomGlobalBroadcastView 组件 + +全局广播通知组件 `ChatroomGlobalBroadcastView` 接收和显示全局全局广播,也是通过添加消息到队列排队显示。 + +简单示例如下: + +```dart +ChatroomController controller = + ChatroomController(roomId: widget.roomId, ownerId: widget.ownerId); +... + +@override +Widget build(BuildContext context) { + return ChatRoomUIKit( + controller: controller, + inputBar: ChatInputBar( // 自定义你需要的输入样式 + actions: [ + InkWell( + onTap: () => controller.showGiftSelectPages(), + child: Padding( + padding: const EdgeInsets.all(3), + child: Image.asset('images/send_gift.png'), + ), + ), + ], + ), + child: (context) { + return Stack( + children: [ + Positioned( + top: MediaQuery.of(context).viewInsets.top + 10, + height: 20, + left: 20, + right: 20, + child: ChatroomGlobalBroadcastView(), // 用于展示广播消息 + ), + const Positioned( + left: 16, + right: 100, + height: 84, + bottom: 300, + child: ChatroomGiftMessageListView(), // 设置礼物展示区域 + ), + const Positioned( + left: 16, + right: 78, + height: 204, + bottom: 90, + child: ChatroomMessageListView(), // 添加消息列表并设置位置 + ) + ], + ); + }, + ); +} +``` + +`ChatroomGlobalBroadcastView` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ----------------------- | -------- | ---------------------------------------------------- | +| icon | 否 | 设置收到广播时的图标。 | +| textStyle | 否 | 设置广播内容字体。 | +| backgroundColor | 否 | 设置广播背景颜色。 | + +## ChatInputBar 组件 + +消息输入框组件 `ChatInputBar` 可以发送文本、表情等消息,可以与聊天室底部工具栏区域互相动态切换。当点击聊天室底部工具栏区域组件时切换到输入状态,发送消息或者关闭输入框时切换为聊天室底部工具栏区域组件。 + +简单示例如下: + +```dart + Widget build(BuildContext context) { + Widget content = ChatRoomUIKit( + controller: controller, + inputBar: ChatInputBar( // 添加一个礼物按钮 + actions: [ + InkWell( + onTap: () => controller.showGiftSelectPages(), + child: Padding( + padding: const EdgeInsets.all(3), + child: Image.asset('assets/images/send_gift.png'), + ), + ), + ], + ), + ); + } +``` + +`ChatInputBar` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ---------------------- | -------- | --------------------------------------------- | +| inputIcon | 否 | 显示图标。 | +| inputHint | 否 | 未输入时占位字符。 | +| leading | 否 | 输入区域左侧区域 widget。 | +| actions | 否 | 输入区域右侧区域 widget 数组,最多允许有 3 个 widget。 | +| textDirection | 否 | 输入区域的方向 | +| onSend | 否 | 点击**发送**按钮的回调。| + +## ChatRoomGiftListView 组件 + +礼物列表组件 `ChatRoomGiftListView` 提供自定义礼物列表,点击礼物项的发送按钮发送到聊天室。可以通过配置 `ChatroomController#giftControllers` 进行内容填充。 + +`giftControllers` 为 `ChatroomGiftPageController` 数组,`chatroom_uikit` 默认提供 `DefaultGiftPageController` 实现。 + +:::tip +礼物列表组件是一个独立的组件,需要应用开发者自行实现显示和加载等操作。 +::: + +示例代码如下: + +```dart +ChatroomController controller = ChatroomController( + roomId: widget.room.id, + ownerId: widget.room.ownerId, + giftControllers: () async { + List service = []; + final value = await rootBundle.loadString('assets/data/Gifts_cn.json'); // 解析json,并赋值给 giftControllers。 + Map map = json.decode(value); + for (var element in map.keys.toList()) { + service.add( + DefaultGiftPageController( + title: element, + gifts: () { + List list = []; + map[element].forEach((element) { + GiftEntityProtocol? gift = ChatroomUIKitClient + .instance.giftService + .giftFromJson(element); + if (gift != null) { + list.add(gift); + } + }); + return list; + }(), + ), + ); + } + return service; + }(), + ); +``` + +## ChatroomReportListView 组件 + +消息举报组件 `ChatroomReportListView`,默认界面不提供自定义部分,可以通过配置进行内容修改。 + +示例代码如下: + +```dart +// 修改举报内容: +ChatRoomSettings.reportMap = {'tag': 'reason'}; +``` diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_integrated.md b/docs/uikit/chatroomuikit/flutter/roomuikit_integrated.md new file mode 100644 index 000000000..25ba7afdb --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_integrated.md @@ -0,0 +1,31 @@ +# 集成 ChatroomUIKit + + + +使用 `chatroom_uikit` 之前,你需要将 `chatroom_uikit` 集成到你的应用中。 + +## 前提条件 + +- 即时通讯 SDK 3.0.0(包含)-4.0.0; +- Flutter 3.3.0 或以上版本; +- 有效的环信即时通讯 IM 开发者账号和 [App Key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 +- 对于 `iOS` 应用: + - Xcode 13 或以上版本; + - ios 11 或以上版本; +- 对于 `Android` 应用: + - minSDKVersion 21。 + - release 时需要在 `xxx/android/app/proguard-rules.pro` 中设置免混淆规则: + +```java +-keep class com.hyphenate.** {*;} +-dontwarn com.hyphenate.** +``` + +## 安装 UIKit 到项目中 + +进入项目,执行以下命令: + +```sh +flutter pub get add chatroom_uikit +``` + diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_overview.md b/docs/uikit/chatroomuikit/flutter/roomuikit_overview.md new file mode 100644 index 000000000..eb238cc0d --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_overview.md @@ -0,0 +1,34 @@ +# 概述 + + + +环信 ChatroomUIKit 提供 UIKit 的各种组件帮助开发者根据实际业务需求快速搭建聊天室应用。通过该 UIKit,聊天室中的用户可实时交互,发送普通弹幕消息、打赏消息和全局广播等功能。 + +- 若要访问源码,请点击[这里](https://github.com/easemob/UIKit_Chatroom_flutter)。 + +- 你可以体验环信 [Android](http://www.pgyer.com/YZUCrW) 和 [iOS](https://testflight.apple.com/join/NzmtvJ6n) 聊天室 UIKit demo: + +## 功能 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - 创建聊天室:ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - 销毁聊天室:ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - 离开聊天室:聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - 发送弹幕消息:用户在聊天室中向其他参与者发送文字和表情的消息。 + - 打赏:用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - 全局广播:向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - 未读消息数:在一个聊天室中用户尚未读取的消息数量。 + - 已禁言列表:记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - 暗黑模式:ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展** + - 消息举报:在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - 消息翻译:将聊天室中的单条消息从一种语言转换成另一种语言。 + - 消息撤回:在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - 禁言成员:聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - 查看成员列表:聊天室成员列表显示了该聊天室中的当前在线用户。 + - 搜索成员:在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - 禁言成员:聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - 移除成员:聊天室所有者将指定成员从聊天室中踢出。 diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_quickstart.md b/docs/uikit/chatroomuikit/flutter/roomuikit_quickstart.md new file mode 100644 index 000000000..41ff32c11 --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_quickstart.md @@ -0,0 +1,173 @@ +# 快速开始 + + + +利用 `chatroom_uikit`,你可以轻松实现聊天室内的用户交互。本文介绍如何实现在聊天室中发送消息。 + +## 前提条件 + +- 即时通讯 SDK 3.0.0(包含)-4.0.0; +- Flutter 3.3.0 或以上版本; +- 有效的环信即时通讯 IM 开发者账号和 [App Key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 + +## 操作流程 + +### 第一步 创建聊天室和用户 + +在环信控制台[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室)和[用户](/product/enable_and_configure_IM.html#创建-im-用户)。 + +### 第二步 创建项目 + +```sh +flutter create --platforms=android,ios room_project +``` + +### 第三步 项目中安装 UIKit + +进入创建的项目,执行以下命令: + +```sh +flutter pub get add chatroom_uikit +``` + +### 第四步 初始化 chatroom_uikit + +你可以在应用加载时或使用 `chatroom_uikit` 之前对其进行初始化。 + +初始化时,需传入 App Key。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**应用详情**页面查看 App Key。 + +```dart +void main() async { + assert(appKey.isNotEmpty, 'appKey is empty'); + await ChatroomUIKitClient.instance.initWithAppkey( + appKey, + ); + runApp(const MyApp()); +} +``` + +### 第五步 登录 chatroom_uikit + +进入聊天室前,需首先通过用户 ID 和用户 Token 登录 `chatroom_uikit` + +:::tip +若你已集成了 IM SDK,SDK 的所有用户 ID 均可用于登录 `chatroom_uikit`。 +::: + +为了方便快速体验,你可以在[环信控制台](https://console.easemob.com/user/login)的**应用概览** > **用户认证**页面创建用户并查看用户 token。**用户认证**页面中的用户仅用于快速体验或调试目的。 + +在开发环境中,你需要在环信控制台[创建 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户),从你的 App Server 获取用户 token,详见[使用环信用户 token 鉴权](/product/easemob_user_token.html)。 + +登录服务, 可使用 `userId` 和 `password` 登录,也可以使用 `userId` 和 token 进行登录。 + +- 使用 `userId` 和 `password` 登录: + +```dart +// ... +//设置当前用户的头像和昵称 + UserEntity user = UserEntity(userId, nickname: nickname, avatarURL: avatarURL); +try { + // 通过密码登录 + await ChatroomUIKitClient.instance.loginWithPassword( + userId: userId!, + password: password, + userInfo: user, + ); + +} on ChatError catch (e) { + // error. +} +``` + +- 使用 `userId` 和 token 登录: + +```dart +//设置当前用户的头像和昵称 + UserEntity user = UserEntity(userId, nickname: nickname, avatarURL: avatarURL); +try { + await ChatroomUIKitClient.instance.loginWithToken( + userId: userId, + token: token!, + userInfo: user, + ); + +} on ChatError catch (e) { + // error. +} +``` + +### 第六步 设置主题颜色 + +可以通过 `ChatUIKitTheme` 进行主题设置,默认提供了 `light` 和 `dart` 两种主题: + +```dart +ChatUIKitTheme( + child: child, +), +``` + +如果需要修改主题色,可以通过修改`ChatUIKitColor` 的 `hue` 值: + +```dart +ChatUIKitColor({ + this.primaryHue = 203, + this.secondaryHue = 155, + this.errorHue = 350, + this.neutralHue = 203, + this.neutralSpecialHue = 220, + this.barrageLightness = LightnessStyle.oneHundred, + this.isDark = false, +}); +``` + + +### 第七步 使用 chatroom_uikit 组件 + +1. 需要确保 `ChatUIKitTheme` 在 `ChatroomUIKit` 组件在你项目的父节点,建议将 `ChatUIKitTheme` 放到项目的根节点。 + +```dart + +@override + Widget build(BuildContext context) { + return MaterialApp( + builder: (context, child) { + return ChatUIKitTheme(child: child!); + }, + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ... + ); + } +``` + + +2. 在需要使用 `chatroom_uikit` 时,需要先创建 `ChatroomController`, 并使 `ChatRoomUIKit` 作为当前页面的根节点,并将其他组件作为 `ChatRoomUIKit` 的子组件。 + +```dart +// roomId: 需要加入的房间id; +// ownerId: 房主id; +ChatroomController controller = ChatroomController(roomId: roomId, ownerId: ownerId); + +@override +Widget build(BuildContext context) { + Widget content = Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar(), + body: ChatRoomUIKit( + controller: controller, + child: (context) { + // 在子组件中构建页面,比如 礼物弹窗,消息列表等。 + return ...; + }, + ), + ); + + return content; +} + +``` + +### 第八步 发送第一条消息 + +输入消息内容,点击 **发送** 按钮,发送消息。 + +![img](@static/images/uikit/chatroomandroid/click_chat.png =500x500) diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_releasenote.md b/docs/uikit/chatroomuikit/flutter/roomuikit_releasenote.md new file mode 100644 index 000000000..1ef4a279a --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_releasenote.md @@ -0,0 +1,31 @@ +# 聊天室 UIKit 更新日志 + + + +## 版本 V1.0.0 2023-12-29 + +### 新增特性 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - [创建聊天室](roomfeature_common.html#创建聊天室):ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - [销毁聊天室](roomfeature_common.html#销毁聊天室):ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - [离开聊天室](roomfeature_common.html#离开聊天室):聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - [发送弹幕消息](roomfeature_common.html#发送弹幕):用户在聊天室中向其他参与者发送文字和表情的消息。 + - [打赏](roomfeature_common.html#打赏):用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - [全局广播](roomfeature_common.html#全局广播):向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - [未读消息数](roomfeature_common.html#未读消息数):在一个聊天室中用户尚未读取的消息数量。 + - [已禁言列表](roomfeature_common.html#已禁言列表):记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - [暗黑模式](roomfeature_common.html#暗黑模式):ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展**(长按一条消息可进行的操作) + - [消息举报](roomfeature_message.html#消息举报):在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - [消息翻译](roomfeature_message.html#消息翻译):将聊天室中的单条消息从一种语言转换成另一种语言。 + - [消息撤回](roomfeature_message.html#消息撤回):在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - [禁言成员](roomfeature_message.html#禁言成员):聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - [查看成员列表](roomfeature_member.html#查看成员列表):聊天室成员列表显示了该聊天室中的当前在线用户。 + - [搜索成员](roomfeature_member.html#搜索成员):在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - [禁言成员](roomfeature_member.html#禁言成员):聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - [移除成员](roomfeature_member.html#移除成员):聊天室所有者将指定成员从聊天室中踢出。 + diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_run.md b/docs/uikit/chatroomuikit/flutter/roomuikit_run.md new file mode 100644 index 000000000..0be019ae1 --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_run.md @@ -0,0 +1,39 @@ +# 跑通示例项目 + + + +环信提供一个开源的 ChatroomUIKit 示例项目,演示了如何使用该 UIKit 快速搭建聊天室页面,实现完整业务。 + +## 开发环境要求 + +- 即时通讯 SDK 3.0.0(包含)-4.0.0; +- Flutter 3.3.0 或以上版本; +- 有效的环信即时通讯 IM 开发者账号和 [App Key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息); +- `iOS` 应用: + - Xcode 13 或以上; + - ios 11 或以上; +- `Android` 应用:minSDKVersion 21。 + +## 操作步骤 + +可以通过 `example` 项目进行演示。`example` 文件夹中为示例项目,可以下载源码、进行编译,然后运行进行体验。 + +### 第一步 下载源码仓库 + +运行以下命令: + +```sh +git clone git@github.com:easemob/UIKit_Chatroom_flutter.git +``` + +或者点击[这里](https://codeload.github.com/easemob/UIKit_Chatroom_flutter/zip/refs/heads/main)直接下载。 + +### 第二步 项目初始化 + +1. 进入 `example` 目录,运行 `flutter pub get` 命令。 + +2. 修改 `example/lib/main.dart` 中的 `appKey`。 + +### 第三步 运行项目 + +在 `vscode` 中运行。 \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/flutter/roomuikit_theme.md b/docs/uikit/chatroomuikit/flutter/roomuikit_theme.md new file mode 100644 index 000000000..4f2b8593f --- /dev/null +++ b/docs/uikit/chatroomuikit/flutter/roomuikit_theme.md @@ -0,0 +1,48 @@ +# 主题 + + + +`ChatUIKitTheme` 内置浅色和深色主题,默认为浅色主题。 + +- 浅色主题 + +![img](@static/images/uikit/chatroomandroid/light_mode.png) + +- 深色主题 + +![img](@static/images/uikit/chatroomandroid/dark_mode.png) + +## 切换主题 + +若切换 ChatUIKitTheme 内置的浅色或深色主题,可使用以下方法: + +```tsx +// ... +// 设置主题 +ChatUIKitTheme( + color: ChatUIKitColor.light() // 浅色主题, 暗色主题为:ChatUIKitColor.dark()。 + child: child, // chatroom_uikit 所有组件需要为主题组件的子组件 +), +``` + +如果需要修改主题色,可以通过修改 `ChatUIKitColor` 的 `hue` 值: + +```dart +ChatUIKitColor({ + this.primaryHue = 203, + this.secondaryHue = 155, + this.errorHue = 350, + this.neutralHue = 203, + this.neutralSpecialHue = 220, + this.barrageLightness = LightnessStyle.oneHundred, + this.isDark = false, +}); +``` + +## 设计指南 + +如果你对主题颜色,设计指南和细节有任何疑问,您可以在 Figma 设计稿中添加评论并提及我们的设计师 Stevie Jiang。 + +- [UI 设计资源](https://www.figma.com/community/file/1322495388317476706/chatroom-uikit)。 + +- [UI 设计指南](design_guide.html)。 diff --git a/docs/uikit/ios/README.md b/docs/uikit/chatroomuikit/ios/README.md similarity index 100% rename from docs/uikit/ios/README.md rename to docs/uikit/chatroomuikit/ios/README.md diff --git a/docs/uikit/chatroomuikit/ios/design_guide.md b/docs/uikit/chatroomuikit/ios/design_guide.md new file mode 100644 index 000000000..52ba5431a --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/design_guide.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/design_guide.html", + title: "设计指南" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/ios/roomfeature_common.md b/docs/uikit/chatroomuikit/ios/roomfeature_common.md new file mode 100644 index 000000000..fb695c37a --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomfeature_common.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_common.html", + title: "通用" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/ios/roomfeature_member.md b/docs/uikit/chatroomuikit/ios/roomfeature_member.md new file mode 100644 index 000000000..703fa2f8b --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomfeature_member.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_member.html", + title: "成员管理" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/ios/roomfeature_message.md b/docs/uikit/chatroomuikit/ios/roomfeature_message.md new file mode 100644 index 000000000..e76f080fa --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomfeature_message.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_message.html", + title: "消息扩展" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_best_practice.md b/docs/uikit/chatroomuikit/ios/roomuikit_best_practice.md new file mode 100644 index 000000000..d02d3ed6f --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_best_practice.md @@ -0,0 +1,77 @@ +# 最佳实践 + +## 初始化 ChatroomUIKit + +初始化是使用 ChatroomUIKit 的必要步骤,需在所有接口方法调用前完成。 + +初始化 ChatroomUIKit 时,你可以传入 `option` 参数,设置各种选项。 + +```Swift +let option = ChatroomUIKitInitialOptions.ChatOptions() +option.enableConsoleLog = true +option.autoLogin = true +let error = ChatroomUIKitClient.shared.setup(appKey,option: option) +``` + +## 登录 ChatroomUIKit + +你可以通过使用工程中的用户对象并遵守 `UserInfoProtocol` 协议登录 ChatroomUIKit,示例代码如下: + +```Swift +public final class YourAppUser: NSObject,UserInfoProtocol { + + public func toJsonObject() -> Dictionary? { + ["userId":self.userId,"nickName":self.nickname,"avatarURL":self.avatarURL,"identity":self.identity,"gender":self.gender] + } + + public var identity: String = ""//用户级别图像的 URL + + public var userId: String = <#T##String#> + + public var nickname: String = "Jack" + + public var avatarURL: String = "https://accktvpic.oss-cn-beijing.aliyuncs.com/pic/sample_avatar/sample_avatar_1.png" + + public var gender: Int = 1 + + } +ChatroomUIKitClient.shared.login(user: YourAppUser(), token: "token", completion: <#T##(ChatError?) -> Void#>) +``` + +## 初始化聊天室视图 + +1. 获取聊天室列表,加入指定的聊天室。除此之外,你还可以在环信控制台上[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室),获取聊天室 ID。 + +2. 创建聊天室视图 `ChatroomView`,传入的参数包括聊天室 ID、布局参数、聊天室所有者的用户 ID 及一些选项。 + +:::tip +- 建议 ChatroomView 的宽度初始化为屏幕的宽度,高度不小于以下算式的值:屏幕高度 x 1/5 + 礼物气泡行高 x 2 + 54(底部工具栏的高度)。 +- 对于有刘海屏的机型,ChatroomView 的高度为以上算式的值加上底部安全区域的高度。 +::: + +3. 添加视图。 + +```Swift +let options = ChatroomUIKitInitialOptions.UIOptions() +options.bottomDataSource = self.bottomBarDatas() +// 实现显示礼物消息区域。 +options.showGiftMessageArea = true +// 是否在聊天区域中显示礼物信息。 +options.chatAreaShowGift = false +let roomView = ChatroomUIKitClient.shared.launchRoomView(roomId: self.roomId, frame: CGRect(x: 0, y: ScreenHeight/2.0, width: ScreenWidth, height: ScreenHeight/2.0), ownerId: "Chatroom's owner user id", options: options) +addSubView(roomView) +``` + +建议你将该视图添加在你的业务视图的上面,便于 ChatroomView 拦截和透传点击事件。例如,若你有播放视频的视图,需要将 ChatroomView 添加在该视图的上面。 + +## 监听 ChatroomUIKit 事件和错误 + +你可以调用 `registerRoomEventsListener` 方法添加监听器用于监听 ChatroomUIKit 事件和错误。 + +```Swift +ChatroomUIKitClient.shared.registerRoomEventsListener(self) +``` + +## 参考 + +若要了解以上最佳实践的详情,请访问 [GitHub 仓库](https://github.com/easemob/ChatroomDemo/tree/dev/iOS/ChatroomDemo)。 diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_config_item.md b/docs/uikit/chatroomuikit/ios/roomuikit_config_item.md new file mode 100644 index 000000000..877a38179 --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_config_item.md @@ -0,0 +1,77 @@ +# 可配置项 + +[Appearance.swift](https://github.com/zjc19891106/ChatroomUIKit/blob/main/Sources/ChatroomUIKit/Classes/UI/Core/UIKit/Utils/Appearance.swift) 是容纳了所有可配置项的类,你需要在初始化 ChatroomView 之前修改其中的属性。 + +## 消息视图 + +1. Appearance.giftDialogContainerConstraintsSize:礼物弹窗的大小。 + +![img](@static/images/uikit/chatroomios/giftContainerConstraintsSize.png) + +2. `Appearance.giftPlaceHolder`:礼物默认图。 + +![img](@static/images/uikit/chatroomios/giftPlaceHolder.png) + +3. Appearance.avatarPlaceHolder:头像默认图。 + +![img](@static/images/uikit/chatroomios/avatarPlaceHolder.png) + +4. Appearance.userIdentifyPlaceHolder:用户身份标识默认图。 + +![img](@static/images/uikit/chatroomios/userIdentityPlaceHolder.png) + +5. Appearance.messageDisplayStyle:弹幕区域 Cell 的展示样式。你可以选择对时间戳、用户标识和用户头像进行显示或隐藏。 + +![img](@static/images/uikit/chatroomios/customchatbarrage.png) + +6. `Appearance.notifyMessageIcon`:全局广播通知左侧图标默认图。 + +![img](@static/images/uikit/chatroomios/notifyMessageIcon.png) + +7. `Appearance.defaultMessageActions`:长按消息后弹起弹窗的数据源。 + +![img](@static/images/uikit/chatroomios/messageActions.png) + +8. `Appearance.actionSheetRowHeight`:`ActionSheet` 单行高度。 + +![img](@static/images/uikit/chatroomios/messageActions.png) + +9. `Appearance.reportTags`:消息举报弹窗内显示的非法信息类型。 + +![img](@static/images/uikit/chatroomios/report.png) + +10. Appearance.messageTranslationLanguage:目标翻译语言。你可以根据你的用户设备的语言环境设置对应的目标翻译语言,前提是需要在环信控制台开通翻译功能。目前,聊天室 UIKit 内置支持中文简体、中文繁体,英文,俄语,德语,法语,日语,韩语。 + +## 文本输入视图 + +1. Appearance.maxInputHeight:输入框的最大高度。 + +![img](@static/images/uikit/chatroomios/maxInputHeight.png) + +2. Appearance.inputPlaceHolder:输入框默认显示的文字。该选项的默认值是 Aa。 + +![img](@static/images/uikit/chatroomios/inputCorner.png) + +3. Appearance.inputBarCorner:输入框的圆角半径,默认为 `large`,即输入框高度的一半。 + +![img](@static/images/uikit/chatroomios/inputCorner.png) + +4. Appearance.emojiMap:若要替换全部的表情可以配置该 map,key 是代码注释中的固定字符串,value 可以传入不同 UIImage 对象即可。 + +![img](@static/images/uikit/chatroomios/customchatbarrage.png) + +## 用户列表 + + `Appearance.defaultOperationUserActions`:成员列表中聊天室所有者对普通成员的操作项。 + + ![img](@static/images/uikit/chatroomios/moreAction.png) + +## 弹窗 + +1. Appearance.pageContainerTitleBarItemWidth:`PageContainerTitleBar`(各弹窗页面顶部)的单个条目的宽度。 + +![img](@static/images/uikit/chatroomios/pageContainerTitleBarItemWidth.png) + +2. Appearance.pageContainerConstraintsSize:`PageContainersDialogController` 弹窗的大小。 + +![img](@static/images/uikit/chatroomios/pageContainerTitleBarItemWidth.png) diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_customize.md b/docs/uikit/chatroomuikit/ios/roomuikit_customize.md new file mode 100644 index 000000000..5e940a4e8 --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_customize.md @@ -0,0 +1,63 @@ +# 自定义 + +你可以对 ChatroomUIKit 中的一些控件进行自定义,添加自己的业务逻辑,实现个性化业务需求。 + +## 支持自定义的控件 + +目前,现有组件中的以下控件支持自定义: + +- `GiftMessageCell`:礼物弹幕列表 Cell 类。 + +![img](@static/images/uikit/chatroomios/GiftBarrageCell.png) + +- `GiftEntityCell`:礼物视图 Cell 类。 + +![img](@static/images/uikit/chatroomios/GiftEntityCell.png) + +- `MessageInputBar`:聊天输入框类。 + +![img](@static/images/uikit/chatroomios/ChatInputBar.png) + +- `ReportOptionsController`:消息举报控制器类。 + +![img](@static/images/uikit/chatroomios/ReportOptionsController.png) + +- `ParticipantsController`:聊天室成员列表/黑名单列表控制器类。 + +![img](@static/images/uikit/chatroomios/ParticipantsController.png) + +- `ChatroomParticipantsCell`:聊天室成员列表/黑名单列表 Cell 类。 + +![img](@static/images/uikit/chatroomios/ChatroomParticipantsCell.png) + +- `GiftsViewController`:礼物视图控制器类。 + +礼物的容器的自定义方式与其他控件类似,你需要继承 `GiftsViewController` 创建新类,在调用时 `DialogManager.shared.showGiftsDialog(titles: ["Gifts","1231232"], gifts: [self.gift1,self.gift2])` 传入新类的对象。 + +你需要在确保你的服务器端的礼物业务处理完毕,再调用 ChatroomUIKit 提供的发送礼物消息 API。 + +![img](@static/images/uikit/chatroomios/GiftsViewController.png) + +## 自定义示例 + +下面以如何自定义礼物弹幕视图 Cell 为例介绍如何自定义控件。首先,继承 `GiftMessageCell`,添加自己的逻辑,然后在 ChatroomUIKit 中注册新类替换原有的类。 + +````Swift +class CustomGiftMessageViewCell: GiftMessageCell { + lazy var redDot: UIView = { + UIView().backgroundColor(.red).cornerRadius(.large) + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + self.addSubview(redDot) + } + + override func refresh(item: GiftEntityProtocol) { + super.refresh(item: item) + self.redDot.isHidden = item.selected + } +} +//在创建 ChatroomView 或使用其他 UI 组件之前调用此方法。 +ComponentsRegister.shared.GiftMessagesViewCell = CustomGiftMessageViewCell.self +```` diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_integrated.md b/docs/uikit/chatroomuikit/ios/roomuikit_integrated.md new file mode 100644 index 000000000..cf4992295 --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_integrated.md @@ -0,0 +1,44 @@ +# 集成 ChatroomUIKit + +使用 ChatroomUIKit 之前,你需要将 ChatroomUIKit 集成到你的应用中。 + +## 前提条件 + +要集成 ChatroomUIKit,你的开发环境需要满足以下需求: + +- Xcode 14.0 或以上版本; +- iOS 13.0 或以上版本; +- 项目中已设置有效的开发者签名。 + +## 使用 CocoaPods 集成 ChatroomUIKit + +你可以使用 CocoaPods 将 ChatroomUIKit 添加为 Xcode 项目的依赖项。 + +1. 在 `Podfile` 文件中添加如下依赖: + +``` +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '13.0' + +target 'YourTarget' do + use_frameworks! + + pod 'ChatroomUIKit' +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' + end + end +end +``` + +2. 打开终端,cd 到 `Podfile` 所在的目录,然后执行以下命令集成 ChatroomUIKit。 + +``` +pod install --repo-update +``` + +若 Xcode 15 编译出现以下报错 **Sandbox: rsync.samba(47334) deny(1) file-write-create...**,你可以在 **Build Setting** 中搜索 **ENABLE_USER_SCRIPT_SANDBOXING**,将 **User Script Sandboxing** 的设置修改为 **NO**。 diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_overview.md b/docs/uikit/chatroomuikit/ios/roomuikit_overview.md new file mode 100644 index 000000000..369dee28b --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_overview.md @@ -0,0 +1,34 @@ +# 概述 + +环信 ChatroomUIKit 提供 UIKit 的各种组件帮助开发者根据实际业务需求快速搭建聊天室应用。通过该 UIKit,聊天室中的用户可实时交互,发送普通弹幕消息、打赏消息和全局广播等功能。 + +- 若要访问源码,请点击[这里](https://github.com/easemob/UIKit_Chatroom_ios)。 + +- 你可以扫描以下二维码体验环信聊天室 UIKit demo: + +![img](@static/images/uikit/chatroomios/demo.png) + +## 功能 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - 创建聊天室:ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - 销毁聊天室:ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - 离开聊天室:聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - 发送弹幕:用户在聊天室中向其他参与者发送文字和表情的消息。 + - 打赏:用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - 发送全局广播通知:向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - 未读消息数:在一个聊天室中用户尚未读取的消息数量。 + - 已禁言列表:记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - 暗黑模式:ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息管理** + - 消息举报:在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - 消息翻译:将聊天室中的单条消息从一种语言转换成另一种语言。 + - 消息撤回:在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - 禁言成员:聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - 查看成员列表:聊天室成员列表显示了该聊天室中的当前在线用户。 + - 搜索成员:在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - 禁言成员:聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - 移除成员:聊天室所有者将指定成员从聊天室中踢出。 diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_quickstart.md b/docs/uikit/chatroomuikit/ios/roomuikit_quickstart.md new file mode 100644 index 000000000..780c0c164 --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_quickstart.md @@ -0,0 +1,87 @@ +# 快速开始 + +利用 ChatroomUIKit,你可以轻松实现聊天室内的用户交互。本文介绍如何实现在聊天室中发送消息。 + +## 前提条件 + +- Xcode (推荐最新版本)。 +- 安装 iOS 13.0 或更高版本的 iOS 模拟器或 Apple 设备。 +- 已使用 CocoaPods 添加了 ChatroomUIKit 依赖项。 +- 有效的环信即时通讯 IM 开发者账号和 App Key,详见 [环信即时通讯云控制台](https://console.easemob.com/user/login)。 +- 如果你的网络环境部署了防火墙,请联系环信技术支持设置白名单。 + +## 创建项目 + +[在 Xcode 中创建一个 iOS 平台下的 App](https://developer.apple.com/cn/documentation/xcode/creating_an_xcode_project_for_an_app/)。在 **Choose options for your new project** 对话框中进行以下设置: + +- **Product Name**:填入 **ChatroomUIKitQuickStart**。 +- **Organization Identifier**:设置为你的标识符。 +- **User Interface**:选择 **Storyboard**。 +- **Language**:选择你常用的开发语言。 + +## 操作流程 + +### 第一步 初始化 ChatroomUIKit + +你可以在应用加载时或使用 ChatroomUIKit 之前对其进行初始化。 + +初始化时,需传入 App Key。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**应用详情**页面查看 App Key。 + +```swift +import ChatroomUIKit + +@UIApplicationMain +class AppDelegate:UIResponder,UIApplicationDelegate { + var window:UIWindow? + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + let error = ChatroomUIKitClient.shared.setup(appKey: "Appkey") + } +} +``` + +### 第二步 登录 ChatroomUIKit + +使用用户 ID 和用户 Token 登录 ChatroomUIKit。 + +:::tip +若你已集成了 IM SDK,SDK 的所有用户 ID 均可用于登录 ChatroomUIKit。 +::: + +为了方便快速体验,你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**应用概览** > **用户认证**页面创建用户并查看用户 token。**用户认证**页面中的用户仅用于快速体验或调试目的。 + +在开发环境中,你需要在环信控制台[创建 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户),从你的 App Server 获取用户 token,详见[使用环信用户 token 鉴权](/product/easemob_user_token.html) 。 + +```swift +ChatroomUIKitClient.shared.login(userId: "user id", token: "token", completion: <#T##(ChatError?) -> Void#>) +``` + +### 第三步 创建聊天室视图 + +创建聊天室视图的步骤如下: + +1. 获取聊天室列表,加入指定的聊天室。除此之外,你还可以在环信控制台上[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室),获取聊天室 ID。 + +2. 创建聊天室视图 `ChatroomView`,传入的参数包括聊天室 ID、布局参数和聊天室所有者的用户 ID。 + +:::tip +- 建议 ChatroomView 的宽度初始化为屏幕的宽度,高度不小于以下算式的值:屏幕高度 x 1/5 + 礼物气泡行高 x 2 + 54(底部工具栏的高度)。 +- 对于有刘海屏的机型,ChatroomView 的高度为以上算式的值加上底部安全区域的高度。 +::: + +```swift +let roomView = ChatroomUIKitClient.shared.launchRoomView(roomId: "Chat room ID",frame: CGRect, ownerId: "Chatroom owner ID") +``` + +3. 将聊天室视图添加到目标区域。 + +在调用 `ChatroomUIKitClient.shared.launchRoomView(roomId: self.roomId, frame: CGRect(x: 0, y: ScreenHeight/2.0, width: ScreenWidth, height: ScreenHeight/2.0), ownerId: "当前聊天室的主播用户ID")` 时,记得将 `ChatroomView` 添加到现有视图之上,以方便拦截和透传点击事件。例如,如果你有一个播放视频流的视图,请添加到视频视图的上方,`ChatroomView` 实质上是全屏覆盖的,传入的 `frame` 是可用区域、弹幕区域、底部工具栏区域以及键盘弹起后输入框中事件的响应高度。 + +![img](@static/images/uikit/chatroomios/hierarchy.png =800x550) + +4. [添加聊天室成员](https://doc.easemob.com/product/enable_and_configure_IM.html#创建聊天室)。 + +### 第四步 发送第一条消息 + +点击屏幕下方的 `说点什么` 按钮唤起键盘,输入消息内容,点击 **发送** 按钮,发送消息。 + +![img](@static/images/uikit/chatroomios/click_chat.png =500x500) diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_releasenote.md b/docs/uikit/chatroomuikit/ios/roomuikit_releasenote.md new file mode 100644 index 000000000..1ef4a279a --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_releasenote.md @@ -0,0 +1,31 @@ +# 聊天室 UIKit 更新日志 + + + +## 版本 V1.0.0 2023-12-29 + +### 新增特性 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - [创建聊天室](roomfeature_common.html#创建聊天室):ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - [销毁聊天室](roomfeature_common.html#销毁聊天室):ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - [离开聊天室](roomfeature_common.html#离开聊天室):聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - [发送弹幕消息](roomfeature_common.html#发送弹幕):用户在聊天室中向其他参与者发送文字和表情的消息。 + - [打赏](roomfeature_common.html#打赏):用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - [全局广播](roomfeature_common.html#全局广播):向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - [未读消息数](roomfeature_common.html#未读消息数):在一个聊天室中用户尚未读取的消息数量。 + - [已禁言列表](roomfeature_common.html#已禁言列表):记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - [暗黑模式](roomfeature_common.html#暗黑模式):ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展**(长按一条消息可进行的操作) + - [消息举报](roomfeature_message.html#消息举报):在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - [消息翻译](roomfeature_message.html#消息翻译):将聊天室中的单条消息从一种语言转换成另一种语言。 + - [消息撤回](roomfeature_message.html#消息撤回):在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - [禁言成员](roomfeature_message.html#禁言成员):聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - [查看成员列表](roomfeature_member.html#查看成员列表):聊天室成员列表显示了该聊天室中的当前在线用户。 + - [搜索成员](roomfeature_member.html#搜索成员):在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - [禁言成员](roomfeature_member.html#禁言成员):聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - [移除成员](roomfeature_member.html#移除成员):聊天室所有者将指定成员从聊天室中踢出。 + diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_run.md b/docs/uikit/chatroomuikit/ios/roomuikit_run.md new file mode 100644 index 000000000..fc1bc206b --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_run.md @@ -0,0 +1,65 @@ +# 跑通示例项目 + +环信提供一个开源的 ChatroomUIKit 示例项目,演示了如何使用该 UIKit 快速搭建聊天室页面,实现完整业务。 + +本文展示如何编译并运行 iOS 平台的聊天室 UIKit 示例项目。 + +## 前提条件 + +开始前,确保你的开发环境满足如下条件: + +- Xcode 14.0 或以上版本; +- iOS 13.0 或以上版本; +- 项目中已设置有效的开发者签名。 + +## 操作步骤 + +### 第一步 下载 ChatroomUIKit 示例代码 + +点击 [github源码](https://github.com/easemob/UIKit_Chatroom_ios)下载示例代码到本机。 + +### 第二步 执行 pod 命令 + +1. 点击打开 **UIKit_Chatroom_ios** 文件夹。 + +2. 将 **Example** 文件夹拖拽到终端。 + +3. 在终端中输入如下命令,然后回车。 + +``` + pod install --repo-update +``` + +### 第三步 编译 + +编译时,需要传入 App Key、用户 ID 和用户 token。因此,编译前,你需要在[环信控制台](https://console.easemob.com/user/login)上创建有效的环信即时通讯 IM 开发者账号,并获取 App Key,[创建环信 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户)。此外,还需[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室)。 + +1. 使用 Xcode 打开 .xcworkspace 工程文件。 + +2. 在键盘上按下 **cmd**+**B** 进行编译,编译结果会有如下报错。 + +![img](@static/images/uikit/chatroomios/buildError.png) + + 将获取的 App Key、用户 token 和用户 ID 分别填入上图中的 `appKey`、`chatToken` 和 `userId` 字段。 + +3. 在键盘上按下 **cmd**+**B** 编译程序即可跑通项目。 + +4. 在键盘上按下 **cmd**+**R**,选中设备运行项目,查看运行结果。 + +### 第四步 体验项目 + +1. 若仅体验 UI,点击 **UIComponent**。 + + 这种情况下,第三步编译过程中的 `appKey`、`chatToken` 和 `userId` 字段可以填入空字符串。体验过程中,你可以选择是否显示 UI 功能的某些配置项。 + +2. 对于 UI 和业务体验(例如,发送礼物、聊天室成员管理或消息操作),点击 **UI&Business**。 + + 这种情况下,第三步编译过程中的 `appKey`、`chatToken` 和 `userId` 字段需传入环信控制台的配置。 + +## 注意事项 + +示例工程仅用于快速跑通流程,暂时未提供多成员交互测试。 + +## 编译常见问题 + +若 Xcode 15 编译出现以下报错 **Sandbox: rsync.samba(47334) deny(1) file-write-create...**,你可以在 **Build Setting** 中搜索 **ENABLE_USER_SCRIPT_SANDBOXING**,将 **User Script Sandboxing** 的设置改为 **NO**。 \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/ios/roomuikit_theme.md b/docs/uikit/chatroomuikit/ios/roomuikit_theme.md new file mode 100644 index 000000000..f1e3212dd --- /dev/null +++ b/docs/uikit/chatroomuikit/ios/roomuikit_theme.md @@ -0,0 +1,76 @@ +# 主题 + +ChatroomUIkit 内置浅色和深色主题,默认为浅色主题。 + +- 浅色主题 + +![img](@static/images/uikit/chatroomios/light_mode.png) + +- 深色主题 + +![img](@static/images/uikit/chatroomios/dark_mode.png) + +## 切换为内置主题 + +若从当前的主题切换到 ChatroomUIKit 内置的浅色或深色主题,可使用以下方法: + +````swift +Theme.switchTheme(style: .dark) +```` + +````swift +Theme.switchTheme(style: .light) +```` + +## 切换为自定义主题 + +自定义设置主题时,需要参考[设计指南](https://github.com/StevieJiang/Chatroom-UIkit-Design-Guide/blob/main/README.md)的主题色定义以下五种主题色的色相值。 + +ChatroomUIKit 中的所有颜色均使用 HSLA 颜色模型定义,该模型是一种使用色调、饱和度、亮度和 Alpha 表示颜色的方式。 + +- H(Hue):色相,颜色的基本属性,是色轮上从 `0` 到 `360` 的度数。`0` 是红色,`120` 是绿色,`240` 是蓝色。 + +- S(饱和度):饱和度是颜色的强度或纯度。饱和度越高,颜色越鲜艳;饱和度越低,颜色越接近灰色。饱和度以百分比值表示,范围为 `0%` 到 `100%`。`0%` 表示灰度,`100%` 表示全色。 + +- L(明度):明度是颜色的亮度或暗度。亮度越高,颜色越亮;亮度越低,颜色越深。亮度以百分比值表示,范围为 `0%` 到 `100%`。`0%`表示黑色,`100%` 表示白色。 + +- A(Alpha):Alpha 是颜色的透明度。值 `1` 表示完全不透明,`0` 表示完全透明。 + +通过调整 HSLA 模型的色相值,你可以实现精确的色彩控制。 + +```Swift +Appearance.primaryHue = 191/360.0 +Appearance.secondaryHue = 210/360.0 +Appearance.errorHue = 189/360.0 +Appearance.neutralHue = 191/360.0 +Appearance.neutralSpecialHue = 199/360.0 +Theme.switchTheme(style: .custom) +``` + +## 切换 App 中除 ChatroomUIKit 之外的其他视图的主题 + +设置 ChatroomUIKit 的主题后,若你希望 app 的其他部分也与 ChatroomUIKit 使用相同的主题,可以使用以下方法确保 app 使用统一主题。 + +1. 在 `Theme` 类中注册你的视图。 + +```Swift +Theme.registerSwitchThemeViews(view: self) +``` + +2. 在上述视图中实现 `ThemeSwitchProtocol` 协议。 + +```Swift +extension YourView: ThemeSwitchProtocol { + +} +``` + +3. 在 `switchTheme` 方法中根据主题类型(浅色、深色和自定义)给你的子视图设置对应颜色。 + +## 设计指南 + +如果你对主题颜色,设计指南和细节有任何疑问,您可以在 Figma 设计稿中添加评论并提及我们的设计师 Stevie Jiang。 + +- [UI 设计资源](https://www.figma.com/community/file/1322495388317476706/chatroom-uikit)。 + +- [UI 设计指南](design_guide.html)。 diff --git a/docs/uikit/chatroomuikit/react-native/design_guide.md b/docs/uikit/chatroomuikit/react-native/design_guide.md new file mode 100644 index 000000000..52ba5431a --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/design_guide.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/design_guide.html", + title: "设计指南" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/react-native/roomfeature_common.md b/docs/uikit/chatroomuikit/react-native/roomfeature_common.md new file mode 100644 index 000000000..fb695c37a --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomfeature_common.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_common.html", + title: "通用" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/react-native/roomfeature_member.md b/docs/uikit/chatroomuikit/react-native/roomfeature_member.md new file mode 100644 index 000000000..703fa2f8b --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomfeature_member.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_member.html", + title: "成员管理" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/react-native/roomfeature_message.md b/docs/uikit/chatroomuikit/react-native/roomfeature_message.md new file mode 100644 index 000000000..e76f080fa --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomfeature_message.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_message.html", + title: "消息扩展" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_best_practice.md b/docs/uikit/chatroomuikit/react-native/roomuikit_best_practice.md new file mode 100644 index 000000000..6aa95c359 --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_best_practice.md @@ -0,0 +1,126 @@ +# 最佳实践 + +## 初始化 ChatroomUIKit + +初始化是使用 ChatroomUIKit 的必要步骤,需在所有接口方法调用前完成。 + +```tsx +export function App() { + const palette = usePresetPalette(); + const dark = useDarkTheme(palette); + const light = useLightTheme(palette); + const [theme, setTheme] = React.useState(light); + // const [isReady, setIsReady] = React.useState(false); + // const fontFamily = 'Twemoji-Mozilla'; + // const [fontsLoaded] = useFonts({ + // [fontFamily]: require('../assets/twemoji.ttf'), + // }); + + return ( + { + if (language === "zh-Hans") { + return createStringSetCn(); + } else { + return createStringSetEn(); + } + }} + // fontFamily={fontFamily} + onInitialized={() => { + // todo: ChatroomUIKit 完成初始化的回调通知。 + }} + avatar={{ borderRadiusStyle: "large", localIcon: a_default_avatar }} + > + {/* todo: 添加应用程序代码 */} + + ); +} +``` + +## 登录 ChatroomUIKit + +你可以通过使用工程中的用户对象并遵守 `UserInfoProtocol` 协议登录 ChatroomUIKit,示例代码如下: + +```tsx +export function LoginScreen(props: Props) { + const {} = props; + const im = useRoomContext(); + const [isLoading, setIsLoading] = React.useState(false); + // ... + const loginAction = React.useCallback( + (onFinished: (isOk: boolean) => void) => { + // ... + im.login({ + userId, + userToken: params.token!, + userNickname: nickName, + userAvatarURL: avatar, + result: (params) => { + if (params.isOk) { + // todo: 登录成功 + } else { + // todo: 登录失败 + } + }, + }); + }, + [im] + ); + + return ( + + {/* todo: 登录页面代码, 触发登录 loginAction */} + + ); +} +``` + +## 初始化聊天室视图 + +1. 获取聊天室列表,加入指定的聊天室。除此之外,你还可以在环信即时通讯云控制台上[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室),获取聊天室 ID。 + +2. 加载聊天室视图 `Chatroom`,传入的参数包括聊天室 ID、聊天室所有者的用户 ID 及一些选项。 + +```tsx +export function ChatroomScreen(props: Props) { + return ( + + + + ); +} +``` + +## 监听聊天室的事件和错误 + +你可以调用 `useRoomListener` 方法添加监听器用于监听聊天室的事件和错误。 + +```tsx +useRoomListener( + React.useMemo(() => { + return { + onError: (params) => { + // todo: 处理错误通知 + }, + onFinished: (params) => { + // todo: 操作完成通知 + }, + }; + }, []) +); +``` + +## 参考 + +若要了解以上最佳实践的详情,请访问 [GitHub 仓库](https://github.com/AsteriskZuo/react-native-chat-room-demo)。 \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_config_item.md b/docs/uikit/chatroomuikit/react-native/roomuikit_config_item.md new file mode 100644 index 000000000..bbcaaed19 --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_config_item.md @@ -0,0 +1,565 @@ +# 可配置项 + +`room uikit sdk` 的组件中包含各种属性,你可以根据需求进行设置。 + +除了[主题组件](#roomuikit_theme.html),`room uikit sdk` 主要包括如下组件: + +| 组件名称 | 组件介绍 | +| --------------- | ---------------------------- | +| [I18n](#国际化组件) | 可以设置 `UIKit` 所有 UI 组件的语言。 | +| [Chatroom](#chatroom-组件) | 聊天室组件,集成了礼物发送、消息列表、成员列表、礼物接收等组件。 | +| [MessageList](#messagelist-组件) | 聊天室消息区域组件,用于显示发送或者接收到的消息。 | +| [ParticipantList](#participantlist-组件) | 聊天室成员列表组件,包括聊天室成员和禁言成员的管理。 | +| [GiftMessageList](#giftmessagelist-组件) | 聊天室打赏消息区域组件,用于显示打赏的礼物。 | +| [GlobalBroadcast](#globalbroadcast-组件) | 聊天室全局广播组件,用于向 app 下的所有聊天室发送消息。 | +| [MessageInput](#messageinput-组件) | 消息输入组件,用于发送各类消息。 | +| [BottomToolbar](#bottomtoolbar-组件) | 聊天室底部工具栏区域,可以与消息输入组件互相切换,支持添加自定义按钮。 | +| [BottomSheetGift](#bottomsheetgift-组件) | 发送礼物组件,可以发送礼物,礼物来源由开发者指定。 | +| [ReportMessage](#reportmessage-组件) | 聊天室举报组件。 | + +## 国际化组件 + +UIKit 支持多国语言切换,目前内置中文和英文,可以扩展其他语言。 + +例如:若要 UIKit 使用英文显示,可以如下设置: + +```tsx + +``` + +语言设置规则: + +- 若未设置语言,则使用默认的系统语言。 +- 若系统语言不是中文或者英文,则国内选择中文,国外选择英文。 +- 若设置的语言不是中文或者英文,并且没有提供相应的语言集合,则国内选择中文,国外选择英文。 + +例如,若开发者希望 `UIKit` 和应用均使用中文,设置如下: + +```tsx +// ... +// 创建应用需要的语言包。 +function createLanguage(type: LanguageCode): StringSet { + return { + 'Chinese text.': '中文文本.', + }; +} +// ... +// 设置指定语言集合,并且提供语言翻译源。 +; +// ... +// 在需要国际化的地方。 +const { tr } = useI18nContext(); +return {tr('Chinese text.')}; +``` + +例如,若开发者希望应用和 UIKit 均显示法语,设置如下: + +```tsx +// ... +// 创建应用扩展语言集合。 +function createAppLanguage(type: LanguageCode): StringSet { + if (type === 'fr') { + return { + 'French text.': 'Text français.', + }; + } + return { + 'French text.': 'French text.', + }; +} +// 创建 UIKit 的语言集合,需要找到 UIKit 内置的文件 `StringSet.en.tsx`, 将所有的 `value` 修改为法语版本。 +export function createUIKitLanguage(type: LanguageCode): StringSet { + if (type === 'fr') { + return { + 'Private Chat': 'Private Chat', + '...': '...', + }; + } +} +// ... +// 设置指定语言集合,并且提供语言翻译源。 +; +``` + +## 初始化 + +`Chatroom UIKit SDK` 的入口为 `Container` 组件,主要负责集成其他组件和参数配置。 + +```tsx +export type ContainerProps = React.PropsWithChildren<{ + appKey: string; + isDevMode?: boolean; + language?: StringSetType; + languageBuiltInFactory?: CreateStringSet; + languageExtensionFactory?: CreateStringSet; + palette?: Palette; + theme?: Theme; + roomOption?: PartialRoomOption; + avatar?: { + borderRadiusStyle?: CornerRadiusPaletteType; + }; + fontFamily?: string; + onInitialized?: () => void; +}>; +``` + +```tsx +// 主要控制 `Chatroom` 组件中的组件是否加载。 +export type RoomOption = { + globalBroadcast: { + isVisible: boolean; + }; + gift: { + isVisible: boolean; + }; + messageList: { + isVisibleGift: boolean; + isVisibleTime: boolean; + isVisibleTag: boolean; + isVisibleAvatar: boolean; + }; +}; +``` + +| 参数 | 是否必需 | 描述 | +| :----------- | :----- | :--------------------- | +| `appKey` | 是 | 你在环信即时通讯云控制台创建应用时填入的应用名称。该参数是 App Key 的一部分。可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的 **应用详情** 页面查看。 | +| `isDevMode` | 否 | 如果设置为 `true`,则激活日志打印等工具。 | +| `language` | 否 | 设置当前的语言,若未设置,则获取系统当前的语言作为默认值。 | +| `languageBuiltInFactory` | 否 | 若未设置则使用内置的语言资源。通常可以修改内置的 UI 内容。 | +| `languageExtensionFactory` | 否 | 如果设置将扩展语言资源。通常应用的 UI 也需要国际化。 | +| `palette` | 否 | 设置当前的调色板,主题服务的重要依赖。 | +| `theme` | 否 | 若未设置主题,则使用 `light` 为默认主题。 | +| `roomOption` | 否 | 聊天室选项。具体参见以下全局配置参数。 | +| `avatar` | 否 | 设置全局头像的圆角样式。 | +| `fontFamily` | 否 | 支持自定义字体。默认使用系统字体。 | +| `onInitialized` | 否 | 初始化完成的回调通知。 | + +全局配置参数如下: + +| 参数 | 是否必需 | 描述 | +| :----------- | :----- | :--------------------- | +| `globalBroadcast` | 否 | 全局广播组件配置,可以设置是否加载。 | +| `gift` | 否 | 聊天室打赏消息区域组件,可以设置是否加载。 | +| `messageList` | 否 | 聊天室消息区域配置:
- `isVisibleGift`: 是否加载聊天室打赏消息区域组件;
- `isVisibleTime`: 是否显示时间标签;
- `isVisibleTag`: 是否显示用户标签;
- `isVisibleAvatar`: 是否显示头像标签。 | + +通常 `Container` 会处于应用的底层,一般为根组件,或者与根组件同一级别。例如: + +```tsx +export function App() { + return {children}; +} +``` + +## Chatroom 组件 + +Chatroom 组件集成了成员列表组件 `ParticipantList`、消息输入组件 `MessageInput`、消息区域组件 `MessageList`、打赏消息区域组件 `GiftMessageList` 和全局广播通知组件 `GlobalBroadcast`等。该组件为页面级组件,基本占据了整个屏幕,如果要添加组件,建议添加为 Chatroom 的子组件或背景组件。 + +示例如下: + +```tsx +// ... +// 创建引用对象 +const ref = React.useRef({} as any); +// ... +// 添加组件到渲染树 +; +``` + +由于 `UIKit` 没有路由 (`React-Native` 未内置),所以若需要成员搜索,设置如下: + +```tsx + { + // todo: 点击搜索按钮跳转到搜索页面 + navigation.push('SearchParticipant', { params: { memberType } }); + }, + }, + }} + roomId={room.roomId} + ownerId={room.owner} +/> +``` + +`Chatroom` 组件提供如下属性: + +| 属性 | 是否必需 | 描述 | +| -------------------------- | -------- | ---------------------------------------------------- | +| containerStyle | 否 | 设置组件容器样式。该属性可以控制 `Chatroom` 组件的背景、位置、大小、边框等样式。 | +| GiftMessageList | 否 | 打赏消息区域组件的渲染器。默认使用内部组件 `GiftMessageList`,可以设置类型为 `GiftMessageListComponent` 的自定义组件。替换之后的行为完全由开发者控制,如果在 `GiftMessageList` 组件的基础上进行扩展或者修改则更为方便。 | +| GlobalBroadcast | 否 | 全局广播组件的渲染器。默认使用内部组件 `GlobalBroadcast`,可以设置类型为 `GlobalBroadcastComponent` 的自定义组件。 | +| MessageList | 否 | 消息区域组件的渲染器。默认使用内部组件 `MessageList`,可以设置类型为 `MessageListComponent` 的自定义组件。 | +| MessageInput | 否 | 输入组件的渲染器。默认使用内部组件 `MessageInput`,可以设置类型为 `MessageInputComponent` 的自定义组件。该组件包括聊天室底部工具栏区域组件 `BottomToolbar`,若要自定义需考虑这一点。 | +| BottomSheetParticipantList | 否 | 成员列表组件的渲染器。默认使用内部组件` BottomSheetParticipantList`,可以设置类型为 `BottomSheetParticipantListComponent` 的自定义组件。| +| input | 否 | 输入组件的属性。 | +| messageList | 否 | 消息区域的属性。 | +| globalBroadcast | 否 | 聊天室全局广播的属性。 | +| gift | 否 | 打赏消息的属性。| +| participantList | 否 | 成员列表的属性。 | +| backgroundView | 否 | 背景组件。 | + +`Chatroom` 提供如下方法: + +| 方法 | 描述 | +| --------------------- | ------------------------------------------ | +| getGlobalBroadcastRef | 获取 `GlobalBroadcast` 组件的引用。默认通过收到后台的消息广播进行显示,开发者可以插入自定义全局广播消息。 | +| getGiftMessageListRef | 获取 `GiftMessageList` 组件的引用。 | +| getParticipantListRef | 获取 `BottomSheetParticipantList` 的组件引用。开发者可以自定义成员管理相关内容。 | +| getMessageListRef | 获取 `MessageList` 组件的引用。默认通过发送消息或者接收消息显示消息,开发者可以手动插入自定义消息、删除消息、滚动到最底部等操作。 | +| joinRoom | 加入聊天室。加载 `Chatroom` 组件时,你会自动加入聊天室。若由于网络等问题加入失败,开发者可以通过该方法尝试重新加入聊天室。 | +| leaveRoom | 退出聊天室,而不用卸载组件。 | + +![img](@static/images/uikit/chatroomrn/chatroom.png) + +## MessageList 组件 + +聊天室消息区域组件 `MessageList` 提供消息的显示,聊天室接收到的文本消息、表情消息、礼物消息以及发送成功的消息会显示在该区域。 + +可以在消息区域中对消息进行操作,例如,翻译文本消息为目标语言、撤销消息和消息上报等。你可以通过长按消息列表项弹出菜单进行相应操作。 + +数据上报组件支持自定义选项,可以自定义选项上报不同内容。 + +示例代码如下: + +```tsx +// ... +// 创建组件引用对象 +const ref = React.useRef({} as any); +// 添加消息列表组件到渲染树 +; +// ... +// 添加消息到消息列表,消息会显示在列表 +ref?.current?.addSendedMessage?.(message); +``` + +`MessageList` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ------------------------ | -------- | --------------------------------------------------------------- | +| visible | 否 | 设置组件是否可见。 | +| onUnreadCount | 否 | 未读数发生变化时的回调通知。 | +| onLongPressItem | 否 | 长按消息列表项时的回调通知。 | +| containerStyle | 否 | 设置组件容器样式。支持背景、位置、大小、边框等的设置。 | +| onLayout | 否 | 组件布局发生变化时的回调通知。 | +| MessageListItemComponent | 否 | 消息列表项的渲染器。 | +| reportProps | 否 | 消息上报的属性。 | +| maxMessageCount | 否 | 组件可以显示的最大消息数,默认为 `1000`,超过限制后将移除最早消息。 | +| messageMenuItems | 否 | 自定义消息菜单项,追加到内置菜单后面。 | + +`MessageList` 提供的方法如下表所示: + +| 方法 | 描述 | +| ---------------- | -------------------------------- | +| addSendedMessage | 将输入框中的内容发送到消息列表。 | +| scrollToEnd | 滚动消息列表到底部。 | + +![img](@static/images/uikit/chatroomrn/message_context_menu.png) + +![img](@static/images/uikit/chatroomrn/message_report.png) + +## ParticipantList 组件 + +聊天室成员组件可以显示和管理聊天室成员,聊天室所有者、禁言列表以及管理权限。 + +聊天室所有者可以修改成员状态,例如,对成员禁言或踢出聊天室。 + +:::tip +聊天室成员列表组件的显示的入口并不在 `UIKit`, 需要应用开发者自行实现,例如,添加一个按钮,点击后显示聊天室成员列表组件。 +::: + +`BottomSheetParticipantList` 组件是一个独立组件,由 `SimulativeModal` 和 `ParticipantList` 组成,可以进行显示和隐藏。 + +示例代码如下: + +```tsx +// ... +// 创建组件引用对象 +const ref = React.useRef({} as any); +// 添加成员列表组件到渲染树 +; +// ... +// 用户实现显示具体动作,例如:添加按钮,点击按钮显示成员列表组件。 +ref?.current?.startShow?.(); +``` + +`BottomSheetParticipantList` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ------------------- | -------- | ---------------------------------------------------- | +| onSearch | 否 | 点击搜索样式的回调通知。 | +| onNoMoreMember | 否 | 下滑加载更多成员时,没有更多成员的回调通知。| +| containerStyle | 否 | 设置组件容器样式。支持背景、位置、大小、边框等的设置。| +| maskStyle | 否 | 设置组件容器以外区域样式。 | +| MemberItemComponent | 否 | 成员列表项的渲染器。 | + +`BottomSheetParticipantList` 提供的方法如下表所示: + +| 方法 | 描述 | +| --------------------- | -------------------------------- | +| startShow | 显示成员列表组件。 | +| startHide | 隐藏成员列表组件,隐藏动画完成后返回通知。 | +| getParticipantListRef | 获取成员列表或者禁言列表组件的引用。 | + +`ParticipantList` 提供的方法如下表所示: + +| 方法 | 描述 | +| ------------ | ---------------------------------------------- | +| initMenu | 初始化自定义成员列表菜单,追加到内置菜单的后面。 | +| removeMember | 删除成员。 | +| muteMember | 禁言或者解除禁言成员。 | +| closeMenu | 关闭菜单。 | + +![img](@static/images/uikit/chatroomrn/member_list.png) + +![img](@static/images/uikit/chatroomrn/member_context_menu.png) + +## GiftMessageList 组件 + +聊天室打赏消息区域组件 `GiftMessageList` 用于展示发送的礼物效果,礼物消息可以显示在消息列表,也可以显示在该组件。 + +示例代码如下: + +```tsx +// ... +// 创建组件引用对象 +const ref = React.useRef({} as any); +// 添加组件到渲染树 +; +// ... +// 添加礼物消息到组件消息队列中,排队显示。 +ref.current?.pushTask({ + model: { + id: seqId('_gf').toString(), + nickName: 'NickName', + giftCount: 1, + giftIcon: 'http://notext.png', + content: 'send Agoraship too too too long', + }, +}); +``` + +`GiftMessageList` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ----------------------- | -------- | ---------------------------------------------- | +| visible | 否 | 设置组件是否可见。 | +| containerStyle | 否 | 设置组件容器样式。支持背景、位置、边框等的设置。 | +| GiftEffectItemComponent | 否 | 打赏消息列表项的渲染器。 | + +`GiftMessageList` 提供的方法如下表所示: + +| 方法 | 描述 | +| -------- | ------------------------------------ | +| pushTask | 将礼物消息任务添加到队列中,排队加载。 | + +## GlobalBroadcast 组件 + +全局广播通知组件 `GlobalBroadcast` 接收和显示全局全局广播,也是通过添加消息到队列排队显示。 + +简单示例如下: + +```tsx +// ... +// 创建组件引用对象 +const ref = React.useRef({} as any); +// ... +// 添加组件到渲染树 +; +// ... +// 将消息添加到任务队列,排队显示。 +let count = 1; +ref.current?.pushTask?.({ + model: { + id: count.toString(), + content: count.toString() + content, + }, +}); +``` + +`GlobalBroadcast` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ----------------------- | -------- | ---------------------- | +| visible | 否 | 设置组件是否可见。 | +| playSpeed | 否 | 消息播放时滚动的速度,默认值为 8。 | +| containerStyle | 否 | 设置组件容器样式。支持背景、位置、大小、边框等的设置。 | +| textStyle | 否 | 设置组件文本样式。 | +| icon | 否 | 设置组件上的图标样式。 | +| GiftEffectItemComponent | 否 | 打赏消息列表项的渲染器。 | +| onFinished | 否 | 所有消息播放完成时的回调通知。 | +| onLayout | 否 | 组件布局发生变化时的回调通知。 | + +`GlobalBroadcast` 提供的方法如下表所示: + +| 方法 | 描述 | +| -------- | ---------------------------- | +| pushTask | 将消息添加到队列中,排队加载。 | + +## MessageInput 组件 + +消息输入框组件 `MessageInput` 可以发送文本、表情等消息,可以与聊天室底部工具栏区域互相动态切换。当点击聊天室底部工具栏区域组件时切换到输入状态,发送消息或者关闭输入框时切换为聊天室底部工具栏区域组件。 + +简单示例如下: + +```tsx +// ... +// 创建引用对象 +const ref = React.useRef({} as any); +// ... +// 添加组件到渲染树 + { + // todo: 调用消息列表引用对象添加消息到消息列表 + }} +/>; +// ... +// 关闭输入状态 +ref?.current?.close?.(); +``` + +`MessageInput` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| ---------------------- | -------- | --------------------------------------------- | +| onInputBarWillShow | 否 | 将要切换为输入状态时的回调通知。 | +| onInputBarWillHide | 否 | 将要切换为聊天室底部工具栏区域时的回调通知。 | +| onSended | 否 | 发送完成时的回调通知。 | +| keyboardVerticalOffset | 否 | 键盘偏移量的数值。 | +| closeAfterSend | 否 | 发送消息后是否切换为聊天室底部工具栏区域。 | +| first | 否 | 聊天室底部工具栏区域的第一个自定义组件。 | +| after | 否 | 聊天室底部工具栏区域的自定义组件列表,最多可添加 3 个自定义组件。 | +| onLayout | 否 | 聊天室底部工具栏区域的布局发生变化时的回调通知。 | + +`MessageInput` 提供的方法如下表所示: + +| 方法 | 描述 | +| ----- | ------------------------------------ | +| close | 主动关闭输入状态,切换为聊天室底部工具栏区域。 | + +![img](@static/images/uikit/chatroomrn/input_bar.png) + +![img](@static/images/uikit/chatroomrn/emoji_list.png) + +## BottomToolbar 组件 + +聊天室底部工具栏区域组件 `BottomToolbar` 与消息输入框组件组成复合组件,可以互相切换。 + +## BottomSheetGift 组件 + +礼物列表组件 `BottomSheetGift` 提供自定义礼物列表,点击礼物项的发送按钮发送到聊天室。 + +:::tip +礼物列表组件是一个独立的组件,需要应用开发者自行实现显示和加载等操作。 +::: + +示例代码如下: + +```tsx +// ... +// 创建引用对象 +const ref = React.useRef({} as any); +// ... +// 添加组件到渲染树 + { + // todo: 发送选择的礼物。 + }} +/>; +// ... +// 显示礼物列表组件 +ref?.current?.startShow?.(); +``` + +:::tip +发送礼物组件提供 `BottomSheetGift` 和 `BottomSheetGift2`,二者的区别为是模态组件还是非模态组件。 +::: + +`BottomSheetGift` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| --------- | -------- | -------------------------- | +| gifts | 否 | 礼物列表数组。 | +| maskStyle | 否 | 设置组件容器以外区域样式。 | +| onSend | 否 | 点击发送按钮时的回调通知。 | + +`BottomSheetGift` 提供的方法如下表所示: + +| 方法 | 描述 | +| ----------------- | -------------------------------- | +| startShow | 显示组件。 | +| startShowWithInit | 显示组件,同时可以初始化列表。 | +| startHide | 隐藏组件,隐藏动画完成后返回通知。 | + +![img](@static/images/uikit/chatroomrn/gift_list.png) + +## ReportMessage 组件 + +消息上报组件 `ReportMessage`,可以设置上报内容。 + +示例代码如下: + +```tsx +// ... +// 创建引用对象 +const ref = React.useRef({} as any); +// ... +// 添加组件到渲染树 +; +// ... +// 显示组件 +ref?.current?.startShow?.(); +// ... +// 选择列表项,确认上报。 +``` + +`BottomSheetMessageReport` 提供的属性如下表所示: + +| 属性 | 是否必需 | 描述 | +| -------------- | -------- | ---------------------------------------------------- | +| data | 否 | 上报内容列表数组。 | +| maskStyle | 否 | 设置组件容器以外区域样式。 | +| containerStyle | 否 | 设置组件容器样式。支持背景、位置、大小、边框等的设置。 | +| onReport | 否 | 点击上报按钮时的回调通知。 | + +`BottomSheetMessageReport` 提供的方法如下表所示: + +| 方法 | 描述 | +| --------- | -------------------------------- | +| startShow | 显示组件。 | +| startHide | 隐藏组件,隐藏动画完成后返回通知。 | + + +![img](@static/images/uikit/chatroomrn/message_report.png) + diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_customize.md b/docs/uikit/chatroomuikit/react-native/roomuikit_customize.md new file mode 100644 index 000000000..6b5a41e1a --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_customize.md @@ -0,0 +1,123 @@ +# 自定义 + +本文以 `Chatroom` 组件为例介绍如何添加自己的业务逻辑,实现个性化业务需求。 + +`Chatroom` 组件为页面级组件,包括成员列表组件 `ParticipantList`、输入组件 `MessageInput`、消息区域组件 `MessageList`、打赏消息区域组件 `GiftMessageList` 和全局广播通知组件 `GlobalBroadcast` 等。除了提供各种属性实现自定义配置,Chatroom 组件中的子组件支持自定义,你可以基于自己的逻辑实现更新或替换这些子组件。 + +## 自定义 GiftMessageList 组件 + +若 ChatroomUIKit 中内置的打赏消息组件 `GiftMessageList` 无法满足需求,你可以在满足 `GiftMessageListComponent` 的约束的前提下创建新组件,例如 `MyGiftMessageList`,实现自定义业务逻辑和自定义样式。 + +```tsx +export const MyGiftMessageList: GiftMessageListComponent = React.forwardRef< + GiftMessageListRef, + GiftMessageListProps +>(function ( + props: GiftMessageListProps, + ref?: React.ForwardedRef +) { + // todo:实现你的业务逻辑或修改现有的业务逻辑。 + const {} = props; + React.useImperativeHandle( + ref, + () => { + return { + pushTask: (task: GiftMessageListTask) => { + // todo: 实现该接口。 + }, + }; + }, + [] + ); + return <>; +}); +``` + +利用新的 `MyGiftMessageList` 组件替换内置的 `GiftMessageList` 组件,添加到 Chatroom 组件。 + +```tsx + +``` + +## 自定义 GlobalBroadcast 组件 + +若 ChatroomUIKit 中内置的全局广播消息组件 `GlobalBroadcast` 无法满足需求,你可以在满足 `GlobalBroadcastComponent` 的约束的情况下创建新组件,例如 `MyGlobalBroadcast`,实现自定义业务逻辑和自定义样式。 + +```tsx +export const MyGlobalBroadcast = React.forwardRef< + GlobalBroadcastRef, + GlobalBroadcastProps +>(function ( + props: GlobalBroadcastProps, + ref?: React.ForwardedRef +) { + // todo: 实现自己的业务逻辑或修改当前业务逻辑。 + React.useImperativeHandle( + ref, + () => { + return { + pushTask: (task: GlobalBroadcastTask) => { + // todo:实现该接口。 + }, + }; + }, + [] + ); + return <>; +}); +``` + +利用 `MyGlobalBroadcast` 组件替换内置的 `GlobalBroadcast` 组件。 + +```tsx + +``` + +## 自定义消息列表项样式 + +修改组件的消息样式。示例代码如下: + +```tsx +export function MyMessageListItem(props: MessageListItemProps) { + // todo:实现自己的业务逻辑或修改当前业务逻辑。 + return <>; +} +export const MyMessageListItemMemo = React.memo(MyMessageListItem); +``` + +更新消息列表项的样式。示例代码如下: + +```tsx + +``` + +## 自定义聊天室成员列表项样式 + +修改聊天室成员组件的列表项样式。示例代码如下: + +```tsx +export function MyParticipantListItem(props: ParticipantListItemProps) { + // todo:实现自己的业务逻辑或修改当前业务逻辑。 + return <>; +} + +export const MyParticipantListItemMemo = React.memo(MyParticipantListItem); +``` + +更新聊天室成员组件的列表项样式。示例代码如下: + +```tsx + +``` diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_integrated.md b/docs/uikit/chatroomuikit/react-native/roomuikit_integrated.md new file mode 100644 index 000000000..c5d7d1988 --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_integrated.md @@ -0,0 +1,34 @@ +# 集成 ChatroomUIKit + +使用 ChatroomUIKit 之前,你需要将 ChatroomUIKit 集成到你的应用中。 + +## 前提条件 + +- MacOS 12 或以上版本; +- React-Native 0.66 或以上版本; +- NodeJs 16.18 或以上版本; +- iOS 应用:Xcode 13 或以上版本以及它的相关依赖工具; +- Android 应用:Android Studio 2021 或以上版本以及它的相关依赖工具; +- 有效的环信即时通讯 IM 开发者账号和 [App key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 + +## 创建项目或现有项目 + +如果创建请执行命令: + +```sh +npx react-native init MyApp --version 0.71.11 +``` + +## 安装 UIKit 到项目中 + +进入项目,执行以下命令: + +```sh +npm install react-native-chat-room +# or +yarn add react-native-chat-room +# or +npx expo install react-native-chat-room +``` + + diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_overview.md b/docs/uikit/chatroomuikit/react-native/roomuikit_overview.md new file mode 100644 index 000000000..27176f6cd --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_overview.md @@ -0,0 +1,35 @@ +# 概述 + +环信 ChatroomUIKit 提供 UIKit 的各种组件帮助开发者根据实际业务需求快速搭建聊天室应用。通过该 UIKit,聊天室中的用户可实时交互,发送普通弹幕消息、打赏消息和全局广播等功能。 + +- 若要访问源码,请点击[这里](https://github.com/easemob/UIKit_Chatroom_rn)。 + +- 你可以扫描以下 Android 和 iOS 平台的二维码体验环信聊天室 UIKit demo: + +![img](@static/images/uikit/chatroomrn/demo_rn.png) + +## 功能 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - 创建聊天室:ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - 销毁聊天室:ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - 离开聊天室:聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - 发送弹幕:用户在聊天室中向其他参与者发送文字和表情的消息。 + - 打赏:用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - 全局广播:向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - 未读消息数:在一个聊天室中用户尚未读取的消息数量。 + - 已禁言列表:记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - 暗黑模式:ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展** + - 消息举报:在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - 消息翻译:将聊天室中的单条消息从一种语言转换成另一种语言。 + - 消息撤回:在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - 禁言成员:聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - 查看成员列表:聊天室成员列表显示了该聊天室中的当前在线用户。 + - 搜索成员:在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - 禁言成员:聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - 移除成员:聊天室所有者将指定成员从聊天室中踢出。 + diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_quickstart.md b/docs/uikit/chatroomuikit/react-native/roomuikit_quickstart.md new file mode 100644 index 000000000..f0a8181a5 --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_quickstart.md @@ -0,0 +1,121 @@ +# 快速开始 + +利用 ChatroomUIKit,你可以轻松实现聊天室内的用户交互。本文介绍如何实现在聊天室中发送消息。 + +## 前提条件 + +- MacOS 12 或以上版本; +- React-Native 0.66 或以上版本; +- NodeJs 16.18 或以上版本; +- iOS 应用:Xcode 13 或以上版本以及它的相关依赖工具; +- Android 应用:Android Studio 2021 或以上版本以及它的相关依赖工具; +- 有效的环信即时通讯 IM 开发者账号和 [App Key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 + +## 操作流程 + +### 第一步 创建聊天室和用户 + +在环信控制台[创建聊天室](/product/enable_and_configure_IM.html#创建聊天室)和[用户](/product/enable_and_configure_IM.html#创建-im-用户)。 + +### 第二步 创建项目 + +```sh +npx react-native init MyApp --version 0.71.11 +``` + +### 第三步 项目中安装 UIKit + +进入创建的项目,执行以下命令: + +```sh +npm install react-native-chat-room +# or +yarn add react-native-chat-room +# or +npx expo install react-native-chat-room +``` + +### 第四步 初始化 ChatroomUIKit + +你可以在应用加载时或使用 ChatroomUIKit 之前对其进行初始化。 + +初始化时,需要填写必要的参数和配置,将 `Container` 放在组件树的根部。 + +初始化时,需传入 App Key。你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**应用详情**页面查看 App Key。 + +```tsx +export function App() { + const appKey = ''; + return {/* // todo: 在这里添加组件 */}; +} +``` + +### 第五步 登录 ChatroomUIKit + +进入聊天室前,需首先通过用户 ID 和用户 Token 登录 ChatroomUIKit。 + +:::tip +若你已集成了 IM SDK,SDK 的所有用户 ID 均可用于登录 ChatroomUIKit。 +::: + +为了方便快速体验,你可以在[环信控制台](https://console.easemob.com/user/login)的**应用概览** > **用户认证**页面创建用户并查看用户 token。**用户认证**页面中的用户仅用于快速体验或调试目的。 + +在开发环境中,你需要在环信控制台[创建 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户),从你的 App Server 获取用户 token,详见[使用环信用户 token 鉴权](/product/easemob_user_token.html)。 + +```tsx +// ... +// 获取 IM 服务对象 +const im = useRoomContext(); +// ... +// 登录服务 +// userId 和 userToken 为必填项 +im.login({ + userId: '', + userToken: '', + userNickname: '', + userAvatarURL: '', + gender: 1, + identify: '', + result: ({ isOk, error }) => { + // todo: isOk === true 用户登录成功 + // todo: isOk === false 用户登录失败 + }, +}); +``` + +### 第六步 进入聊天室 + +进入聊天室前,需要调用 `im.fetchChatroomList` 方法获取要加入的聊天室 ID 以及该聊天室的创建者的用户 ID。 + +通过加载 `Chatroom` 组件,你会自动加入聊天室,并返回是否成功加入。若该组件加载失败,你可以调用加入聊天室的 API 加入聊天室。 + +```tsx +// ... +// 创建组件引用对象。 +const chatroomRef = React.useRef({} as any); +// ... +// 关注组件状态变化。 +useRoomListener( + React.useMemo(() => { + return { + onError: (params) => { + // todo: 失败通知处理。错误类型可参考 UIKitError。 + // todo: 例如:被踢出聊天室后,可调用 API 重新加入:chatroomRef.current?.joinRoom({roomId, ownerId}}); + }, + onFinished: (params) => { + // todo: 该通知会包含完成结果。例如:加入聊天室之后收到通知。通知类型可以参考 RoomEventType。 + }, + }; + }, []) +); +// ... +// 加载组件到渲染树。 +; +// ... +``` + +### 第七步 发送第一条消息 + +在屏幕下方输入消息内容,点击 **发送** 按钮,发送消息。 + +![img](@static/images/uikit/chatroomandroid/click_chat.png =500x500) diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_releasenote.md b/docs/uikit/chatroomuikit/react-native/roomuikit_releasenote.md new file mode 100644 index 000000000..1ef4a279a --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_releasenote.md @@ -0,0 +1,31 @@ +# 聊天室 UIKit 更新日志 + + + +## 版本 V1.0.0 2023-12-29 + +### 新增特性 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - [创建聊天室](roomfeature_common.html#创建聊天室):ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - [销毁聊天室](roomfeature_common.html#销毁聊天室):ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - [离开聊天室](roomfeature_common.html#离开聊天室):聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - [发送弹幕消息](roomfeature_common.html#发送弹幕):用户在聊天室中向其他参与者发送文字和表情的消息。 + - [打赏](roomfeature_common.html#打赏):用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - [全局广播](roomfeature_common.html#全局广播):向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - [未读消息数](roomfeature_common.html#未读消息数):在一个聊天室中用户尚未读取的消息数量。 + - [已禁言列表](roomfeature_common.html#已禁言列表):记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - [暗黑模式](roomfeature_common.html#暗黑模式):ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展**(长按一条消息可进行的操作) + - [消息举报](roomfeature_message.html#消息举报):在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - [消息翻译](roomfeature_message.html#消息翻译):将聊天室中的单条消息从一种语言转换成另一种语言。 + - [消息撤回](roomfeature_message.html#消息撤回):在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - [禁言成员](roomfeature_message.html#禁言成员):聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - [查看成员列表](roomfeature_member.html#查看成员列表):聊天室成员列表显示了该聊天室中的当前在线用户。 + - [搜索成员](roomfeature_member.html#搜索成员):在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - [禁言成员](roomfeature_member.html#禁言成员):聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - [移除成员](roomfeature_member.html#移除成员):聊天室所有者将指定成员从聊天室中踢出。 + diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_run.md b/docs/uikit/chatroomuikit/react-native/roomuikit_run.md new file mode 100644 index 000000000..345954668 --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_run.md @@ -0,0 +1,63 @@ +# 跑通示例项目 + +环信提供一个开源的 ChatroomUIKit 示例项目,演示了如何使用该 UIKit 快速搭建聊天室页面,实现完整业务。 + +## 开发环境要求 + +- MacOS 12 或以上版本; +- React-Native 0.66 或以上版本; +- NodeJs 16.18 或以上版本; +- iOS 应用:Xcode 13 或以上版本,以及它的相关依赖工具。 +- Android 应用:Android Studio 2021 或以上版本,以及它的相关依赖工具。 + +## 操作步骤 + +### 第一步 在项目中安装 ChatroomUIKit + +```tsx +npm install react-native-chat-room +// or +yarn add react-native-chat-room +// or +npx expo install react-native-chat-room +``` + +### 第二步 示例项目演示 + +`example` 文件夹中为示例项目,可以下载源码、进行编译,然后运行进行体验。 + +下载源码仓库: + +```sh +git clone https://github.com/agora/rncr/react-native-chat-room +``` + +或者,你可以下载源码压缩包: + +```sh +curl -L -o file.zip https://github.com/AsteriskZuo/react-native-chat-room/archive/refs/heads/main.zip +``` + +### 第三步 项目初始化 + +1. 进入项目根目录,运行 `yarn & yarn env` 命令完成初始化。 + +2. 在生成的文件 `example/src/env.ts` 中,修改必要的配置项。 + +- 对于 `iOS` 应用: + + 需要运行 `pod install` 命令进行初始化。 + +- 对于 `Android` 应用: + + 需要执行 `gradle sync` 命令进行初始化。 + +### 第四步 运行项目 + +在 `react-native-chat-room/tree/main/example` 目录下运行以下命令: + +```sh +yarn run ios +// or +yarn run android +``` \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/react-native/roomuikit_theme.md b/docs/uikit/chatroomuikit/react-native/roomuikit_theme.md new file mode 100644 index 000000000..d0bd23e86 --- /dev/null +++ b/docs/uikit/chatroomuikit/react-native/roomuikit_theme.md @@ -0,0 +1,58 @@ +# 主题 + +ChatroomUIkit 内置浅色和深色主题,默认为浅色主题。每个 UI 组件都会用到主题。 + +- 浅色主题 + +![img](@static/images/uikit/chatroomandroid/light_mode.png) + +- 深色主题 + +![img](@static/images/uikit/chatroomandroid/dark_mode.png) + +## 切换主题 + +若切换 ChatroomUIKit 内置的浅色或深色主题,可使用以下方法: + +```tsx +// ... +// 设置主题 +const palette = usePresetPalette(); +const dark = useDarkTheme(palette); +const light = useLightTheme(palette); +const [theme, setTheme] = React.useState(light); +// ... +// 添加组件到渲染树 +; +// ... +// 切换为浅色或深色主题 +setTheme(theme === light ? dark : light); +``` + +## 设置自定义主题颜色 + +`usePresetPalette` 可以使用内置的默认主题颜色,也可以使用 `useCreatePalette` 设置自定义主题颜色。 + +```Swift +// 自定义颜色。通过修改颜色具体值,组件中对应颜色将统一改变。 +// 参考这里:https://www.figma.com/file/OX2dUdilAKHahAh9VwX8aI/Streamuikit?type=design&node-id=101-41012&mode=design&t=Fzou3Gwsk4owLLbr-4 +const { createPalette } = useCreatePalette({ + colors: { + primary: 203, + secondary: 155, + error: 350, + neutral: 203, + neutralSpecial: 220, + }, +}); +const palette = createPalette(); +// ... +``` + +## 设计指南 + +如果你对主题颜色,设计指南和细节有任何疑问,您可以在 Figma 设计稿中添加评论并提及我们的设计师 Stevie Jiang。 + +- [UI 设计资源](https://www.figma.com/community/file/1322495388317476706/chatroom-uikit)。 + +- [UI 设计指南](design_guide.html)。 diff --git a/docs/uikit/chatroomuikit/web/design_guide.md b/docs/uikit/chatroomuikit/web/design_guide.md new file mode 100644 index 000000000..52ba5431a --- /dev/null +++ b/docs/uikit/chatroomuikit/web/design_guide.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/design_guide.html", + title: "设计指南" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/web/roomfeature_common.md b/docs/uikit/chatroomuikit/web/roomfeature_common.md new file mode 100644 index 000000000..fb695c37a --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomfeature_common.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_common.html", + title: "通用" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/web/roomfeature_member.md b/docs/uikit/chatroomuikit/web/roomfeature_member.md new file mode 100644 index 000000000..703fa2f8b --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomfeature_member.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_member.html", + title: "成员管理" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/web/roomfeature_message.md b/docs/uikit/chatroomuikit/web/roomfeature_message.md new file mode 100644 index 000000000..e76f080fa --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomfeature_message.md @@ -0,0 +1,6 @@ +--- +{ + pageUri: "/uikit/chatroomuikit/android/roomfeature_message.html", + title: "消息扩展" +} +--- \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/web/roomuikit_best_practice.md b/docs/uikit/chatroomuikit/web/roomuikit_best_practice.md new file mode 100644 index 000000000..27ccece3c --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_best_practice.md @@ -0,0 +1,124 @@ +# 最佳实践 + + + +## 初始化 + +`Chatroom` 和 `ChatroomMember` 组件需要包裹在 `UIKitProvider` 组件内部使用。如果 `UIKitProvider` 在初始化完成前在组件内部使用 `useClient` 获取 SDK,则会获取失败,所以建议将 `UIKitProvider` 放在使用 `Chatroom` 或 `ChatroomMember` 组件的父组件中。 + +```tsx +// App.ts +// ... +const App = () => { + return +} + +// idnex.ts +// ... +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( + + + +) +``` + +## 登录 + +UIKit 提供两种登录方式: + +- 初始化时指定 `userId` 和 `password/token` 进行自动登录。 +- 使用 `useClient` 获取 SDK 实例进行手动登录。 + +```tsx +// 手动登录 +// ... +const App = () => { + const client = useClient() + const login = () => { + client.open({ + user: 'userId', + token: 'token' + }) + } + return +} + +// 自动登录 +// ... +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( + + + +) +``` + +## 聊天室事件 + +ChatroomUIKit 中提供了聊天室事件的监听接口。你可以通过注册聊天室监听器,获取聊天室事件,并作出相应处理。 + +ChatroomUIKit 中主动调用 API 的事件监听如下: + +```javascript +import { eventHandler } from "easemob-chat-uikit"; + +eventHandler.addEventHandler("chatroom", { + onError: (error) => { + // 所有 API 调用失败除了回调相应的事件外都会回调 onError 事件 + }, + joinChatRoom: { + error: (err) => {}, + success: () => {}, + }, + recallMessage: { + error: (err) => {}, + success: () => {}, + }, + reportMessage: { + // ... + }, + sendMessage: { + // ... + }, + getChatroomMuteList: { + // ... + }, + removeUserFromMuteList: { + // ... + }, + unmuteChatRoomMember: { + // ... + }, + removerChatroomMember: { + // ... + }, +}); +``` + +从 UIKit 中获取 Chat SDK 实例来监听收到的聊天室事件: + +```javascript +import React, { useEffect } from "react"; +import { useClient } from "easemob-chat-uikit"; + +const ChatroomApp = () => { + const client = useClient(); + + useEffect(() => { + client.addEventHandler("chatroom", { + onChatroomEvent: (event: EasemobChat.EventData) => { + if (event.operation === "muteMember") { + // console.log('你已被禁言') + } + // 全部事件请参考 https://doc.easemob.com/document/web/room_manage.html#监听聊天室事件 + }, + }); + }, []); +}; +``` + +## 参考 + +若要了解以上最佳实践的详情,请访问 [GitHub 仓库](https://github.com/easemob/ChatroomDemo/tree/dev/WEB/ChatroomDemo)。 diff --git a/docs/uikit/chatroomuikit/web/roomuikit_config_item.md b/docs/uikit/chatroomuikit/web/roomuikit_config_item.md new file mode 100644 index 000000000..6b698e8ff --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_config_item.md @@ -0,0 +1,71 @@ +# 可配置项 + + + +ChatroomUIKit 提供 `Chatroom` 和 `ChatroomMember` 组件,组件中包含各种属性,你可以根据需求进行设置。 + +## Chatroom 组件 + +![img](@static/images/uikit/chatroomweb/chatroom.png) + +`Chatroom` 是整个聊天界面组件,由 `Header`、`MessageList`、`MessageInput` 和 `Broadcast` 子组件组成。每个组件可以用 `renderX` 方法替换成自定义的组件。 + +| 属性 | 是否必需 | 类型 | 描述 | +| ---------- | -------- | ----------------- | ------------ | +| className | 否 | String | 组件的类名。 | +| prefix | 否 | String | CSS 类名的前缀。 | +| style | 否 | React.CSSProperties | 组件的样式。 | +| chatroomId | 是 | String | 聊天室 ID。 | +| renderEmpty | 否 | () => ReactNode | 自定义渲染没有会话时的内容。 | +| renderHeader | 否 | (roomInfo: ChatroomInfo) => ReactNode | 自定义渲染 Header。 | +| headerProps | 否 | HeaderProps | Header 组件的属性。 | +| renderMessageList | 否 | () => ReactNode | 自定义渲染聊天室消息区域。 | +| renderMessageInput | 否 | () => ReactNode | 自定义渲染消息输入区域。 | +| messageInputProps | 否 | MessageEditorProps | 消息输入区域组件的属性。 | +| messageListProps | 否 | MsgListProps | 聊天室消息区域组件的属性。 | +| renderBroadcast | 否 | () => ReactNode | 自定义渲染全局广播组件。 | +| broadcastProps | 否 | BroadcastProps | 全局广播组件的属性。 | + +例如,可以通过组件的属性传递 `className`、`style` 和 `prefix` 修改样式: + +```javascript +import { Chatroom, Button } from "easemob-chat-uikit"; + +const ChatApp = () => { + return ( +
+ + +
+ ); +}; +``` + +## ChatroomMember 组件 + +![img](@static/images/uikit/chatroomweb/chatroomMember.png) + +`ChatroomMember` 用于展示聊天室所有者和聊天室成员,以及禁言列表。聊天室所有者可以对成员禁言或踢出聊天室。 + +| 属性 | 是否必需 | 类型 | 描述 | +| --------------- | -------- | -------------------------------------- | -------------------- | +| className | 否 | String | 组件的类名。 | +| prefix | 否 | String | CSS 类名的前缀。 | +| style | 否 | React.CSSProperties | 组件的样式。 | +| chatroomId | 否 | String | 聊天室 ID。 | +| renderHeader | 否 | (roomInfo: ChatroomInfo) => ReactNode | 自定义渲染 Header。 | +| headerProps | 否 | HeaderProps | Header 组件的属性。 | +| memberListProps | 否 | { search?: boolean; placeholder?: string; renderEmpty?: () => ReactNode; renderItem?: (item: AppUserInfo) => ReactNode; UserItemProps?: UserItemProps; } | 成员列表组件的属性。 | +| muteListProps | 否 | { search?: boolean; placeholder?: string; renderEmpty?: () => ReactNode; renderItem?: (item: AppUserInfo) => ReactNode; UserItemProps?: UserItemProps; } | 禁言列表组件的属性。 | + +```javascript +import { ChatroomMember } from "easemob-chat-uikit"; + +const ChatApp = () => { + return ( +
+ +
+ ); +}; +``` diff --git a/docs/uikit/chatroomuikit/web/roomuikit_customize.md b/docs/uikit/chatroomuikit/web/roomuikit_customize.md new file mode 100644 index 000000000..4258d4680 --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_customize.md @@ -0,0 +1,128 @@ +# 自定义 + + + +本文通过几个示例介绍如何添加自己的业务逻辑,实现个性化业务需求。 + +## 自定义渲染 header + +你可以通过容器组件的 `renderHeader` 方法渲染自定义 header: + +```javascript +import {Chatroom, Header} from 'easemob-chat-uikit' + +const ChatApp = () => { + const CustomHeader =
+ return( +
+ CustomHeader}> +
+ ) +} +``` + +## 自定义渲染消息 + +你可以通过容器组件的 `renderMessageList` 方法渲染自定义聊天室消息区域: + +```tsx +import { Chatroom, MessageList } from "easemob-chat-uikit"; + +const ChatApp = () => { + const renderMessage = (message) => { + switch (message.type) { + case "txt": + return
{message.msg}
; + } + }; + return ( +
+ ( + + )} + > +
+ ); +}; +``` + +## 自定义礼物 + +你可以通过容器组件的 `messageEditorProps` 属性自定义 `giftConfig`: + +```tsx +import { Chatroom, MessageList } from "easemob-chat-uikit"; + +const ChatApp = () => { + const renderMessage = (message) => { + switch (message.type) { + case "txt": + return
{message.msg}
; + } + }; + return ( +
+ +
+ ); +}; +``` + +## Context + +UIKit 使用 React Context 管理全局数据,用户可以使用自定义 hook `useChatroomContext` 获取和管理聊天室相关数据。 + +### 使用示例 + +```javascript +import React from "react"; +import { useChatroomContext, Button } from "easemob-chat-uikit"; + +const ChatAPP = () => { + const { + chatroom, + muteChatRoomMember, + unmuteChatRoomMember, + removerChatroomMember, + } = useChatroomContext(); + + const muteMember = () => { + muteChatRoomMember("chatroomId", "userId"); + }; + return ; +}; +``` + +### useChatroomContext 总览 + +| 属性/方法 | 类型 | 描述 | +| :-------------------- | :-------------- | :-------------------- | +| `chatroom` | `ChatroomInfo` | 聊天室信息。 | +| `muteChatRoomMember` | `(chatroomId: string, userId: string, muteDuration?: number) => Promise` | 对成员禁言。 | +| `unmuteChatRoomMember` | `(chatroomId: string, userId: string) => Promise` | 对成员解除禁言。 | +| `removerChatroomMember` | `(chatroomId: string, userId: string) => void` | 移除成员。 | diff --git a/docs/uikit/chatroomuikit/web/roomuikit_integrated.md b/docs/uikit/chatroomuikit/web/roomuikit_integrated.md new file mode 100644 index 000000000..51ad699a3 --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_integrated.md @@ -0,0 +1,55 @@ +# 集成 ChatroomUIKit + + + +使用 ChatroomUIKit 之前,你需要将 ChatroomUIKit 集成到你的应用中。 + +## 前提条件 + +- React 16.8.0 或以上版本; +- React DOM 16.8.0 或以上版本; +- 有效的 Easemob IM 开发者账号,并[获取 App Key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 + +## 创建项目 + +```bash +# 安装 CLI 工具。 +npm install create-react-app +# 构建一个 my-app 的项目。 +npx create-react-app my-app +cd my-app +``` + +``` +项目目录: +├── package.json +├── public # Webpack 的静态目录。 +│ ├── favicon.ico +│ ├── index.html # 默认的单页面应用。 +│ └── manifest.json +├── src +│ ├── App.css # App 根组件的 CSS。 +│ ├── App.js # App 组件代码。 +│ ├── App.test.js +│ ├── index.css # 启动文件样式。 +│ ├── index.js # 启动文件。 +│ ├── logo.svg +│ └── serviceWorker.js +└── yarn.lock +``` + +## 安装 easemob-chat-uikit + +- 通过 npm 安装,运行以下命令: + +```bash +npm install easemob-chat-uikit --save +``` + +- 通过 yarn 安装,运行以下命令: + +```bash +yarn add easemob-chat-uikit +``` + + diff --git a/docs/uikit/chatroomuikit/web/roomuikit_overview.md b/docs/uikit/chatroomuikit/web/roomuikit_overview.md new file mode 100644 index 000000000..104c426e3 --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_overview.md @@ -0,0 +1,34 @@ +# 概述 + + + +环信 ChatroomUIKit 提供 UIKit 的各种组件帮助开发者根据实际业务需求快速搭建聊天室应用。通过该 UIKit,聊天室中的用户可实时交互,发送普通弹幕消息、打赏消息和全局广播等功能。 + +- 若要访问源码,请点击[这里](https://github.com/easemob/Easemob-UIKit-web)。 + +- 要体验环信聊天室 UIKit demo,请点击[这里](https://livestream-hsb.oss-cn-beijing.aliyuncs.com/index.html)。 + +## 功能 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - 创建聊天室:ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - 销毁聊天室:ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - 离开聊天室:聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - 发送弹幕:用户在聊天室中向其他参与者发送文字和表情的消息。 + - 打赏:用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - 全局广播:向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - 未读消息数:在一个聊天室中用户尚未读取的消息数量。 + - 已禁言列表:记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - 暗黑模式:ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展** + - 消息举报:在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - 消息翻译:将聊天室中的单条消息从一种语言转换成另一种语言。 + - 消息撤回:在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - 禁言成员:聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - 查看成员列表:聊天室成员列表显示了该聊天室中的当前在线用户。 + - 搜索成员:在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - 禁言成员:聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - 移除成员:聊天室所有者将指定成员从聊天室中踢出。 diff --git a/docs/uikit/chatroomuikit/web/roomuikit_quickstart.md b/docs/uikit/chatroomuikit/web/roomuikit_quickstart.md new file mode 100644 index 000000000..723db8be7 --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_quickstart.md @@ -0,0 +1,166 @@ +# 快速开始 + + + +利用 ChatroomUIKit,你可以轻松实现聊天室内的用户交互。本文介绍如何实现在聊天室中发送第一条消息。 + +## 前提条件 + +- React 16.8.0 或以上版本; +- React DOM 16.8.0 或以上版本; +- 有效的 Easemob IM 开发者账号,并获取 App Key。 + +## 支持的浏览器 + +| 浏览器 | 支持的版本 | +| ----------------- | ---------- | +| Internet Explorer | 11 或以上 | +| Edge | 43 或以上 | +| Firefox | 10 或以上 | +| Chrome | 54 或以上 | +| Safari | 11 或以上 | + +## 操作流程 + +### 第一步 创建项目 + +```bash +# 安装 CLI 工具。 +npm install create-react-app +# 构建一个 my-app 的项目。 +npx create-react-app my-app +cd my-app +``` + +``` +项目目录: +├── package.json +├── public # Webpack 的静态目录。 +│ ├── favicon.ico +│ ├── index.html # 默认的单页面应用。 +│ └── manifest.json +├── src +│ ├── App.css # App 根组件的 CSS。 +│ ├── App.js # App 组件代码。 +│ ├── App.test.js +│ ├── index.css # 启动文件样式。 +│ ├── index.js # 启动文件。 +│ ├── logo.svg +│ └── serviceWorker.js +└── yarn.lock +``` + +### 第二步 安装 easemob-chat-uikit + +- 通过 npm 安装,运行以下命令: + +```bash +npm install easemob-chat-uikit --save +``` + +- 通过 yarn 安装,运行以下命令: + +```bash +yarn add easemob-chat-uikit +``` + +### 第三步 使用 easemob-chat-uikit 组件构建应用 + +将 easemob-chat-uikit 库导入到你的代码中: + +```javascript +// App.js +import React, { Component, useEffect } from "react"; +import { + Provider, + Chatroom, + useClient, + rootStore, + ChatroomMember, +} from "easemob-chat-uikit"; +import "easemob-chat-uikit/style.css"; + +const ChatroomApp = observer(() => { + const client = useClient(); + const chatroomId = ""; // 要加入的聊天室 + const appKey = ""; // 你的 App Key + + useEffect(() => { + if (client.addEventHandler) { + client.addEventHandler("chatroom", { + onConnected: () => { + console.log("登录成功"); + }, + }); + } + }, [client]); + + const [userId, setUserId] = useState(""); + const [password, setPassword] = useState(""); + const login = () => { + client + .open({ + user: userId, + pwd: password, + //accessToken: '', + }) + .then((res) => { + console.log("获取token成功"); + }); + }; + return ( + <> + +
+
+ + { + setUserId(e.target.value); + }} + > +
+
+ + { + setPassword(e.target.value); + }} + > +
+
+ +
+
+ +
+ +
+
+ +
+
+ + ); +}); +export default ChatroomApp; +``` + +### 第四步 运行项目 + +```bash +npm run start +``` + +### 第五步 发送第一条消息 + +输入消息内容,点击 **发送** 按钮,发送消息。 + +![img](@static/images/uikit/chatroomweb/chatroom.png) \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/web/roomuikit_releasenote.md b/docs/uikit/chatroomuikit/web/roomuikit_releasenote.md new file mode 100644 index 000000000..1ef4a279a --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_releasenote.md @@ -0,0 +1,31 @@ +# 聊天室 UIKit 更新日志 + + + +## 版本 V1.0.0 2023-12-29 + +### 新增特性 + +ChatroomUIKit 提供以下功能: + +- **通用特性** + - [创建聊天室](roomfeature_common.html#创建聊天室):ChatroomUIKit 不提供创建聊天室的功能,你可以[调用即时通讯 IM SDK 的接口创建聊天室](/document/server-side/chatroom.html#创建聊天室)。 + - [销毁聊天室](roomfeature_common.html#销毁聊天室):ChatroomUIKit 不提供销毁聊天室的功能,你可以[调用即时通讯 IM SDK 的接口销毁聊天室](/document/server-side/chatroom.html#删除聊天室)。 + - [离开聊天室](roomfeature_common.html#离开聊天室):聊天室中的成员可自行离开聊天室,聊天室所有者也可以将成员移出聊天室。 + - [发送弹幕消息](roomfeature_common.html#发送弹幕):用户在聊天室中向其他参与者发送文字和表情的消息。 + - [打赏](roomfeature_common.html#打赏):用户通过赠送虚拟礼物,向聊天室中的主播或其他用户表达赞赏或者支持 + - [全局广播](roomfeature_common.html#全局广播):向 App 内所有在线聊天室中的所有用户发送相同的消息或通知。 + - [未读消息数](roomfeature_common.html#未读消息数):在一个聊天室中用户尚未读取的消息数量。 + - [已禁言列表](roomfeature_common.html#已禁言列表):记录被禁止发言用户的列表。当用户违反了聊天室的规则时,聊天室所有者将其禁言,即添加至已禁言列表。 + - [暗黑模式](roomfeature_common.html#暗黑模式):ChatroomUIKit 默认风格为明亮模式,切换为暗黑模式后,聊天室界面中所有元素将替换为暗黑风格设计,提供用户舒适的视觉体验。 +- **消息扩展**(长按一条消息可进行的操作) + - [消息举报](roomfeature_message.html#消息举报):在聊天室中,用户可以举报不适当、违规或有害的消息内容以促使聊天室所有者采取适当的行动。 + - [消息翻译](roomfeature_message.html#消息翻译):将聊天室中的单条消息从一种语言转换成另一种语言。 + - [消息撤回](roomfeature_message.html#消息撤回):在聊天室中撤销已经发送的消息。所有用户只能撤回自己发送的消息,即使聊天室所有者也不能撤回其他成员发送的消息。 + - [禁言成员](roomfeature_message.html#禁言成员):聊天室所有者对聊天室中的成员禁止发言。 +- **成员管理** + - [查看成员列表](roomfeature_member.html#查看成员列表):聊天室成员列表显示了该聊天室中的当前在线用户。 + - [搜索成员](roomfeature_member.html#搜索成员):在聊天室中查找指定成员的功能,支持支持本地搜索和模糊匹配。 + - [禁言成员](roomfeature_member.html#禁言成员):聊天室所有者可以在聊天室中对某个特定的成员禁言。 + - [移除成员](roomfeature_member.html#移除成员):聊天室所有者将指定成员从聊天室中踢出。 + diff --git a/docs/uikit/chatroomuikit/web/roomuikit_run.md b/docs/uikit/chatroomuikit/web/roomuikit_run.md new file mode 100644 index 000000000..9f117780e --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_run.md @@ -0,0 +1,31 @@ +# 跑通示例项目 + + + +环信提供一个[开源的 ChatroomUIKit 示例项目](https://github.com/easemob/ChatroomDemo/tree/dev/WEB/ChatroomDemo),演示了如何使用该 UIKit 快速搭建聊天室页面,实现完整业务。 + +本文展示如何运行 Web 平台的聊天室 UIKit 示例项目。 + +## 下载项目 + +```sh +git clone git@github.com:easemob/ChatroomDemo.git +``` + +## 安装依赖 + +```sh +cd WEB/ChatroomDemo + +npm install +``` + +## 运行项目 + +```sh +npm start +``` + +浏览器会显示以下页面: + +![img](@static/images/uikit/chatroomweb/chatroom_enter.png) diff --git a/docs/uikit/chatroomuikit/web/roomuikit_storybook.md b/docs/uikit/chatroomuikit/web/roomuikit_storybook.md new file mode 100644 index 000000000..1f7ccdd62 --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_storybook.md @@ -0,0 +1,5 @@ +# 组件文档 + +ChatroomUIKit 提供 container 组件 `Chatroom` 和 `ChatroomMember`,module 组件 `ChatroomMessage`。组件中包含各种属性供你配置。 + +若要查看组件配置详情,请点击[这里](https://storybook.easemob.com/)。 \ No newline at end of file diff --git a/docs/uikit/chatroomuikit/web/roomuikit_theme.md b/docs/uikit/chatroomuikit/web/roomuikit_theme.md new file mode 100644 index 000000000..f192bce60 --- /dev/null +++ b/docs/uikit/chatroomuikit/web/roomuikit_theme.md @@ -0,0 +1,42 @@ +# 主题 + + + +ChatroomUIkit 内置浅色和深色主题,默认为浅色主题。 + +- 浅色主题 + +![img](@static/images/uikit/chatroomweb/light_mode.png) + +- 深色主题 + +![img](@static/images/uikit/chatroomweb/dark_mode.png) + +## 修改主题 + +你可以设置 `Provider` 组件的主题属性修改主题: + +```javascript +import { Chatroom, UIKitProvider } from 'easemob-chat-uikit'; + +const ChatApp = () => { + return ( + + + + ); +}; +``` + +## 设计指南 + +如果你对主题颜色,设计指南和细节有任何疑问,您可以在 Figma 设计稿中添加评论并提及我们的设计师 Stevie Jiang。 + +- [UI 设计资源](https://www.figma.com/community/file/1322495388317476706/chatroom-uikit)。 + +- [UI 设计指南](design_guide.html)。 diff --git a/docs/uikit/chatuikit/README.md b/docs/uikit/chatuikit/README.md new file mode 100644 index 000000000..4cbd52515 --- /dev/null +++ b/docs/uikit/chatuikit/README.md @@ -0,0 +1,3 @@ +--- +title: 单群聊 UIKit +--- diff --git a/docs/uikit/android/README.md b/docs/uikit/chatuikit/android/README.md similarity index 100% rename from docs/uikit/android/README.md rename to docs/uikit/chatuikit/android/README.md diff --git a/docs/uikit/chatuikit/android/chatfeature_common.md b/docs/uikit/chatuikit/android/chatfeature_common.md new file mode 100644 index 000000000..5f1564645 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatfeature_common.md @@ -0,0 +1,83 @@ +# 单群聊 UIKit 通用特性 + +本文介绍单群聊 UIKit 通用特性,包括会话列表、聊天、群组和联系人等相关功能。 + + + +## 会话列表 + +会话列表呈现了用户所有正在进行的对话,帮助用户快速找到所需联系人并查看消息进展。 + +![img](@static/images/uikit/chatuikit/feature/common/conversation_list.png =350x750) + +## 聊天 + +聊天是即时通讯的核心功能之一,它允许用户与其他用户进行实时文字交流。聊天通常以会话的形式进行,每个会话由两个或多个用户组成。 + +![img](@static/images/uikit/chatuikit/feature/common/chat.png =350x750) + +## 创建会话 + +创建会话是即时通讯的核心功能之一,它允许用户启动与一个或多个其他用户交流。 + +![img](@static/images/uikit/chatuikit/feature/common/conversation_create.png) + +## 创建群组 + +群组是允许多个用户加入的聊天会话。用户可以邀请其他用户加入群组,并对群组进行管理。 + +![img](@static/images/uikit/chatuikit/feature/common/group_create.png) + +## 群组管理员 + +群组管理员拥有对群组的所有权限,包括:添加或删除群成员,修改群组名称、描述和头像,禁言或踢出群成员等。 + +![img](@static/images/uikit/chatuikit/feature/common/group_admin.png) + +## 用户列表 + +用户列表显示了用户的所有联系人,包括联系人列表,群成员列表和黑名单等。用户可以通过用户列表快速找到需要联系的人。 + +![img](@static/images/uikit/chatuikit/feature/common/user_list.png =350x760) + +## 文件共享 + +文件共享允许用户通过即时通讯应用发送和接收文件。文件共享可以用于分享文档、图片、视频等文件。 + +![img](@static/images/uikit/chatuikit/feature/common/file_share.png =600x630) + +## 未读消息数 + +未读消息数是指用户收到的但尚未查看的消息数量。 + +![img](@static/images/uikit/chatuikit/feature/common/message_unread_count.png =600x630) + +## 已发送回执 + +已发送回执用于告知消息发送者,其发送的消息已经成功发送到服务器、接收方以及发送失败。 + +![img](@static/images/uikit/chatuikit/feature/common/message_delivery_receipt.png) + +## 已读回执 + +已读回执用于告知消息发送者,接收者已经阅读了其发送的消息。 + +![img](@static/images/uikit/chatuikit/feature/common/message_read_receipt.png =300x630) + +## 联系人名片 + +联系人名片指包含联系人详细信息的电子卡片,通常包括头像和昵称等信息。通过联系人名片,用户可以快速添加联系人或开始会话。 + +![img](@static/images/uikit/chatuikit/feature/common/contact_namecard.png) + +## 语音消息 + +语音消息指以语音形式发送和接收的消息,可替代文字交流。 + +![img](@static/images/uikit/chatuikit/feature/common/message_audio.png =700x730) + +## 消息审核 + +消息审核对用户发送的消息内容进行审查,判断其是否符合平台的社区准则、服务条款和相关法律法规。 + +![img](@static/images/uikit/chatuikit/feature/common/message_report.png =300x630) \ No newline at end of file diff --git a/docs/uikit/chatuikit/android/chatfeature_conversation.md b/docs/uikit/chatuikit/android/chatfeature_conversation.md new file mode 100644 index 000000000..36c5be16a --- /dev/null +++ b/docs/uikit/chatuikit/android/chatfeature_conversation.md @@ -0,0 +1,37 @@ +# 会话特性 + +本文介绍会话相关特性,包括会话已读、置顶、免打扰和删除功能。 + + + +## 会话已读 + +会话已读是指显示用户是否已阅读过含有未读消息的特定会话。 + +在单群聊 UIKit 中,用户可以通过左滑会话/右滑会话或长按会话的操作触发会话拓展功能菜单,选择会话已读选项,指定会话将会被置为已读。 + +![img](@static/images/uikit/chatuikit/feature/conversation/conversation_read.png) + +## 会话置顶 + +会话置顶是指用户将重要的会话固定在聊天列表顶部,方便快速访问常用或优先级别的会话。 + +在单群聊 UIKit 中,用户可以通过左滑会话/右滑会话或长按会话的操作触发会话拓展功能菜单,选择会话置顶选项,指定会话将会被放置在会话列表前排区域。 + +![img](@static/images/uikit/chatuikit/feature/conversation/conversation_pin.png) + +## 会话免打扰 + +会话免打扰是指用户暂时关闭特定会话的通知,避免被打扰。 + +在单群聊 UIKit 中,用户可以通过左滑会话/右滑会话或长按会话的操作触发会话拓展功能菜单,选择会话免打扰选项,指定会话将不再接收通知。 + +![img](@static/images/uikit/chatuikit/feature/conversation/conversation_dnd.png) + +## 会话删除 + +会话删除是指用户永久删除不再需要的会话,清理会话列表。 + +在单群聊 UIKit 中,用户可以通过左滑会话/右滑会话或长按会话的操作触发会话拓展功能菜单,选择会话删除选项,指定会话将会被删除。 + +![img](@static/images/uikit/chatuikit/feature/conversation/conversation_delete.png) \ No newline at end of file diff --git a/docs/uikit/chatuikit/android/chatfeature_message.md b/docs/uikit/chatuikit/android/chatfeature_message.md new file mode 100644 index 000000000..e54c5d1d7 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatfeature_message.md @@ -0,0 +1,35 @@ +# 消息特性 + +本文介绍消息相关特性,包括消息复制、删除、撤回、编辑和引用。 + + + +## 消息复制 + +消息复制是指用户可以将一条消息复制到剪贴板。消息复制可以帮助用户将消息保存到其他地方,或将其粘贴到其他应用程序中。 + +![img](@static/images/uikit/chatuikit/feature/message/message_copy.png =600x600) + +## 消息删除 + +消息删除是指用户可以删除一条消息。消息删除可以帮助用户删除错误发送的消息,或删除不想保留的消息。 + +![img](@static/images/uikit/chatuikit/feature/message/message_delete.png) + +## 消息撤回 + +消息撤回是指用户可以撤回一条已发送的消息。消息撤回可以帮助用户撤回错误发送的消息,或撤回不想让其他用户看到的消息。 + +![img](@static/images/uikit/chatuikit/feature/message/message_recall.png) + +## 消息编辑 + +消息编辑是指用户可以编辑一条已发送的消息。消息编辑可以帮助用户纠正错误,或添加新信息。 + +![img](@static/images/uikit/chatuikit/feature/message/message_edit.png) + +## 消息引用 + +消息引用是指用户可以引用一条已发送的消息。消息引用可以帮助用户回复特定的消息,或强调特定的信息。 + +![img](@static/images/uikit/chatuikit/feature/message/message_reply.png) \ No newline at end of file diff --git a/docs/uikit/chatuikit/android/chatuikit_advancedusage.md b/docs/uikit/chatuikit/android/chatuikit_advancedusage.md new file mode 100644 index 000000000..5be3c4983 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_advancedusage.md @@ -0,0 +1,102 @@ +# 进阶用法 + + + +## Activity 跳转路径设置 + +如果默认的 Activity 及其提供的可配置项不满足需求时,需要你继承默认的 Activity 新增需要的逻辑。如果该 Activity 为 UIKit 内部调用的页面,你可以通过下面方法修改 Activity 的跳转。 + +例如,若 `EaseChatActivity` 无法满足当前需求,可以继承 `EaseChatActivity` 实现新的 `ChatActivity`。当调用 `EaseChatActivity.actionStart` 跳转页面时,会通过`getActivityRoute()` 拦截跳转指向 `ChatActivity`。 + +:::tip +只有实现了 `EaseIM.getCustomActivityRoute()?.getActivityRoute()` 的 Activity 才可以进行拦截。 +::: + +```kotlin +// EaseChatActivity 中的跳转实现 + +companion object { + private const val REQUEST_CODE_STORAGE_PICTURE = 111 + private const val REQUEST_CODE_STORAGE_VIDEO = 112 + private const val REQUEST_CODE_STORAGE_FILE = 113 + + fun actionStart(context: Context, conversationId: String, chatType: EaseChatType) { + Intent(context, EaseChatActivity::class.java).apply { + putExtra(EaseConstant.EXTRA_CONVERSATION_ID, conversationId) + putExtra(EaseConstant.EXTRA_CHAT_TYPE, chatType.ordinal) + EaseIM.getCustomActivityRoute()?.getActivityRoute(this.clone() as Intent)?.let { + if (it.hasRoute()) { + context.startActivity(it) + return + } + } + context.startActivity(this) + } + } +} + + +// application 中路由拦截实现 +EaseIM.setCustomActivityRoute(object : EaseCustomActivityRoute { + override fun getActivityRoute(intent: Intent): Intent { + if (intent.component?.className == EaseChatActivity::class.java.name) { + intent.setClass(this@DemoApplication, ChatActivity::class.java) + } + return intent + } +}) +``` + +## 全局配置 + +单群聊 UIKit 提供了一些全局配置,可以在初始化时进行设置,示例代码如下: + +```kotlin +val avatarConfig = EaseAvatarConfig() +// 将头像设置为圆角 +avatarConfig.avatarShape = EaseImageView.ShapeType.ROUND +val config = EaseIMConfig(avatarConfig = avatarConfig) +EaseIM.init(this, options, config) +``` + +`EaseAvatarConfig` 提供的配置项如下表所示: + +| 属性 | 描述 | +| -------------------------------------- | ---------------------------------------------------------------- | +| avatarShape | 头像样式,有默认,圆形和矩形三种样式,默认样式为默认。 | +| avatarRadius | 头像圆角半径,仅在头像样式设置为矩形后有效。 | +| avatarBorderColor | 头像边框的颜色。 | +| avatarBorderWidth | 头像边框的宽度。 | + +`EaseChatConfig` 提供的配置项如下表所示: + +| 属性 | 描述 | +| -------------------------------------- | ---------------------------------------------------------------- | +| enableReplyMessage | 消息回复功能是否可用,默认为可用。 | +| enableModifyMessageAfterSent | 消息编辑功能是否可用,默认为可用。 | +| timePeriodCanRecallMessage | 设置消息可撤回的时间,默认为 2 分钟。 | + + +`EaseDateFormatConfig` 提供的配置项如下表所示: + +| 属性 | 描述 | +| -------------------------------------- | ---------------------------------------------------------------- | +| convTodayFormat | 会话列表当天日期格式,英文环境默认为:"HH:mm"。 | +| convOtherDayFormat | 会话列表其他日期的格式,英文环境默认为: "MMM dd"。 | +| convOtherYearFormat | 会话列表其他年日期的格式,英文环境默认为: "MMM dd, yyyy"。 | + + +`EaseSystemMsgConfig` 提供的配置项如下表所示: + +| 属性 | 描述 | +| -------------------------------------- | ---------------------------------------------------------------- | +| useDefaultContactInvitedSystemMsg | 是否启用系统消息功能,默认为启用。 | + + +`EaseMultiDeviceEventConfig` 提供的配置项如下表所示: + +| 属性 | 描述 | +|--------------------------------------|-------------------| +| useDefaultMultiDeviceContactEvent | 是否启用默认的多设备联系人事件处理。 | +| useDefaultMultiDeviceGroupEvent | 是否启用默认的多设备群组事件处理。 | + diff --git a/docs/uikit/chatuikit/android/chatuikit_chat.md b/docs/uikit/chatuikit/android/chatuikit_chat.md new file mode 100644 index 000000000..f31e96dea --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_chat.md @@ -0,0 +1,397 @@ +# 聊天消息 + + + +环信单群聊 UIKit 提供 `EaseChatActivity` 和 `EaseChatFragment` 两种方式方便用户快速集成聊天页面和自定义聊天页面。该页面提供如下功能: + +- 发送和接收消息, 包括文本、表情、图片、语音、视频、文件和名片消息。 +- 对消息进行复制、引用、撤回、删除、编辑、重新发送和审核。 +- 从服务器拉取漫游消息。 +- 清除本地消息。 + +消息相关功能,详见[功能介绍文档](chatfeature_message.html)。 + +![img](@static/images/uikit/chatuikit/android/page_chat.png =300x630) + +## 使用示例 + +`EaseChatActivity` 页面主要进行了权限的请求,比如相机权限,语音权限等。 + +```kotlin +// conversationId: 单聊为对端用户的用户 ID,群聊为群组 ID。 +// chatType:单聊和群聊分别为 EaseChatType#SINGLE_CHAT 和 EaseChatType#GROUP_CHAT。 +EaseChatActivity.actionStart(mContext, conversationId, chatType) +``` + +```kotlin +class ChatActivity: AppCompactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_chat) + // conversationId: 单聊为对端用户的用户 ID,群聊为群组 ID。 + // chatType:单聊和群聊分别为 EaseChatType#SINGLE_CHAT 和 EaseChatType#GROUP_CHAT。 + EaseChatFragment.Builder(conversationId, chatType) + .build()?.let { fragment -> + supportFragmentManager.beginTransaction() + .replace(R.id.fl_fragment, fragment).commit() + } + } +} +``` + +![img](@static/images/uikit/chatuikit/android/buble1.png =500x900) + +## 进阶用法 + +### 通过 EaseChatFragment.Builder 自定义设置 + +`EaseChatFragment` 提供了 Builder 构建方式,方便开发者进行一些自定义设置,目前提供的设置项如下: + +```kotlin +// conversationID: 单聊为对端用户的用户 ID,群聊为群组 ID。 +// easeChatType: 单聊和群聊分别为 SINGLE_CHAT 和 GROUP_CHAT。 +EaseChatFragment.Builder(conversationID, easeChatType) + .useTitleBar(true) + .setTitleBarTitle("title") + .setTitleBarSubTitle("subtitle") + .enableTitleBarPressBack(true) + .setTitleBarBackPressListener(onBackPressListener) + .getHistoryMessageFromServerOrLocal(false) + .setOnChatExtendMenuItemClickListener(onChatExtendMenuItemClickListener) + .setOnChatInputChangeListener(onChatInputChangeListener) + .setOnMessageItemClickListener(onMessageItemClickListener) + .setOnMessageSendCallBack(onMessageSendCallBack) + .setOnWillSendMessageListener(willSendMessageListener) + .setOnChatRecordTouchListener(onChatRecordTouchListener) + .setOnModifyMessageListener(onModifyMessageListener) + .setOnReportMessageListener(onReportMessageListener) + .setMsgTimeTextColor(msgTimeTextColor) + .setMsgTimeTextSize(msgTimeTextSize) + .setReceivedMsgBubbleBackground(receivedMsgBubbleBackground) + .setSentBubbleBackground(sentBubbleBackground) + .showNickname(false) + .hideReceiverAvatar(false) + .hideSenderAvatar(true) + .setChatBackground(chatBackground) + .setChatInputMenuBackground(inputMenuBackground) + .setChatInputMenuHint(inputMenuHint) + .sendMessageByOriginalImage(true) + .setEmptyLayout(R.layout.layout_chat_empty) + .setCustomAdapter(customAdapter) + .setCustomFragment(myChatFragment) + .build() +``` + +`EaseChatFragment#Builder` 提供的方法如下表所示: + +| 方法 | 描述 | +| -------------------------------------- | ---------------------------------------------------- | +| useTitleBar() | 是否使用默认的标题栏(`EaseTitleBar`):
- `true`:是。
- (默认) `false`: 否。 | +| setTitleBarTitle() | 设置标题栏的标题。 | +| setTitleBarSubTitle() | 设置标题栏的子标题。 | +| enableTitleBarPressBack() | 设置是否支持显示返回按钮:
- `true`:是。
- (默认) `false`: 否。 | +| setTitleBarBackPressListener() | 设置点击标题栏返回按钮的监听事件。 | +| getHistoryMessageFromServerOrLocal() | 设置优先从服务器还是本地获取消息。 | +| setOnChatExtendMenuItemClickListener() | 设置扩展功能的条目点击事件监听。 | +| setOnChatInputChangeListener() | 设置菜单中文本变化的监听。 | +| setOnMessageItemClickListener() | 设置消息条目的点击事件监听,包括气泡区域及头像的点击及长按事件。 | +| setOnMessageSendCallBack() | 设置发送消息的结果回调监听。 | +| setOnWillSendMessageListener() | 设置发送消息前添加消息扩展属性的回调。 | +| setOnChatRecordTouchListener() | 设置录音按钮的触摸事件回调。 | +| setOnModifyMessageListener() | 设置编辑消息的结果回调监听。 | +| setOnReportMessageListener() | 设置举报消息的结果回调监听。 | +| setMsgTimeTextColor() | 设置时间线文本的颜色。 | +| setMsgTimeTextSize() | 设置时间线文本的字体大小。 | +| setReceivedMsgBubbleBackground() | 设置接收消息气泡区域的背景。 | +| setSentBubbleBackground() | 设置发送消息气泡区域的背景。 | +| showNickname() | 是否显示昵称:
- `true`:是。
- (默认) `false`: 否。 | +| hideReceiverAvatar() | 设置不展示接收方头像,默认展示接收方头像。 | +| hideSenderAvatar() | 设置不展示发送方头像,默认展示发送方头像。 | +| setChatBackground() | 设置聊天列表区域的背景。 | +| setChatInputMenuBackground() | 设置菜单区域的背景。 | +| setChatInputMenuHint() | 设置菜单区域输入文本框的提示文字。 | +| sendMessageByOriginalImage() | 设置图片消息是否发送原图:
- `true`:是。
- (默认) `false`: 否。 | +| setEmptyLayout() | 设置聊天列表的空白页面。 | +| setCustomAdapter() | 设置自定义的适配器,默认为 `EaseMessageAdapter`。 | +| setCustomFragment() | 设置自定义聊天 Fragment,需要继承自 `EaseChatFragment`。 | + +### 添加自定义消息布局 + +开发者可以继承 `EaseMessageAdapter`、`EaseChatRowViewHolder` 和 `EaseChatRow`,实现自己的 `CustomMessageAdapter`、`CustomChatTypeViewViewHolder` 和 `CustomTypeChatRow`,然后将 `CustomMessageAdapter` 设置到 `EaseChatFragment#Builder#setCustomAdapter` 中。 + +1. 创建自定义适配器 `CustomMessageAdapter` 继承自 `EaseMessageAdapter`,重写 `getViewHolder` 和 `getItemNotEmptyViewType` 方法。 + +```kotlin +class CustomMessageAdapter: EaseMessagesAdapter() { + + override fun getItemNotEmptyViewType(position: Int): Int { + // 根据消息类型设置自己的 itemViewType。 + // 如果要使用默认的,返回 super.getItemNotEmptyViewType(position) 即可。 + return CUSTOM_YOUR_MESSAGE_TYPE + } + + override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + // 根据返回的 viewType 返回对应的 ViewHolder。 + // 返回自定义的 ViewHolder 或者使用默认的 super.getViewHolder(parent, viewType)。 + return CUSTOM_VIEW_HOLDER() + } +} +``` + +2. 创建` CustomTypeChatRow` ,继承自 `EaseChatRow`。 + +```kotlin +class CustomTypeChatRow( + private val context: Context, + private val attrs: AttributeSet? = null, + private val defStyle: Int = 0, + isSender: Boolean = false +): EaseChatRow(context, attrs, defStyle, isSender) { + + override fun onInflateView() { + inflater.inflate(if (!isSender) R.layout.layout_row_received_custom_type + else R.layout.layout_row_sent_custom_type, + this) + } + + override fun onSetUpView() { + (message?.getMessage()?.body as? ChatTextMessageBody)?.let { txtBody -> + contentView.text = txtBody.message + } + } +} +``` + +3. 创建 `CustomChatTypeViewViewHolder`,继承自 `EaseChatRowViewHolder`。 + +```kotlin +class CustomChatTypeViewViewHolder( + itemView: View +): EaseChatRowViewHolder(itemView) { + + override fun onBubbleClick(message: EaseMessage?) { + super.onBubbleClick(message) + // 添加点击事件 + } +} +``` + +4. 完善 `CustomMessageAdapter`。 + +```kotlin +class CustomMessageAdapter: EaseMessagesAdapter() { + + override fun getItemNotEmptyViewType(position: Int): Int { + // 根据消息类型设置自己的 itemViewType。 + mData?.get(position)?.getMessage()?.let { msg -> + msg.getStringAttribute("type", null)?.let { type -> + if (type == CUSTOM_TYPE) { + return if (msg.direct() == ChatMessageDirection.SEND) { + VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME + } else { + VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER + } + } + } + } + // 如果要使用默认的,返回 super.getItemNotEmptyViewType(position) 即可。 + return super.getItemNotEmptyViewType(position) + } + + override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + // 根据返回的 viewType 返回对应的 ViewHolder。 + if (viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME || viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER) { + CustomChatTypeViewViewHolder( + CustomTypeChatRow(parent.context, isSender = viewType == VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME) + ) + } + // 返回自定义的 ViewHolder 或者 使用默认的 super.getViewHolder(parent, viewType) + return super.getViewHolder(parent, viewType) + } + + companion object { + private const val CUSTOM_TYPE = "custom_type" + private const val VIEW_TYPE_MESSAGE_CUSTOM_VIEW_ME = 1000 + private const val VIEW_TYPE_MESSAGE_CUSTOM_VIEW_OTHER = 1001 + } +} +``` + +5. 添加 `CustomMessageAdapter` 到 `EaseChatFragment#Builder`。 + +```kotlin +builder.setCustomAdapter(CustomMessageAdapter()) +``` + +![img](@static/images/uikit/chatuikit/android/buble2.png =400x750) + +### 列表控件相关功能设置 + +```kotlin +val chatMessageListLayout:EaseChatMessageListLayout? = binding?.layoutChat?.chatMessageListLayout +``` + +`EaseChatMessageListLayout` 提供了如下方法: + +| 方法 | 描述 | +| ------------------------------ | ---------------------------------------------------- | +| setViewModel() | UIKit 中提供了默认的实现 `EaseMessageListViewModel`,开发者可以继承 `IChatMessageListRequest` 添加自己的数据逻辑。 | +| setMessagesAdapter() | 设置消息列表的适配器,需要是 `EaseMessagesAdapter` 的子类。 | +| getMessagesAdapter() | 返回消息列表的适配器。 | +| addHeaderAdapter() | 添加消息列表的头布局的适配器。 | +| addFooterAdapter() | 添加消息列表的尾布局的适配器。 | +| removeAdapter() | 移除指定适配器。 | +| addItemDecoration() | 添加消息列表的装饰器。 | +| removeItemDecoration() | 移除消息列表的装饰器。 | +| setAvatarDefaultSrc() | 设置条目的默认头像。 | +| setAvatarShapeType() | 设置头像的样式,分为默认样式,圆形和矩形三种样式。 | +| showNickname() | 是否展示条目的昵称,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | +| setItemSenderBackground() | 设置发送方的背景,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | +| setItemReceiverBackground() | 设置接收方的背景,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | +| setItemTextSize() | 设置文本消息的字体大小。 | +| setItemTextColor() | 设置文本消息的字体颜色。 | +| setTimeTextSize() | 设置时间线文本的字体大小,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | +| setTimeTextColor() | 设置时间线文本的颜色,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | +| setTimeBackground() | 设置时间线的背景。 | +| hideChatReceiveAvatar() | 不展示接收方头像,默认为展示,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | +| hideChatSendAvatar() | 不展示发送方头像,默认为展示,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | +| setOnChatErrorListener() | 设置发送消息时的错误回调,`EaseChatFragment#Builder` 也提供了此功能的设置方法。 | + + +### 扩展功能设置 + +```kotlin +val chatExtendMenu: IChatExtendMenu? = binding?.layoutChat?.chatInputMenu?.chatExtendMenu +``` + +获取到 `chatExtendMenu` 对象后,对于扩展功能可以进行添加,移除,排序以及处理扩展功能的点击事件等。 + +`IChatExtendMenu` 提供的方法如下表所示: + +| 方法 | 描述 | +| -------------------------------------- | ---------------------------------------------------- | +| clear() | 清除所有的扩展菜单项。 | +| setMenuOrder() | 对指定的菜单项进行排序。 | +| registerMenuItem() | 添加新的菜单项。 | + +![img](@static/images/uikit/chatuikit/android/editor2.png =400x700) + +### 监听扩展条目点击事件 + +开发者可以利用 `EaseChatFragment#Builder#setOnChatExtendMenuItemClickListener` 进行监听,也可以在自定义的 `Fragment` 中重写 `onChatExtendMenuItemClick` 方法。 + +```kotlin +override fun onChatExtendMenuItemClick(view: View?, itemId: Int): Boolean { + if(itemId == CUSTOM_YOUR_EXTEND_MENU_ID) { + // 处理你自己的点击事件逻辑 + // 如果要自定义点击事件需要返回 `true` + return true + } + return super.onChatExtendMenuItemClick(view, itemId) +} +``` + +### 长按菜单功能设置 + +- 增加自定义菜单条目 + +```kotlin +binding?.let { + it.layoutChat.addItemMenu(menuId, menuOrder, menuTile) +} +``` + +`EaseChatLayout` 提供的长按菜单方法如下表所示: + +| 方法 | 描述 | +| -------------------------------------- | ---------------------------------------------------- | +| clearMenu() | 清除菜单项。 | +| addItemMenu() | 添加新的菜单项。 | +| findItemVisible() | 通过指定 `itemId` 设置菜单项的可见性。 | +| setOnMenuChangeListener() | 设置菜单项的点击事件监听,`EaseChatFragment` 中已经设置此监听。 | + +- 处理菜单的事件 + + 在自定义的 `Fragment` 中重写以下方法: + +```kotlin +override fun onPreMenu(helper: EaseChatMenuHelper?, message: ChatMessage?) { + // 菜单展示前的回调事件,可以通过 helper 对象在这里设置菜单条目是否展示。 +} + +override fun onMenuItemClick(item: EaseMenuItem?, message: ChatMessage?): Boolean { + // 如果要拦截某个点击事件,需要设置返回 `true`。 + return false +} + +override fun onDismiss() { + // 可以在这里处理快捷菜单的隐藏事件。 +} +``` + +### 设置输入菜单相关属性 + +- 获取 `EaseChatInputMenu` 对象: + +```kotlin +val chatInputMenu: EaseChatInputMenu? = binding?.layoutChat?.chatInputMenu +``` + +`EaseChatInputMenu` 提供了如下方法: + +| 方法 | 描述 | +| -------------------------- | ------------------------------------------------------------ | +| setCustomPrimaryMenu() | 设置自定义的菜单项,支持 View 和 Fragment 两种方式。 | +| setCustomEmojiconMenu() | 设置自定义的表情功能,支持 View 和 Fragment 两种方式。 | +| setCustomExtendMenu() | 设置自定义的扩展功能,支持 View ,Dialog 和 Fragment 三种方式。 | +| setCustomTopExtendMenu() | 设置自定义的菜单顶部布局,支持 View ,Fragment 两种方式。 | +| hideExtendContainer() | 隐藏扩展区域,包括表情区域和扩展功能区域。 | +| hideInputMenu() | 隐藏除了菜单顶部区域外的区域。 | +| showEmojiconMenu() | 展示表情功能区域。 | +| showExtendMenu() | 展示扩展功能区域。 | +| showTopExtendMenu() | 展示顶部扩展功能区域。 | +| setChatInputMenuListener() | 设置输入菜单监听。 | +| chatPrimaryMenu | 获取菜单项接口。 | +| chatEmojiMenu | 获取表情功能菜单接口。 | +| chatExtendMenu | 获取扩展功能接口。 | +| chatTopExtendMenu | 获取顶部扩展功能接口。 | + +- 获取菜单项对象: + +```kotlin +val primaryMenu: IChatPrimaryMenu? = binding?.layoutChat?.chatInputMenu?.chatPrimaryMenu +``` + +IChatPrimaryMenu 提供了如下方法: + +| 方法 | 描述 | +| ------------------- | ----------------------------------------- | +| onTextInsert() | 在光标处插入文本 | +| editText | 获取菜单输入框对象 | +| setMenuBackground() | 设置菜单的背景 | + +- 获取表情菜单对象: + +```kotlin +val emojiconMenu: IChatEmojiconMenu? = binding?.layoutChat?.chatInputMenu?.chatEmojiMenu +``` + +`IChatEmojiconMenu` 提供了如下方法: + +| 方法 | 描述 | +| --------------------- | ------------------ | +| addEmojiconGroup() | 添加自定义表情。 | +| removeEmojiconGroup() | 移除指定的表情组。 | +| setTabBarVisibility() | 设置 `TabBar` 可见性。 | + +添加自定义表情: + +```kotlin +binding?.let { + it.layoutChat.chatInputMenu?.chatEmojiMenu?.addEmojiconGroup(EmojiconExampleGroupData.getData()) +} +``` + + + + diff --git a/docs/uikit/chatuikit/android/chatuikit_contactlist.md b/docs/uikit/chatuikit/android/chatuikit_contactlist.md new file mode 100644 index 000000000..46d7163a7 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_contactlist.md @@ -0,0 +1,152 @@ +# 通讯录 + + + +`EaseContactsListFragment` 用于展示通讯录列表,包括联系人搜索,添加联系人,好友申请列表入口,群组列表入口,联系人列表。 + +昵称在中文或者英文的情况下可以实现按首字母分类。 + +![img](@static/images/uikit/chatuikit/android/page_contact_list.png =400x850) + +## 使用示例 + +```kotlin +class ContactListActivity: AppCompactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_contact_list) + + EaseContactsListFragment.Builder() + .build()?.let { fragment -> + supportFragmentManager.beginTransaction() + .replace(R.id.fl_fragment, fragment).commit() + } + } +} +``` + +## 进阶用法 + +### 通过 EaseContactsListFragment.Builder 自定义设置 + +`EaseContactsListFragment` 提供了 Builder 构建方式,方便开发者进行一些自定义设置。目前提供的设置项如下: + +```kotlin +EaseContactsListFragment.Builder() + .useTitleBar(true) + .setTitleBarTitle("title") + .enableTitleBarPressBack(true) + .setTitleBarBackPressListener(onBackPressListener) + .useSearchBar(false) + .setSearchType(EaseSearchType.USER) + .setListViewType(EaseListViewType.VIEW_TYPE_LIST_CONTACT) + .setSideBarVisible(true) + .setHeaderItemVisible(true) + .setHeaderItemList(mutableListOf()) + .setOnHeaderItemClickListener(OnHeaderItemClickListener) + .setOnUserListItemClickListener(OnUserListItemClickListener) + .setOnItemLongClickListener(onItemLongClickListener) + .setOnContactSelectedListener(OnContactSelectedListener) + .setEmptyLayout(R.layout.layout_conversation_empty) + .setCustomAdapter(customAdapter) + .setCustomFragment(myContactsListFragment) + .build() +``` + +`EaseContactsListFragment#Builder` 提供的方法解释: + +| 方法 | 描述 | +|----------------------------------|-----------------------------------------------------------------------------------------------| +| useTitleBar() | 是否使用默认的标题栏(EaseTitleBar)。
- `true`:是。
- (默认) `false`: 否。 | +| setTitleBarTitle() | 设置标题栏的标题。 | +| enableTitleBarPressBack() | 设置是否支持显示返回按钮,默认为不显示返回按钮。
- `true`:是。
- (默认) `false`: 否。 | +| setTitleBarBackPressListener() | 设置点击标题栏返回按钮的监听器。 | +| useSearchBar() | 设置是否使用搜索栏。
- `true`:是。
- (默认) `false`: 否。 | +| setSearchType() | 设置搜索类型 EaseSearchType。
- `USER`
- `SELECT_USER`
- `CONVERSATION` | +| setListViewType() | 设置列表类型 EaseListViewType。
- `LIST_CONTACT`:默认联系人列表,不带复选框;
- `LIST_SELECT_CONTACT`:带复选框的联系人列表。 | +| setSideBarVisible() | 设置是否显示首字母索引工具栏。
- (默认) `true`:是。
- `false`: 否。 | +| setHeaderItemVisible() | 设置是否显示列表头部布局。 | +| setHeaderItemList() | 设置列表头部 Item 数据对象列表。 | +| setOnHeaderItemClickListener() | 设置列表头部 Item 点击事件。 | +| setOnUserListItemClickListener() | 设置列表条目点击事件。 | +| setOnItemLongClickListener() | 设置条目长按事件监听器。 | +| setOnContactSelectedListener() | 设置条目选中事件监听器。 | +| setEmptyLayout() | 设置会话列表的空白页面。 | +| setCustomAdapter() | 设置自定义的适配器,默认为 `EaseContactListAdapter`。 | +| setCustomFragment() | 设置自定义聊天 Fragment,需要继承自 `EaseContactsListFragment`。 | + +## 自定义联系人列表 + +### 添加自定义联系人布局 + +开发者可以继承 `EaseContactListAdapter` 实现自己的 `CustomContactListAdapter`,然后将 `CustomContactListAdapter` 设置到 `EaseContactsListFragment#Builder#setCustomAdapter` 中。 + +1. 创建自定义适配器 `CustomContactListAdapter`,继承自 `EaseContactListAdapter`,重写 `getViewHolder` 和 `getItemNotEmptyViewType` 方法。 + +```kotlin +class CustomContactListAdapter : EaseContactListAdapter() { + override fun getItemNotEmptyViewType(position: Int): Int { + // 根据消息类型设置自定义 itemViewType。 + // 如果使用默认的 itemViewTyp,返回 super.getItemNotEmptyViewType(position) 即可。 + return CUSTOM_YOUR_CONTACT_TYPE + } + + override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + // 根据返回的 viewType 返回对应的 ViewHolder。 + // 返回自定义的 ViewHolder 或者使用默认的 super.getViewHolder(parent, viewType) + return CUSTOM_YOUR_VIEW_HOLDER() + } +} +``` + +2. 添加 `CustomContactListAdapter` 到 `EaseContactsListFragment#Builder`。 + +```kotlin +builder.setCustomAdapter(CustomContactListAdapter) +``` + +![img](@static/images/uikit/chatuikit/android/group_creating.png =350x600) + +### 设置成可选择的联系人列表 + +例如,创建群组时需添加多个用户,可点击联系人对应的复选框进行选择。 + +```kotlin +builder.setSearchType(EaseSearchType.SELECT_USER) +``` + +![img](@static/images/uikit/chatuikit/android/contactlist_configurable.png =350x600) + +## 事件监听 + +```kotlin +EaseContactsListFragment.Builder() + .setOnHeaderItemClickListener(OnHeaderItemClickListener) + .setOnUserListItemClickListener(OnUserListItemClickListener) + .setOnItemLongClickListener(onItemLongClickListener) + .setOnContactSelectedListener(OnContactSelectedListener) + .build() +``` + +| 方法 | 描述 | +|----------------------------------|-----------------------------------------------------------------------------------------------| +| setOnHeaderItemClickListener() | 设置列表头部 Item 点击事件。 | +| setOnUserListItemClickListener() | 设置列表条目点击事件。 | +| setOnItemLongClickListener() | 设置条目长按事件监听器。 | +| setOnContactSelectedListener() | 设置条目选中事件监听器。 | + + +## 更多 + +### 获取联系人系统通知未读数 + +```kotlin +val systemConversation = EaseNotificationMsgManager.getInstance().getConversation() +systemConversation.let { cv-> + newRequestCount = cv.unreadMsgCount +} +``` + + + + diff --git a/docs/uikit/chatuikit/android/chatuikit_conversation.md b/docs/uikit/chatuikit/android/chatuikit_conversation.md new file mode 100644 index 000000000..478593365 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_conversation.md @@ -0,0 +1,206 @@ +# 会话列表 + + + +`EaseConversationListFragment` 用于展示当前用户的所有会话,包含单聊和群组聊天(不包括聊天室),并且提供会话搜索、删除、置顶和免打扰功能。 + +- 点击搜索按钮,跳转到搜索页面,搜索会话。 +- 点击会话列表项,跳转到会话详情页面。 +- 点击导航栏的扩展按钮,选择新会话,创建新会话。 +- 长按会话列表项显示菜单,可进行删除会话、置顶会话、消息免打扰操作。 + +单条会话展示会话名称、最后一条消息、最后一条消息的时间以及置顶和禁言状态等。 + +- 对于单聊, 会话展示的名称为对端用户的昵称,若对端用户未设置昵称则展示对方的用户 ID;会话头像是对方的头像,如果没有设置则使用默认头像。 +- 对于群聊,会话名称为当前群组的名称,头像为默认头像。 + +会话列表相关功能,详见[功能介绍文档](chatfeature_conversation.html)。 + +![img](@static/images/uikit/chatuikit/android/page_conversation.png =400x840) + +## 使用示例 + +```kotlin +class ConversationListActivity: AppCompactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_conversation_list) + + EaseConversationListFragment.Builder() + .build()?.let { fragment -> + supportFragmentManager.beginTransaction() + .replace(R.id.fl_fragment, fragment).commit() + } + } +} +``` + +## 进阶用法 + +### 通过 EaseConversationListFragment.Builder 自定义设置 + +`EaseConversationListFragment` 提供了 Builder 构建方式,方便开发者进行一些自定义设置,目前提供的设置项如下: + +```kotlin +EaseConversationListFragment.Builder() + .useTitleBar(true) + .setTitleBarTitle("title") + .enableTitleBarPressBack(true) + .setTitleBarBackPressListener(onBackPressListener) + .useSearchBar(false) + .setItemClickListener(onItemClickListener) + .setOnItemLongClickListener(onItemLongClickListener) + .setOnMenuItemClickListener(onMenuItemClickListener) + .setConversationChangeListener(conversationChangeListener) + .setEmptyLayout(R.layout.layout_conversation_empty) + .setCustomAdapter(customAdapter) + .setCustomFragment(myConversationListFragment) + .build() +``` + +`EaseConversationListFragment#Builder` 提供的方法如下表所示: + +| 方法 | 描述 | +| -------------------------------- | ------------------------------------------------------------ | +| useTitleBar() | 是否使用默认的标题栏(`EaseTitleBar`)。
- `true`:是。
- (默认) `false`: 否。 | +| setTitleBarTitle() | 设置标题栏的标题。 | +| enableTitleBarPressBack() | 设置是否支持显示返回按钮,默认为不显示返回按钮。
- `true`:是。
- (默认) `false`: 否。 | +| setTitleBarBackPressListener() | 设置点击标题栏返回按钮的监听器。 | +| setItemClickListener() | 设置条目点击事件监听器。 | +| setOnItemLongClickListener() | 设置条目长按事件监听器。 | +| setOnMenuItemClickListener() | 设置条目菜单点击事件监听器。 | +| setConversationChangeListener() | 设置会话变化的监听器。 | +| setEmptyLayout() | 设置会话列表的空白页面。 | +| setCustomAdapter() | 设置自定义的适配器,默认为 `EaseConversationListAdapter`。 | +| setCustomFragment() | 设置自定义聊天 `Fragment`,需要继承自 `EaseConversationListFragment`。 | + + +### 添加自定义会话布局 + +开发者可以继承 `EaseConversationListAdapter` 实现自己的 `CustomConversationListAdapter`,然后将 `CustomConversationListAdapter` 设置到 `EaseConversationListFragment#Builder#setCustomAdapter` 中。 + +1. 创建自定义适配器 `CustomConversationListAdapter`,继承自 `EaseConversationListAdapter`,重写 `getViewHolder` 和 `getItemNotEmptyViewType` 方法。 + +```kotlin +class CustomConversationListAdapter : EaseConversationListAdapter() { + override fun getItemNotEmptyViewType(position: Int): Int { + // 根据消息类型设置自定义 itemViewType。 + // 如果使用默认的 itemViewTyp,返回 super.getItemNotEmptyViewType(position) 即可。 + return CUSTOM_YOUR_CONVERSATION_TYPE + } + + override fun getViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + // 根据返回的 viewType 返回对应的 ViewHolder。 + // 返回自定义的 ViewHolder 或者使用默认的 super.getViewHolder(parent, viewType) + return CUSTOM_YOUR_VIEW_HOLDER() + } +} +``` + +2. 添加 `CustomConversationListAdapter` 到 `EaseConversationListFragment#Builder`。 + +```kotlin +builder.setCustomAdapter(customConversationListAdapter); +``` + +### 通过继承 EaseConversationListFragment 进行自定义设置 + +创建自定义 `CustomConversationListFragment`,继承自 `EaseConversationListFragment`,并设置到 `EaseConversationListFragment#Builder` 中。 + +```kotlin +builder.setCustomFragment(customConversationListFragment); +``` + +![img](@static/images/uikit/chatuikit/android/conversation_list_custom.png) + +### 设置会话头像和昵称 + +```kotlin +EaseIM.setConversationInfoProvider(object : EaseConversationInfoProvider { + // 同步获取会话信息 + override fun getProfile(id: String?, type: ChatConversationType): EaseProfile? { + return when(type) { + ChatConversationType.Chat ->{ + // 可以从本地数据库或者缓存中获取用户信息,并返回,不可进行异步操作。 + loadUserInfoFromLocal(id) + } + + ChatConversationType.GroupChat -> { + // 可以从本地数据库或者缓存中获取群组信息,并返回,不可进行异步操作。 + loadGroupInfoFromLocal(id) + } + + else -> null + } + return null + } + + override fun fetchProfiles( + idsMap: Map>, + onValueSuccess: OnValueSuccess> + ) { + fetchProfilesFromServer(idsMap, onValueSuccess) + } + +}) +``` + +![img](@static/images/uikit/chatuikit/android/cvs-nick.png =450x800) + +## EaseConversationListFragment 中默认实现的功能 + +### 免打扰 + +使用 `EaseConversationListViewModel` 提供的方法设置免打扰,例如: + +- `makeSilentForConversation`:设置会话免打扰。 +- `cancelSilentForConversation` :取消会话免打扰。 + +### 会话置顶 + +使用 `EaseConversationListViewModel` 提供的方法设置会话置顶,例如: + +- `pinConversation`:置顶一个会话。 +- `unpinConversation`:取消会话置顶。 + +### 会话标记已读 + +使用 `EaseConversationListViewModel` 提供的 `makeConversionRead` 方法标记会话已读。 + +### 会话删除 + +使用 `EaseConversationListViewModel` 提供的方法 `deleteConversation` 方法删除会话。 + +![img](@static/images/uikit/chatuikit/android/cvs-action.png =350x600) + +## 事件监听 + +`EaseConversationListFragment#Builder` 提供的如下监听: + +```kotlin +EaseConversationListFragment.Builder() + .setTitleBarBackPressListener() + .setItemClickListener(onItemClickListener) + .setOnItemLongClickListener(onItemLongClickListener) + .setOnMenuItemClickListener(onMenuItemClickListener) + .setConversationChangeListener(conversationChangeListener) + .build() +``` + +| 方法 | 描述 | +| -------------------------------- | ------------------------------------------------------------| +| setTitleBarBackPressListener() | 设置点击标题栏返回按钮的监听器。 | +| setItemClickListener() | 设置条目点击事件监听器。 | +| setOnItemLongClickListener() | 设置条目长按事件监听器。 | +| setOnMenuItemClickListener() | 设置条目菜单点击事件监听器。 | +| setConversationChangeListener() | 设置会话变化的监听器。 | + + + + + + + + + + diff --git a/docs/uikit/chatuikit/android/chatuikit_design_guide.md b/docs/uikit/chatuikit/android/chatuikit_design_guide.md new file mode 100644 index 000000000..8b71e8594 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_design_guide.md @@ -0,0 +1,668 @@ +# 移动端单/群聊人机交互界面工具包设计指南 + +![img](@static/images/uikit/chatuikit/design/CUIcover2.png) + +## 0.总的设计原则 + +### 0.1.功能与行为上确保通用、普遍、一般 + +### 0.2.风格上易于自定义 + +### 0.3.在业务形态上尽量不替用户做决定 + +## 1.全局样式(Style) + +### 1.1.UIkit 色彩规范 + +#### 1.1.1.颜色配置说明: + +##### 1.1.1.1.颜色类(Color Class) + +一般颜色类分为八类: +主题色(Theme Color):Primary、 Secondary、Error 三类; +渐变主题色(Primary Gradient)一类(含 8 种); +透明色(Alpha Color):On Light、On Dark 两类; +中性色(Neutral Colors):Neutral、Neutral Special 两类; + +##### 1.1.1.2.颜色模式(Hsla Model) + +颜色模式为比较直观的 hsla 模式: +整个模型是一个圆柱体,圆柱体底面周长划分为 360°,对应不同的色相(Hue); +圆柱体的半径为饱和度(Saturation),圆心为 0(最灰),半径值为 100(最艳); +圆柱体的高为亮度(Lightness),起始点为 0(纯黑色),中心点是 50(标准色,),结束点为 100(纯白色)。 + +##### 1.1.1.3.模型概览: + +![img](@static/images/uikit/chatroomdesign/cruk1113.png) + +#### 1.1.2.三种主题色(Theme Color)的色彩规范: + +##### 1.1.2.1.关于用户可配项(Hue value): + +用户可设定颜色类的可配项 Hue(0-360)为任意数值,修改后每类颜色的色相会发生变化,以贴合用户场景所需要的主题颜色。 +Hue 值(0-360)与色相的对应关系大致如以下图示所例: + +![img](@static/images/uikit/chatroomdesign/cruk11211.png) + +用户可依据自身产品的品牌色指定色相数值(Hue),从而确认主题色 Primary(主要用于 UI 组件中关键操作与重要文本展示,如推荐的 action、高亮显示的文本等),以及用于积极提示的 Secondary,和表示警示提示的 Error。 + +![img](@static/images/uikit/chatroomdesign/cruk11212.png) + +##### 1.1.2.2.关于饱和度(Saturation value): + +饱和度(Saturation)不开放给用户设置,三种主题色 Primary、 Secondary、Error 默认饱和度为 100%,Neutral 默认为 8%,Neutral Special 默认为 36% + +![img](@static/images/uikit/chatroomdesign/cruk1122.png) + +##### 1.1.2.3.关于亮度级别(Lightness level): + +亮度(Lightness)百分比用户不可随意设置,每个颜色类提供:0(0%) / 1(10%) / 2(20%) / 3(30%) / 4(40%) / 5(50%) / 6(60%) / 7(70%) / 8(80%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)十三个级别供用户可选; + +![img](@static/images/uikit/chatroomdesign/cruk1123.png) + +##### 1.1.2.4.举个例子吧: + +如指定主题色 Primary 色相(Hue)为 203,成功色 Secondary 色相(Hue)为 155,警示色 Error 色相(Hue)为 350,则会生成如下 39 种主题色可供用户在指定 UI 件块(View)颜色时使用: + +![img](@static/images/uikit/chatroomdesign/cruk1124.png) + +其中,主题色 Primary 的 L5 为亮色模式下的基色(Key Color),L6 为暗色模式下的基色(Key Color)。所有的颜色体系都是依照基色生成。 + +#### 1.1.3.关于渐变主题色(Primary Gradient)的规范: + +渐变主题色是由 Primary 色派生出的渐变色,为线性渐变(Linear Gradient),渐变方向依图示坐标系分为 8 类: + +![img](@static/images/uikit/chatroomdesign/cruk113.png) + +##### 1.1.3.1.关于渐变色的起始色(Start Color): + +渐变色中 Start Color 规则和 Primary 类的色值保持一致; + +![img](@static/images/uikit/chatroomdesign/cruk1131.png) + +##### 1.1.3.2.关于渐变色的结束色(End Color): + +End Color 用户可配置色相(Hue),亮度以 0(20%) / 1(30%) / 2(40%) / 3(50%) / 4(60%) / 5(70%) / 6(75%) / 7(80%) / 8(85%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)(对应 Primary 的 13 级亮度梯度值)为固定梯度值 + +以下以 Hue:233 为例,按照 End Color 颜色公式依旧得到 13 级颜色: + +![img](@static/images/uikit/chatroomdesign/cruk11321.png) + +起始色和结束色结合,得到相应的渐变结果 + +![img](@static/images/uikit/chatroomdesign/cruk11322.png) + +##### 1.1.3.3.关于渐变主题色可配项(End Color Hue Value): + +用户仅可配置渐变色中 End Color 的色相(Hue)以达成与用户业务场景符合的渐变颜色效果; + +##### 1.1.3.4.举个例子吧: + +用户设置 End Color Hue = 233,选择渐变方向为“↓”,则可得到如下效果: + +![img](@static/images/uikit/chatroomdesign/cruk11341.png) + +如使用渐变主题色,那么它将替代掉所有应用于背景色的 Primary 色 + +![img](@static/images/uikit/chatroomdesign/cruk11342.png) + +但一般不替代 UI 件块的前景色,因为没有什么意义,且有干扰文字阅读的可能性 + +![img](@static/images/uikit/chatroomdesign/cruk11343.png) + +#### 1.1.4.关于透明色(Alpha)的规范: + +##### 1.1.4.1.透明色(Alpha Color): + +在本案内带有透明度的组件仅有模态背景色、轻提示背景色,应用范围有限,单独定义两个特殊的颜色类用于以上四种组件:Alpha onlight(hsl0, 0%, 0%) 和 Alpha ondark(hsl0, 0%, 100%),Alpha 值被指定为 0(0.0) / 1(0.1) / 2(0.2) / 3(0.3) / 4(0.4) / 5(0.5) / 6(0.6) / 7(0.7) / 8(0.8) / 9(0.9) / 95(0.95) / 98(0.98) / 100(1.0) 十三个梯度值,共 26 种颜色用例,以调整组件的背景色透明度。 + +![img](@static/images/uikit/chatroomdesign/cruk1141.png) + +Alpha onlight 和 Alpha ondark 均为默认值,无任何可配置项。 + +### 1.1.5.关于中性色(Neutral Colors): + +#### 1.1.5.1.中性色(Neutral) + +中性色(Neutral)仅有一个可配项:色相(Hue),饱和度(Saturation)固定值为 8,亮度级别(Lightness level)也和主题色相同,分为 0(0%) / 1(10%) / 2(20%) / 3(30%) / 4(40%) / 5(50%) / 6(60%) / 7(70%) / 8(80%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)十三个级别供用户可选; + +![img](@static/images/uikit/chatroomdesign/cruk1151.png) + +Neutral 和 Primary 的默认 Hue 值(色相)相同,也建议用户设置和主题色相同的 Hue 值已达成主题颜色和无彩色系的配套。但这仅仅是建议; + +#### 1.1.5.2.举个例子吧: + +如指定主题色 Primary 色相(Hue)为 203,饱和度(Saturation)固定值为 100%,中性色(Neutral)则也指定色相(Hue)为 203,饱和度(Saturation)固定值为 8%,则得到以下色列可供用户选择使用: + +![img](@static/images/uikit/chatroomdesign/cruk11521.png) + +其中,L98 为亮色模式下背景色的主色,L1 为亮色模式下前景色的主色;L1 为暗色模式下背景色的主色,L98 为暗色模式下前景色的主色。 + +![img](@static/images/uikit/chatroomdesign/cruk11522.png) + +### 1.1.6.关于特殊中性色(Neutral Special): + +特殊中性色 Neutral Special 主要用于级别低于 Primary 和 Secondary 的强调信息,如当前页面状态、消息发送者的昵称等。 +Neutral Special 和 Primary 的默认 Hue 值(色相)类似,为近似色,也建议用户设置和主题色近似的 Hue 值已达成主题色和无彩色系的配套。但这仅仅是建议; + +![img](@static/images/uikit/chatroomdesign/cruk116a.png) + +![img](@static/images/uikit/chatroomdesign/cruk116b.png) + +#### 1.1.6.1.举个例子吧: + +如指定主题色 Primary 色相(Hue)为 203,特殊中性色(Neutral)通过相似色原理(正负 30 度内)指定色相(Hue)为 220,饱和度(Saturation)固定值为 36%,则得到以下色列可供用户选择使用: + +![img](@static/images/uikit/chatroomdesign/cruk1161.png) + +## 1.2.主题 + +本期主题分为 2 种,每种分明亮(Light mode)和黑暗(Dark)两类。 + +### 1.2.1.圆润主题 + +组件一般采用较大的圆角,柔和轻盈 + +![image text](@static/images/uikit/chatuikit/design/1.2.1.png) + +### 1.2.2.硬朗主题 + +组件一般避免比较大的圆角,硬朗实在 + +![image text](@static/images/uikit/chatuikit/design/1.2.2.png) + +以上两种主题可通过应用渐变主题色(Primary Gradient)得到两外两种渐变色主题。 +至于业务相关的主题,如“社交”、“游戏”、“教育”、“商务”等主题分类,因违反本案的最基本设计原则“在业务形态上尽量不替用户做决定”,所以不在本期考虑范围内。 + +## 1.3.图标(Icon) + +### 1.3.1.图标模板(Template) + +图标参照 Material Icon Font 的模板 ,以 24 为基本栅格,须在安全区域(20x20 的中心区域)内绘制,基本描边控制为 1.5 栅格。 + +![img](@static/images/uikit/chatroomdesign/cruk131.png) + +### 1.3.2 图标命名(Name) + +为防止将图标语意固定,icon 命名需要尽力避免定义操作行为,而是以“看见什么就是什么“进行命名,方便相同图标在不同操作行为下的复用。 +如 + +![img](@static/images/uikit/chatroomdesign/cruk132.png) + +## 1.4.字体(Typography) + +### 1.4.1.字族(Font Family) + +#### 1.4.1.1.iOS 字族 + +默认 SF Pro 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 SF Arabic、SF Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认苹方(PingFang SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +#### 1.4.1.2.Android 字族 + +默认 Roboto 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 Noto Sans Arabic、Noto Sans Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认思源黑体(Noto Sans SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +#### 1.4.1.3.Web 字族 + +默认 Roboto 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 Noto Sans Arabic、Noto Sans Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认思源黑体(Noto Sans SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +### 1.4.2.字号(Font Size) + +#### 1.4.2.1.最小字号 + +移动端最小字号为:11;web 端最小字号为:12 + +#### 1.4.2.2.字号规则 + +除移动端最小字号外,字号以 2 为梯度递增: +11,12,14,16,18,20 + +### 1.4.3.字重(Font Weight) + +字重分为标准(Regular, 400)、中等(Medium,510)、加粗(semibold,590)三种; +在一些跨平台框架中,如遇不支持设置非百位整数字重,则取近似值百位整数; +如字族没有 semibold,则以 bold 替换。 + +### 1.4.4.行高(Line height) + +行高依照以下固定值(字号/行高): +11/14,12/16,14/20,16/22,18/26,20/28。 + +### 1.4.5.字体角色(Font Role) + +字体角色分为 3 类: +大标题 Headline、标题 Title、标签 Label、正文 Body +需要注意的是,这些角色只是推荐的角色指示,并不具有完全的指定性,具体使用什么角色的字体需依照所使用的组件的实际情况(组件内信息的层级重要性,越重要的越大越重)而使用。 + +### 1.4.6.字体 Token + +依照依照 4.1-4.5 规则,设定以下西文字体排版 token, + + + +简体中文字体 token 示意 + + + +## 1.5.效果(Effects) + +所应用的效果主要分为两种:背景模糊(Background Blur)和阴影(Shadow) + +### 1.5.1.背景模糊(Background Blur) + +背景模糊主要应用于组件背景色使用 Alpha color 时,如组件背景色的透明度会造成组件前后层级干扰的话,则推荐使用背景模糊解决, +也应用于模态显示的弹出层的背景虚化; + +背景模糊的模糊半径值默认为 20 + +``` +/* bg_blur_modal */ backdrop-filter: blur(20); +``` + +### 1.5.2.阴影(Shadow) + +阴影应用于弹窗(Alert)、浮层(pop)、抽屉(Drawer)等,为区分层级,凸显聚焦的组件。 + +#### 1.5.2.1.阴影型号(Size) + +阴影分为小(small)、中(medium)、大(Large)三种型号,应用于不同尺寸的组件中,总体原则为:越小的组件越推荐使用小的阴影、反之越大的组件推荐使用大的阴影;圆角越小的组件越推荐使用小的阴影、反之亦然。 + +#### 1.5.2.2.阴影 token + +为保证阴影效果自然柔和,每个阴影都有两层不同偏移、不同模糊度、不同透明度的值。同时针对亮色/暗色模式有两套不同颜色的阴影。 + +**Shadow on Light:** + +``` +/* shadow/onlight/large */ +box-shadow: x0 y24 blur36 color(Neutral3) Alpha0.15, x8 y0 blur24 color(Neutral1) Alpha0.1 + +/* shadow/onlight/medium */ +box-shadow: x0 y4 blur4 color(Neutral3) Alpha0.15, x2 y0 blur8 color(Neutral1) Alpha0.1 + +/* shadow/onlight/small */ +box-shadow: x0 y1 blur3 color(Neutral3) Alpha0.15, x1 y0 blur2 color(Neutral1) Alpha0.1 +``` + +![img](@static/images/uikit/chatroomdesign/cruk1522a.png) + +**Shadow on Dark:** + +``` +/* shadow/onlight/large */ +box-shadow: x0 y24 blur36 color(Neutral4) Alpha0.15, x8 y0 blur24 color(Neutral1) Alpha0.1 + +/* shadow/onlight/medium */ +box-shadow: x0 y4 blur4 color(Neutral4) Alpha0.15, x2 y0 blur8 color(Neutral1) Alpha0.1 + +/* shadow/onlight/small */ +box-shadow: x0 y1 blur3 color(Neutral4) Alpha0.15, x1 y0 blur2 color(Neutral1) Alpha0.1 +``` + +![img](@static/images/uikit/chatroomdesign/cruk1522b.png) + +## 1.6.圆角(Radius) + +### 1.6.1.一般圆角 + +一般圆角分为 None(r=0)、Extra Small(r=4)、Small(r=8)、Medium(r=12)、Large(r=16)、Extra Large(r=½ Height)六个枚举值, +一般情况下组件的四个圆角为同一值 + +![img](@static/images/uikit/chatroomdesign/cruk161.png) + +#### 1.6.1.1.Extra Small(r=4) + +通常适用于如下组件 +Button(Small Radius) +Input(Small Radius) +Float(Small Radius) +Message Bubble(Small Radius) +Avatar(Small Radius) +Popover +Global Broadcast(Small Radius) + +#### 1.6.1.2.Small(r=8) + +通常适用于如下组件 +Alert(Small Radius) +Drawer(Small Radius) + +#### 1.6.1.3.Medium(r=12) + +通常适用于如下组件 +本案暂不涉及 + +#### 1.6.1.4.Large(r=16) + +通常适用于如下组件 +Input Area(Large Radius) +Alert(Large Radius) +Drawer(Large Radius) +Float(Large Radius) + +#### 1.6.1.5. Extra Large(r=½ Height) + +通常适用于如下组件 +Input Area(Large Radius) +Alert(Large Radius) +Drawer(Large Radius) +Message Bubble(Large Radius) + +### 1.6.2.特殊圆角 + +特殊圆角应用于有背景色的 IM 聊天消息组件: +Message Bubble(Large Radius) + + + +## 2.小控件(Widgets) +小控件为最基础的视觉交互模块。 + +### 2.1.按钮(Bottom) +按钮组件分为普通按钮、文本按钮、图标按钮三种,每种包含的状态有 Enabled、Hovered(限 web 端) 、Pressed、Loading、Pressed 五种状态,同时分为大、中、小三种按钮尺寸以贴合不同容器的使用。 + +### 2.1.1.普通按钮(Normal) + +普通按钮分主要操作(Primary)和次要操作(Secondary)两种类型。 + +#### 2.1.1.1.主要操作(Primary) + +主要操作用于推荐行为,一般背景色为主题色(Primary5\Primary6)或者渐变主题色,被禁用时置灰显示,圆角可配,依据需要可增加左侧或右侧 icon + +![img](@static/images/uikit/chatroomdesign/cruk2111.png) + +#### 2.1.1.2.次要操作(Secondary) + +次要操作用于辅助主要操作,一般不单独出现,一般背景色为亮色(Neutral98)或者暗色(Neutral1),同时有描边,被禁用时置灰显示,圆角可配 +依据需要可增加左侧或右侧 icon + +![img](@static/images/uikit/chatroomdesign/cruk2112.png) + +### 2.1.2.文字按钮(Text) + +文字按钮仅有前景色,也分为主要操作和次要操作,一般用于更频繁的常规操作(如表单填写的下一步、取消,消息的显示、隐藏等)或者在页面有普通按钮(主要操作)时作为更次一级操作出现 + +![img](@static/images/uikit/chatroomdesign/cruk212.png) + +### 2.1.3.图标按钮(Icon) + +图标按钮为组件位置局促又必须出现按钮时的补充形式,如输入条的键盘切换、顶部条的更多操作、表单填写时的推荐操作、输入框的清空和下拉操作等。 + +![img](@static/images/uikit/chatroomdesign/cruk213.png) + +需要注意的是,在 web 端,如非特殊说明,图标按钮必须搭配 Popover 使用,以交代清楚按钮的具体操作行为。如: + +![img](@static/images/uikit/chatroomdesign/cruk213b.png) + +### 2.2.输入框(Input) + +输入框为需要输入较少文字时使用的组件。 +也按照所放组件的大小分为大中小三种尺寸可配项,样式上,背景色和描边颜色可开关,圆角可配,状态上分为失焦未填写、失焦填写、聚焦未填写、聚焦填写、禁用填写、禁用未填写六种。 + + + +### 2.3.输入区域(InputArea) + +输入框为需要输入较多文字时使用的组件。 +在用于输入器的文本输入,和表单中、发布内容时需要填写较多文本时使用,样式上,背景色和描边颜色可开关,圆角可配,可显示最大输入字符数分数。状态上分为失焦未填写、失焦填写、聚焦未填写、聚焦填写、禁用填写、禁用未填写六种。 + + + +### 2.4.单选器和多选器(Checkboxes n' Radios) +单选器和多选器允许终端用户在列表中选择一项或者多项。分为选中、未选中、选中禁用、未选中禁用四种状态。 + + +### 2.5.开关(Switch) +开关为终端用户对列表项打开和关闭的直观操作。 +分为关闭、打开、关闭禁用、打开禁用四中状态。 +此操作一般需要避免自动化开启和关闭,必须终端用户主动操作。 + +样式采用iOS或Material 默认样式,开启颜色对应Primary5/Primary6的KeyColor色值。 + + +### 2.6.滑块(Slider) +滑块用于终端用户精确设置数值。 +可配项有:两侧图标或单侧数值,状态上分为禁用和可用。 + +### 2.7.浮层菜单(PopMenu) +浮层菜单为非常住的的选项或列表的展示。支持配置操作项有无左侧icon + +### 2.8.头像(Avatar) +头像是一类信息数据展示的控件,如用户、某个操作项的头像展示,常放置于个人信息页、与用户相关的列表项中 +头像圆角有两个枚举值:Extra Small(r=4)、Extra Large(r=½ Height)以配合不同主题的使用 +头像的尺寸可以依据所属组件的大小自由配置,但需要注意的是,头像的比例永远是 1:1 + +### 2.8.1.图片头像 + +能读取用户头像信息时展示图片头像。 + +![img](@static/images/uikit/chatroomdesign/cruk241.png) + +### 2.8.2.字符头像 + +用户未上传头像时显示字符头像,字符头像分为单字符和双字符两种 + +![img](@static/images/uikit/chatroomdesign/cruk242.png) + +### 2.8.3.组合头像 + +组合头像用于用户未上传数据时的群组聊天自动生成头像 +本案不涉及 + +![img](@static/images/uikit/chatroomdesign/cruk243.png) + +### 2.8.4.图标头像 + +图标头像用于获取不到用户头像信息的空状态以及表单单项有 icon 时的头像。 + +![img](@static/images/uikit/chatroomdesign/cruk244.png) + +### 2.8.5.头像徽章 + +头像可配置徽章(Badge)以体现用户的在离线等状态,徽章位置分两种:右下和右上 + + + +### 2.9.徽章(Badge) +徽章用于导航项、列表项、头像处,用于显示状态、通知和计数。 +配置项有:计数的有无、标准和小、icon的有无。 +(配图) + +### 2.10.表情符号(Emojis) + +### 2.10.1.Twemoji [↗](https://github.com/twitter/twemoji) + +表情使用开源可免费商用的 Twemoji 作为基本表情,默认提供 52 个表情作为内置的表情,用户可根据自己的产品规划从 twemoji 提供的 3,245 个表情中进行替换增减; + +![img](@static/images/uikit/chatroomdesign/cruk291.png) +### 2.10.2.表情模版(Emoji Template) + +如用户需替换 Twemoji,或者需要自己创作表情,需依照以下模板进行替换或绘制; + +![img](@static/images/uikit/chatroomdesign/cruk292.png) + +### 2.10.3.表情组件状态(State) + +表情组件的状态分为以下 4 种: +启用 Enabled、悬停 Hovered(仅限 web 端)、按下 Pressed、聚焦 Focused(本案不涉及) +悬停时,背景色递增一级;按下时,背景色递减一级;聚焦时,背景色转换为 Key Color。 + +![img](@static/images/uikit/chatroomdesign/cruk293.png) + +### 2.11.轻提示(Toast) +请提示为针对终端用户当前操作的简单反馈。 +分为有图标、无图标两类。 + +### 2.12.模态背景(Model) +模态为临时的弹出的关键信息,需要用户主动操作来退出。 +模态背需配合弹窗(Alert)使用。颜色可配置为任意AlphaColor,也可设置背景模糊效果。 +(配图) + +### 2.13.索引(Index) +索引应用于联系人页面通过分类迅速查找联系人。 + +#### 2.13.1.目录索引(SectionIndex) +目录索引位于联系人或成员列表最右侧,为快速通过字母定位到相关联系人的滚动条。 + +#### 2.13.2.列表索引(IndexInList) +列表内的索引用于不同字母分类的联系人的分割。可以配置是否有底部分割线。 + +### 2.14.底部标签栏(BottomTabs) +底部导航栏应用于移动设备上不同视图(View)的切换,最少两个切换项,超过5个项时分页展示。 + +### 2.15.顶部标签栏(TopTabs) +顶部部导航栏应用于移动设备上不同视图(View)的切换,最少一个项,超过5个项时分页展示。 + +## 3.控件(Components) + +### 3.1.顶部条(TopBar) +顶部条用于展示当前视图标题,并可对当前页面进行整体的控制。 +左侧支持配置返回操作、支持有/无头像、支持有/无小标题,右侧支持 1 至 3 个action。 + +### 3.2.搜索条(SearchBar) +搜索条用于搜索当前页面的项。 +可配项有左侧返回icon、是否显示取消按钮。 + +### 3.3.底部条(BottomBars) + +#### 3.3.1.底部操作条(navigation_bar) +底部操作条用于针对当前视图的操作,最少支持一项,最多支持三项,操作按钮支持配置为文本按钮或图标按钮。 + +#### 3.3.2.输入条(InputBar) + +输入条为会话详情页文本等消息的发布器。 +可配置左侧actionbtn、右侧Action1、Action2、Action3、sendbtn +样式上支持配置顶部分割线、输入框圆角样式、sendbtn可配置为文本按钮或者图标按钮。 + +#### 3.3.3.录音浮层(RecordingModel) +录音浮层为录制和发送语音消息的控件。 + +### 3.4.表情盘(EmojisPick) + +表情键盘是发送 app 内自建表情的键盘,内容上支持表情个数的增减,底部发送和退格按钮支持修改圆角。同时应满足接入第三方表情/贴纸库。 + +![img](@static/images/uikit/chatroomdesign/cruk34.png) + +本键盘不同于系统自带的 emoji 输入键盘,通过此组件输入的 emoji 不会同步为系统的 emoji,而是在任何平台同一 app 内均显示 app 内自建的表情符号。为满足版权方面的法律要求,请勿使用非申明开源可免费商用的表情符号(不限资源图或者源码)在 App 中(如:集成苹果表情符号在自己的 app 内,这样或许会导致 App 无法上架苹果应用商店) + +### 3.5.列表项(ListItem) + +#### 3.5.1.表单列表项(FromItem) +表单列表项应用再联系人/群组详情页面/App设置页面的表单中, +支持点击事件、右侧可配置按钮、数据展示、开关、滑动条、单/多选器等功能,左侧可配置单/多选器。 +信息展示上可配置左侧头像、subtitle、列表项的分类标题(Headline)和注解(postil) + +#### 3.5.2.会话列表项(ConversationItem) +会话列表项为会话详情的入口,可展示的信息有:联系人头像(Avatar)、联系人昵称(Title)、最新消息(Subtitle)、新消息通知(Badge)、新消息时间戳(Time)。 +样式上支持头像配置大/小圆角、是否配置列表项的分割线。 + +#### 3.5.3.联系人列表项(ContactsItem) +联系人列表项为联系人详情的入口,可展示的信息有:联系人头像(Avatar)、联系人昵称(Title)、联系人状态(Subtitle)。 +样式上支持头像配置大/小圆角、是否配置列表项的分割线。 + +### 3.6.弹窗(Alert) +弹窗通知是一类模态提示,会提示用户正在进行的操作所需的关键信息,如警告等,或需要用户填写关键信息(通过输入框),需用户做出主要操作或次要操作。 +内容上,description 可配、输入框可配、操作项支持最多三个。 +样式上,弹窗的圆角可配,需要注意的是,组件内部的输入框和操作按钮圆角需要同弹窗按钮的圆角适配,以达成风格的一致性。 + +![img](@static/images/uikit/chatroomdesign/cruk27.png) + +### 3.7.操作面板(ActionSheet) +操作表单是以模态形式展示的多操作项表单,单个操作项分为 Enabled、Pressed、Disabled、Destructive 四种状态,以及 Cancel 特殊类型。同时可配置是否显示 icon、是否有分割线(stroke) +此组件仅限移动端 + + + + +## 4.消息气泡(MessageBubble) + +### 4.1.文本消息(TextsMsg) +文本消息为发送字符和emoji表情时使用的气泡样式。 + +### 4.2.语音消息(AudioMsg) +文本消息为发送语音时使用的气泡样式。 +气泡宽度会随着语音消息的时长而改变宽度。支持点击后播放。播放中有动画显示。 + +### 4.3.文件消息(FileMsg) +文件消息为发送文件时候展示的气泡样式。 +支持显示的字段有:文件图标、文件名(Title)、文件大小(Subtitle) + +### 4.4.联系人消息(ContactMsg) +联系人消息为一种展示联系人的气泡样式,支持点击事件, +支持显示的字段有:联系人头像、联系人昵称(Title) + +### 4.5.缩略图消息(ImgMsg) +缩略图消息为发送图片和视频消息时的消息气泡。 +展示规则: + + +### 4.6.顶部附加消息(DescantMsg) +顶部附加消息为本消息的附属信息的展示,如:消息的回复(Reply) +支持点击事件 + +### 4.7.底部附加消息(OrganumMsg) +*本期不涉及* + +### 4.8.消息的长按操作列表(MsgActionSheet) +支持对当前消息进行复制、编辑、撤回、回复等的操作。 + +## 5.模块视图(Module View) + +### 5.1.会话视图(ConversationView) + +#### 5.1.1.会话列表(ConversationList) +会话视图为会话搜索、会话列表项组合而成的页面。 + +#### 5.1.2.新会话(NewMsg) +通过会话右上角action调取的操作列表,可以此发起会话、创建群、添加联系人。 +##### 5.1.2.1. 发起会话(StartConversation) +点击此项将调取联系人列表,终端用户可点选或者搜索联系人,点击后将进入会话详情页面,用户可以通过发送消息发起会话。 +##### 5.1.2.2. 创建群组(CreateGroup) +点击此项将调取多选状态的联系人列表,终端用户在此页面点选群组成员,当群成员≥2(包含群主和群成员)时,用户可以点击创建进入群组会话详情页面,以创建一个群组。 +##### 5.1.2.3. 添加联系人(Addcontact) +点击此项将大家添加联系人弹窗,终端用户输入要添加的联系人ID后发送添加信息。 + +### 5.2.联系人视图(ContactsView) +联系人视图是联系人搜索、联系人列表项组合而成的页面。 + +#### 5.2.2.新申请列表(NewRequest) +如用户收到添加联系人的申请,将在此展示相关信息。用户可以通过添加操作处理联系人添加请求。 + +#### 5.2.3.群组列表(GroupList) +将在此展示用户加入的所有群。用户可以通过添加操作处理联系人添加请求。 + +### 5.3.会话详情视图(ConversationDetailView) +会话详情为群聊或者群组聊天的详情页面 +页面分为header(展示会话title信息),body(消息气泡列表),footer(消息发送三部分) + +#### 5.3.1.会话的顶部导航栏(header) +顶部导航栏承接两项主要功能: + +1)会话关键信息的展示:联系人/群的头像、联系人昵称/群名称、联系人的在/离线状态等 + +2)关于相关会话的操作:退出会话、查看联系人/群详情、针对当前会话的 1-3 个操作 + +#### 5.3.2.消息气泡列表(body) +会话内成员所发送的消息将以时间的先后顺序在此视图内进行由上到下的排列。 + +#### 5.3.3.消息的发送(footer) +用于发送文本、语音、附件、自定义消息。 + +### 5.4.联系人详情视图(ContactDetailView) +联系人详情为联系人详情展示的页面,主要展示联系人头像、昵称、ID等联系人信息; +支持在本页面操作联系人免打扰、联系人删除操作; +支持在本页面进入消息详情等入口; + +### 5.5.群组详情视图(GroupDetailView) +群组详情为群组详情展示的页面,主要展示群组头像、群组名称、群ID等群组信息; +支持在本页面操作群组免打扰、退出群组等操作; +管理员(Owner和Admins)支持修改群信息(群名称、群详情等),支持群主(Owner)转让群主身份和解散群组; +支持在本页面进入消息详情等入口; + +## 6.设计资源(Design Resources) +设计资源详见 [figma 链接](https://www.figma.com/community/file/1327193019424263350/chat-uikit-for-mobile)。 diff --git a/docs/uikit/chatuikit/android/chatuikit_integrated.md b/docs/uikit/chatuikit/android/chatuikit_integrated.md new file mode 100644 index 000000000..7612b3020 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_integrated.md @@ -0,0 +1,163 @@ +# 集成单群聊 UIKit + + + +使用单群聊 UIKit 之前,你需要将其集成到你的应用中。 + +## 前提条件 + +- Android Studio 4.0 及以上 +- Gradle 4.10.x 及以上 +- targetVersion 26 及以上 +- Android SDK API 21 及以上 +- JDK 11 及以上 + +## 集成单群聊 UIKit + +单群聊 UIKit 支持 Gradle 接入和 Module 源码集成。 + +### Gradle 接入集成 + +#### Gradle 7.0 之前 + +在项目根目录的 `build.gradle` 或者 `build.gradle.kts` 文件中添加 MavenCentral 远程仓库。 + +```kotlin +buildscript { + repositories { + ... + mavenCentral() + } +} +allprojects { + repositories { + ... + mavenCentral() + } +} +``` + +#### Gradle 7.0 及以上版本 + +在项目根目录的 `settings.gradle` 或者 `settings.gradle.kts` 文件中检查并添加 MavenCentral 远程仓库。 + +```kotlin +pluginManagement { + repositories { + ... + mavenCentral() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + ... + mavenCentral() + } +} +``` + +### Module 源码集成 + +从 GitHub 获取[单群聊 UIKit](https://github.com/easemob/chatuikit-android) 源码,按照下面的方式集成: + +1. 在根目录 `settings.gradle.kts` 文件(/Gradle Scripts/settings.gradle.kts)中添加如下代码: + +```kotlin +include(":ease-im-kit") +project(":ease-im-kit").projectDir = File("../chatuikit-android/ease-im-kit") +``` + +2. 在 app 的 `build.gradle.kts` 文件(/Gradle Scripts/build.gradle)中添加如下代码: + +```kotlin +//chatuikit-android +implementation(project(mapOf("path" to ":ease-im-kit"))) +``` + +### 防止代码混淆 + +在 `app/proguard-rules.pro` 文件中添加如下行,防止代码混淆: + +```kotlin +-keep class com.hyphenate.** {*;} +-dontwarn com.hyphenate.** +``` + +## 快速搭建页面 + +### 创建聊天页面 + +- 使用 `EaseChatActivity` + +单群聊 UIKit 提供 `EaseChatActivity` 页面,调用 `EaseChatActivity#actionStart` 方法即可,示例代码如下: + +```kotlin +// conversationId: 单聊会话为对端用户 ID,群聊会话为群组 ID。 +// chatType:单聊为 EaseChatType#SINGLE_CHAT,群聊为 EaseChatType#GROUP_CHAT。 +EaseChatActivity.actionStart(mContext, conversationId, chatType) +``` +`EaseChatActivity` 页面主要进行权限的请求,比如相机权限,语音权限等。 + +- 使用 `EaseChatFragment` + +开发者也可以使用单群聊 UIKit 提供的 `EaseChatFragment` 创建聊天页面,示例代码如下: + +```kotlin +class ChatActivity: AppCompactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_chat) + // conversationID: 1v1 is peer's userID, group chat is groupID + // chatType can be EaseChatType#SINGLE_CHAT, EaseChatType#GROUP_CHAT + EaseChatFragment.Builder(conversationId, chatType) + .build()?.let { fragment -> + supportFragmentManager.beginTransaction() + .replace(R.id.fl_fragment, fragment).commit() + } + } +} +``` + +### 创建会话列表页面 + +单群聊 UIKit 提供 `EaseConversationListFragment`,添加到 Activity 中即可使用。 + +示例如下: + +```kotlin +class ConversationListActivity: AppCompactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_conversation_list) + + EaseConversationListFragment.Builder() + .build()?.let { fragment -> + supportFragmentManager.beginTransaction() + .replace(R.id.fl_fragment, fragment).commit() + } + } +} +``` + +### 创建联系人列表页面 + +单群聊 UIKit 提供 `EaseContactsListFragment`,添加到 Activity 中即可使用。 + +示例如下: + +```kotlin +class ContactListActivity: AppCompactActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_contact_list) + + EaseContactsListFragment.Builder() + .build()?.let { fragment -> + supportFragmentManager.beginTransaction() + .replace(R.id.fl_fragment, fragment).commit() + } + } +} +``` + diff --git a/docs/uikit/chatuikit/android/chatuikit_overview.md b/docs/uikit/chatuikit/android/chatuikit_overview.md new file mode 100644 index 000000000..4a67af36f --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_overview.md @@ -0,0 +1,61 @@ +# 概述 + + + +环信单群聊 UIKit 是基于环信即时通讯云 IM SDK 开发的一款即时通讯 UI 组件库,提供各种组件实现会话列表、聊天界面、联系人列表及后续界面等功能,帮助开发者根据实际业务需求快速搭建包含 UI 界面的即时通讯应用。 + +若要访问源码,请点击[这里](https://github.com/easemob/chatuikit-android)。 + +## UIKit 基本项目结构 + +``` +└── easeui + ├── EaseIM // UIKit SDK 入口 + ├── EaseIMConfig // UIKit SDK 配置类 + ├── feature // UIKit 功能模块 + │ ├── chat // 聊天功能模块 + │ │ ├── activities // 聊天功能模块的 Activity 文件夹 + │ │ │ └── EaseChatActivity // UIKit 内置的聊天界面 + │ │ ├── adapter // 聊天功能模块的适配器文件夹 + │ │ │ └── EaseMessagesAdapter // 聊天功能模块的消息列表适配器 + │ │ ├── reply // 聊天功能模块的回复功能相关 + │ │ ├── report // 聊天功能模块的举报消息功能相关 + │ │ ├── viewholders // 聊天功能模块的消息类型 ViewHolder + │ │ ├── widgets // 聊天功能模块的自定义 View + │ │ └── EaseChatFragment // UIKit 内提供的聊天 Fragment + │ ├── conversation // 会话列表功能模块 + │ │ ├── adapter // 会话列表功能模块的适配器文件夹 + │ │ │ └── EaseConversationListAdapter // 会话列表功能模块的会话列表适配器 + │ │ ├── viewholders // 会话列表功能模块的会话类型 ViewHolder + │ │ ├── widgets // 会话列表功能模块的自定义 View + │ │ └── EaseConversationListFragment // UIKit 内提供的会话列表 Fragment + │ ├── contact // 联系人列表功能模块 + │ │ ├── adapter // 联系人列表功能模块的适配器文件夹 + │ │ │ └── EaseContactListAdapter // 联系人列表功能模块的联系人列表适配器 + │ │ ├── viewholders // 联系人列表功能模块的联系人相关 ViewHolder + │ │ ├── widgets // 联系人列表功能模块的自定义 View + │ │ └── EaseContactsListFragment // UIKit 内提供的联系人列表 Fragment + │ └── group // 群组功能模块 + ├── repository // UIKit SDK 数据仓库 + ├── viewmodel // UIKit SDK ViewModel + ├── provider // UIKit SDK Provider + ├── common // UIKit SDK 公共类 + ├── interfaces // UIKit SDK 接口类 + └── widget // UIKit SDK 自定义 View +``` + +## 功能 + +单群聊 UIKit 中业务相关的 UI 控件主要包含在以下三个 Fragment 中: + +- Chat Fragment 提供所有聊天视图的容器。 + +![img](@static/images/uikit/chatuikit/android/page_chat.png =400x866) + +- Conversation Fragment 提供会话列表容器。 + +![img](@static/images/uikit/chatuikit/android/page_conversation.png =400x866) + +- Contact Fragment 提供联系人、群组及其详情等容器。 + +![img](@static/images/uikit/chatuikit/android/page_contact_list.png =400x866) diff --git a/docs/uikit/chatuikit/android/chatuikit_quickstart.md b/docs/uikit/chatuikit/android/chatuikit_quickstart.md new file mode 100644 index 000000000..9bad1f3a1 --- /dev/null +++ b/docs/uikit/chatuikit/android/chatuikit_quickstart.md @@ -0,0 +1,318 @@ +# 快速开始 + + + +利用环信单群聊 UIKit,你可以轻松实现单群和群聊。本文介绍如何快速实现在单聊会话中发送消息。 + +## 前提条件 + +开始前,请确保你的开发环境满足以下条件: + +- Android Studio 4.0 及以上 +- Gradle 4.10.x 及以上 +- targetVersion 26 及以上 +- Android SDK API 21 及以上 +- JDK 11 及以上 + +## 项目准备 + +本节介绍将单群聊 UIKit 引入项目中的必要环境配置。 + +1. 使用 **Android Studio** 创建一个[新项目](https://developer.android.com/studio/projects/create-project)。 + - 在 **Phone and Tablet** 标签选择 **Empty Views Activity**。 + - **Minimum SDK** 选择 **API 21: Android 5.0 (Lollipop)**。 + - **Language** 选择 **Kotlin**。 + + 创建项目成功后,请确保项目同步完成。 + +2. 检查工程是否引入 **mavenCentral** 仓库。 + + - Gradle 7.0 之前 + + 在 `/Gradle Scripts/build.gradle.kts(Project: )` 文件内,检查是否有 **mavenCentral** 仓库。 + + ```kotlin + buildscript { + repositories { + mavenCentral() + } + } + ``` + - Gradle 7.0 即之后 + + 在 `/Gradle Scripts/settings.gradle.kts(Project Settings)` 文件内,检查是否有 **mavenCentral** 仓库。 + + ```kotlin + dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + mavenCentral() + } + } + ``` +3. 在项目中引入单群聊 UIKit。 + +从 GitHub 获取[单群聊 UIKit](https://github.com/easemob/chatuikit-android) 源码,按照下面的方式集成: + +- 在根目录 `settings.gradle.kts` 文件(/Gradle Scripts/settings.gradle.kts)中添加如下代码: + +```kotlin +include(":ease-im-kit") +project(":ease-im-kit").projectDir = File("../chatuikit-android/ease-im-kit") +``` + +- 在 app 的 `build.gradle.kts` 文件(/Gradle Scripts/build.gradle)中添加如下代码: + +```kotlin +//chatuikit-android +implementation(project(mapOf("path" to ":ease-im-kit"))) +``` + +4. 防止代码混淆 + +在 `/Gradle Scripts/proguard-rules.pro` 文件中添加如下代码: + + ``` + -keep class com.hyphenate.** {*;} + -dontwarn com.hyphenate.** + ``` + +## 实现发送第一条单聊消息 + +本节介绍如何通过单群聊 UIKit 实现发送第一条单聊消息。 + +### 第一步 创建快速开始页面 + +1. 打开 `app/res/values/strings.xml` 文件,并替换为如下内容: + +```xml + + quickstart + + [你申请的 app key] + + +``` +:::tip +你需要将 **app_key** 替换为你申请的 App Key。 +::: + +2. 打开 `app/res/layout/activity_main.xml` 文件,并替换为如下内容: + +```xml + + + + + + + + + + ); +}; +``` + +### useConversationContext 概览 + +下表中黑色字体为属性名称,蓝色字体为方法名称。 + + +    +        +        +        +    +    +        +        +        +    +    +        +        +        +    +    +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    +
属性/方法类型描述
currentConversationCurrentConversation当前会话。
conversationListConversation[]所有会话。
setCurrentConversation(currentCvs: CurrentConversation) => void设置当前会话。
deleteConversation(conversation: CurrentConversation) => void将会话从会话列表删除。
topConversation (conversation: Conversation) => void置顶会话。
addConversation (conversation: Conversation) => void将会话添加到会话列表
modifyConversation (conversation: Conversation) => void修改会话。
+ +## useChatContext + +该自定义 hook 可返回消息相关数据和数据管理方法。 + +### Usage example + +```javascript +import React from "react"; +import { useChatContext, useSDK } from "easemob-chat-uikit"; + +const ChatAPP = () => { + const { easemobChat } = useSDK(); // 获取即时通讯 IM SDK + const { messages, sendMessage } = useChatContext(); + const sendCustomMessage = () => { + const customMsg = easemobChat.message.create({ + type: "custom", + to: "targetId", // 单聊为对端用户 ID,群组聊天为当前群组 ID。 + chatType: "singleChat", + customEvent: "CARD", + customExts: { + id: "userId", + }, + }); + sendMessage(customMsg); + }; + + return ( +
+ +
+ ); +}; +``` + +### useChatContext 概览 + +下表中黑色字体为属性名称,蓝色字体为方法名称。 + + +    +        +        +        +    +    +        +        +        +    +    +        +        +        +    + +        +        +        +    +    +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    + +        +        +        +    +
属性/方法类型描述
messagesMessageUIKit 中的所有消息数据。
repliedMessageeasemobChat.MessagesType正在回复的消息
typingTyping正在输入的用户对象。
sendMessage(message: easemobChat.MessageBody) => Promise<void>发送消息。
deleteMessagedeleteMessage: (cvs: CurrentConversation, messageId: string | string[]) => void | Promise<void>删除消息。
recallMessage(cvs: CurrentConversation, messageId: string, isChatThread?: boolean) => Promise<void>撤回消息。
translateMessage(cvs: CurrentConversation, messageId: string, language: string) => Promise<boolean>翻译文本消息。
modifyMessage(messageId: string, msg: easemobChat.TextMsgBody) => Promise<void>编辑服务器上的消息。编辑后,对端用户会显示修改后的消息。该方法仅对文本消息有效。
modifyLocalMessage(id: string, message: easemobChat.MessageBody | RecallMessage) => void编辑本地消息。该方法对任何类型的消息均有效。
updateMessageStatus(msgId: string, status: 'received' | 'read' | 'unread' | 'sent' | 'failed' | 'sending' | 'default') => void更新消息状态。
sendTypingCommand (cvs: CurrentConversation) => void发送正在输入的命令。
setRepliedMessage(message: easemobChat.MessageBody | null) => void设置回复的消息。
clearMessages(cvs: CurrentConversation) => void清空会话的本地消息。
+ +## useAddressContext + +该自定义 hook 可以返回联系人和群组相关的数据以及数据管理方法。 + +### 使用示例 + +```javascript +import React from "react"; +import { useAddressContext } from "easemob-chat-uikit"; + +const ChatAPP = () => { + const { appUsersInfo } = useAddressContext(); + console.log(appUsersInfo); + return
ChatAPP
; +}; +``` + +### useAddressContext 概览 + +下表中黑色字体为属性名称,蓝色字体为方法名称。 + + +    +        +        +        +    +    +        +        +        +    +    +        +        +        +    +    +        +        +        +    + +        +        +        +    + +        +        +        +    +
属性/方法类型描述
appUsersInfoRecord<string, AppUserInfo>所有用户的信息。
groupsGroupItem[]所有群组。
setAppUserInfo(appUsersInfo: Record<string, AppUserInfo>) => void设置用户信息。
setGroups (groups: GroupItem[]) => void设置群组数据。
setGroupMemberAttributes(groupId: string, userId: string, attributes: easemobChat.MemberAttributes) => void设置群成员属性。
diff --git a/docs/uikit/chatuikit/web/chatuikit_conversation.md b/docs/uikit/chatuikit/web/chatuikit_conversation.md new file mode 100644 index 000000000..c55a1ade6 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_conversation.md @@ -0,0 +1,314 @@ +# 会话列表 + + + +`ConversationList` 组件用于展示当前用户的所有会话 (包含单聊和群聊, 但是不包括聊天室),并且提供会话搜索、删除、置顶和免打扰功能。 + +- 点击搜索按钮,跳转到搜索页面,搜索会话。 +- 点击会话列表项,跳转到会话详情页面。 +- 点击导航栏的扩展按钮,选择新会话,创建新会话。 +- 长按会话列表项显示菜单,可进行删除会话、置顶会话、消息免打扰操作。 + +单条会话展示会话名称、最后一条消息、最后一条消息的时间以及置顶和禁言状态等。 + +- 对于单聊, 会话展示的名称为对方昵称,若对方未设置昵称则展示对方的用户 ID,会话头像是对方的头像,如果没有设置则使用默认头像。 +- 对于群聊,会话名称为当前群组的名称,头像为默认头像。 + +会话列表相关功能,详见[功能介绍文档](chatfeature_conversation.html)。 + +![img](@static/images/uikit/chatuikit/web/page_conversation.png =400x930) + +## 使用示例 + +```jsx +import React, { useEffect, useState } from 'react'; +import { ConversationList } from 'easemob-chat-uikit'; +import 'easemob-chat-uikit/style.css'; + +const Conversation = () => { + return ( +
+ +
+ ); +}; +``` + +![img](@static/images/uikit/chatuikit/web/cvs-header1.png) + +## 自定义会话列表 + +如果默认的会话列表页面不能满足需求,你可以使用 `ConversationList` 组件提供的属性进行自定义。 + +### 自定义会话列表区域的样式 + +你可以自定义会话列表区域的背景颜色、大小等样式。 + +1. 对组件添加 `className` 定义样式。 + +```jsx +import React from 'react'; +import { ConversationList } from 'easemob-chat-uikit'; +import 'easemob-chat-uikit/style.css'; +import './index.css'; + +const Conversation = () => { + return ( +
+ +
+ ); +}; +``` + +2. 在 index.css 中定义会话 UI 样式: + +```css +.conversation { + background-color: '#03A9F4'; + height: 100%; + width: 100%; +} +``` + +![img](@static/images/uikit/chatuikit/web/cvs-bg.png =300x800) + +### 自定义会话列表页面的 header + +你可以自定义 `ConversationList` 组件的 header 元素,例如,标题名称为 `custom header`。 + +```jsx +import React from 'react'; +import { ConversationList, Header, Avatar } from 'easemob-chat-uikit'; +import 'easemob-chat-uikit/style.css'; + +const Conversation = () => { + return ( +
+ ( +
D} + content="custom header" + moreAction={{ + visible: true, + actions: [ + { + content: 'my info', + onClick: () => { + console.log('my info'); + }, + }, + ], + }} + /> + )} + > +
+ ); +}; +``` + +![img](@static/images/uikit/chatuikit/web/cvs-header2.png) + +### 设置用户的头像和昵称 + +- 使用 `renderItem` 方法来渲染每个会话条目。 +- 使用 `ConversationItem` 组件的属性自定义组件。 + +```jsx +import React from 'react'; +import { ConversationList, ConversationItem, Avatar } from 'easemob-chat-uikit'; +import 'easemob-chat-uikit/style.css'; +import './index.css'; + +const Conversation = () => { + // 在单聊中,将对端用户的用户 ID 与其用户昵称进行映射。 + const idToName = { + userId1: 'name1', + zd2: 'Henry 2', + }; + return ( +
+ { + return ( + + {idToName[cvs.conversationId] || cvs.conversationId} + + } + data={{ + ...cvs, + name: idToName[cvs.conversationId] || cvs.conversationId, + }} + /> + ); + }} + > + /> +
+ ); +}; +``` + +![img](@static/images/uikit/chatuikit/web/cvs-nick.png =300x700) + +### 添加和置顶会话 + +使用 `conversationStore` 提供的方法,例如: + +- 使用 `topConversation` 方法置顶一个会话。 +- 使用 `addConversation` 方法添加一个会话。 + +```jsx +import React from 'react'; +import { ConversationList, ConversationItem, rootStore, Button } from 'easemob-chat-uikit'; +import 'easemob-chat-uikit/style.css'; + +const Conversation = () => { + // 置顶会话。 + const topConversation = () => { + rootStore.conversationStore.topConversation({ + chatType: 'singleChat', // 群聊为 `groupChat`。 + conversationId: 'userID', // 输入从会话列表获取的会话 ID。 + lastMessage: {}, + }); + }; + + // 创建新会话。 + const createConversation = () => { + rootStore.conversationStore.addConversation({ + chatType: 'singleChat', + conversationId: 'conversationId', + lastMessage: {}, + unreadCount: 3, + }); + }; + return ( +
+ { + return ( + + ); + }} + > +
+ +
+
+ ); +}; +``` + +![img](@static/images/uikit/chatuikit/web/cvs-action.png =300x700) + +### 修改会话列表相关的主题 + +`ConversationList` 组件提供了会话列表页面主题相关的变量,如下所示。关于如修改主题,请单击[这里](chatuikit_theme.html#设置-scss-变量)。 + +```scss +// 用于设置会话主题的变量。 +$cvs-background: $component-background; +$cvs-search-margin: $margin-xs $margin-sm; +$cvs-item-height: 74px; +$cvs-item-padding: $padding-s; +$cvs-item-border-radius: 16px; +$cvs-item-margin: $margin-xss $margin-xs; +$cvs-item-selected-bg-color: #e6f5ff; +$cvs-item-selected-name-color: $blue-6; +$cvs-item-hover-bg-color: $gray-98; +$cvs-item-active-bg-color: $gray-9; +$cvs-item-info-right: 16px; +$cvs-item-name-margin: 0 $margin-sm; +$cvs-item-name-font-size: $font-size-lg; +$cvs-item-name-font-weight: 500; +$cvs-item-name-color: $title-color; +$cvs-item-message-margin-left: $margin-sm; +$cvs-item-message-font-size: $font-size-base; +$cvs-item-message-font-weight: 400; +$cvs-item-message-color: $font-color; +$cvs-item-time-font-weight: 400; +$cvs-item-time-font-size: $font-size-sm; +$cvs-item-time-color: $gray-5; +$cvs-item-time-margin-bottom: 9px; +``` + +## ConversationList 属性总览 + +`ConversationList` 组件包含以下属性: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
参数类型描述
+ className + + String + + 组件的类名 +
prefixStringCSS 类名的前缀
headerPropsHeaderPropsHeader 组件的参数
itemPropsConversationItemPropsConversationItem 组件的参数
renderHeader() => React.ReactNode自定义渲染 Header 组件的方法
renderSearch() => React.ReactNode自定义渲染 Search 组件的方法
onItemClick(data: ConversationData[0]) => void点击会话列表中每个会话的回调事件
onSearch(e: React.ChangeEvent<HTMLInputElement>) => boolean 搜索输入框的 change 事件,当函数返回 false 时,会组织默认的搜索行为,你可以使用自己的搜索条件来搜索
diff --git a/docs/uikit/chatuikit/web/chatuikit_design_guide.md b/docs/uikit/chatuikit/web/chatuikit_design_guide.md new file mode 100644 index 000000000..6a6a8ef58 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_design_guide.md @@ -0,0 +1,668 @@ +# Web 端单/群聊人机交互界面工具包设计指南 + +![img](@static/images/uikit/chatuikit/design/CUIcover2.png) + +## 0.总的设计原则 + +### 0.1.功能与行为上确保通用、普遍、一般 + +### 0.2.风格上易于自定义 + +### 0.3.在业务形态上尽量不替用户做决定 + +## 1.全局样式(Style) + +### 1.1.UIkit 色彩规范 + +#### 1.1.1.颜色配置说明: + +##### 1.1.1.1.颜色类(Color Class) + +一般颜色类分为八类: +主题色(Theme Color):Primary、 Secondary、Error 三类; +渐变主题色(Primary Gradient)一类(含 8 种); +透明色(Alpha Color):On Light、On Dark 两类; +中性色(Neutral Colors):Neutral、Neutral Special 两类; + +##### 1.1.1.2.颜色模式(Hsla Model) + +颜色模式为比较直观的 hsla 模式: +整个模型是一个圆柱体,圆柱体底面周长划分为 360°,对应不同的色相(Hue); +圆柱体的半径为饱和度(Saturation),圆心为 0(最灰),半径值为 100(最艳); +圆柱体的高为亮度(Lightness),起始点为 0(纯黑色),中心点是 50(标准色,),结束点为 100(纯白色)。 + +##### 1.1.1.3.模型概览: + +![img](@static/images/uikit/chatroomdesign/cruk1113.png) + +#### 1.1.2.三种主题色(Theme Color)的色彩规范: + +##### 1.1.2.1.关于用户可配项(Hue value): + +用户可设定颜色类的可配项 Hue(0-360)为任意数值,修改后每类颜色的色相会发生变化,以贴合用户场景所需要的主题颜色。 +Hue 值(0-360)与色相的对应关系大致如以下图示所例: + +![img](@static/images/uikit/chatroomdesign/cruk11211.png) + +用户可依据自身产品的品牌色指定色相数值(Hue),从而确认主题色 Primary(主要用于 UI 组件中关键操作与重要文本展示,如推荐的 action、高亮显示的文本等),以及用于积极提示的 Secondary,和表示警示提示的 Error。 + +![img](@static/images/uikit/chatroomdesign/cruk11212.png) + +##### 1.1.2.2.关于饱和度(Saturation value): + +饱和度(Saturation)不开放给用户设置,三种主题色 Primary、 Secondary、Error 默认饱和度为 100%,Neutral 默认为 8%,Neutral Special 默认为 36% + +![img](@static/images/uikit/chatroomdesign/cruk1122.png) + +##### 1.1.2.3.关于亮度级别(Lightness level): + +亮度(Lightness)百分比用户不可随意设置,每个颜色类提供:0(0%) / 1(10%) / 2(20%) / 3(30%) / 4(40%) / 5(50%) / 6(60%) / 7(70%) / 8(80%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)十三个级别供用户可选; + +![img](@static/images/uikit/chatroomdesign/cruk1123.png) + +##### 1.1.2.4.举个例子吧: + +如指定主题色 Primary 色相(Hue)为 203,成功色 Secondary 色相(Hue)为 155,警示色 Error 色相(Hue)为 350,则会生成如下 39 种主题色可供用户在指定 UI 件块(View)颜色时使用: + +![img](@static/images/uikit/chatroomdesign/cruk1124.png) + +其中,主题色 Primary 的 L5 为亮色模式下的基色(Key Color),L6 为暗色模式下的基色(Key Color)。所有的颜色体系都是依照基色生成。 + +#### 1.1.3.关于渐变主题色(Primary Gradient)的规范: + +渐变主题色是由 Primary 色派生出的渐变色,为线性渐变(Linear Gradient),渐变方向依图示坐标系分为 8 类: + +![img](@static/images/uikit/chatroomdesign/cruk113.png) + +##### 1.1.3.1.关于渐变色的起始色(Start Color): + +渐变色中 Start Color 规则和 Primary 类的色值保持一致; + +![img](@static/images/uikit/chatroomdesign/cruk1131.png) + +##### 1.1.3.2.关于渐变色的结束色(End Color): + +End Color 用户可配置色相(Hue),亮度以 0(20%) / 1(30%) / 2(40%) / 3(50%) / 4(60%) / 5(70%) / 6(75%) / 7(80%) / 8(85%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)(对应 Primary 的 13 级亮度梯度值)为固定梯度值 + +以下以 Hue:233 为例,按照 End Color 颜色公式依旧得到 13 级颜色: + +![img](@static/images/uikit/chatroomdesign/cruk11321.png) + +起始色和结束色结合,得到相应的渐变结果 + +![img](@static/images/uikit/chatroomdesign/cruk11322.png) + +##### 1.1.3.3.关于渐变主题色可配项(End Color Hue Value): + +用户仅可配置渐变色中 End Color 的色相(Hue)以达成与用户业务场景符合的渐变颜色效果; + +##### 1.1.3.4.举个例子吧: + +用户设置 End Color Hue = 233,选择渐变方向为“↓”,则可得到如下效果: + +![img](@static/images/uikit/chatroomdesign/cruk11341.png) + +如使用渐变主题色,那么它将替代掉所有应用于背景色的 Primary 色 + +![img](@static/images/uikit/chatroomdesign/cruk11342.png) + +但一般不替代 UI 件块的前景色,因为没有什么意义,且有干扰文字阅读的可能性 + +![img](@static/images/uikit/chatroomdesign/cruk11343.png) + +#### 1.1.4.关于透明色(Alpha)的规范: + +##### 1.1.4.1.透明色(Alpha Color): + +在本案内带有透明度的组件仅有模态背景色、轻提示背景色,应用范围有限,单独定义两个特殊的颜色类用于以上四种组件:Alpha onlight(hsl0, 0%, 0%) 和 Alpha ondark(hsl0, 0%, 100%),Alpha 值被指定为 0(0.0) / 1(0.1) / 2(0.2) / 3(0.3) / 4(0.4) / 5(0.5) / 6(0.6) / 7(0.7) / 8(0.8) / 9(0.9) / 95(0.95) / 98(0.98) / 100(1.0) 十三个梯度值,共 26 种颜色用例,以调整组件的背景色透明度。 + +![img](@static/images/uikit/chatroomdesign/cruk1141.png) + +Alpha onlight 和 Alpha ondark 均为默认值,无任何可配置项。 + +### 1.1.5.关于中性色(Neutral Colors): + +#### 1.1.5.1.中性色(Neutral) + +中性色(Neutral)仅有一个可配项:色相(Hue),饱和度(Saturation)固定值为 8,亮度级别(Lightness level)也和主题色相同,分为 0(0%) / 1(10%) / 2(20%) / 3(30%) / 4(40%) / 5(50%) / 6(60%) / 7(70%) / 8(80%) / 9(90%) / 95(95%) / 98(98%) / 100(100%)十三个级别供用户可选; + +![img](@static/images/uikit/chatroomdesign/cruk1151.png) + +Neutral 和 Primary 的默认 Hue 值(色相)相同,也建议用户设置和主题色相同的 Hue 值已达成主题颜色和无彩色系的配套。但这仅仅是建议; + +#### 1.1.5.2.举个例子吧: + +如指定主题色 Primary 色相(Hue)为 203,饱和度(Saturation)固定值为 100%,中性色(Neutral)则也指定色相(Hue)为 203,饱和度(Saturation)固定值为 8%,则得到以下色列可供用户选择使用: + +![img](@static/images/uikit/chatroomdesign/cruk11521.png) + +其中,L98 为亮色模式下背景色的主色,L1 为亮色模式下前景色的主色;L1 为暗色模式下背景色的主色,L98 为暗色模式下前景色的主色。 + +![img](@static/images/uikit/chatroomdesign/cruk11522.png) + +### 1.1.6.关于特殊中性色(Neutral Special): + +特殊中性色 Neutral Special 主要用于级别低于 Primary 和 Secondary 的强调信息,如当前页面状态、消息发送者的昵称等。 +Neutral Special 和 Primary 的默认 Hue 值(色相)类似,为近似色,也建议用户设置和主题色近似的 Hue 值已达成主题色和无彩色系的配套。但这仅仅是建议; + +![img](@static/images/uikit/chatroomdesign/cruk116a.png) + +![img](@static/images/uikit/chatroomdesign/cruk116b.png) + +#### 1.1.6.1.举个例子吧: + +如指定主题色 Primary 色相(Hue)为 203,特殊中性色(Neutral)通过相似色原理(正负 30 度内)指定色相(Hue)为 220,饱和度(Saturation)固定值为 36%,则得到以下色列可供用户选择使用: + +![img](@static/images/uikit/chatroomdesign/cruk1161.png) + +## 1.2.主题 + +本期主题分为 2 种,每种分明亮(Light mode)和黑暗(Dark)两类。 + +### 1.2.1.圆润主题 + +组件一般采用较大的圆角,柔和轻盈 + +![image text](@static/images/uikit/chatuikit/design/1.2.1.png) + +### 1.2.2.硬朗主题 + +组件一般避免比较大的圆角,硬朗实在 + +![image text](@static/images/uikit/chatuikit/design/1.2.2.png) + +以上两种主题可通过应用渐变主题色(Primary Gradient)得到两外两种渐变色主题。 +至于业务相关的主题,如“社交”、“游戏”、“教育”、“商务”等主题分类,因违反本案的最基本设计原则“在业务形态上尽量不替用户做决定”,所以不在本期考虑范围内。 + +## 1.3.图标(Icon) + +### 1.3.1.图标模板(Template) + +图标参照 Material Icon Font 的模板 ,以 24 为基本栅格,须在安全区域(20x20 的中心区域)内绘制,基本描边控制为 1.5 栅格。 + +![img](@static/images/uikit/chatroomdesign/cruk131.png) + +### 1.3.2 图标命名(Name) + +为防止将图标语意固定,icon 命名需要尽力避免定义操作行为,而是以“看见什么就是什么“进行命名,方便相同图标在不同操作行为下的复用。 +如 + +![img](@static/images/uikit/chatroomdesign/cruk132.png) + +## 1.4.字体(Typography) + +### 1.4.1.字族(Font Family) + +#### 1.4.1.1.iOS 字族 + +默认 SF Pro 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 SF Arabic、SF Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认苹方(PingFang SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +#### 1.4.1.2.Android 字族 + +默认 Roboto 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 Noto Sans Arabic、Noto Sans Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认思源黑体(Noto Sans SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +#### 1.4.1.3.Web 字族 + +默认 Roboto 为基本西文(拉丁字母、希腊字母、西里尔字母等)字体; +默认 Noto Sans Arabic、Noto Sans Hebrew 等为基本右向左(Dextral-sinistral)文字字体; +默认思源黑体(Noto Sans SC、TC、HK)为中文(简体中文、繁体中文、香港繁体中文)字体; + +### 1.4.2.字号(Font Size) + +#### 1.4.2.1.最小字号 + +移动端最小字号为:11;web 端最小字号为:12 + +#### 1.4.2.2.字号规则 + +除移动端最小字号外,字号以 2 为梯度递增: +11,12,14,16,18,20 + +### 1.4.3.字重(Font Weight) + +字重分为标准(Regular, 400)、中等(Medium,510)、加粗(semibold,590)三种; +在一些跨平台框架中,如遇不支持设置非百位整数字重,则取近似值百位整数; +如字族没有 semibold,则以 bold 替换。 + +### 1.4.4.行高(Line height) + +行高依照以下固定值(字号/行高): +11/14,12/16,14/20,16/22,18/26,20/28。 + +### 1.4.5.字体角色(Font Role) + +字体角色分为 3 类: +大标题 Headline、标题 Title、标签 Label、正文 Body +需要注意的是,这些角色只是推荐的角色指示,并不具有完全的指定性,具体使用什么角色的字体需依照所使用的组件的实际情况(组件内信息的层级重要性,越重要的越大越重)而使用。 + +### 1.4.6.字体 Token + +依照依照 4.1-4.5 规则,设定以下西文字体排版 token, + + + +简体中文字体 token 示意 + + + +## 1.5.效果(Effects) + +所应用的效果主要分为两种:背景模糊(Background Blur)和阴影(Shadow) + +### 1.5.1.背景模糊(Background Blur) + +背景模糊主要应用于组件背景色使用 Alpha color 时,如组件背景色的透明度会造成组件前后层级干扰的话,则推荐使用背景模糊解决, +也应用于模态显示的弹出层的背景虚化; + +背景模糊的模糊半径值默认为 20 + +``` +/* bg_blur_modal */ backdrop-filter: blur(20); +``` + +### 1.5.2.阴影(Shadow) + +阴影应用于弹窗(Alert)、浮层(pop)、抽屉(Drawer)等,为区分层级,凸显聚焦的组件。 + +#### 1.5.2.1.阴影型号(Size) + +阴影分为小(small)、中(medium)、大(Large)三种型号,应用于不同尺寸的组件中,总体原则为:越小的组件越推荐使用小的阴影、反之越大的组件推荐使用大的阴影;圆角越小的组件越推荐使用小的阴影、反之亦然。 + +#### 1.5.2.2.阴影 token + +为保证阴影效果自然柔和,每个阴影都有两层不同偏移、不同模糊度、不同透明度的值。同时针对亮色/暗色模式有两套不同颜色的阴影。 + +**Shadow on Light:** + +``` +/* shadow/onlight/large */ +box-shadow: x0 y24 blur36 color(Neutral3) Alpha0.15, x8 y0 blur24 color(Neutral1) Alpha0.1 + +/* shadow/onlight/medium */ +box-shadow: x0 y4 blur4 color(Neutral3) Alpha0.15, x2 y0 blur8 color(Neutral1) Alpha0.1 + +/* shadow/onlight/small */ +box-shadow: x0 y1 blur3 color(Neutral3) Alpha0.15, x1 y0 blur2 color(Neutral1) Alpha0.1 +``` + +![img](@static/images/uikit/chatroomdesign/cruk1522a.png) + +**Shadow on Dark:** + +``` +/* shadow/onlight/large */ +box-shadow: x0 y24 blur36 color(Neutral4) Alpha0.15, x8 y0 blur24 color(Neutral1) Alpha0.1 + +/* shadow/onlight/medium */ +box-shadow: x0 y4 blur4 color(Neutral4) Alpha0.15, x2 y0 blur8 color(Neutral1) Alpha0.1 + +/* shadow/onlight/small */ +box-shadow: x0 y1 blur3 color(Neutral4) Alpha0.15, x1 y0 blur2 color(Neutral1) Alpha0.1 +``` + +![img](@static/images/uikit/chatroomdesign/cruk1522b.png) + +## 1.6.圆角(Radius) + +### 1.6.1.一般圆角 + +一般圆角分为 None(r=0)、Extra Small(r=4)、Small(r=8)、Medium(r=12)、Large(r=16)、Extra Large(r=½ Height)六个枚举值, +一般情况下组件的四个圆角为同一值 + +![img](@static/images/uikit/chatroomdesign/cruk161.png) + +#### 1.6.1.1.Extra Small(r=4) + +通常适用于如下组件 +Button(Small Radius) +Input(Small Radius) +Float(Small Radius) +Message Bubble(Small Radius) +Avatar(Small Radius) +Popover +Global Broadcast(Small Radius) + +#### 1.6.1.2.Small(r=8) + +通常适用于如下组件 +Alert(Small Radius) +Drawer(Small Radius) + +#### 1.6.1.3.Medium(r=12) + +通常适用于如下组件 +本案暂不涉及 + +#### 1.6.1.4.Large(r=16) + +通常适用于如下组件 +Input Area(Large Radius) +Alert(Large Radius) +Drawer(Large Radius) +Float(Large Radius) + +#### 1.6.1.5. Extra Large(r=½ Height) + +通常适用于如下组件 +Input Area(Large Radius) +Alert(Large Radius) +Drawer(Large Radius) +Message Bubble(Large Radius) + +### 1.6.2.特殊圆角 + +特殊圆角应用于有背景色的 IM 聊天消息组件: +Message Bubble(Large Radius) + + + +## 2.小控件(Widgets) +小控件为最基础的视觉交互模块。 + +### 2.1.按钮(Bottom) +按钮组件分为普通按钮、文本按钮、图标按钮三种,每种包含的状态有 Enabled、Hovered(限 web 端) 、Pressed、Loading、Pressed 五种状态,同时分为大、中、小三种按钮尺寸以贴合不同容器的使用。 + +### 2.1.1.普通按钮(Normal) + +普通按钮分主要操作(Primary)和次要操作(Secondary)两种类型。 + +#### 2.1.1.1.主要操作(Primary) + +主要操作用于推荐行为,一般背景色为主题色(Primary5\Primary6)或者渐变主题色,被禁用时置灰显示,圆角可配,依据需要可增加左侧或右侧 icon + +![img](@static/images/uikit/chatroomdesign/cruk2111.png) + +#### 2.1.1.2.次要操作(Secondary) + +次要操作用于辅助主要操作,一般不单独出现,一般背景色为亮色(Neutral98)或者暗色(Neutral1),同时有描边,被禁用时置灰显示,圆角可配 +依据需要可增加左侧或右侧 icon + +![img](@static/images/uikit/chatroomdesign/cruk2112.png) + +### 2.1.2.文字按钮(Text) + +文字按钮仅有前景色,也分为主要操作和次要操作,一般用于更频繁的常规操作(如表单填写的下一步、取消,消息的显示、隐藏等)或者在页面有普通按钮(主要操作)时作为更次一级操作出现 + +![img](@static/images/uikit/chatroomdesign/cruk212.png) + +### 2.1.3.图标按钮(Icon) + +图标按钮为组件位置局促又必须出现按钮时的补充形式,如输入条的键盘切换、顶部条的更多操作、表单填写时的推荐操作、输入框的清空和下拉操作等。 + +![img](@static/images/uikit/chatroomdesign/cruk213.png) + +需要注意的是,在 web 端,如非特殊说明,图标按钮必须搭配 Popover 使用,以交代清楚按钮的具体操作行为。如: + +![img](@static/images/uikit/chatroomdesign/cruk213b.png) + +### 2.2.输入框(Input) + +输入框为需要输入较少文字时使用的组件。 +也按照所放组件的大小分为大中小三种尺寸可配项,样式上,背景色和描边颜色可开关,圆角可配,状态上分为失焦未填写、失焦填写、聚焦未填写、聚焦填写、禁用填写、禁用未填写六种。 + + + +### 2.3.输入区域(InputArea) + +输入框为需要输入较多文字时使用的组件。 +在用于输入器的文本输入,和表单中、发布内容时需要填写较多文本时使用,样式上,背景色和描边颜色可开关,圆角可配,可显示最大输入字符数分数。状态上分为失焦未填写、失焦填写、聚焦未填写、聚焦填写、禁用填写、禁用未填写六种。 + + + +### 2.4.单选器和多选器(Checkboxes n' Radios) +单选器和多选器允许终端用户在列表中选择一项或者多项。分为选中、未选中、选中禁用、未选中禁用四种状态。 + + +### 2.5.开关(Switch) +开关为终端用户对列表项打开和关闭的直观操作。 +分为关闭、打开、关闭禁用、打开禁用四中状态。 +此操作一般需要避免自动化开启和关闭,必须终端用户主动操作。 + +样式采用iOS或Material 默认样式,开启颜色对应Primary5/Primary6的KeyColor色值。 + + +### 2.6.滑块(Slider) +滑块用于终端用户精确设置数值。 +可配项有:两侧图标或单侧数值,状态上分为禁用和可用。 + +### 2.7.浮层菜单(PopMenu) +浮层菜单为非常住的的选项或列表的展示。支持配置操作项有无左侧icon + +### 2.8.头像(Avatar) +头像是一类信息数据展示的控件,如用户、某个操作项的头像展示,常放置于个人信息页、与用户相关的列表项中 +头像圆角有两个枚举值:Extra Small(r=4)、Extra Large(r=½ Height)以配合不同主题的使用 +头像的尺寸可以依据所属组件的大小自由配置,但需要注意的是,头像的比例永远是 1:1 + +### 2.8.1.图片头像 + +能读取用户头像信息时展示图片头像。 + +![img](@static/images/uikit/chatroomdesign/cruk241.png) + +### 2.8.2.字符头像 + +用户未上传头像时显示字符头像,字符头像分为单字符和双字符两种 + +![img](@static/images/uikit/chatroomdesign/cruk242.png) + +### 2.8.3.组合头像 + +组合头像用于用户未上传数据时的群组聊天自动生成头像 +本案不涉及 + +![img](@static/images/uikit/chatroomdesign/cruk243.png) + +### 2.8.4.图标头像 + +图标头像用于获取不到用户头像信息的空状态以及表单单项有 icon 时的头像。 + +![img](@static/images/uikit/chatroomdesign/cruk244.png) + +### 2.8.5.头像徽章 + +头像可配置徽章(Badge)以体现用户的在离线等状态,徽章位置分两种:右下和右上 + + + +### 2.9.徽章(Badge) +徽章用于导航项、列表项、头像处,用于显示状态、通知和计数。 +配置项有:计数的有无、标准和小、icon的有无。 +(配图) + +### 2.10.表情符号(Emojis) + +### 2.10.1.Twemoji [↗](https://github.com/twitter/twemoji) + +表情使用开源可免费商用的 Twemoji 作为基本表情,默认提供 52 个表情作为内置的表情,用户可根据自己的产品规划从 twemoji 提供的 3,245 个表情中进行替换增减; + +![img](@static/images/uikit/chatroomdesign/cruk291.png) +### 2.10.2.表情模版(Emoji Template) + +如用户需替换 Twemoji,或者需要自己创作表情,需依照以下模板进行替换或绘制; + +![img](@static/images/uikit/chatroomdesign/cruk292.png) + +### 2.10.3.表情组件状态(State) + +表情组件的状态分为以下 4 种: +启用 Enabled、悬停 Hovered(仅限 web 端)、按下 Pressed、聚焦 Focused(本案不涉及) +悬停时,背景色递增一级;按下时,背景色递减一级;聚焦时,背景色转换为 Key Color。 + +![img](@static/images/uikit/chatroomdesign/cruk293.png) + +### 2.11.轻提示(Toast) +请提示为针对终端用户当前操作的简单反馈。 +分为有图标、无图标两类。 + +### 2.12.模态背景(Model) +模态为临时的弹出的关键信息,需要用户主动操作来退出。 +模态背需配合弹窗(Alert)使用。颜色可配置为任意AlphaColor,也可设置背景模糊效果。 +(配图) + +### 2.13.索引(Index) +索引应用于联系人页面通过分类迅速查找联系人。 + +#### 2.13.1.目录索引(SectionIndex) +目录索引位于联系人或成员列表最右侧,为快速通过字母定位到相关联系人的滚动条。 + +#### 2.13.2.列表索引(IndexInList) +列表内的索引用于不同字母分类的联系人的分割。可以配置是否有底部分割线。 + +### 2.14.底部标签栏(BottomTabs) +底部导航栏应用于移动设备上不同视图(View)的切换,最少两个切换项,超过5个项时分页展示。 + +### 2.15.顶部标签栏(TopTabs) +顶部部导航栏应用于移动设备上不同视图(View)的切换,最少一个项,超过5个项时分页展示。 + +## 3.控件(Components) + +### 3.1.顶部条(TopBar) +顶部条用于展示当前视图标题,并可对当前页面进行整体的控制。 +左侧支持配置返回操作、支持有/无头像、支持有/无小标题,右侧支持 1 至 3 个action。 + +### 3.2.搜索条(SearchBar) +搜索条用于搜索当前页面的项。 +可配项有左侧返回icon、是否显示取消按钮。 + +### 3.3.底部条(BottomBars) + +#### 3.3.1.底部操作条(navigation_bar) +底部操作条用于针对当前视图的操作,最少支持一项,最多支持三项,操作按钮支持配置为文本按钮或图标按钮。 + +#### 3.3.2.输入条(InputBar) + +输入条为会话详情页文本等消息的发布器。 +可配置左侧actionbtn、右侧Action1、Action2、Action3、sendbtn +样式上支持配置顶部分割线、输入框圆角样式、sendbtn可配置为文本按钮或者图标按钮。 + +#### 3.3.3.录音浮层(RecordingModel) +录音浮层为录制和发送语音消息的控件。 + +### 3.4.表情盘(EmojisPick) + +表情键盘是发送 app 内自建表情的键盘,内容上支持表情个数的增减,底部发送和退格按钮支持修改圆角。同时应满足接入第三方表情/贴纸库。 + +![img](@static/images/uikit/chatroomdesign/cruk34.png) + +本键盘不同于系统自带的 emoji 输入键盘,通过此组件输入的 emoji 不会同步为系统的 emoji,而是在任何平台同一 app 内均显示 app 内自建的表情符号。为满足版权方面的法律要求,请勿使用非申明开源可免费商用的表情符号(不限资源图或者源码)在 App 中(如:集成苹果表情符号在自己的 app 内,这样或许会导致 App 无法上架苹果应用商店) + +### 3.5.列表项(ListItem) + +#### 3.5.1.表单列表项(FromItem) +表单列表项应用再联系人/群组详情页面/App设置页面的表单中, +支持点击事件、右侧可配置按钮、数据展示、开关、滑动条、单/多选器等功能,左侧可配置单/多选器。 +信息展示上可配置左侧头像、subtitle、列表项的分类标题(Headline)和注解(postil) + +#### 3.5.2.会话列表项(ConversationItem) +会话列表项为会话详情的入口,可展示的信息有:联系人头像(Avatar)、联系人昵称(Title)、最新消息(Subtitle)、新消息通知(Badge)、新消息时间戳(Time)。 +样式上支持头像配置大/小圆角、是否配置列表项的分割线。 + +#### 3.5.3.联系人列表项(ContactsItem) +联系人列表项为联系人详情的入口,可展示的信息有:联系人头像(Avatar)、联系人昵称(Title)、联系人状态(Subtitle)。 +样式上支持头像配置大/小圆角、是否配置列表项的分割线。 + +### 3.6.弹窗(Alert) +弹窗通知是一类模态提示,会提示用户正在进行的操作所需的关键信息,如警告等,或需要用户填写关键信息(通过输入框),需用户做出主要操作或次要操作。 +内容上,description 可配、输入框可配、操作项支持最多三个。 +样式上,弹窗的圆角可配,需要注意的是,组件内部的输入框和操作按钮圆角需要同弹窗按钮的圆角适配,以达成风格的一致性。 + +![img](@static/images/uikit/chatroomdesign/cruk27.png) + +### 3.7.操作面板(ActionSheet) +操作表单是以模态形式展示的多操作项表单,单个操作项分为 Enabled、Pressed、Disabled、Destructived 四种状态,以及 Cancel 特殊类型。同时可配置是否显示 icon、是否有分割线(stroke) +此组件仅限移动端 + + + + +## 4.消息气泡(MessageBubble) + +### 4.1.文本消息(TextsMsg) +文本消息为发送字符和emoji表情时使用的气泡样式。 + +### 4.2.语音消息(AudioMsg) +文本消息为发送语音时使用的气泡样式。 +气泡宽度会随着语音消息的时长而改变宽度。支持点击后播放。播放中有动画显示。 + +### 4.3.文件消息(FileMsg) +文件消息为发送文件时候展示的气泡样式。 +支持显示的字段有:文件图标、文件名(Title)、文件大小(Subtitle) + +### 4.4.联系人消息(ContactMsg) +联系人消息为一种展示联系人的气泡样式,支持点击事件, +支持显示的字段有:联系人头像、联系人昵称(Title) + +### 4.5.缩略图消息(ImgMsg) +缩略图消息为发送图片和视频消息时的消息气泡。 +展示规则: + + +### 4.6.顶部附加消息(DescantMsg) +顶部附加消息为本消息的附属信息的展示,如:消息的回复(Reply) +支持点击事件 + +### 4.7.底部附加消息(OrganumMsg) +*本期不涉及* + +### 4.8.消息的长按操作列表(MsgActionSheet) +支持对当前消息进行复制、编辑、撤回、回复等的操作。 + +## 5.模块视图(Module View) + +### 5.1.会话视图(ConversationView) + +#### 5.1.1.会话列表(ConversationList) +会话视图为会话搜索、会话列表项组合而成的页面。 + +#### 5.1.2.新会话(NewMsg) +通过会话右上角action调取的操作列表,可以此发起会话、创建群、添加联系人。 +##### 5.1.2.1. 发起会话(StartConversation) +点击此项将调取联系人列表,终端用户可点选或者搜索联系人,点击后将进入会话详情页面,用户可以通过发送消息发起会话。 +##### 5.1.2.2. 创建群组(CreateGroup) +点击此项将调取多选状态的联系人列表,终端用户在此页面点选群组成员,当群成员≥2(包含群主和群成员)时,用户可以点击创建进入群组会话详情页面,以创建一个群组。 +##### 5.1.2.3. 添加联系人(Addcontact) +点击此项将大家添加联系人弹窗,终端用户输入要添加的联系人ID后发送添加信息。 + +### 5.2.联系人视图(ContactsView) +联系人视图是联系人搜索、联系人列表项组合而成的页面。 + +#### 5.2.2.新申请列表(NewRequest) +如用户收到添加联系人的申请,将在此展示相关信息。用户可以通过添加操作处理联系人添加请求。 + +#### 5.2.3.群组列表(GroupList) +将在此展示用户加入的所有群。用户可以通过添加操作处理联系人添加请求。 + +### 5.3.会话详情视图(ConversationDetailView) +会话详情为群聊或者群组聊天的详情页面 +页面分为header(展示会话title信息),body(消息气泡列表),footer(消息发送三部分) + +#### 5.3.1.会话的顶部导航栏(header) +顶部导航栏承接两项主要功能: + +1)会话关键信息的展示:联系人/群的头像、联系人昵称/群名称、联系人的在/离线状态等 + +2)关于相关会话的操作:退出会话、查看联系人/群详情、针对当前会话的 1-3 个操作 + +#### 5.3.2.消息气泡列表(body) +会话内成员所发送的消息将以时间的先后顺序在此视图内进行由上到下的排列。 + +#### 5.3.3.消息的发送(footer) +用于发送文本、语音、附件、自定义消息。 + +### 5.4.联系人详情视图(ContactDetailView) +联系人详情为联系人详情展示的页面,主要展示联系人头像、昵称、ID等联系人信息; +支持在本页面操作联系人免打扰、联系人删除操作; +支持在本页面进入消息详情等入口; + +### 5.5.群组详情视图(GroupDetailView) +群组详情为群组详情展示的页面,主要展示群组头像、群组名称、群ID等群组信息; +支持在本页面操作群组免打扰、退出群组等操作; +管理员(Owner和Admins)支持修改群信息(群名称、群详情等),支持群主(Owner)转让群主身份和解散群组; +支持在本页面进入消息详情等入口; + +## 6.设计资源(Design Resources) +设计资源详见 [figma 链接](https://www.figma.com/community/file/1327193019424263350/chat-uikit-for-mobile)。 diff --git a/docs/uikit/chatuikit/web/chatuikit_integrated.md b/docs/uikit/chatuikit/web/chatuikit_integrated.md new file mode 100644 index 000000000..8f4d001ee --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_integrated.md @@ -0,0 +1,105 @@ +# 集成单群聊 UIKit + + + +使用单群聊 UIKit 之前,你需要将其集成到你的应用中。 + +## 前提条件 + +开始前,确保你的开发环境满足如下条件: + +- React 16.8.0 或以上版本; +- React DOM 16.8.0 或以上版本; +- 即时通讯 IM 项目和 App Key。 + +## 操作步骤 + +### 第一步 安装单群聊 UIKit + +使用 `npm` 或者 `yarn` 安装 `easemob-chat-uikit`: + +```bash +npm i easemob-chat-uikit --save; +``` + +### 第二步 引入所需组件 + +将单群聊 UIKit 组件导入到你的 React 项目中。 + +```jsx +// 导入组件 +import { + UIKitProvider, + Chat, + ConversationList, + // ... +} from "easemob-chat-uikit"; + +// 导入样式 +import "easemob-chat-uikit/style.css"; +``` + +### 第三步 初始化 + +项目中用到的组件都需要在 `UIKitProvider` 内部使用。使用单群聊 UIKit 时,首先要配置 `UIKitProvider` 参数,示例如下: + +若要实现自动登录,初始化时需传入 `userId`、`password` 或 `token`。 + +你需要在环信控制台[创建 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户),获取用户 ID 和密码。如果使用 token,你需要从你的 App Server 获取用户 token,详见[使用环信用户 token 鉴权](/product/easemob_user_token.html) 。 + +```jsx +import React from 'react'; +import { UIKitProvider } from 'easemob-chat-uikit'; +import 'easemob-chat-uikit/style.css'; +ReactDOM.createRoot(document.getElementById('root') as Element).render( +
+ +
+) +``` + +如要了解更多配置,详见 [`UIKitProvider` 文档](chatuikit_provider.html)。 + +### 第四步 登录 + +当 Provider 渲染和销毁时,单群聊 UIKit 内部会自动完成登录登出。 + +关于自动和手动登录,详见[登录文档](chatuikit_login.html)。 + +### 第五步 搭建界面 + +单群聊 UIKit 提供会话列表、聊天、群组设置和通讯录等组件。你可以使用这些组件搭建界面,这些组件支持自定义,具体可以参考相应组件的文档。 + +单群聊 UIKit 提供的 container 级别组件使用 flex 布局,默认宽高均为 100%,所以需要自己实现布局,然后将组件放在布局的容器组件中。 + +下面以会话列表和聊天组件组成的界面为例: + +```jsx +import React from "react"; +import { Chat, MessageList, TextMessage } from "easemob-chat-uikit"; +import "easemob-chat-uikit/style.css"; + +const App = () => { + return ( +
+
+ +
+
+ +
+
+ ); +}; +``` + +## 相关参考 + +- [组件库源码](https://github.com/easemob/Easemob-UIKit-web) +- [其他示例 demo](https://github.com/easemob/Easemob-UIKit-web/tree/main/demo) diff --git a/docs/uikit/chatuikit/web/chatuikit_listener.md b/docs/uikit/chatuikit/web/chatuikit_listener.md new file mode 100644 index 000000000..df5956811 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_listener.md @@ -0,0 +1,52 @@ +# 注册事件监听 + + + +单群聊 UIKit 提供 eventHandler 注册监听事件,可以监听 UIKit 内部所有调用的 API,事件名称则为 SDK 提供的相应 API 的名称。 + +## 使用示例 + +```javascript +import React, { useEffect } from "react"; +import { eventHandler } from "easemob-chat-uikit"; + +const ChatApp = () => { + useEffect(() => { + eventHandler.addEventHandler("handlerId", { + onError: (err) => { + // 所有的事件的 error 事件同时会在 onError 回调出来 + console.error(err); + }, + recallMessage: { + success: () => { + toast.success("撤回成功"); + }, + error: (error) => { + toast.error("撤回失败"); + }, + }, + reportMessage: { + success: () => { + toast.success("举报成功"); + }, + error: (error) => { + toast.error("举报失败"); + }, + }, + sendMessage: { + error: (error) => { + if (error.type == 507) { + toast.error("你已被禁言,无法发送消息"); + } else if ( + error.type == 602 && + error.message == "not in group or chatroom" + ) { + toast.error("消息发送失败,你已不在当前群组"); + } + }, + }, + }); + }, []); + return
; +}; +``` diff --git a/docs/uikit/chatuikit/web/chatuikit_login.md b/docs/uikit/chatuikit/web/chatuikit_login.md new file mode 100644 index 000000000..390f93569 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_login.md @@ -0,0 +1,46 @@ +# 登录 + + + +如果[初始化](chatuikit_integrated.html#第三步-初始化)时设置了用户 ID `userId` 和 `token`,单群聊 UIKit 在 [Provider](chatuikit_provider.html) 加载完成时会自动登录,在 Provider 被卸载时会自动登出。 + +```javascript +import { UIKitProvider } from "easemob-chat-uikit"; + +const App = () => { + return ( + + ); +}; +``` + +若要手动登录登出,你可以获取即时通讯 IM SDK connection 实例,然后[调用 SDK 的 API 进行登录登出](/document/web/overview.html#手动登录)。 + +```javascript +import { useClient } from "easemob-chat-uikit"; + +const ChatApp = () => { + const client = useClient(); + const login = () => { + client.open({ + user: "userId", + token: "chat token", + }); + }; + const logout = () => { + client.close(); + }; + return ( +
+ + +
+ ); +}; +``` diff --git a/docs/uikit/chatuikit/web/chatuikit_overview.md b/docs/uikit/chatuikit/web/chatuikit_overview.md new file mode 100644 index 000000000..59e2274f7 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_overview.md @@ -0,0 +1,35 @@ +# 概述 + + + +环信单群聊 UIKit 是基于环信即时通讯云 IM SDK 开发的一款即时通讯 React UI 组件库。该组件库提供了聊天相关的组件,包括会话列表、聊天界面、联系人列表和群组设置等组件,组件内部集成了 IM SDK,可以帮助开发者不关心内部实现和数据管理就能根据实际业务需求快速搭建包含 UI 界面的即时通讯应用。 + +若要访问源码,请点击[这里](https://github.com/easemob/Easemob-UIKit-web/tree/main)。 + +## 技术原理 + +环信单群聊 UIKit 组件内部集成 IM SDK 和环信服务器连接,实现收发消息等功能。组件使用 React Context API 管理内部状态,用户可以使用 UIKit 提供的自定义 hooks 从全局数据获取需要的数据,也可以用自定义 hooks 获取操作这些数据的方法。 + +![img](@static/images/uikit/chatuikit/web/uikit.png =600x730) + +## 功能 + +`easemob-chat-uikit` 目前提供如下组件: + +- 容器组件:`Provider`、`Chat` 、`ConversationList`、`ContactList`。 +- module 组件:`BaseMessage`、`AudioMessage`、`FileMessage`、 `VideoMessage`、`ImageMessage`、`TextMessage`、`CombinedMessage`、`UserCardMessage`、`GroupDetail`、`UserSelect`、`Header`、`Empty`、`MessageList`、`ConversationItem`、`MessageInput`、`MessageStatus`、`Typing`。 +- 纯 UI 组件:`Avatar`、`Badge`、`Button`、`Checkbox`、`Icon`、`Modal`、`Tooltip`、`scrollList`、`Switch`、`UserItem`、`Broadcast`、`Dropdown`。 + +单群聊 UIKit 中业务相关的 UI 控件主要包含在以下三个组件中: + +- Chat 提供所有聊天视图的容器。 + +![img](@static/images/uikit/chatuikit/web/page_chat.png =500x550) + +- ConversationList 提供会话列表容器。 + +![img](@static/images/uikit/chatuikit/web/page_conversation.png =400x900) + +- ContactList 提供联系人、群组及其详情等容器。 + +![img](@static/images/uikit/chatuikit/web/page_contact_list.png =400x900) diff --git a/docs/uikit/chatuikit/web/chatuikit_provider.md b/docs/uikit/chatuikit/web/chatuikit_provider.md new file mode 100644 index 000000000..e04a19fd7 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_provider.md @@ -0,0 +1,144 @@ +# UIKitProvider + + + +`easemob-chat-uikit` 提供 `UIKitProvider` 组件管理数据。`UIKitProvider` 不渲染任何 UI, 只用于为其他组件提供全局的 context,自动监听 SDK 事件, 在组件树中向下传递数据来驱动组件更新。单群聊 UIKit 中其他组件必须用 `UIKitProvider` 包裹。 + +## 使用示例 + +```jsx +import React from 'react'; +import { UIKitProvider } from 'easemob-chat-uikit'; +import 'easemob-chat-uikit/style.css'; +import ChatApp from './ChatApp' +ReactDOM.createRoot(document.getElementById('root') as Element).render( +
+ , + 'emoji_2': {'emoji_2'}, + } + }} + + features={{ + conversationList: { + // search: false, + item: { + moreAction: false, + deleteConversation: false, + }, + }, + chat: { + header: { + threadList: true, + moreAction: true, + clearMessage: true, + deleteConversation: false, + audioCall: false, + }, + message: { + status: false, + reaction: true, + thread: true, + recall: true, + translate: false, + edit: false, + }, + messageEditor: { + mention: false, + typing: false, + record: true, + emoji: false, + moreAction: true, + picture: true, + }, + }, + }} + > + + +
, +); +``` + +## UIKitProvider 属性概览 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
属性类型描述
+ initConfig + + ProviderProps['initConfig'] + 初始化参数,如设置 appKey、userId、token、是否使用用户属性、翻译的目标语言
+ local + + ProviderProps['local'] + 国际化配置参数,你可以在初始化时配置 i18next 的参数。
+ features + + ProviderProps['features'] + 全局配置你需要的功能,UIKit 默认展示全部的功能。如果在相应的组件中也配置了需要的功能,以组件中的配置为准。
+ reactionConfig + + ProviderProps['reactionConfig'] + 全局配置消息表情回复功能的表情。如果在消息组件中也设置了这个参数,以消息组件中设置的为准。
+ theme + + ProviderProps['theme'] + 主题相关配置,如主要色、明暗主题、组件圆角。
diff --git a/docs/uikit/chatuikit/web/chatuikit_quickstart.md b/docs/uikit/chatuikit/web/chatuikit_quickstart.md new file mode 100644 index 000000000..b59e1162a --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_quickstart.md @@ -0,0 +1,156 @@ +# 快速开始 + + + +利用环信单群聊 UIKit,你可以轻松实现单群和群聊。本文介绍如何快速实现在单聊会话中发送消息。 + +## 前提条件 + +开启单群聊 UIKit 服务前,需确保已经具备以下条件: + +- React 16.8.0 或以上版本; +- React DOM 16.8.0 或以上版本; +- 已在[环信即时通讯云控制台](https://console.easemob.com/user/login)创建了有效的环信即时通讯 IM 开发者账号,并[获取了 App Key](/product/enable_and_configure_IM.html#获取环信即时通讯-im-的信息)。 + +## 支持的浏览器 + +| 浏览器 | 支持的版本 | +| --------- | ---------- | +| IE 浏览器 | 11 或以上 | +| Edge | 43 或以上 | +| Firefox | 10 或以上 | +| Chrome | 54 或以上 | +| Safari | 11 或以上 | + +## 实现发送第一条单聊消息 + +### 第一步 创建 chat-uikit 项目 + +```bash +# 安装 CLI 工具。 +npm install create-react-app +# 构建一个 my-app 的项目。 +npx create-react-app my-app +cd my-app +``` + +``` +项目目录: +├── package.json +├── public # Webpack 的静态目录。 +│ ├── favicon.ico +│ ├── index.html # 默认的单页面应用。 +│ └── manifest.json +├── src +│ ├── App.css # App 根组件的 CSS。 +│ ├── App.js # App 组件代码。 +│ ├── App.test.js +│ ├── index.css # 启动文件样式。 +│ ├── index.js # 启动文件。 +│ ├── logo.svg +│ └── serviceWorker.js +└── yarn.lock +``` + +### 第二步 集成 easemob-chat-uikit + +#### 安装 easemob-chat-uikit + +- 若通过 npm 安装,运行以下命令: + +```bash +npm install easemob-chat-uikit --save +``` + +- 若通过 yarn 安装,运行以下命令: + +```bash +yarn add easemob-chat-uikit +``` + +#### 使用 easemob-chat-uikit 组件构建应用 + +为了方便快速体验,你可以在[环信即时通讯云控制台](https://console.easemob.com/user/login)的**应用概览** > **用户认证**页面创建用户并查看用户 token。**用户认证**页面中的用户仅用于快速体验或调试目的。 + +在开发环境中,你需要在环信控制台[创建 IM 用户](/product/enable_and_configure_IM.html#创建-im-用户),从你的 App Server 获取用户 token,详见[使用环信用户 token 鉴权](/product/easemob_user_token.html) 。 + +将 easemob-chat-uikit 库导入你的代码中: + +```javascript +// App.js +import React, { Component, useEffect } from "react"; +import { + Provider, + Chat, + ConversationList, + useClient, + rootStore, +} from "easemob-chat-uikit"; +import "easemob-chat-uikit/style.css"; + +const ChatApp = () => { + const client = useClient(); + useEffect(() => { + client && + client + .open({ + user: "", + token: "", + }) + .then((res) => { + // 创建会话 + rootStore.conversationStore.addConversation({ + chatType: "singleChat", // 单聊和群聊分别为 'singleChat' 和 'groupChat'。 + conversationId: "userId", // 单聊为对端用户 ID,群聊为群组 ID。 + name: "用户1", // 单聊为对端用户昵称,群聊为群组名称。 + lastMessage: {}, + }); + }); + }, [client]); + + return ( +
+
+ +
+
+ +
+
+ ); +}; + +class App extends Component { + render() { + return ( + + + + ); + } +} + +export default App; +``` + +### 第三步 运行项目并发送你的第一条消息 + +1. 运行项目: + +```bash +npm run start +``` + +在浏览器可看到你的应用。 + +2. 输入你的第一条消息并发送。 + +:::tip +使用自定义 App Key 时,由于没有联系人,需先添加好友。 +::: + +![img](@static/images/uikit/chatuikit/web/message_first.png) diff --git a/docs/uikit/chatuikit/web/chatuikit_storybook.md b/docs/uikit/chatuikit/web/chatuikit_storybook.md new file mode 100644 index 000000000..dd8dd3970 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_storybook.md @@ -0,0 +1,7 @@ +# 组件文档 + + + +`easemob-chat-uikit` 提供三类组件:容器组件、module 组件和纯 UI 组件。组件中包含各种属性供你配置。 + +若要查看组件配置详情,请点击[这里](https://storybook.easemob.com/)。 \ No newline at end of file diff --git a/docs/uikit/chatuikit/web/chatuikit_theme.md b/docs/uikit/chatuikit/web/chatuikit_theme.md new file mode 100644 index 000000000..553357241 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_theme.md @@ -0,0 +1,113 @@ +# 主题 + + + +单群聊 UIKit 内置浅色和深色主题,默认为浅色主题。 + +- 浅色主题 + +![img](@static/images/uikit/chatuikit/web/light_mode.png) + +- 深色主题 + +![img](@static/images/uikit/chatuikit/web/dark_mode.png) + +## 切换内置主题 + +你可以切换为浅色或深色主题: + +```jsx +import { UIKitProvider } from 'easemob-chat-uikit'; + +const App = () => { + return ( + + ); +}; +``` + +## 自定义主题色 + +在单群聊 UIKit 中, 主题色要用于默认头像颜色,消息气泡颜色,按钮颜色等位置。默认的主题色如下图所示,你可以自定义为其他颜色。 + +![img](@static/images/uikit/chatuikit/web/image.png) + +```javascript +import { UIKitProvider } from 'agora-chat-uikit'; + +const App = () => { + return ( + + ); +}; +``` + +## 设置组件形状 + +默认情况下,组件为大圆角形状。你可以设置 `componentsShape` 修改消息气泡、头像和输入框的圆角。 + +```javascript +import { UIKitProvider } from 'easemob-chat-uikit'; + +const App = () => { + return ( + + ); +}; +``` + +## 设置 SCSS 变量 + +单群聊 UIKit 内部使用 SCSS,并定义了一些全局变量。如果你的项目也使用 SCSS,可以通过覆盖这些全局变量修改主题,不过,这种用法并不推荐。 + +你可以点击[这里](https://github.com/easemob/Easemob-UIKit-web/blob/dev/common/style/themes/default.scss)查看定义的变量。 + +下文介绍如何修改这些变量。 + +### 在 Create React App 项目中修改 SCSS 变量 + +在使用 Create React App 创建的项目中,你可以创建一个 SCSS 文件用于覆盖默认的变量。在以下示例中,我们将创建的文件命名为 `your-theme.scss`,然后按照下面的顺序引入文件。 + +```scss +@import 'easemob-chat-uikit/style.scss'; // easemob-chat-uikit 主题 +@import 'your-theme.scss'; // 你的主题文件 +@import 'easemob-chat-uikit/components.scss'; // UIKit 组件样式 +``` + +### 通过修改 Webpack 配置覆盖 SCSS 变量 + +通过配置 SCSS 加载器自动引入自定义的 `style.scss` 文件,覆盖 UIKit 内部的 SCSS 变量。 + +```javascript +module.exports = { + module: { + rules: [ + { + test: /\.s[ac]ss$/i, + use: [ + 'style-loader', + 'css-loader', + { + loader: 'sass-loader', + options: { + additionalData: `@import "@/styles/index.scss";`, + }, + }, + ], + }, + ], + }, +}; +``` diff --git a/docs/uikit/chatuikit/web/chatuikit_video.md b/docs/uikit/chatuikit/web/chatuikit_video.md new file mode 100644 index 000000000..6bec673a7 --- /dev/null +++ b/docs/uikit/chatuikit/web/chatuikit_video.md @@ -0,0 +1,29 @@ +# 音视频通话 + + + +单群聊 UIKit 内部集成了声网音视频 SDK,可以实现在单聊或群组会话中使用音视频通话。 + +## 使用示例 + +使用时需要配置如下参数,可参考 [Callkit 集成文档](https://www.npmjs.com/package/chat-callkit)。 + +```javascript +import { Chat } from "easemob-chat-uikit"; + +const ChatApp = () => { + return ( + + ); +}; +``` diff --git a/static/images/android/push/appsetting.png b/static/images/android/push/appsetting.png new file mode 100644 index 000000000..88279be1c Binary files /dev/null and b/static/images/android/push/appsetting.png differ diff --git a/static/images/android/push/deadline.png b/static/images/android/push/deadline.png new file mode 100644 index 000000000..629e89270 Binary files /dev/null and b/static/images/android/push/deadline.png differ diff --git a/static/images/android/push/fcm_certificate_v1.png b/static/images/android/push/fcm_certificate_v1.png new file mode 100644 index 000000000..4e7904a3a Binary files /dev/null and b/static/images/android/push/fcm_certificate_v1.png differ diff --git a/static/images/android/push/fcm_v1.png b/static/images/android/push/fcm_v1.png index 18f494164..464888c21 100644 Binary files a/static/images/android/push/fcm_v1.png and b/static/images/android/push/fcm_v1.png differ diff --git a/static/images/android/push/fcmproject.png b/static/images/android/push/fcmproject.png new file mode 100644 index 000000000..062c87336 Binary files /dev/null and b/static/images/android/push/fcmproject.png differ diff --git a/static/images/android/push/huawei-notifier-category.png b/static/images/android/push/huawei-notifier-category.png new file mode 100644 index 000000000..fe883e35b Binary files /dev/null and b/static/images/android/push/huawei-notifier-category.png differ diff --git a/static/images/android/push/hxconsoleedit.png b/static/images/android/push/hxconsoleedit.png new file mode 100644 index 000000000..e674a8d33 Binary files /dev/null and b/static/images/android/push/hxconsoleedit.png differ diff --git a/static/images/android/push/old2V1.png b/static/images/android/push/old2V1.png new file mode 100644 index 000000000..f1cbdefdb Binary files /dev/null and b/static/images/android/push/old2V1.png differ diff --git a/static/images/android/push/oppo-notifier-channelId.png b/static/images/android/push/oppo-notifier-channelId.png new file mode 100644 index 000000000..731e5e4a6 Binary files /dev/null and b/static/images/android/push/oppo-notifier-channelId.png differ diff --git a/static/images/android/push/push_template_custom.png b/static/images/android/push/push_template_custom.png new file mode 100644 index 000000000..14691ee77 Binary files /dev/null and b/static/images/android/push/push_template_custom.png differ diff --git a/static/images/android/push/v1Chosefile.png b/static/images/android/push/v1Chosefile.png new file mode 100644 index 000000000..3098649cb Binary files /dev/null and b/static/images/android/push/v1Chosefile.png differ diff --git a/static/images/android/push/v1json.png b/static/images/android/push/v1json.png new file mode 100644 index 000000000..85b7c4195 Binary files /dev/null and b/static/images/android/push/v1json.png differ diff --git a/static/images/android/push/vivo-notifier-category.png b/static/images/android/push/vivo-notifier-category.png new file mode 100644 index 000000000..49ae3f010 Binary files /dev/null and b/static/images/android/push/vivo-notifier-category.png differ diff --git a/static/images/android/push/xiaomi-notifier-channelId.png b/static/images/android/push/xiaomi-notifier-channelId.png new file mode 100644 index 000000000..b5fd859c2 Binary files /dev/null and b/static/images/android/push/xiaomi-notifier-channelId.png differ diff --git a/static/images/callback/callback_payment.png b/static/images/callback/callback_payment.png index 29a7dd520..6af7727b2 100644 Binary files a/static/images/callback/callback_payment.png and b/static/images/callback/callback_payment.png differ diff --git a/static/images/callback/callback_purchase.png b/static/images/callback/callback_purchase.png index a7eb6826b..8bfbc1711 100644 Binary files a/static/images/callback/callback_purchase.png and b/static/images/callback/callback_purchase.png differ diff --git a/static/images/callback/post_delivery_rule_add.png b/static/images/callback/post_delivery_rule_add.png index 9a9acd1f4..3448f88ff 100644 Binary files a/static/images/callback/post_delivery_rule_add.png and b/static/images/callback/post_delivery_rule_add.png differ diff --git a/static/images/electron/sdk_design.png b/static/images/electron/sdk_design.png new file mode 100644 index 000000000..6e12d8000 Binary files /dev/null and b/static/images/electron/sdk_design.png differ diff --git a/static/images/instantpush/huawei_receipt_id.png b/static/images/instantpush/huawei_receipt_id.png new file mode 100644 index 000000000..fd0775214 Binary files /dev/null and b/static/images/instantpush/huawei_receipt_id.png differ diff --git a/static/images/instantpush/huawei_report_v1.png b/static/images/instantpush/huawei_report_v1.png new file mode 100644 index 000000000..6a1546d21 Binary files /dev/null and b/static/images/instantpush/huawei_report_v1.png differ diff --git a/static/images/product/enable_and_configure/message_report_enable.png b/static/images/product/enable_and_configure/message_report_enable.png new file mode 100644 index 000000000..4d19cb1d0 Binary files /dev/null and b/static/images/product/enable_and_configure/message_report_enable.png differ diff --git a/static/images/product/enable_and_configure/user_device_log.png b/static/images/product/enable_and_configure/user_device_log.png new file mode 100644 index 000000000..f6290315c Binary files /dev/null and b/static/images/product/enable_and_configure/user_device_log.png differ diff --git a/static/images/product/push/enable_advanced_function.png b/static/images/product/push/enable_advanced_function.png new file mode 100644 index 000000000..24739e0dd Binary files /dev/null and b/static/images/product/push/enable_advanced_function.png differ diff --git a/static/images/product/credentials.png b/static/images/product/push/push_app_list.png similarity index 100% rename from static/images/product/credentials.png rename to static/images/product/push/push_app_list.png diff --git a/static/images/product/push-settings.png b/static/images/product/push/push_settings.png similarity index 100% rename from static/images/product/push-settings.png rename to static/images/product/push/push_settings.png diff --git a/static/images/product/push-settings-form.png b/static/images/product/push/push_settings_form.png similarity index 100% rename from static/images/product/push-settings-form.png rename to static/images/product/push/push_settings_form.png diff --git a/static/images/product/push-settings-window.png b/static/images/product/push/push_settings_window.png similarity index 100% rename from static/images/product/push-settings-window.png rename to static/images/product/push/push_settings_window.png diff --git a/static/images/product/push/push_template.png b/static/images/product/push/push_template.png new file mode 100644 index 000000000..501861261 Binary files /dev/null and b/static/images/product/push/push_template.png differ diff --git a/static/images/product/push/push_template_add.png b/static/images/product/push/push_template_add.png new file mode 100644 index 000000000..f09fd0400 Binary files /dev/null and b/static/images/product/push/push_template_add.png differ diff --git a/static/images/uikitflutter/ChatConversationsView.png b/static/images/uikit/chatflutter/ChatConversationsView.png similarity index 100% rename from static/images/uikitflutter/ChatConversationsView.png rename to static/images/uikit/chatflutter/ChatConversationsView.png diff --git a/static/images/uikitflutter/ChatConversationsView_avatar.png b/static/images/uikit/chatflutter/ChatConversationsView_avatar.png similarity index 100% rename from static/images/uikitflutter/ChatConversationsView_avatar.png rename to static/images/uikit/chatflutter/ChatConversationsView_avatar.png diff --git a/static/images/uikitflutter/ChatConversationsView_click.png b/static/images/uikit/chatflutter/ChatConversationsView_click.png similarity index 100% rename from static/images/uikitflutter/ChatConversationsView_click.png rename to static/images/uikit/chatflutter/ChatConversationsView_click.png diff --git a/static/images/uikitflutter/ChatConversationsView_custom.png b/static/images/uikit/chatflutter/ChatConversationsView_custom.png similarity index 100% rename from static/images/uikitflutter/ChatConversationsView_custom.png rename to static/images/uikit/chatflutter/ChatConversationsView_custom.png diff --git a/static/images/uikitflutter/ChatConversationsView_nickname.png b/static/images/uikit/chatflutter/ChatConversationsView_nickname.png similarity index 100% rename from static/images/uikitflutter/ChatConversationsView_nickname.png rename to static/images/uikit/chatflutter/ChatConversationsView_nickname.png diff --git a/static/images/uikitflutter/ChatMessagesView.png b/static/images/uikit/chatflutter/ChatMessagesView.png similarity index 100% rename from static/images/uikitflutter/ChatMessagesView.png rename to static/images/uikit/chatflutter/ChatMessagesView.png diff --git a/static/images/uikitflutter/MessagesPage.png b/static/images/uikit/chatflutter/MessagesPage.png similarity index 100% rename from static/images/uikitflutter/MessagesPage.png rename to static/images/uikit/chatflutter/MessagesPage.png diff --git a/static/images/uikitflutter/MessagesPage_custom_avatar.png b/static/images/uikit/chatflutter/MessagesPage_custom_avatar.png similarity index 100% rename from static/images/uikitflutter/MessagesPage_custom_avatar.png rename to static/images/uikit/chatflutter/MessagesPage_custom_avatar.png diff --git a/static/images/uikitflutter/MessagesPage_custom_bubble.png b/static/images/uikit/chatflutter/MessagesPage_custom_bubble.png similarity index 100% rename from static/images/uikitflutter/MessagesPage_custom_bubble.png rename to static/images/uikit/chatflutter/MessagesPage_custom_bubble.png diff --git a/static/images/uikitflutter/MessagesPage_custom_bubble_click.png b/static/images/uikit/chatflutter/MessagesPage_custom_bubble_click.png similarity index 100% rename from static/images/uikitflutter/MessagesPage_custom_bubble_click.png rename to static/images/uikit/chatflutter/MessagesPage_custom_bubble_click.png diff --git a/static/images/uikitflutter/MessagesPage_custom_input.png b/static/images/uikit/chatflutter/MessagesPage_custom_input.png similarity index 100% rename from static/images/uikitflutter/MessagesPage_custom_input.png rename to static/images/uikit/chatflutter/MessagesPage_custom_input.png diff --git a/static/images/uikitflutter/MessagesPage_custom_nickname.png b/static/images/uikit/chatflutter/MessagesPage_custom_nickname.png similarity index 100% rename from static/images/uikitflutter/MessagesPage_custom_nickname.png rename to static/images/uikit/chatflutter/MessagesPage_custom_nickname.png diff --git a/static/images/uikitrn/chat_detail_bg.png b/static/images/uikit/chatrn/chat_detail_bg.png similarity index 100% rename from static/images/uikitrn/chat_detail_bg.png rename to static/images/uikit/chatrn/chat_detail_bg.png diff --git a/static/images/uikitrn/chat_detail_msg_list_item_custom_1.png b/static/images/uikit/chatrn/chat_detail_msg_list_item_custom_1.png similarity index 100% rename from static/images/uikitrn/chat_detail_msg_list_item_custom_1.png rename to static/images/uikit/chatrn/chat_detail_msg_list_item_custom_1.png diff --git a/static/images/uikitrn/chat_detail_msg_list_item_custom_2.png b/static/images/uikit/chatrn/chat_detail_msg_list_item_custom_2.png similarity index 100% rename from static/images/uikitrn/chat_detail_msg_list_item_custom_2.png rename to static/images/uikit/chatrn/chat_detail_msg_list_item_custom_2.png diff --git a/static/images/uikitrn/chat_detail_msg_list_item_custom_3.png b/static/images/uikit/chatrn/chat_detail_msg_list_item_custom_3.png similarity index 100% rename from static/images/uikitrn/chat_detail_msg_list_item_custom_3.png rename to static/images/uikit/chatrn/chat_detail_msg_list_item_custom_3.png diff --git a/static/images/uikitrn/chat_detail_msg_list_item_long_press.png b/static/images/uikit/chatrn/chat_detail_msg_list_item_long_press.png similarity index 100% rename from static/images/uikitrn/chat_detail_msg_list_item_long_press.png rename to static/images/uikit/chatrn/chat_detail_msg_list_item_long_press.png diff --git a/static/images/uikitrn/chat_detail_overview.png b/static/images/uikit/chatrn/chat_detail_overview.png similarity index 100% rename from static/images/uikitrn/chat_detail_overview.png rename to static/images/uikit/chatrn/chat_detail_overview.png diff --git a/static/images/uikitrn/chat_detail_send_voice_msg.png b/static/images/uikit/chatrn/chat_detail_send_voice_msg.png similarity index 100% rename from static/images/uikitrn/chat_detail_send_voice_msg.png rename to static/images/uikit/chatrn/chat_detail_send_voice_msg.png diff --git a/static/images/uikitrn/chat_detail_time_label.png b/static/images/uikit/chatrn/chat_detail_time_label.png similarity index 100% rename from static/images/uikitrn/chat_detail_time_label.png rename to static/images/uikit/chatrn/chat_detail_time_label.png diff --git a/static/images/uikitrn/conv_list_custom_1.png b/static/images/uikit/chatrn/conv_list_custom_1.png similarity index 100% rename from static/images/uikitrn/conv_list_custom_1.png rename to static/images/uikit/chatrn/conv_list_custom_1.png diff --git a/static/images/uikitrn/conv_list_custom_2.png b/static/images/uikit/chatrn/conv_list_custom_2.png similarity index 100% rename from static/images/uikitrn/conv_list_custom_2.png rename to static/images/uikit/chatrn/conv_list_custom_2.png diff --git a/static/images/uikitrn/conv_list_long_press.png b/static/images/uikit/chatrn/conv_list_long_press.png similarity index 100% rename from static/images/uikitrn/conv_list_long_press.png rename to static/images/uikit/chatrn/conv_list_long_press.png diff --git a/static/images/uikitrn/conv_list_overview.png b/static/images/uikit/chatrn/conv_list_overview.png similarity index 100% rename from static/images/uikitrn/conv_list_overview.png rename to static/images/uikit/chatrn/conv_list_overview.png diff --git a/static/images/uikitrn/conv_list_sort.png b/static/images/uikit/chatrn/conv_list_sort.png similarity index 100% rename from static/images/uikitrn/conv_list_sort.png rename to static/images/uikit/chatrn/conv_list_sort.png diff --git a/static/images/uikitrn/conv_list_unread_count.png b/static/images/uikit/chatrn/conv_list_unread_count.png similarity index 100% rename from static/images/uikitrn/conv_list_unread_count.png rename to static/images/uikit/chatrn/conv_list_unread_count.png diff --git a/static/images/uikitrn/conversation_list_slide_menu.png b/static/images/uikit/chatrn/conversation_list_slide_menu.png similarity index 100% rename from static/images/uikitrn/conversation_list_slide_menu.png rename to static/images/uikit/chatrn/conversation_list_slide_menu.png diff --git a/static/images/uikitrn/uikit_quick_start.png b/static/images/uikit/chatrn/uikit_quick_start.png similarity index 100% rename from static/images/uikitrn/uikit_quick_start.png rename to static/images/uikit/chatrn/uikit_quick_start.png diff --git a/static/images/uikit/chatroomandroid/click_chat.png b/static/images/uikit/chatroomandroid/click_chat.png new file mode 100644 index 000000000..c35dee848 Binary files /dev/null and b/static/images/uikit/chatroomandroid/click_chat.png differ diff --git a/static/images/uikit/chatroomandroid/dark_mode.png b/static/images/uikit/chatroomandroid/dark_mode.png new file mode 100644 index 000000000..48fe41839 Binary files /dev/null and b/static/images/uikit/chatroomandroid/dark_mode.png differ diff --git a/static/images/uikit/chatroomandroid/demo.png b/static/images/uikit/chatroomandroid/demo.png new file mode 100644 index 000000000..403fee4ab Binary files /dev/null and b/static/images/uikit/chatroomandroid/demo.png differ diff --git a/static/images/uikit/chatroomandroid/light_mode.png b/static/images/uikit/chatroomandroid/light_mode.png new file mode 100644 index 000000000..9958aa61c Binary files /dev/null and b/static/images/uikit/chatroomandroid/light_mode.png differ diff --git a/static/images/uikit/chatroomdesign/cruk111212.png b/static/images/uikit/chatroomdesign/cruk111212.png new file mode 100644 index 000000000..c3e99ba8a Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk111212.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1113.png b/static/images/uikit/chatroomdesign/cruk1113.png new file mode 100644 index 000000000..a6a2fcb1c Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1113.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11211.png b/static/images/uikit/chatroomdesign/cruk11211.png new file mode 100644 index 000000000..c46fb5943 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11211.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11212.png b/static/images/uikit/chatroomdesign/cruk11212.png new file mode 100644 index 000000000..c3e99ba8a Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11212.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1122.png b/static/images/uikit/chatroomdesign/cruk1122.png new file mode 100644 index 000000000..34ef4c7ba Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1122.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1123.png b/static/images/uikit/chatroomdesign/cruk1123.png new file mode 100644 index 000000000..f675a4aac Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1123.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1124.png b/static/images/uikit/chatroomdesign/cruk1124.png new file mode 100644 index 000000000..b1c63984e Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1124.png differ diff --git a/static/images/uikit/chatroomdesign/cruk113.png b/static/images/uikit/chatroomdesign/cruk113.png new file mode 100644 index 000000000..e1ee0af98 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk113.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1131.png b/static/images/uikit/chatroomdesign/cruk1131.png new file mode 100644 index 000000000..69a054e8d Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1131.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11321.png b/static/images/uikit/chatroomdesign/cruk11321.png new file mode 100644 index 000000000..d987a1736 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11321.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11322.png b/static/images/uikit/chatroomdesign/cruk11322.png new file mode 100644 index 000000000..a9d4b47b0 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11322.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11341.png b/static/images/uikit/chatroomdesign/cruk11341.png new file mode 100644 index 000000000..81fc02465 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11341.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11342.png b/static/images/uikit/chatroomdesign/cruk11342.png new file mode 100644 index 000000000..7eb55d0d5 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11342.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11343.png b/static/images/uikit/chatroomdesign/cruk11343.png new file mode 100644 index 000000000..6b0725d6c Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11343.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1141.png b/static/images/uikit/chatroomdesign/cruk1141.png new file mode 100644 index 000000000..2a1365f6b Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1141.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1151.png b/static/images/uikit/chatroomdesign/cruk1151.png new file mode 100644 index 000000000..5b54276ca Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1151.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11521.png b/static/images/uikit/chatroomdesign/cruk11521.png new file mode 100644 index 000000000..8b1faf285 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11521.png differ diff --git a/static/images/uikit/chatroomdesign/cruk11522.png b/static/images/uikit/chatroomdesign/cruk11522.png new file mode 100644 index 000000000..7ff98d075 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk11522.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1161.png b/static/images/uikit/chatroomdesign/cruk1161.png new file mode 100644 index 000000000..c8daeb483 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1161.png differ diff --git a/static/images/uikit/chatroomdesign/cruk116a.png b/static/images/uikit/chatroomdesign/cruk116a.png new file mode 100644 index 000000000..e5aba6b4e Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk116a.png differ diff --git a/static/images/uikit/chatroomdesign/cruk116b.png b/static/images/uikit/chatroomdesign/cruk116b.png new file mode 100644 index 000000000..e524c73c1 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk116b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk121.png b/static/images/uikit/chatroomdesign/cruk121.png new file mode 100644 index 000000000..c2c3c8200 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk121.png differ diff --git a/static/images/uikit/chatroomdesign/cruk122.png b/static/images/uikit/chatroomdesign/cruk122.png new file mode 100644 index 000000000..92b67595b Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk122.png differ diff --git a/static/images/uikit/chatroomdesign/cruk131.png b/static/images/uikit/chatroomdesign/cruk131.png new file mode 100644 index 000000000..0e21a5ee3 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk131.png differ diff --git a/static/images/uikit/chatroomdesign/cruk132.png b/static/images/uikit/chatroomdesign/cruk132.png new file mode 100644 index 000000000..8347b0037 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk132.png differ diff --git a/static/images/uikit/chatroomdesign/cruk146a.png b/static/images/uikit/chatroomdesign/cruk146a.png new file mode 100644 index 000000000..b6d23a6f7 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk146a.png differ diff --git a/static/images/uikit/chatroomdesign/cruk146b.png b/static/images/uikit/chatroomdesign/cruk146b.png new file mode 100644 index 000000000..ff22669ed Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk146b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk151.png b/static/images/uikit/chatroomdesign/cruk151.png new file mode 100644 index 000000000..97bfc9ecd Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk151.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1522a.png b/static/images/uikit/chatroomdesign/cruk1522a.png new file mode 100644 index 000000000..90d414301 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1522a.png differ diff --git a/static/images/uikit/chatroomdesign/cruk1522b.png b/static/images/uikit/chatroomdesign/cruk1522b.png new file mode 100644 index 000000000..145ec8f2f Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk1522b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk161.png b/static/images/uikit/chatroomdesign/cruk161.png new file mode 100644 index 000000000..c2d24d802 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk161.png differ diff --git a/static/images/uikit/chatroomdesign/cruk162.png b/static/images/uikit/chatroomdesign/cruk162.png new file mode 100644 index 000000000..2d0f519d2 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk162.png differ diff --git a/static/images/uikit/chatroomdesign/cruk2111.png b/static/images/uikit/chatroomdesign/cruk2111.png new file mode 100644 index 000000000..212be2e50 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk2111.png differ diff --git a/static/images/uikit/chatroomdesign/cruk2112.png b/static/images/uikit/chatroomdesign/cruk2112.png new file mode 100644 index 000000000..4d6eac59d Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk2112.png differ diff --git a/static/images/uikit/chatroomdesign/cruk212.png b/static/images/uikit/chatroomdesign/cruk212.png new file mode 100644 index 000000000..b6c6c527f Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk212.png differ diff --git a/static/images/uikit/chatroomdesign/cruk213.png b/static/images/uikit/chatroomdesign/cruk213.png new file mode 100644 index 000000000..4d1d984c5 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk213.png differ diff --git a/static/images/uikit/chatroomdesign/cruk213b.png b/static/images/uikit/chatroomdesign/cruk213b.png new file mode 100644 index 000000000..ac496283e Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk213b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk22.png b/static/images/uikit/chatroomdesign/cruk22.png new file mode 100644 index 000000000..7c1511d1b Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk22.png differ diff --git a/static/images/uikit/chatroomdesign/cruk23.png b/static/images/uikit/chatroomdesign/cruk23.png new file mode 100644 index 000000000..de026a151 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk23.png differ diff --git a/static/images/uikit/chatroomdesign/cruk241.png b/static/images/uikit/chatroomdesign/cruk241.png new file mode 100644 index 000000000..5e745d697 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk241.png differ diff --git a/static/images/uikit/chatroomdesign/cruk242.png b/static/images/uikit/chatroomdesign/cruk242.png new file mode 100644 index 000000000..7a302ddb8 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk242.png differ diff --git a/static/images/uikit/chatroomdesign/cruk243.png b/static/images/uikit/chatroomdesign/cruk243.png new file mode 100644 index 000000000..b98174cb0 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk243.png differ diff --git a/static/images/uikit/chatroomdesign/cruk244.png b/static/images/uikit/chatroomdesign/cruk244.png new file mode 100644 index 000000000..98a528e60 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk244.png differ diff --git a/static/images/uikit/chatroomdesign/cruk245.png b/static/images/uikit/chatroomdesign/cruk245.png new file mode 100644 index 000000000..26925e58e Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk245.png differ diff --git a/static/images/uikit/chatroomdesign/cruk25.png b/static/images/uikit/chatroomdesign/cruk25.png new file mode 100644 index 000000000..bd77389ce Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk25.png differ diff --git a/static/images/uikit/chatroomdesign/cruk26.png b/static/images/uikit/chatroomdesign/cruk26.png new file mode 100644 index 000000000..d9424f35b Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk26.png differ diff --git a/static/images/uikit/chatroomdesign/cruk27.png b/static/images/uikit/chatroomdesign/cruk27.png new file mode 100644 index 000000000..41882f64c Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk27.png differ diff --git a/static/images/uikit/chatroomdesign/cruk28.png b/static/images/uikit/chatroomdesign/cruk28.png new file mode 100644 index 000000000..1f59b663b Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk28.png differ diff --git a/static/images/uikit/chatroomdesign/cruk291.png b/static/images/uikit/chatroomdesign/cruk291.png new file mode 100644 index 000000000..fa0f6e141 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk291.png differ diff --git a/static/images/uikit/chatroomdesign/cruk292.png b/static/images/uikit/chatroomdesign/cruk292.png new file mode 100644 index 000000000..22f003c60 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk292.png differ diff --git a/static/images/uikit/chatroomdesign/cruk293.png b/static/images/uikit/chatroomdesign/cruk293.png new file mode 100644 index 000000000..ef39ddbed Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk293.png differ diff --git a/static/images/uikit/chatroomdesign/cruk311.png b/static/images/uikit/chatroomdesign/cruk311.png new file mode 100644 index 000000000..1a0cb35b9 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk311.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3131.png b/static/images/uikit/chatroomdesign/cruk3131.png new file mode 100644 index 000000000..a06456b82 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3131.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3132.png b/static/images/uikit/chatroomdesign/cruk3132.png new file mode 100644 index 000000000..1a0cb35b9 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3132.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3141.png b/static/images/uikit/chatroomdesign/cruk3141.png new file mode 100644 index 000000000..a51fa6d65 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3141.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3142.png b/static/images/uikit/chatroomdesign/cruk3142.png new file mode 100644 index 000000000..adbcbd763 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3142.png differ diff --git a/static/images/uikit/chatroomdesign/cruk315.png b/static/images/uikit/chatroomdesign/cruk315.png new file mode 100644 index 000000000..2127ff6be Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk315.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3151.png b/static/images/uikit/chatroomdesign/cruk3151.png new file mode 100644 index 000000000..96fa26b8e Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3151.png differ diff --git a/static/images/uikit/chatroomdesign/cruk316.png b/static/images/uikit/chatroomdesign/cruk316.png new file mode 100644 index 000000000..f96e89f1d Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk316.png differ diff --git a/static/images/uikit/chatroomdesign/cruk316b.png b/static/images/uikit/chatroomdesign/cruk316b.png new file mode 100644 index 000000000..e6a0a6431 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk316b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk32.png b/static/images/uikit/chatroomdesign/cruk32.png new file mode 100644 index 000000000..b1ac19014 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk32.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3311.png b/static/images/uikit/chatroomdesign/cruk3311.png new file mode 100644 index 000000000..6e344e55e Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3311.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3311b.png b/static/images/uikit/chatroomdesign/cruk3311b.png new file mode 100644 index 000000000..c57c7a805 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3311b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3311c.png b/static/images/uikit/chatroomdesign/cruk3311c.png new file mode 100644 index 000000000..e6d1380d3 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3311c.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3312.png b/static/images/uikit/chatroomdesign/cruk3312.png new file mode 100644 index 000000000..c6d2f84db Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3312.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3312b.png b/static/images/uikit/chatroomdesign/cruk3312b.png new file mode 100644 index 000000000..9f9abb99c Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3312b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk34.png b/static/images/uikit/chatroomdesign/cruk34.png new file mode 100644 index 000000000..9d4c278c2 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk34.png differ diff --git a/static/images/uikit/chatroomdesign/cruk351.png b/static/images/uikit/chatroomdesign/cruk351.png new file mode 100644 index 000000000..f77a0d6e7 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk351.png differ diff --git a/static/images/uikit/chatroomdesign/cruk352.png b/static/images/uikit/chatroomdesign/cruk352.png new file mode 100644 index 000000000..40cf0a761 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk352.png differ diff --git a/static/images/uikit/chatroomdesign/cruk361.png b/static/images/uikit/chatroomdesign/cruk361.png new file mode 100644 index 000000000..18c69c6f3 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk361.png differ diff --git a/static/images/uikit/chatroomdesign/cruk362.png b/static/images/uikit/chatroomdesign/cruk362.png new file mode 100644 index 000000000..5642aef45 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk362.png differ diff --git a/static/images/uikit/chatroomdesign/cruk363.png b/static/images/uikit/chatroomdesign/cruk363.png new file mode 100644 index 000000000..f3ccdb289 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk363.png differ diff --git a/static/images/uikit/chatroomdesign/cruk363b.png b/static/images/uikit/chatroomdesign/cruk363b.png new file mode 100644 index 000000000..0766466c3 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk363b.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3641.png b/static/images/uikit/chatroomdesign/cruk3641.png new file mode 100644 index 000000000..3a66d067b Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3641.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3642.png b/static/images/uikit/chatroomdesign/cruk3642.png new file mode 100644 index 000000000..82aa4bf44 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3642.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3643.png b/static/images/uikit/chatroomdesign/cruk3643.png new file mode 100644 index 000000000..22100de30 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3643.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3644.png b/static/images/uikit/chatroomdesign/cruk3644.png new file mode 100644 index 000000000..6c1698e84 Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3644.png differ diff --git a/static/images/uikit/chatroomdesign/cruk3645.png b/static/images/uikit/chatroomdesign/cruk3645.png new file mode 100644 index 000000000..30fab08ef Binary files /dev/null and b/static/images/uikit/chatroomdesign/cruk3645.png differ diff --git a/static/images/uikit/chatroomdesign/crukcover.png b/static/images/uikit/chatroomdesign/crukcover.png new file mode 100644 index 000000000..241e137da Binary files /dev/null and b/static/images/uikit/chatroomdesign/crukcover.png differ diff --git a/static/images/uikit/chatroomdesign/crukcover_ease.png b/static/images/uikit/chatroomdesign/crukcover_ease.png new file mode 100644 index 000000000..6e5dfaf5e Binary files /dev/null and b/static/images/uikit/chatroomdesign/crukcover_ease.png differ diff --git a/static/images/uikit/chatroomfeature/barrage_send.png b/static/images/uikit/chatroomfeature/barrage_send.png new file mode 100644 index 000000000..79665e5ed Binary files /dev/null and b/static/images/uikit/chatroomfeature/barrage_send.png differ diff --git a/static/images/uikit/chatroomfeature/barrage_time.png b/static/images/uikit/chatroomfeature/barrage_time.png new file mode 100644 index 000000000..827a7a9de Binary files /dev/null and b/static/images/uikit/chatroomfeature/barrage_time.png differ diff --git a/static/images/uikit/chatroomfeature/chatroom_create.png b/static/images/uikit/chatroomfeature/chatroom_create.png new file mode 100644 index 000000000..5bd7d2c34 Binary files /dev/null and b/static/images/uikit/chatroomfeature/chatroom_create.png differ diff --git a/static/images/uikit/chatroomfeature/chatroom_destroy.png b/static/images/uikit/chatroomfeature/chatroom_destroy.png new file mode 100644 index 000000000..4aeea046a Binary files /dev/null and b/static/images/uikit/chatroomfeature/chatroom_destroy.png differ diff --git a/static/images/uikit/chatroomfeature/dark_mode.png b/static/images/uikit/chatroomfeature/dark_mode.png new file mode 100644 index 000000000..3131cef25 Binary files /dev/null and b/static/images/uikit/chatroomfeature/dark_mode.png differ diff --git a/static/images/uikit/chatroomfeature/gift.png b/static/images/uikit/chatroomfeature/gift.png new file mode 100644 index 000000000..3ac8b47ee Binary files /dev/null and b/static/images/uikit/chatroomfeature/gift.png differ diff --git a/static/images/uikit/chatroomfeature/global_broadcast.png b/static/images/uikit/chatroomfeature/global_broadcast.png new file mode 100644 index 000000000..6f5827d0f Binary files /dev/null and b/static/images/uikit/chatroomfeature/global_broadcast.png differ diff --git a/static/images/uikit/chatroomfeature/member_list.png b/static/images/uikit/chatroomfeature/member_list.png new file mode 100644 index 000000000..a1d7f55b3 Binary files /dev/null and b/static/images/uikit/chatroomfeature/member_list.png differ diff --git a/static/images/uikit/chatroomfeature/member_mute.png b/static/images/uikit/chatroomfeature/member_mute.png new file mode 100644 index 000000000..0b4cab801 Binary files /dev/null and b/static/images/uikit/chatroomfeature/member_mute.png differ diff --git a/static/images/uikit/chatroomfeature/member_remove.png b/static/images/uikit/chatroomfeature/member_remove.png new file mode 100644 index 000000000..448b91534 Binary files /dev/null and b/static/images/uikit/chatroomfeature/member_remove.png differ diff --git a/static/images/uikit/chatroomfeature/member_search.png b/static/images/uikit/chatroomfeature/member_search.png new file mode 100644 index 000000000..77d9f2644 Binary files /dev/null and b/static/images/uikit/chatroomfeature/member_search.png differ diff --git a/static/images/uikit/chatroomfeature/message_unread.png b/static/images/uikit/chatroomfeature/message_unread.png new file mode 100644 index 000000000..dc04cb2a0 Binary files /dev/null and b/static/images/uikit/chatroomfeature/message_unread.png differ diff --git a/static/images/uikit/chatroomfeature/msg_mute.png b/static/images/uikit/chatroomfeature/msg_mute.png new file mode 100644 index 000000000..31fa36a2e Binary files /dev/null and b/static/images/uikit/chatroomfeature/msg_mute.png differ diff --git a/static/images/uikit/chatroomfeature/msg_recall.png b/static/images/uikit/chatroomfeature/msg_recall.png new file mode 100644 index 000000000..21240c72f Binary files /dev/null and b/static/images/uikit/chatroomfeature/msg_recall.png differ diff --git a/static/images/uikit/chatroomfeature/msg_report.png b/static/images/uikit/chatroomfeature/msg_report.png new file mode 100644 index 000000000..68847415c Binary files /dev/null and b/static/images/uikit/chatroomfeature/msg_report.png differ diff --git a/static/images/uikit/chatroomfeature/msg_translate.png b/static/images/uikit/chatroomfeature/msg_translate.png new file mode 100644 index 000000000..9ca004b94 Binary files /dev/null and b/static/images/uikit/chatroomfeature/msg_translate.png differ diff --git a/static/images/uikit/chatroomfeature/mute_list.png b/static/images/uikit/chatroomfeature/mute_list.png new file mode 100644 index 000000000..70b3d188f Binary files /dev/null and b/static/images/uikit/chatroomfeature/mute_list.png differ diff --git a/static/images/uikit/chatroomios/ChatInputBar.png b/static/images/uikit/chatroomios/ChatInputBar.png new file mode 100644 index 000000000..f74baceac Binary files /dev/null and b/static/images/uikit/chatroomios/ChatInputBar.png differ diff --git a/static/images/uikit/chatroomios/ChatroomParticipantsCell.png b/static/images/uikit/chatroomios/ChatroomParticipantsCell.png new file mode 100644 index 000000000..729948250 Binary files /dev/null and b/static/images/uikit/chatroomios/ChatroomParticipantsCell.png differ diff --git a/static/images/uikit/chatroomios/GiftBarrageCell.png b/static/images/uikit/chatroomios/GiftBarrageCell.png new file mode 100644 index 000000000..d2b454937 Binary files /dev/null and b/static/images/uikit/chatroomios/GiftBarrageCell.png differ diff --git a/static/images/uikit/chatroomios/GiftEntityCell.png b/static/images/uikit/chatroomios/GiftEntityCell.png new file mode 100644 index 000000000..3078e9bfc Binary files /dev/null and b/static/images/uikit/chatroomios/GiftEntityCell.png differ diff --git a/static/images/uikit/chatroomios/GiftsViewController.png b/static/images/uikit/chatroomios/GiftsViewController.png new file mode 100644 index 000000000..390d97519 Binary files /dev/null and b/static/images/uikit/chatroomios/GiftsViewController.png differ diff --git a/static/images/uikit/chatroomios/ParticipantsController.png b/static/images/uikit/chatroomios/ParticipantsController.png new file mode 100644 index 000000000..b638d993b Binary files /dev/null and b/static/images/uikit/chatroomios/ParticipantsController.png differ diff --git a/static/images/uikit/chatroomios/ReportOptionsController.png b/static/images/uikit/chatroomios/ReportOptionsController.png new file mode 100644 index 000000000..16c7f525d Binary files /dev/null and b/static/images/uikit/chatroomios/ReportOptionsController.png differ diff --git a/static/images/uikit/chatroomios/avatarPlaceHolder.png b/static/images/uikit/chatroomios/avatarPlaceHolder.png new file mode 100644 index 000000000..06b8be3e1 Binary files /dev/null and b/static/images/uikit/chatroomios/avatarPlaceHolder.png differ diff --git a/static/images/uikit/chatroomios/buildError.png b/static/images/uikit/chatroomios/buildError.png new file mode 100644 index 000000000..f6d356343 Binary files /dev/null and b/static/images/uikit/chatroomios/buildError.png differ diff --git a/static/images/uikit/chatroomios/click_chat.png b/static/images/uikit/chatroomios/click_chat.png new file mode 100644 index 000000000..35d0381ce Binary files /dev/null and b/static/images/uikit/chatroomios/click_chat.png differ diff --git a/static/images/uikit/chatroomios/customchatbarrage.png b/static/images/uikit/chatroomios/customchatbarrage.png new file mode 100644 index 000000000..db6b35613 Binary files /dev/null and b/static/images/uikit/chatroomios/customchatbarrage.png differ diff --git a/static/images/uikit/chatroomios/dark_mode.png b/static/images/uikit/chatroomios/dark_mode.png new file mode 100644 index 000000000..746340bd3 Binary files /dev/null and b/static/images/uikit/chatroomios/dark_mode.png differ diff --git a/static/images/uikit/chatroomios/demo.png b/static/images/uikit/chatroomios/demo.png new file mode 100644 index 000000000..64acd9d1b Binary files /dev/null and b/static/images/uikit/chatroomios/demo.png differ diff --git a/static/images/uikit/chatroomios/emoji.png b/static/images/uikit/chatroomios/emoji.png new file mode 100644 index 000000000..04226b785 Binary files /dev/null and b/static/images/uikit/chatroomios/emoji.png differ diff --git a/static/images/uikit/chatroomios/giftBarrage.png b/static/images/uikit/chatroomios/giftBarrage.png new file mode 100644 index 000000000..81b93b268 Binary files /dev/null and b/static/images/uikit/chatroomios/giftBarrage.png differ diff --git a/static/images/uikit/chatroomios/giftContainerConstraintsSize.png b/static/images/uikit/chatroomios/giftContainerConstraintsSize.png new file mode 100644 index 000000000..a26303dab Binary files /dev/null and b/static/images/uikit/chatroomios/giftContainerConstraintsSize.png differ diff --git a/static/images/uikit/chatroomios/giftPlaceHolder.png b/static/images/uikit/chatroomios/giftPlaceHolder.png new file mode 100644 index 000000000..c02b22359 Binary files /dev/null and b/static/images/uikit/chatroomios/giftPlaceHolder.png differ diff --git a/static/images/uikit/chatroomios/hierarchy.png b/static/images/uikit/chatroomios/hierarchy.png new file mode 100644 index 000000000..449b17759 Binary files /dev/null and b/static/images/uikit/chatroomios/hierarchy.png differ diff --git a/static/images/uikit/chatroomios/inputBar.png b/static/images/uikit/chatroomios/inputBar.png new file mode 100644 index 000000000..6ec34d9cc Binary files /dev/null and b/static/images/uikit/chatroomios/inputBar.png differ diff --git a/static/images/uikit/chatroomios/inputCorner.png b/static/images/uikit/chatroomios/inputCorner.png new file mode 100644 index 000000000..441b9031c Binary files /dev/null and b/static/images/uikit/chatroomios/inputCorner.png differ diff --git a/static/images/uikit/chatroomios/light_mode.png b/static/images/uikit/chatroomios/light_mode.png new file mode 100644 index 000000000..c94a067f6 Binary files /dev/null and b/static/images/uikit/chatroomios/light_mode.png differ diff --git a/static/images/uikit/chatroomios/maxInputHeight.png b/static/images/uikit/chatroomios/maxInputHeight.png new file mode 100644 index 000000000..df006e304 Binary files /dev/null and b/static/images/uikit/chatroomios/maxInputHeight.png differ diff --git a/static/images/uikit/chatroomios/messageActions.png b/static/images/uikit/chatroomios/messageActions.png new file mode 100644 index 000000000..1b1a85338 Binary files /dev/null and b/static/images/uikit/chatroomios/messageActions.png differ diff --git a/static/images/uikit/chatroomios/moreAction.png b/static/images/uikit/chatroomios/moreAction.png new file mode 100644 index 000000000..c46455d66 Binary files /dev/null and b/static/images/uikit/chatroomios/moreAction.png differ diff --git a/static/images/uikit/chatroomios/notifyMessageIcon.png b/static/images/uikit/chatroomios/notifyMessageIcon.png new file mode 100644 index 000000000..d7098f855 Binary files /dev/null and b/static/images/uikit/chatroomios/notifyMessageIcon.png differ diff --git a/static/images/uikit/chatroomios/pageContainerTitleBarItemWidth.png b/static/images/uikit/chatroomios/pageContainerTitleBarItemWidth.png new file mode 100644 index 000000000..93d64cb73 Binary files /dev/null and b/static/images/uikit/chatroomios/pageContainerTitleBarItemWidth.png differ diff --git a/static/images/uikit/chatroomios/report.png b/static/images/uikit/chatroomios/report.png new file mode 100644 index 000000000..6a84a7b19 Binary files /dev/null and b/static/images/uikit/chatroomios/report.png differ diff --git a/static/images/uikit/chatroomios/userIdentityPlaceHolder.png b/static/images/uikit/chatroomios/userIdentityPlaceHolder.png new file mode 100644 index 000000000..681a7450b Binary files /dev/null and b/static/images/uikit/chatroomios/userIdentityPlaceHolder.png differ diff --git a/static/images/uikit/chatroomrn/chatroom.png b/static/images/uikit/chatroomrn/chatroom.png new file mode 100644 index 000000000..3f5b5ee79 Binary files /dev/null and b/static/images/uikit/chatroomrn/chatroom.png differ diff --git a/static/images/uikit/chatroomrn/demo_rn.png b/static/images/uikit/chatroomrn/demo_rn.png new file mode 100644 index 000000000..c1829419c Binary files /dev/null and b/static/images/uikit/chatroomrn/demo_rn.png differ diff --git a/static/images/uikit/chatroomrn/emoji_list.png b/static/images/uikit/chatroomrn/emoji_list.png new file mode 100644 index 000000000..b3c365ed5 Binary files /dev/null and b/static/images/uikit/chatroomrn/emoji_list.png differ diff --git a/static/images/uikit/chatroomrn/gift_list.png b/static/images/uikit/chatroomrn/gift_list.png new file mode 100644 index 000000000..24a862c4a Binary files /dev/null and b/static/images/uikit/chatroomrn/gift_list.png differ diff --git a/static/images/uikit/chatroomrn/input_bar.png b/static/images/uikit/chatroomrn/input_bar.png new file mode 100644 index 000000000..12ba59ee6 Binary files /dev/null and b/static/images/uikit/chatroomrn/input_bar.png differ diff --git a/static/images/uikit/chatroomrn/member_context_menu.png b/static/images/uikit/chatroomrn/member_context_menu.png new file mode 100644 index 000000000..c6ce5e825 Binary files /dev/null and b/static/images/uikit/chatroomrn/member_context_menu.png differ diff --git a/static/images/uikit/chatroomrn/member_list.png b/static/images/uikit/chatroomrn/member_list.png new file mode 100644 index 000000000..b00ce7535 Binary files /dev/null and b/static/images/uikit/chatroomrn/member_list.png differ diff --git a/static/images/uikit/chatroomrn/message_context_menu.png b/static/images/uikit/chatroomrn/message_context_menu.png new file mode 100644 index 000000000..c4bf5e783 Binary files /dev/null and b/static/images/uikit/chatroomrn/message_context_menu.png differ diff --git a/static/images/uikit/chatroomrn/message_report.png b/static/images/uikit/chatroomrn/message_report.png new file mode 100644 index 000000000..9f557e2b8 Binary files /dev/null and b/static/images/uikit/chatroomrn/message_report.png differ diff --git a/static/images/uikit/chatroomweb/chatroom-dark.png b/static/images/uikit/chatroomweb/chatroom-dark.png new file mode 100644 index 000000000..59713195a Binary files /dev/null and b/static/images/uikit/chatroomweb/chatroom-dark.png differ diff --git a/static/images/uikit/chatroomweb/chatroom.png b/static/images/uikit/chatroomweb/chatroom.png new file mode 100644 index 000000000..9ac2c6841 Binary files /dev/null and b/static/images/uikit/chatroomweb/chatroom.png differ diff --git a/static/images/uikit/chatroomweb/chatroomMember-dark.png b/static/images/uikit/chatroomweb/chatroomMember-dark.png new file mode 100644 index 000000000..d8c412751 Binary files /dev/null and b/static/images/uikit/chatroomweb/chatroomMember-dark.png differ diff --git a/static/images/uikit/chatroomweb/chatroomMember.png b/static/images/uikit/chatroomweb/chatroomMember.png new file mode 100644 index 000000000..1682c6937 Binary files /dev/null and b/static/images/uikit/chatroomweb/chatroomMember.png differ diff --git a/static/images/uikit/chatroomweb/chatroom_enter.png b/static/images/uikit/chatroomweb/chatroom_enter.png new file mode 100644 index 000000000..35ca34251 Binary files /dev/null and b/static/images/uikit/chatroomweb/chatroom_enter.png differ diff --git a/static/images/uikit/chatroomweb/dark_mode.png b/static/images/uikit/chatroomweb/dark_mode.png new file mode 100644 index 000000000..fe194df0a Binary files /dev/null and b/static/images/uikit/chatroomweb/dark_mode.png differ diff --git a/static/images/uikit/chatroomweb/light_mode.png b/static/images/uikit/chatroomweb/light_mode.png new file mode 100644 index 000000000..2ebae2dd3 Binary files /dev/null and b/static/images/uikit/chatroomweb/light_mode.png differ diff --git a/static/images/uikit/chatuikit/android/buble1.png b/static/images/uikit/chatuikit/android/buble1.png new file mode 100644 index 000000000..76ffb9b3e Binary files /dev/null and b/static/images/uikit/chatuikit/android/buble1.png differ diff --git a/static/images/uikit/chatuikit/android/buble2.png b/static/images/uikit/chatuikit/android/buble2.png new file mode 100644 index 000000000..9cca14867 Binary files /dev/null and b/static/images/uikit/chatuikit/android/buble2.png differ diff --git a/static/images/uikit/chatuikit/android/contact.png b/static/images/uikit/chatuikit/android/contact.png new file mode 100644 index 000000000..b87481cb8 Binary files /dev/null and b/static/images/uikit/chatuikit/android/contact.png differ diff --git a/static/images/uikit/chatuikit/android/contactlist_configurable.png b/static/images/uikit/chatuikit/android/contactlist_configurable.png new file mode 100644 index 000000000..4806ca8bb Binary files /dev/null and b/static/images/uikit/chatuikit/android/contactlist_configurable.png differ diff --git a/static/images/uikit/chatuikit/android/conversation_list_custom.png b/static/images/uikit/chatuikit/android/conversation_list_custom.png new file mode 100644 index 000000000..3dcf049cf Binary files /dev/null and b/static/images/uikit/chatuikit/android/conversation_list_custom.png differ diff --git a/static/images/uikit/chatuikit/android/cvs-action.png b/static/images/uikit/chatuikit/android/cvs-action.png new file mode 100644 index 000000000..ba8f49e53 Binary files /dev/null and b/static/images/uikit/chatuikit/android/cvs-action.png differ diff --git a/static/images/uikit/chatuikit/android/cvs-header1.png b/static/images/uikit/chatuikit/android/cvs-header1.png new file mode 100644 index 000000000..e06de4884 Binary files /dev/null and b/static/images/uikit/chatuikit/android/cvs-header1.png differ diff --git a/static/images/uikit/chatuikit/android/cvs-nick.png b/static/images/uikit/chatuikit/android/cvs-nick.png new file mode 100644 index 000000000..5145b3aeb Binary files /dev/null and b/static/images/uikit/chatuikit/android/cvs-nick.png differ diff --git a/static/images/uikit/chatuikit/android/dark_mode.png b/static/images/uikit/chatuikit/android/dark_mode.png new file mode 100644 index 000000000..928427bf5 Binary files /dev/null and b/static/images/uikit/chatuikit/android/dark_mode.png differ diff --git a/static/images/uikit/chatuikit/android/editor2.png b/static/images/uikit/chatuikit/android/editor2.png new file mode 100644 index 000000000..c979ac28e Binary files /dev/null and b/static/images/uikit/chatuikit/android/editor2.png differ diff --git a/static/images/uikit/chatuikit/android/group_creating.png b/static/images/uikit/chatuikit/android/group_creating.png new file mode 100644 index 000000000..e2c1ab262 Binary files /dev/null and b/static/images/uikit/chatuikit/android/group_creating.png differ diff --git a/static/images/uikit/chatuikit/android/light_mode.png b/static/images/uikit/chatuikit/android/light_mode.png new file mode 100644 index 000000000..a0a5bcf6c Binary files /dev/null and b/static/images/uikit/chatuikit/android/light_mode.png differ diff --git a/static/images/uikit/chatuikit/android/message_first.png b/static/images/uikit/chatuikit/android/message_first.png new file mode 100644 index 000000000..efb1ba54e Binary files /dev/null and b/static/images/uikit/chatuikit/android/message_first.png differ diff --git a/static/images/uikit/chatuikit/android/msg_bubble_longpressed.png b/static/images/uikit/chatuikit/android/msg_bubble_longpressed.png new file mode 100644 index 000000000..32d4f3548 Binary files /dev/null and b/static/images/uikit/chatuikit/android/msg_bubble_longpressed.png differ diff --git a/static/images/uikit/chatuikit/android/page_chat.png b/static/images/uikit/chatuikit/android/page_chat.png new file mode 100644 index 000000000..8a7ba72c6 Binary files /dev/null and b/static/images/uikit/chatuikit/android/page_chat.png differ diff --git a/static/images/uikit/chatuikit/android/page_contact_list.png b/static/images/uikit/chatuikit/android/page_contact_list.png new file mode 100644 index 000000000..a02c17888 Binary files /dev/null and b/static/images/uikit/chatuikit/android/page_contact_list.png differ diff --git a/static/images/uikit/chatuikit/android/page_conversation.png b/static/images/uikit/chatuikit/android/page_conversation.png new file mode 100644 index 000000000..dac2686f5 Binary files /dev/null and b/static/images/uikit/chatuikit/android/page_conversation.png differ diff --git a/static/images/uikit/chatuikit/design/1.2.1.png b/static/images/uikit/chatuikit/design/1.2.1.png new file mode 100644 index 000000000..4258ca437 Binary files /dev/null and b/static/images/uikit/chatuikit/design/1.2.1.png differ diff --git a/static/images/uikit/chatuikit/design/1.2.2.png b/static/images/uikit/chatuikit/design/1.2.2.png new file mode 100644 index 000000000..b4fb56832 Binary files /dev/null and b/static/images/uikit/chatuikit/design/1.2.2.png differ diff --git a/static/images/uikit/chatuikit/design/CUIcover2.png b/static/images/uikit/chatuikit/design/CUIcover2.png new file mode 100644 index 000000000..aa8e5eef1 Binary files /dev/null and b/static/images/uikit/chatuikit/design/CUIcover2.png differ diff --git a/static/images/uikit/chatuikit/feature/common/chat.png b/static/images/uikit/chatuikit/feature/common/chat.png new file mode 100644 index 000000000..fb1a599c9 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/chat.png differ diff --git a/static/images/uikit/chatuikit/feature/common/contact_namecard.png b/static/images/uikit/chatuikit/feature/common/contact_namecard.png new file mode 100644 index 000000000..1d99815ec Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/contact_namecard.png differ diff --git a/static/images/uikit/chatuikit/feature/common/contact_remark.png b/static/images/uikit/chatuikit/feature/common/contact_remark.png new file mode 100644 index 000000000..472532d30 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/contact_remark.png differ diff --git a/static/images/uikit/chatuikit/feature/common/conversation_create.png b/static/images/uikit/chatuikit/feature/common/conversation_create.png new file mode 100644 index 000000000..443388e7c Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/conversation_create.png differ diff --git a/static/images/uikit/chatuikit/feature/common/conversation_list.png b/static/images/uikit/chatuikit/feature/common/conversation_list.png new file mode 100644 index 000000000..4dca93fe0 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/conversation_list.png differ diff --git a/static/images/uikit/chatuikit/feature/common/file_share.png b/static/images/uikit/chatuikit/feature/common/file_share.png new file mode 100644 index 000000000..da627bde9 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/file_share.png differ diff --git a/static/images/uikit/chatuikit/feature/common/group_admin.png b/static/images/uikit/chatuikit/feature/common/group_admin.png new file mode 100644 index 000000000..ce8074d70 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/group_admin.png differ diff --git a/static/images/uikit/chatuikit/feature/common/group_create.png b/static/images/uikit/chatuikit/feature/common/group_create.png new file mode 100644 index 000000000..d2e2cdf83 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/group_create.png differ diff --git a/static/images/uikit/chatuikit/feature/common/group_member_nickname.png b/static/images/uikit/chatuikit/feature/common/group_member_nickname.png new file mode 100644 index 000000000..2892dafd5 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/group_member_nickname.png differ diff --git a/static/images/uikit/chatuikit/feature/common/message_audio.png b/static/images/uikit/chatuikit/feature/common/message_audio.png new file mode 100644 index 000000000..5170dc81d Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/message_audio.png differ diff --git a/static/images/uikit/chatuikit/feature/common/message_delivery_receipt.png b/static/images/uikit/chatuikit/feature/common/message_delivery_receipt.png new file mode 100644 index 000000000..be9cef440 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/message_delivery_receipt.png differ diff --git a/static/images/uikit/chatuikit/feature/common/message_read_receipt.png b/static/images/uikit/chatuikit/feature/common/message_read_receipt.png new file mode 100644 index 000000000..c749678ae Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/message_read_receipt.png differ diff --git a/static/images/uikit/chatuikit/feature/common/message_report.png b/static/images/uikit/chatuikit/feature/common/message_report.png new file mode 100644 index 000000000..024fb2491 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/message_report.png differ diff --git a/static/images/uikit/chatuikit/feature/common/message_search.png b/static/images/uikit/chatuikit/feature/common/message_search.png new file mode 100644 index 000000000..4e3d77ff9 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/message_search.png differ diff --git a/static/images/uikit/chatuikit/feature/common/message_unread_count.png b/static/images/uikit/chatuikit/feature/common/message_unread_count.png new file mode 100644 index 000000000..51755a634 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/message_unread_count.png differ diff --git a/static/images/uikit/chatuikit/feature/common/user_list.png b/static/images/uikit/chatuikit/feature/common/user_list.png new file mode 100644 index 000000000..a6f0ac581 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/common/user_list.png differ diff --git a/static/images/uikit/chatuikit/feature/conversation/conversation_delete.png b/static/images/uikit/chatuikit/feature/conversation/conversation_delete.png new file mode 100644 index 000000000..48a4bc216 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/conversation/conversation_delete.png differ diff --git a/static/images/uikit/chatuikit/feature/conversation/conversation_dnd.png b/static/images/uikit/chatuikit/feature/conversation/conversation_dnd.png new file mode 100644 index 000000000..060e7ae4a Binary files /dev/null and b/static/images/uikit/chatuikit/feature/conversation/conversation_dnd.png differ diff --git a/static/images/uikit/chatuikit/feature/conversation/conversation_pin.png b/static/images/uikit/chatuikit/feature/conversation/conversation_pin.png new file mode 100644 index 000000000..f144f8fa1 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/conversation/conversation_pin.png differ diff --git a/static/images/uikit/chatuikit/feature/conversation/conversation_read.png b/static/images/uikit/chatuikit/feature/conversation/conversation_read.png new file mode 100644 index 000000000..44cce9276 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/conversation/conversation_read.png differ diff --git a/static/images/uikit/chatuikit/feature/message/message_copy.png b/static/images/uikit/chatuikit/feature/message/message_copy.png new file mode 100644 index 000000000..04c5db9df Binary files /dev/null and b/static/images/uikit/chatuikit/feature/message/message_copy.png differ diff --git a/static/images/uikit/chatuikit/feature/message/message_delete.png b/static/images/uikit/chatuikit/feature/message/message_delete.png new file mode 100644 index 000000000..cca3bef14 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/message/message_delete.png differ diff --git a/static/images/uikit/chatuikit/feature/message/message_edit.png b/static/images/uikit/chatuikit/feature/message/message_edit.png new file mode 100644 index 000000000..e932a1855 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/message/message_edit.png differ diff --git a/static/images/uikit/chatuikit/feature/message/message_recall.png b/static/images/uikit/chatuikit/feature/message/message_recall.png new file mode 100644 index 000000000..b5bb0d909 Binary files /dev/null and b/static/images/uikit/chatuikit/feature/message/message_recall.png differ diff --git a/static/images/uikit/chatuikit/feature/message/message_reply.png b/static/images/uikit/chatuikit/feature/message/message_reply.png new file mode 100644 index 000000000..e2287a7dc Binary files /dev/null and b/static/images/uikit/chatuikit/feature/message/message_reply.png differ diff --git a/static/images/uikit/chatuikit/ios/buildError.png b/static/images/uikit/chatuikit/ios/buildError.png new file mode 100644 index 000000000..f6d356343 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/buildError.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_audioDuration.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_audioDuration.png new file mode 100644 index 000000000..b8f060c87 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_audioDuration.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_bubbleColor.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_bubbleColor.png new file mode 100644 index 000000000..7f09321c3 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_bubbleColor.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_bubbleStyle.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_bubbleStyle.png new file mode 100644 index 000000000..3e62cd7d9 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_bubbleStyle.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_contentStyle.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_contentStyle.png new file mode 100644 index 000000000..96972ae83 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_contentStyle.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_dateFormat.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_dateFormat.png new file mode 100644 index 000000000..1dbd678da Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_dateFormat.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_imageMessageCorner.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_imageMessageCorner.png new file mode 100644 index 000000000..287e2aa54 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_imageMessageCorner.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_input.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_input.png new file mode 100644 index 000000000..4a65fdd8b Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_input.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_messageLongPressedActions.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_messageLongPressedActions.png new file mode 100644 index 000000000..44abca31e Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_messageLongPressedActions.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_receiveAudioAnimationImages.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_receiveAudioAnimationImages.png new file mode 100644 index 000000000..9853caf0e Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_receiveAudioAnimationImages.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_report.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_report.png new file mode 100644 index 000000000..5687f51cb Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_report.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_textColor.png b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_textColor.png new file mode 100644 index 000000000..b1174b2eb Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/chat/Appearance_chat_textColor.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_actionSheetRowHeight.png b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_actionSheetRowHeight.png new file mode 100644 index 000000000..e88118d12 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_actionSheetRowHeight.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_alertContainerConstraintsSize.png b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_alertContainerConstraintsSize.png new file mode 100644 index 000000000..dc9217920 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_alertContainerConstraintsSize.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_pageContainerConstraintsSize.png b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_pageContainerConstraintsSize.png new file mode 100644 index 000000000..01cbcc5a1 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_pageContainerConstraintsSize.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_pageContainerTitleBarItemWidth.png b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_pageContainerTitleBarItemWidth.png new file mode 100644 index 000000000..93d64cb73 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/common/Appearance_pageContainerTitleBarItemWidth.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_detailExtensionActionItems.png b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_detailExtensionActionItems.png new file mode 100644 index 000000000..c894bee86 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_detailExtensionActionItems.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_headerRowHeight.png b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_headerRowHeight.png new file mode 100644 index 000000000..e807705ba Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_headerRowHeight.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_listHeaderExtensionActions.png b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_listHeaderExtensionActions.png new file mode 100644 index 000000000..66cc27e49 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_listHeaderExtensionActions.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_moreActions.png b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_moreActions.png new file mode 100644 index 000000000..9e54b8873 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_moreActions.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_rowHeight.png b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_rowHeight.png new file mode 100644 index 000000000..e326e7345 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/contact/Appearance_contact_rowHeight.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_dateFormat.png b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_dateFormat.png new file mode 100644 index 000000000..172f70156 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_dateFormat.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_list_more.png b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_list_more.png new file mode 100644 index 000000000..5574fbad0 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_list_more.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_placeHolder.png b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_placeHolder.png new file mode 100644 index 000000000..f6ca25bec Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_placeHolder.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_rowHeight.png b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_rowHeight.png new file mode 100644 index 000000000..454b22309 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_rowHeight.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_swipeLeftActions.png b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_swipeLeftActions.png new file mode 100644 index 000000000..7ee680bc0 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_swipeLeftActions.png differ diff --git a/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_swipe_right_more.png b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_swipe_right_more.png new file mode 100644 index 000000000..a6dd3a35d Binary files /dev/null and b/static/images/uikit/chatuikit/ios/configurationitem/conversation/Appearance_conversation_swipe_right_more.png differ diff --git a/static/images/uikit/chatuikit/ios/dark_mode.png b/static/images/uikit/chatuikit/ios/dark_mode.png new file mode 100644 index 000000000..5144f662b Binary files /dev/null and b/static/images/uikit/chatuikit/ios/dark_mode.png differ diff --git a/static/images/uikit/chatuikit/ios/light_mode.png b/static/images/uikit/chatuikit/ios/light_mode.png new file mode 100644 index 000000000..3187960c6 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/light_mode.png differ diff --git a/static/images/uikit/chatuikit/ios/message_first.png b/static/images/uikit/chatuikit/ios/message_first.png new file mode 100644 index 000000000..fc591c932 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/message_first.png differ diff --git a/static/images/uikit/chatuikit/ios/page_chat.png b/static/images/uikit/chatuikit/ios/page_chat.png new file mode 100644 index 000000000..36697f982 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/page_chat.png differ diff --git a/static/images/uikit/chatuikit/ios/page_contact_list.png b/static/images/uikit/chatuikit/ios/page_contact_list.png new file mode 100644 index 000000000..db038335a Binary files /dev/null and b/static/images/uikit/chatuikit/ios/page_contact_list.png differ diff --git a/static/images/uikit/chatuikit/ios/page_conversation.png b/static/images/uikit/chatuikit/ios/page_conversation.png new file mode 100644 index 000000000..a6119ad10 Binary files /dev/null and b/static/images/uikit/chatuikit/ios/page_conversation.png differ diff --git a/static/images/uikit/chatuikit/web/buble1.png b/static/images/uikit/chatuikit/web/buble1.png new file mode 100644 index 000000000..212af2d99 Binary files /dev/null and b/static/images/uikit/chatuikit/web/buble1.png differ diff --git a/static/images/uikit/chatuikit/web/buble2.png b/static/images/uikit/chatuikit/web/buble2.png new file mode 100644 index 000000000..3bbd95ebc Binary files /dev/null and b/static/images/uikit/chatuikit/web/buble2.png differ diff --git a/static/images/uikit/chatuikit/web/contact-block.png b/static/images/uikit/chatuikit/web/contact-block.png new file mode 100644 index 000000000..f56d7a663 Binary files /dev/null and b/static/images/uikit/chatuikit/web/contact-block.png differ diff --git a/static/images/uikit/chatuikit/web/contact-header.png b/static/images/uikit/chatuikit/web/contact-header.png new file mode 100644 index 000000000..db445b11a Binary files /dev/null and b/static/images/uikit/chatuikit/web/contact-header.png differ diff --git a/static/images/uikit/chatuikit/web/contact-select.png b/static/images/uikit/chatuikit/web/contact-select.png new file mode 100644 index 000000000..dcb1b60f3 Binary files /dev/null and b/static/images/uikit/chatuikit/web/contact-select.png differ diff --git a/static/images/uikit/chatuikit/web/custom-msg.png b/static/images/uikit/chatuikit/web/custom-msg.png new file mode 100644 index 000000000..9ff2bab22 Binary files /dev/null and b/static/images/uikit/chatuikit/web/custom-msg.png differ diff --git a/static/images/uikit/chatuikit/web/cvs-action.png b/static/images/uikit/chatuikit/web/cvs-action.png new file mode 100644 index 000000000..c219025db Binary files /dev/null and b/static/images/uikit/chatuikit/web/cvs-action.png differ diff --git a/static/images/uikit/chatuikit/web/cvs-bg.png b/static/images/uikit/chatuikit/web/cvs-bg.png new file mode 100644 index 000000000..ff9dd9204 Binary files /dev/null and b/static/images/uikit/chatuikit/web/cvs-bg.png differ diff --git a/static/images/uikit/chatuikit/web/cvs-header1.png b/static/images/uikit/chatuikit/web/cvs-header1.png new file mode 100644 index 000000000..c721ff08c Binary files /dev/null and b/static/images/uikit/chatuikit/web/cvs-header1.png differ diff --git a/static/images/uikit/chatuikit/web/cvs-header2.png b/static/images/uikit/chatuikit/web/cvs-header2.png new file mode 100644 index 000000000..8ccefd761 Binary files /dev/null and b/static/images/uikit/chatuikit/web/cvs-header2.png differ diff --git a/static/images/uikit/chatuikit/web/cvs-nick.png b/static/images/uikit/chatuikit/web/cvs-nick.png new file mode 100644 index 000000000..0a4902121 Binary files /dev/null and b/static/images/uikit/chatuikit/web/cvs-nick.png differ diff --git a/static/images/uikit/chatuikit/web/dark_mode.png b/static/images/uikit/chatuikit/web/dark_mode.png new file mode 100644 index 000000000..78c949471 Binary files /dev/null and b/static/images/uikit/chatuikit/web/dark_mode.png differ diff --git a/static/images/uikit/chatuikit/web/editor2.png b/static/images/uikit/chatuikit/web/editor2.png new file mode 100644 index 000000000..4012fbc82 Binary files /dev/null and b/static/images/uikit/chatuikit/web/editor2.png differ diff --git a/static/images/uikit/chatuikit/web/image.png b/static/images/uikit/chatuikit/web/image.png new file mode 100644 index 000000000..f2a288f4c Binary files /dev/null and b/static/images/uikit/chatuikit/web/image.png differ diff --git a/static/images/uikit/chatuikit/web/light_mode.png b/static/images/uikit/chatuikit/web/light_mode.png new file mode 100644 index 000000000..a351f7fc8 Binary files /dev/null and b/static/images/uikit/chatuikit/web/light_mode.png differ diff --git a/static/images/uikit/chatuikit/web/message_first.png b/static/images/uikit/chatuikit/web/message_first.png new file mode 100644 index 000000000..a44684419 Binary files /dev/null and b/static/images/uikit/chatuikit/web/message_first.png differ diff --git a/static/images/uikit/chatuikit/web/page_chat.png b/static/images/uikit/chatuikit/web/page_chat.png new file mode 100644 index 000000000..ded616a6f Binary files /dev/null and b/static/images/uikit/chatuikit/web/page_chat.png differ diff --git a/static/images/uikit/chatuikit/web/page_contact_list.png b/static/images/uikit/chatuikit/web/page_contact_list.png new file mode 100644 index 000000000..0a5a2f730 Binary files /dev/null and b/static/images/uikit/chatuikit/web/page_contact_list.png differ diff --git a/static/images/uikit/chatuikit/web/page_conversation.png b/static/images/uikit/chatuikit/web/page_conversation.png new file mode 100644 index 000000000..0df4cffb3 Binary files /dev/null and b/static/images/uikit/chatuikit/web/page_conversation.png differ diff --git a/static/images/uikit/chatuikit/web/uikit.png b/static/images/uikit/chatuikit/web/uikit.png new file mode 100644 index 000000000..f170be5c6 Binary files /dev/null and b/static/images/uikit/chatuikit/web/uikit.png differ