feat:引入wfc即时通讯IM plugin

This commit is contained in:
ctw committed 2025-11-21 17:32:22 +08:00
1 parent 18f3b76cf2
commit f85c71cb0a
145 files changed
+11733 -4

No files matched your search

+15
View File
@@ -1,6 +1,7 @@
<script setup>
import { onLaunch, onShow, onError } from '@dcloudio/uni-app';
import { ShoproInit } from './sheep';
import RecentApi from './sheep/api/member/recent';
onLaunch(() => {
// 隐藏原生导航栏 使用自定义底部导航
@@ -10,6 +11,20 @@
// 加载Shopro底层依赖
ShoproInit();
// 更新用户位置
uni.getLocation({
success: (res) => {
const params = {
issueLat: String(res.latitude),
issueLong: String(res.longitude),
};
RecentApi.updateUserLocation(params);
},
fail: (err) => {
uni.showToast({ title: '位置信息获取失败', icon: 'none' });
},
});
});
onShow(() => {
+153
View File
@@ -0,0 +1,153 @@
export default class Config {
// 调试用
static ENABLE_AUTO_LOGIN = true;
// 是否支持多人音视频通话
static ENABLE_MULTI_VOIP_CALL = true;
// 是否支持1对1音视频通话
static ENABLE_SINGLE_VOIP_CALL = true;
static DEFAULT_PORTRAIT_URL = 'data:image/png;base64,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';
static DEFAULT_GROUP_PORTRAIT_URL = 'data:image/png;base64,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'
static DEFAULT_ORGANIZATION_PORTRAIT_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAACXBIWXMAAAsTAAALEwEAmpwYAAABlUlEQVR4nO2aIW7DQBBFc409UJRD9AoFJr1DeUADSrogoDws8EslloKCLeUEOcDWEzWtii133d2xH/h0ZD/9Pzs72lVSMBRGM1gBL/zJQAAUAK1kinCgAGg4UH4nASIsABoOVPkoEmEtBGDcN5PodFgvA+Dm+WMSfUFcDMDm/WK79jObANgC0HAgETZ6oDhEjENEnMKMMWIONAbplkHauIlwlTPuwprhMuFhd74vFHJpccuEDeus6UHHfXMHXcJVVTswARCACQcGIpwqaDP0QAHQcKAYY4wxpkLFJQ3Sp8M6+1ONp5fX3ztublUHMP64xYuqBZgyfpiXmgAUAA0Higibh35FDxQADQc6jltkjAkATDjQb9wiEQ6+AY5dGqQZ1MwKcHu8DNLj23nwz9ZeMyvA7toP0vb4/W5lDjUBeAWg4UARYRf9KtIDewB2ONBv3CIR7gHY4UC/cYtEuAdghwP/Z00UndTMskwY+worzaBmFoAoADBlNgIOFACtZGvBgQKg4UD5PeGJsABoOFDlo0iEVQbgDWanvolAkB8PAAAAAElFTkSuQmCC';
static DEFAULT_DEPARTMENT_PORTRAIT_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABQCAYAAACOEfKtAAAAAXNSR0IArs4c6QAAAIRlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAFCgAwAEAAAAAQAAAFAAAAAAwtohTAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KGV7hBwAAAjlJREFUeAHt28FOwkAQgOGt8UF4Cg0nOJjo1bfgEfRkPekj8BZeOGjigRuRcNeTJ30NsW0g2UzatTNTpE3+JiS7dGba/dgAW0oIbAgggAACCCCAAAIIIIAAAgMTyI59vlcPq2lxDuVDtT3fjnNVwoGCTw9UV1N2us3CnSZhF5sbcjpP6QNgNajri7NWg/v4/A7vxaMv20lfTmSo5wGg85UDEECngDOdGQigU8CZzgwE0CngTGcGAugUcKYzAwF0CjjTmYEAOgWc6b25nPX0unYO5TjpfQBcZtvawY9+QhgV7zHL2r08mRYoLvXnl4+retp06r/u5UPEyQ0ggE4BZzozEECngDOdGQigU8CZ3smtHdbbM1LnXnyJnmZZmBRfsu9TcZZ9Xd4W0tVKxHp7RuP496+s8baPxrq7HflfAW33dwVYHe/lZrwfd9vjN8aVK5ES7xA1Gw9q2MGHiAEtTgEw1jC0ATSgxSkAxhqGNoAGtDgFwFjD0AbQgBanABhrGNoAGtDiFNXKIbHmTf4AlFp7DqVmjBa3tUu5xjVv+UoUvwBN4uJRO4/asjmUmvK8q74WsEqaz85ri8knF5uvsNi0+0vCUGrKMfIeKEWUfQCVYDIcQCmi7AOoBJPhAEoRZR9AJZgMB1CKKPsAKsFkOIBSRNkHUAkmwwGUIso+gEowGQ6gFFH2AVSCyXDT5azZ/E3WcfeHUlMOVAvY9JcEWVfTH0pNzZiIRQABBBBAAAEEEEAAAQQQ6K/ALz1vZTdxNVa5AAAAAElFTkSuQmCC';
// 视频消息发送完成之前,无法拿到缩略图,故显示一个占位图,256x256
static DEFAULT_VIDEO_POSTER = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAY/klEQVR4nO3de6yV1ZnH8W9PTggxhBhCDEOIMYYSYgyxDOMwjsOsodYyahHvtVbrhdZ6q+NUShtCiGMYq9bqVNEW75eqY62ll1GGWnyGOMQSa40xxjiEEEIIYwhhDCGEkJP541n7uDnuc/btffd6L79PQjgczn7PI5732etd61nPAhEREamfz6UOQHpjZpOAk4DZwFzg8/HjE4CpwBRguOn3g8DRpkuMxM+NNP3dIeBI/PPh+Hvj4/+LHx9o+rU//toXQjic13+r5EcJoODMbAg4GVgA/BV+s8/Gb/5J6SL7jAPAbmAn8D7wJ2AbsDuEMJIwLpmAEkCBxJt9Fp/e7AuA+cC0lHH1aQ/wDvBH4G1gWwhhf9qQpEEJIKF4w88EFgNfAgKeAKrsCPAesBl4A9gaQvgkbUj1pQQwQPGGnwoswm/4xfiQfihlXIkdxh8VDHgNeCeEcCRpRDWiBJCzpmH9MuB84EyK9exeNLuAjcCvgC0hhEOJ46k0JYAcxJt+NrAUuAh/lh9OGlQ5HQA24clgYwjhQOJ4KkcJICPxpj8R+DpwAXAa9R7aZ+0AsAF4FnhTjwnZUALok5lNBpYA3wTOQsP7QdgBvAT8HPhAy4y9UwLoQdMQ/xr8Hb/qM/dFNQK8CTwC/C6EcDBxPKWjBNCFWH23BLgFX7LTc31x7AIeB55CxUcdUwLogJlNBS4GbgXmJQ5HJnYInytYhxcdHW3z9bWmBDABMzsBuBa4AZ/gk/IYwVcQ7sYnDZUIWlACaMHMTgRuA66i3GW44olgM3AfsFmrB8dSAmhiZtPxYf7NwPGJw5HsbQHuAl7XiMApAQBmNgUf6q/Ea/OluhqPBmuAt+s+WVjrBBDX8C8EVuM1+VIfR/BagjuB7XVNBLVMAHEdfyFwL3BG4nAkrYPAeuDeEMLe1MEMWu0SQJzZXw0sByYnDkeKYzf+CPhynSYKa5MAYhHPMnxZ6KS00UiB/QZYEUL4KHUgg1CLBGBmc/Ebf2nqWKQU9gNrgZ9WfTtypRNAnORbjk/0aFlPurUVuCGE8F7qQPJS2QQQi3n+DR/2i/TqAPAD4Kkqdj6uXAIws2HgPOBBtEtPsvMycFsIYXfqQLJUqQRgZtOAO4Bvo516kr1dwE14d6JKVBJWJgGY2TzgSbyNtkhejgA/AtZWYYKw9AkgDvmX4ds/T0gcjtTHq8D1ZX8kKHUCMLPjgFXA7agVlwzedrwr1NaylhKXNgGY2UzgZ/iEn0gqnwAr8FWC0lUQljIBmNlpwAtoA48UwwjwE2BV2eYFSpUA4iaexXhr6BmJwxEZ62V8XqA0Zx+Wpm99vPm/BvwS3fxSTBcDv45FaKVQigQQS3pvx5f5piYOR2QiZwK/j4+phVf4R4A4038X8J3UsYh0YS9wWQhhS+pAJlLoBBBbdd2Pb+gRKZt9wJUhhI2pAxlPYRNAvPnX4Z15RcrqAHAFXj5cuFqBQs4BxIM4Hkc3v5Tf8fiS9YVxIrtQCjcCiDf/k3izTpGqOAhch7ccK8xIoFAJIN78T6M9/FJNB/HS4VeKkgQKMySJs/3r0M0v1TUFf7RdkjqQhkIkgLjOfx9+1LZIlU0FnjWzkDoQKEACiN16G008ROpgGvCCmZ2eOpCkCSDu5f9e/CVSJzOAX5rZqSmDSDYJGJdErgIeRe27pL7eB74cQtiT4punHAEEvGuvbn6ps1OBJ+MK2MAlSQBmdgq+3KeNPSJwNnBXnA8bqIEngHg237OoZbdIsxuBmwddLTjQbxbX+h9FnXtFWlnLgI+vG1gCiJltJTqfT2Q8k4GfxUfkgRjkCOAc4PsD/H4iZXQC8LiZDeQsy4EkADObg3fwVetukfYWAmtjnUyuck8AcXnjUWBm3t9LpEK+jffAzFWuCSBmsDXAojy/j0gFDQH3591bMO8RwNnAzTl/D5GqmoZPCk7J6xvklgDMbAZe6afnfpHenQ6szKs+IJeLxqH/XcDsPK4vUjO3A2fkceG8RgDLUD8/kaxMBtblsTSYeQIws1n40D95rwGRCpkHrMn6USDTi8Wh/91oyU8kDzfiJw9lJut36bOASzO+ZtUcTR2AlNYk4L64pyYTmSWAWPBzL9rf386LwCagdGfJSyEsAL6V1cWyHAF8B29uIBN7A7gAuAnYjp8tL9KNVWZ2UhYXyiQBmNlcYEUW16qBkRDCoRDCY8DfAw8ApTlPXgphOhntFeg7AcQg1qLuPp062Pgg9oFbAfwjeiyQ7lyKt9XrSxYjgIAO8+jGMZOAIYSREMI24HzgBvRYIJ0ZxkcBk/u5SF8JIH7zO/q9To0cZZxVgBDC4RDCE8AXgfXAJ4MMTErpdODifi7Q7427jJxKFCtqhDbD/BDCLnyC8AJgS7uvl9pb3U9H4Z4TQNyhtKbX18v44mPBZuBc4LvATvRYIK3NAZb3+uJ+RgDXAnP7eL20EUI4GEJ4CPgS8AxNE4giTVbEbttd6ykBxE0JK3t5rXQvhLAd+CZwGbANVRPKsWYAt/bywl5HAFehev+BCiEcDSG8CnwZf/RKcpSUFNZyM5ve7Yu6TgDx2b+nbCOM0Oe7dwjhQAjhX/HagZeBQ1kEJqV3Aj3MBfQyArgUOLmH14nf/JnM6ocQ3gOuAK4B3kOThAK3dLsi0FUCiOv+KvktiBDCkRDCS/gk4T3AvsQhSVozgau7eUG3I4ClaOa/cEIIHwOr8GXDV4HDaSOShG7ppoloxwkg1vzf1lNIkrumkuJL8JLij9BjQR3NpovS/G5GAPPx0kMpsLjT8Cm8pPgh4EDaiCSB6zvdKdhNAri+y6+XhEIIu/ER2/nAZlRSXCdn4D0E2+roho5VRn1tOpDBi48FW/AkoJLi+hjCHwM7+sJOfA3t9y+tMSXFT6CdhnVwaSeFQW0TgJlNwstQpX9HSFi4E0uKb8BLit9CJcVVNhX4ersv6mQEsBA4pe9wpBBiSfFGvJJwNSoprrJr2k0GdpIArswoGCmQWFL8Q3xvwUuopLiK5tFmMnDCBBALCtTuq8JCCO/jSV4lxdV0xUR/2W4EsATvQCoV1lRS/GXgR6ikuEoujPN4LY2bAOIZZBNmD6mWEMJe4AfAV4CNqHagCk5iguPEJhoBTAfOzjoaKbZYO/AWcBFwC+pSXAWXj/cXEyWApUBmZ5BJucSS4vV47YC6FJfbsvHah0+UAM7NKRgpkRDCTnwkcBHwJqodKKPp+HL+Z7RMAPH00cV5RlRjpRtOx9qB1/G5gZXArsQhSfe+0uqT440AFqHS3zwcpcR79WPtwI/xIqLnUJfiMlkSJ/aPMV4CaJktpG+le/dvJYTwAXAdXj/wNnosKIO5eK+AY3wmAcTSwSWDiEjKK9YObMBHA3cCexOHJBMbAs5p9cmx5qKmn9KhEMK+EMK/4JPGGyjxI04NfGZiv1UCCPnHIVUTQngHX2++DviAijzuVMzCOME/qlUC+IcBBSMVE084fh4vKX4A2J84JDnWFGBB8yeOSQDx+X/cskGRTsR2ZCvwE45fRyXFRbKo+Q9jRwBz8BNGRPrS1I7sArw34Q70WFAEf9f8h7EJYBEiGYrtyB7GHwvUjiy9hc1lwWMTgJ7/JRdN7cguR+3IUpoKnNb4w9gE0LJeWCQLTSccn4ufcLw7cUh1dUbjg9EEEFt/z0oSTn2MoAkxQgj74wnH56J2ZCl8ofFB8wjgNHTwR976Ph68SuIJx99A7cgGbX7jg7EJQGSgYu2A2pEN1pzGAaLNCeAvEwUjonZkgzUMnArHJoD5rb9WZDCa2pFdAtyK2pHlaT7EBGBmU/HmgSLJxdqBn+I7DVU7kI8vwKcjgNn4sECkMMYcZbYVTaBmaS4cmwBECqfpKLOvAKtQ7UBWTgYlACmJWDtwD/5Y8CKqHejXDDOb0kgAn08aikiH4lFm1+D1A++iScJeDQGzGwngxJSRiHQj1g68jI8G7kG1A706sZEAtAVYSifWDqwCzke1A72Y3kgAM5KGIdKjWDuwFa8d0FFm3ZkxFLsATUsdiUg/Yu3Aeryk+DFUO9CJ4SF8+K9NQFIJIYQdwE34iEC1A20MAcenDkIkS7F2YBOqHWhrCO8UKlI5TbUDjb4DOrNgDCUAqbymvgPfAN5Hk4SjlACkFsb0HfgxOrMA8ASgU4ClNkIIe/Ajzs/Hzyyo9SThEFoBkJqJtQNvAhcB3wV2JQ4pmSFgUuogRFIIIXwSQvgJ/ljwHDXcYDQEHNf2q0QqLITwIX6o6ZXUrDmphv8iQAjhSAjhFXw0UJsNRkoAIk3GbDCq/CShEoDIGE0bjC7CTzmubCWhEoDIOOIk4QP4eYZ7UseTBzUCFRmHmQ3h5+itoaI9M4ZREwWRz4hnZd4GLAemJw4nN8PUcO1TZDxmNgk4B1hNDc7LHKZGa54iEzGzufjxZBdTk/qYYeBg6iBEUoonY12NlwXXqkGuEoDUVpzkC/hw/0xqOCmuBCC1ZGaz8DX+q6hxVywlAKkVM5sMLMOr/U6h4pN87Qyj7qlSE2Y2D7/xlwKTE4dTCMPUZNOD1JeZTQe+hXcLnpk4nEIZDiEcMrMD1Pg5SKopnnlxNj7Jt4AaTvK1MdL4B9mHEoBUiJmdjLf++hrqezmefY0EsAcdES4VYGZT8Jt+BXAyNZ/ka2NvcwIQKa24pr8QH+4vRq3uOrGnkQB2JA1DpA9mNhO4FbiWCm/cycH2RgL4n6RhiPQgrukvxZf2TkXD/W7sCyHsbySAj5KGItIlMzsVH+6fR0027mRsO3y6LLI9YSAiHTOz4/E1/VuAWYnDKbMd8GkC2If3PdM/qBRSXNNfjL/rL0Rr+v36M8RnphDCCPBu0nBExhHX9B8EfkFNd+3l4B049h/yXf Line truncated
// APP SERVER的地址,不能省略http(s)前缀。
// 默认的app server使用端口是8888,注意端口号别忘记了。
// 上线建议使用https,使用https更安全。
//static APP_SERVER = 'http://wildfirechat.net:8888';
static APP_SERVER = 'https://app.wildfirechat.net';
// 组织结构服务地址,如果没有部署组织结构服务,或者不需要组织结构的话,可置为 null
// 组织结构项目:https://github.com/wildfirechat/organization-platform 或 https://gitee.com/wfchat/organization-platform
static ORGANIZATION_SERVER = 'https://org.wildfirechat.cn';
// 工作台地址,如果不需要工作台,请删除 pages.json 里面,WorkspacePage 相关配置
static WORKSPACE_URL = "https://open.wildfirechat.cn/work.html";
// 请仔细看注释
// 仅仅是 HOST,没有 http 前缀,后面也没有端口
// IM SERVER 的 host 地址,一定要和 APP_SERVER 对应起来,即 APP_SERVER 上配置的 im-server 和下面所配置的im-server 是同一个
static IM_SERVER_HOST = 'wildfirechat.net'/** 请仔细看上面的注释,仅仅是 HOST,没有 http 前缀,后面也没有端口 **/;
static QR_CODE_PREFIX_PC_SESSION = "wildfirechat://pcsession/";
// 如果使用的是高级版音视频 SDK,则不需要配置 ICE_SERVER,否则需要配置。<br>
// 请参考 src/wfc/av/internal/README.MD 切换音视频 SDK <br>
// turn server 配置,可以添加多个<br>
// 格式: [uri, 用户名, 密码],可以添加多个<br>
// Turn服务配置,用户音视频通话功能,详情参考 https://docs.wildfirechat.net/webrtc/ <br>
// 我们提供的服务能力有限,总体带宽仅3Mbps,只能用于用户测试和体验,为了保证测试可用,我们会不定期的更改密码。<br>
// 上线时请一定要切换成你们自己的服务。可以购买腾讯云或者阿里云的轻量服务器,价格很便宜,可以避免影响到您的用户体验。<br>
static ICE_SERVERS = [{uri: 'turn:turn.wildfirechat.net:3478', userName: 'wfchat', password: 'wfchatpwd'}];
static LANGUAGE = 'zh_CN';
// 允许主动加入多人音视频通话
static ENABLE_MULTI_CALL_AUTO_JOIN = true;
// 是否启用语音对讲功能,语音对讲是和对讲机类似的功能,不是和微信类似的,发送语音消息功能
// 启用后,请联系官方获取对讲插件
static ENABLE_PTT = false;
// 是否启用音视频通话功能
static ENABLE_VOIP = true;
static SDK_PLATFORM_WINDOWS = 3;
static SDK_PLATFORM_OSX = 4;
static SDK_PLATFORM_WEB = 5;
static SDK_PLATFORM_WX = 6;
// uni-app 默认录音格式为mp3
// 如果只有 uni-app 端,没有Android、iOS、Web、小程序 或者 PC 端时,录音可以直接播放,可将下面的AMR_TO_MP3_SERVER_ADDRESS置为""
// html5 audio 标签不能播放amr格式的音频,需要将amr格式转换为mp3格式
// 本服务传入amr音频文件的地址,将音频文件转换为mp3格式,并以application/octet-stream的格式返回
// 如果语音消息很多,建议使用cdn
//static AMR_TO_MP3_SERVER_ADDRESS = Config.APP_SERVER + '/amr2mp3?path=';
static AMR_TO_MP3_SERVER_ADDRESS = '';
// 文件传输助手ID
static FILE_HELPER_ID = 'wfc_file_transfer';
/**
* 允许重新编辑多长时间内的撤回消息,单位是秒
*/
static RECALL_REEDIT_TIME_LIMIT = 60;
static platform = -1;
static DEFAULT_SILENT_WHEN_PC_ONLINE = true;
static getWFCPlatform() {
if (Config.platform > 0) {
return Config.platform;
}
let info = uni.getSystemInfoSync();
console.log('systemInfo', info);
if (info.osName === 'ios' || info.platform === 'ios') {
Config.platform = info.deviceType !== 'phone' ? 8 : 1;
} else if (info.osName === 'android' || info.platform === 'android') {
Config.platform = info.deviceType !== 'phone' ? 9 : 2;
} else {
Config.platform = 0;
}
return Config.platform;
}
static config(options) {
Object.keys(options).forEach(key => {
Config[key] = options[key];
});
}
/**
* 网络地址重定向
*
* 仅当双网环境时,需要特殊处理,默认原样返回
*
* @param {string} url
* @return {string} newUrl
*/
static urlRedirect(url) {
if (!url) {
return url;
}
// 示例代码
// url = url.replace('oss.xxxx.com', '192.168.2.19');
return url;
}
/**
* 表情 base 路径
* @return {string}
*/
static emojiBaseUrl() {
// 表情的 baseUrl,一定要求以 / 结尾
let emojiBaseUrl = 'https://static.wildfirechat.net/twemoji/assets/';
// 实例代码
// 双网环境时,将表情地址切换到备选网络
// if (!wfc.connectedToMainNetwork()) {
// emojiBaseUrl = 'https://192.168.2.169/twemoji/assets/';
// }
return emojiBaseUrl;
}
/**
* 动态表情 base 路径
* @return {string}
*/
static stickerBaseUrl() {
// 动态表情的 baseUrl,一定要求以 / 结尾
let stickerBaseUrl = 'https://static.wildfirechat.net/sticker/';
// 实例代码
// 双网环境时,将动态表情地址切换到备选网络
// if (!wfc.connectedToMainNetwork()) {
// stickerBaseUrl = 'https://192.168.2.169/sticker/';
// }
return stickerBaseUrl;
}
}
+28 -2
View File
@@ -10,7 +10,7 @@
<scroll-view style="height: calc(100dvh - 88px)" scroll-y>
<view
class="mx-4 mt-4 p-4 rounded-2 bg-#000 b-4 b-solid b-t-#ffcd32/80 b-l-#ffcd32/60 b-r-#ffcd32/60 b-b-#ffcd32/40"
class="mx-4 p-4 rounded-2 bg-#000 b-4 b-solid b-t-#ffcd32/80 b-l-#ffcd32/60 b-r-#ffcd32/60 b-b-#ffcd32/40"
>
<view class="text-color-theme-dark font-900 font-italic text-xl mb-1">VIP</view>
<view class="flex-col-center mb-4">
@@ -53,6 +53,31 @@
</scroll-view>
</view>
<!-- 支付方式切换 -->
<view class="mt-5 px-4">
<view class="text-base font-600 mb-2">选择支付方式</view>
<view class="flex justify-between gap-3">
<view
class="flex-1 rounded-full flex-row-center px-4 py-2 b-3 b-solid b-#222 bg-#333 transition-all duration-200"
:style="{ borderColor: payMethod === 'alipay' ? '#ffcd32' : '' }"
@click="payMethod = 'alipay'"
>
<image class="size-40rpx mr-2" src="@/static/alipay.png" mode="aspectFill" />
<text>支付宝</text>
</view>
<view
class="flex-1 rounded-full flex-row-center px-4 py-2 b-3 b-solid b-#222 bg-#333 transition-all duration-200"
:style="{ borderColor: payMethod === 'wechat' ? '#ffcd32' : '' }"
@click="payMethod = 'wechat'"
>
<image class="size-40rpx mr-2" src="@/static/weixin.png" mode="aspectFill" />
<text>微信支付</text>
</view>
</view>
</view>
<!-- 协议 -->
<view class="mt-4 px-4 text-xs text-gray leading-relaxed text-center">
开通即视为同意
<text class="text-color-theme-dark">《VIP会员服务协议》</text>
@@ -60,8 +85,8 @@
<text class="text-color-theme-dark">《自动续费协议》</text>
</view>
<!-- v-if="openTypeList?.length" -->
<view
v-if="openTypeList?.length"
class="mt-4 w-2/3 mx-auto py-2 text-center rounded-full bg-color-theme-dark text-black text-sm active:bg-color-theme"
@click="handleOpenVip"
>
@@ -116,6 +141,7 @@
{ title: '查看谁喜欢我', desc: '查看所有喜欢你的用户' },
{ title: '专属身份标识', desc: '昵称后展示 VIP 标识,提升可信度' },
];
const payMethod = ref<'alipay' | 'wechat'>('alipay'); // 支付方式:alipay / wechat
const openTypeList = ref<OpenTypeItem[]>(); // 会员类型列表
const curOpenTypeId = ref<number>(); // 当前选择的会员类型id
const currentOpenType = computed<OpenTypeItem | undefined>(() =>
+1 -2
View File
@@ -68,8 +68,7 @@
</view>
<!-- 用户相册 -->
<user-ablum :ablumList="ablumList"></user-ablum>
<user-ablum :ablumList="ablumList" />
<!-- 菜单 -->
<view class="mt-4 mx-1">
<wd-cell-group>
+11
View File
@@ -2,6 +2,17 @@
import request from '@/sheep/request';
const RecentApi = {
// 更新用户位置
updateUserLocation: (data: any) => {
return request({
url: '/member/location/create',
method: 'POST',
data,
custom: {
showLoading: false,
},
});
},
// 查询附近/广场
quickPage: (data: any) => {
return request({
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

+78
View File
@@ -0,0 +1,78 @@
import ConversationType from "../../model/conversationType";
import CallSession from "./callSession";
export class AvengineCallback {
innerAudioContext
onReceiveCall(session) {
console.log('onReceiveCall', session)
if (typeof session === 'string') {
session = Object.assign(new CallSession(), JSON.parse(session));
}
let url;
if (session.conversation.type === ConversationType.Single) {
url = '/pages/voip/Single'
} else if (session.conversation.type === ConversationType.Group) {
// TODO multi
url = '/pages/voip/Multi'
}
url += `?session=${JSON.stringify(session)}`
if (url) {
uni.navigateTo({
url: url,
success: (res) => {
console.log(`navigate to ${url} success`)
res.eventChannel.emit('options', {
callSession: session,
});
},
fail: (e) => {
console.log(`navigate to ${url} error`, e)
}
})
}
}
shouldStartRing(isIncoming) {
self.innerAudioContext = uni.createInnerAudioContext();
self.innerAudioContext.src = isIncoming ? '/static/audios/incoming_call_ring.mp3' : '/static/audios/outgoing_call_ring.mp3'
self.innerAudioContext.autoplay = true;
self.innerAudioContext.loop = true;
self.innerAudioContext.play()
self.innerAudioContext.onPlay(() => {
console.log('开始播放');
});
self.innerAudioContext.onError((e) => {
console.error('播放响铃失败', e)
})
}
shouldStopRing() {
console.log('shouldStopRing')
self.innerAudioContext.stop()
self.innerAudioContext.destroy()
self.innerAudioContext = null
}
didCallEnded(reason, duration) {
// TODO toast
console.log('didCallEnded', reason, duration)
let pages = getCurrentPages();
let singleVoipRoute = 'pages/voip/Single'
let multiVoipRoute = 'pages/voip/Multi'
let conferenceVoipRoute = 'pages/voip/conference/ConferencePage'
let curRoute = pages[pages.length - 1].route;
if (curRoute === singleVoipRoute || curRoute === multiVoipRoute || curRoute === conferenceVoipRoute) {
uni.navigateBack({
delta: 1,
fail: err => {
console.log('nav back to conversationView err', err);
}
});
}
}
}
let self = new AvengineCallback();
export default self
+464
View File
@@ -0,0 +1,464 @@
import avengineCallback from "./avengineCallback";
import CallSession from './callSession';
import ParticipantProfile from "./participantProfile";
import ConversationType from "../../model/conversationType";
import Config from "../../../config";
const avengineKitPlugin = Config.ENABLE_VOIP ? uni.requireNativePlugin("wf-uni-wfc-avclient") : null;
export class AVEngineKit {
avengineCallback = avengineCallback;
sessionCallback;
/**
屏幕分享替换模式。为ture时,屏幕分享会替换摄像头的数据流。为false时,屏幕分享会再单独发起一路,不会影响摄像头的输入。
*/
static SCREEN_SHARING_REPLACE_MODE = true;
/**
* 判断 UIKit 原生插件是否集成
* @return {boolean}
*/
isAVEngineKitEnable() {
return !!avengineKitPlugin;
}
init() {
avengineKitPlugin.initAVEngineKit();
// avengineKitPlugin.setScreenShareReplaceMode(AVEngineKit.SCREEN_SHARING_REPLACE_MODE);
plus.globalEvent.addEventListener("wfc-av-event", (e) => {
// console.debug('wfc-av-event', e);
self._handleNativeAVEngineEvent(e);
// this.log = [this.interpreter(e), ...this.log];
});
plus.globalEvent.addEventListener("wfc-av-session-event", (e) => {
// console.debug('wfc-av-session-event', e);
self._handleNativeCallSessionEvent(e);
// this.log = [this.interpreter(e), ...this.log];
});
}
_handleNativeAVEngineEvent(e) {
let args = e.args;
if (this.avengineCallback) {
let func = this.avengineCallback[args[0]]
//console.log('avengineCallback', func, ...args.slice(1))
if (func) {
func(...args.slice(1));
}
} else {
console.warn('_handleNativeAVEngineEvent avengineCallback is null', args)
}
}
_handleNativeCallSessionEvent(e) {
let args = e.args;
if (args[0] !== 'didReportAudioVolume') {
console.log('_handleNativeCallSessionEvent', args)
}
if (args[0] === 'resumeVoipPage') {
let session = this.currentCallSession();
if (session) {
this._resumeVoipPage(session);
}
return;
}
if (this.sessionCallback) {
let func = this.sessionCallback[args[0]]
if (func) {
// 类型不对时,特殊处理
if (args[0] === 'didChangeState') {
func(Number(args[1]));
} else if (args[0] === 'didCallEndWithReason') {
func(Number(args[1]));
} else {
func(...args.slice(1));
}
}
} else {
if(args[0] !== 'didReportAudioVolume'){
console.warn('_handleNativeCallSessionEvent sessionCallback is null', args)
}
}
}
_resumeVoipPage(session) {
console.log('_resumeVoipPage', session)
let url;
if (session.conference) {
url = '/pages/voip/conference/ConferencePage'
} else if (session.conversation.type === ConversationType.Single) {
url = '/pages/voip/Single'
} else if (session.conversation.type === ConversationType.Group) {
url = '/pages/voip/Multi'
}
url += `?session=${JSON.stringify(session)}`
if (url) {
uni.navigateTo({
url: url,
success: (res) => {
console.log(`navigate to ${url} success`)
},
fail: (e) => {
console.log(`navigate to ${url} error`, e)
}
})
}
}
setSessionCallback(cb) {
this.sessionCallback = cb;
}
/**
* 发起单人音视频通话
* @param {string} userId 用户 id
* @param {boolean} audioOnly 是否是音频通话
* @return {CallSession}
*/
startSingleCall(userId, audioOnly) {
let sessionStr = avengineKitPlugin.startSingleCall(userId, audioOnly);
return !sessionStr ? null : Object.assign(new CallSession(), JSON.parse(sessionStr));
}
/**
* 发起群音视频通话
* @param {string} groupId 群 id
* @param {[string]} participants 参与者 id,要求是群成员
* @param {boolean} audioOnly 是否是音频通话
* @return {CallSession}
*/
startMultiCall(groupId, participants, audioOnly) {
let sessionStr = avengineKitPlugin.startMultiCall(groupId, participants, audioOnly)
return !sessionStr ? null : Object.assign(new CallSession(), JSON.parse(sessionStr));
}
/**
* 开始会议
* @param {string} callId 会议id
* @param {boolean} audioOnly 是否仅仅开启音频; true,音频会议;false,视频会议
* @param {string} pin 入会pin码
* @param {string} host 主持人用户id
* @param {string} title 会议标题
* @param {string} desc 会议描述
* @param {boolean} audience 其他人加入会议时,是否默认为观众;true,默认为观众;false,默认为互动者
* @param {boolean} advance 是否为高级会议,当预计参与人员很多的时候,开需要开启超级会议
* @param {boolean} record 是否开启服务端录制
* @param {string} callExtra 通话附件信息,会议的所有参与者都能看到该附加信息
* @return {CallSession}
*/
startConference(callId, audioOnly, pin, host, title, desc, audience, advance, record = false, callExtra = '') {
let sessionStr = avengineKitPlugin.startConference(callId, audioOnly, pin, host, title, desc, audience, advance, record, callExtra);
return !sessionStr ? null : Object.assign(new CallSession(), JSON.parse(sessionStr));
}
/**
* 加入会议
* @param {string} callId 会议id
* @param {boolean} audioOnly 是否只开启音频
* @param {string} pin 会议pin码
* @param {string} host 会议主持人
* @param {string} title 会议标题
* @param {string} desc 会议描述
* @param {boolean} audience 是否是以观众角色入会
* @param {boolean} advance 是否是高级会议
* @param {boolean} muteAudio 是否是静音加入会议
* @param {boolean} muteVideo 是否是关闭摄像头加入会议
* @param {string} callExtra 通话附加信息,会议的所有参与者都能看到该附加信息
* @return {CallSession}
*/
joinConference(callId, audioOnly, pin, host, title, desc, audience, advance, muteAudio, muteVideo, callExtra = '') {
let sessionStr = avengineKitPlugin.joinConference(callId, audioOnly, pin, host, title, desc, audience, advance, muteAudio, muteVideo, callExtra);
return !sessionStr ? null : Object.assign(new CallSession(), JSON.parse(sessionStr));
}
/**
* 离开会议
* @param {string} callId 会议id
* @param {boolean} destroyRoom 是否销毁会议,主持有效
*/
leaveConference(callId, destroyRoom = false) {
avengineKitPlugin.leaveConference(callId, destroyRoom);
}
/**
* 仅会议版有效
*
* 将参与者踢出会议
*
* @param {string} callId 会议 id
* @param userId
* @param successCB
* @param failCB
*/
kickoffParticipant(callId, userId, successCB, failCB) {
avengineKitPlugin.kickoffParticipant(callId, userId, () => {
successCB && successCB()
}, err => {
failCB && failCB(err)
})
}
/**
* 仅会议版有效
* 设置参与者的 videoType
* @param {string} callId 通话 id
* @param {string} userId 用户 id
* @param {boolean} screenSharing 是否是屏幕共享
* @param {number} videoType 视频流类型,可选值参考{@link VideoType}
*/
setParticipantVideoType(callId, userId, screenSharing, videoType) {
console.log('setParticipantVideoType', userId, screenSharing, videoType)
avengineKitPlugin.setParticipantVideoType(callId, userId, screenSharing, videoType);
}
/**
* 判断是否支持多人音视频通话
* @return {boolean}
*/
isSupportMultiCall() {
return avengineKitPlugin.isSupportMultiCall();
}
/**
* 判断是否支持会议
* @return {boolean}
*/
isSupportConference() {
return avengineKitPlugin.isSupportConference();
}
/**
* 设置视频通话时的视频属性
* @param {number} profile 可选值参考{@link VideoProfile}
* @param {boolean} swapWidthHeight 是否交换宽高,默认不不用设置
*/
setVideoProfile(profile, swapWidthHeight = false) {
avengineKitPlugin.setVideoProfile(profile, swapWidthHeight);
}
/**
* 添加 ICE Server
* @param {string} url
* @param {string} name
* @param {string} password
*/
addICEServer(url, name, password) {
avengineKitPlugin.addICEServer(url, name, password)
}
/**
* 获取当前通话会话
*
* @@return {callSession}
*/
currentCallSession() {
let result = avengineKitPlugin.currentCallSession();
if (!result) {
return null;
}
return Object.assign(new CallSession(), JSON.parse(result));
}
/**
* 接听
* @param {string} callId
* @param {boolean} audioOnly 是否是以语音方式接听
*/
answerCall(callId, audioOnly) {
avengineKitPlugin.answerCall(callId, audioOnly);
}
/**
* 挂断
* @param {Object} callId 通话ID
*/
endCall(callId) {
avengineKitPlugin.endCall(callId);
}
/**
* 仅 Android 端高级版音视频支持
* 开启屏幕共享
* @param {Object} callId 通话ID
*/
startScreenShare(callId) {
avengineKitPlugin.startScreenShare(callId);
}
/**
* 仅 Android 端高级版音视频支持
* 停止屏幕共享
* @param {Object} callId 通话ID
*/
stopScreenShare(callId) {
avengineKitPlugin.stopScreenShare(callId);
}
/**
* 仅 Android 端高级版音视频支持
* 是否在进行屏幕共享
* @param {Object} callId 通话ID
*/
isScreenSharing(callId) {
return avengineKitPlugin.isScreenSharing(callId);
}
/**
* 关闭/开启摄像头
* @param {string} callId 通话 id
* @param {boolean} mute 是否关闭摄像头
*/
muteVideo(callId, mute) {
avengineKitPlugin.muteVideo(callId, mute)
}
/**
* 关闭/开启麦克风
* @param {string} callId 通话 id
* @param {boolean} mute 是否关闭麦克风
* @return {boolean} 是否关闭成功
*/
muteAudio(callId, mute) {
avengineKitPlugin.muteAudio(callId, mute);
}
/**
* 会议时有效
* 切换为观众
* @param {string} callId 通话 id
* @param {boolean} audience 是否切换成观众
* @return {boolean} 是否切换成功
*/
switchAudience(callId, audience) {
return avengineKitPlugin.switchAudience(callId, audience);
}
/**
* 将视频通话,降级到语音通话
* @param {string} callId 通话 id
*/
downgrade2Voice(callId) {
avengineKitPlugin.downgrade2Voice(callId);
}
/**
* 邀请新的通话成员
* @param {string} callId 通话 id
* @param {[string]} userIds 新参与者 id 列表
*/
inviteNewParticipant(callId, userIds) {
avengineKitPlugin.inviteNewParticipant(callId, userIds);
}
/**
* 设置本地视频流容器 view
* @param {string} callId 通话 id
* @param {number} ref 容器 view 的 id
*/
setLocalVideoView(callId, ref) {
avengineKitPlugin.setLocalVideoView(callId, ref);
}
/**
* 设置远程视频流容器 view
* @param {string} callId 通话 id
* @param {string} userId 用户 id
* @param {number} ref 容器 view 的 id
* @param {boolean} screenSharing 是否是屏幕共享
*/
setRemoteVideoView(callId, userId, ref, screenSharing = false) {
avengineKitPlugin.setRemoteVideoView(callId, userId, screenSharing, ref);
}
/**
* 获取除自己外,所有通话参与者的 {@link ParticipantProfile}
* @param {string} callId 通话 id
* @return {[ParticipantProfile]}
*/
getParticipantProfiles(callId) {
let str = avengineKitPlugin.getParticipantProfiles(callId)
if (!str) {
return [];
}
let profiles = [];
let ps = JSON.parse(str);
ps.map(p => {
profiles.push(Object.assign(new ParticipantProfile(), p));
});
return profiles;
}
/**
* 获取某个通话参与者(可以是自己)的{@link ParticipantProfile}
* @param {string} callId 通话 id
* @param {string} userId 用户 id
* @param {boolean} screenSharing 是否是屏幕共享
* @return {any| ParticipantProfile}
*/
getParticipantProfile(callId, userId, screenSharing) {
let str = avengineKitPlugin.getParticipantProfile(callId, userId, screenSharing);
if (!str) {
return null;
}
return Object.assign(new ParticipantProfile(), JSON.parse(str))
}
/**
* 获取自己的 {@link ParticipantProfile}
* @return {any|ParticipantProfile}
* @param {string} callId
*/
getMyProfile(callId) {
let str = avengineKitPlugin.getMyProfile(callId);
if (!str) {
return null;
}
return Object.assign(new ParticipantProfile(), JSON.parse(str))
}
/**
* 检查是否允许显示悬浮窗
* @return {boolean}
*/
checkOverlayPermission() {
return avengineKitPlugin.checkOverlayPermission();
}
/**
* 最小化
* @param {string} callId
* @param {string} focusVideoUser 视频通话/会议时有效,表示悬浮窗显示那个用户的视频流
* 最小化,显示悬浮窗
*/
minimize(callId, focusVideoUser = '') {
avengineKitPlugin.minimize(callId, focusVideoUser);
this.sessionCallback = null;
}
/**
* 打开或关闭扬声器
* @param {string} callId 通话 id
* @param {boolean} speakerOn 是否打开扬声器
*/
setSpeakerOn(callId, speakerOn) {
avengineKitPlugin.setSpeakerOn(callId, speakerOn);
}
/**
* 切换摄像头
* @param {string} callId
*/
switchCamera(callId) {
avengineKitPlugin.switchCamera(callId);
}
}
const self = new AVEngineKit();
export default self;
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class CallEndReason {
static REASON_Unknown = 0;
static REASON_Busy = 1;
static REASON_SignalError = 2;
static REASON_Hangup = 3;
static REASON_MediaError = 4;
static REASON_RemoteHangup = 5;
static REASON_OpenCameraFailure = 6;
static REASON_Timeout = 7;
static REASON_AcceptByOtherClient = 8;
static REASON_AllLeft = 9;
static RemoteBusy = 10;
static RemoteTimeout = 11;
static RemoteNetworkError = 12;
static RoomDestroyed = 13;
static RoomNotExist = 14;
static RoomParticipantsFull = 15;
static Interrupted = 16;
static RemoteInterrupted = 17;
}
+61
View File
@@ -0,0 +1,61 @@
export default class CallSession {
//通话ID
callId;
title;
desc;
//通话的发起者,如果发起者离开,会重新选举出最早加入者为发起者
initiator;
//邀请当前用户加入通话的用户
inviter;
//通话状态
state;
//开始时间
startTime;
//接通时间
connectedTime;
//结束时间
endTime
//会话
conversation;
//是否是音频
audioOnly;
//通话结束原因
endReason;
//是否是会议
conference;
//是否是观众,仅当会议有效
audience;
//是否是超级会议
advanced;
//是否是多人通话
multiCall;
// 是否关闭摄像头
videoMuted;
// 是否关闭麦克风
audioMuted;
//call状态
static kWFAVEngineStateIdle = 0;
static kWFAVEngineStateOutgoing = 1;
static kWFAVEngineStateIncomming = 2;
static kWFAVEngineStateConnecting = 3;
static kWFAVEngineStateConnected = 4;
//通话结束原因
static kWFAVCallEndReasonUnknown = 0;
static kWFAVCallEndReasonBusy = 1;
static kWFAVCallEndReasonSignalError = 2;
static kWFAVCallEndReasonHangup = 3;
static kWFAVCallEndReasonMediaError = 4;
static kWFAVCallEndReasonRemoteHangup = 5;
static kWFAVCallEndReasonOpenCameraFailure = 6;
static kWFAVCallEndReasonTimeout = 7;
static kWFAVCallEndReasonAcceptByOtherClient = 8;
static kWFAVCallEndReasonAllLeft = 9;
static kWFAVCallEndReasonRemoteBusy = 10;
static kWFAVCallEndReasonRemoteTimeout = 11;
static kWFAVCallEndReasonRemoteNetworkError = 12;
static kWFAVCallEndReasonRoomDestroyed = 13;
static kWFAVCallEndReasonRoomNotExist = 14;
static kWFAVCallEndReasonRoomParticipantsFull = 15;
}
+178
View File
@@ -0,0 +1,178 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class CallSessionCallback {
/**
* 自己挂断回调
* @param {number} reason 挂断原因,参考{@link CallEndReason}
*/
didCallEndWithReason(reason) {
console.log('didCallEndWithReason', reason)
}
/**
* 可用来实现响铃相关
* 1. outgoing -> connecting: 开始 -> 结束播放呼出铃声
* 2. incoming -> connecting: 开始 -> 结束播放呼入铃声
* 自己通话状态变化时调用
* @param {CallState} state 状态
*/
didChangeState(state) {
console.log('didChangeState', state)
}
/**
* 新参与者加入回调
* @param {string} userId 用户 id
* @param {boolean} screenSharing 是否是屏幕共享
*/
didParticipantJoined(userId, screenSharing = false) {
console.log('didParticipantJoined', userId, screenSharing);
}
/**
* 参与者连接成功
* @param {string} userId 用户 id
* @param {boolean} screenSharing 是否是屏幕共享
*/
didParticipantConnected(userId, screenSharing = false) {
console.log('didParticipantConnected', userId, screenSharing)
}
/**
* 参与者挂断回调
* @param {string} userId 用户 id
* @param {CallEndReason} callEndReason 挂断原因
* @param {boolean} screenSharing 是否是屏幕共享
*/
didParticipantLeft(userId, callEndReason, screenSharing = false) {
console.log('didParticipantLeft', userId, callEndReason, screenSharing)
}
/**
* 视频通话切换到语音通话回调
* @param {boolean} audioOnly 目前都是 true
*/
didChangeMode(audioOnly) {
console.log('didChangeMode', audioOnly)
}
/**
* 发起者变更回调,多人通话过程中,原始发起者退出通话,会触发选举新的发起者
* @param {string} initiator 新的发起者
*/
didChangeInitiator(initiator) {
console.log('didChangeInitiator', initiator)
}
/**
* 本地音视频流创建成功回调
* @param {boolean} screenSharing 是否是屏幕共享
*/
didCreateLocalVideoTrack(screenSharing) {
console.log('didCreateLocalVideoTrack', screenSharing)
}
/**
* 收到用户远程视频流回调
* @param {String} userId 用户 id
* @param {boolean} screenSharing 是否是屏幕共享
*/
didReceiveRemoteVideoTrack(userId, screenSharing) {
console.log('didReceiveRemoteVideoTrack', userId, screenSharing)
}
/**
* 用户视频流被移除回调
* @param {String} userId
*/
didRemoveRemoteVideoTrack(userId) {
console.log('didRemoveRemoteVideoTrack', userId)
}
didAudioDeviceChanged(audioDevice) {
console.log('didAudioDeviceChanged', audioDevice)
}
didError(error) {
console.log('didError', error)
}
didGetStats(reports) {
}
/**
* 单人、多人音视频通话时生效,会议时调用的是 {@link didMuteStateChanged}
* @param {string} userId
* @param {boolean} muted
*/
didVideoMuted(userId, muted) {
console.log('didVideoMuted', userId, muted)
}
/**
* 高级版生效,多人版调用的是 {@link didVideoMuted}
* @param {[string]} participants
*/
didMuteStateChanged(participants) {
console.log('didMuteStateChanged', participants)
}
/**
* 当前用户发送媒体丢包回调
* @param media 媒体类型,audio 或 video
* @param lostPacket 丢包数
* @param {boolean} screenSharing
*/
didMediaLostPacket(media, lostPacket, screenSharing = false) {
console.log('didMediaLostPacket', media, lostPacket, screenSharing)
}
/**
* 接收用户媒体丢包回调
* @param userId 用户id
* @param media 媒体类型,audio 或 video
* @param lostPacket 丢包数
* @param uplink 方向,true是对方丢的,false是己方丢的
* @param {boolean} screenSharing
*/
didUserMediaLostPacket(userId, media, lostPacket, uplink, screenSharing = false) {
console.log('didUserMediaLostPacket', userId, media, lostPacket, uplink, screenSharing)
}
/**
* 会议时有效
* 听众或互动者角色变更回调
* @param {string} userId
* @param {boolean} audience
* @param {boolean} screenSharing
*/
didChangeType(userId, audience, screenSharing = false) {
console.log('didChangeType', userId, audience, screenSharing)
}
/**
* 音量回调
* @param {string} userId 用户 id
* @param {number} volume 音量
*/
didReportAudioVolume(userId, volume) {
}
/**
* 会议时有效
* 听众和互动者角色切换回调
* @param {boolean} audience 是否是切换为听众
*/
onRequestChangeMode(audience) {
console.log('onRequestChangeMode', audience)
}
}
+11
View File
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class CallState {
static STATUS_IDLE = 0;
static STATUS_OUTGOING = 1;
static STATUS_INCOMING = 2;
static STATUS_CONNECTING = 3;
static STATUS_CONNECTED = 4;
}
+14
View File
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class ParticipantProfile {
userId;
callExtra;
state;
joinTime = 0;
acceptTime = 0;
audioMuted = false;
videoMuted = false;
audience = false;
screenSharing = false;
}
+166
View File
@@ -0,0 +1,166 @@
/*
视频属性 (Profile) 定义
视频属性 枚举值 分辨率(宽x高) 帧率(fps) 码率(kbps)
120P 0 160x120 15 120
120P_3 2 120x120 15 100
180P 10 320x180 15 280
180P_3 12 180x180 15 200
180P_4 13 240x180 15 240
240P 20 320x240 15 360
240P_3 22 240x240 15 280
240P_4 24 424x240 15 400
360P 30 640x360 15 800
360P_3 32 360x360 15 520
360P_4 33 640x360 30 1200
360P_6 35 360x360 30 780
360P_7 36 480x360 15 1000
360P_8 37 480x360 30 1500
480P 40 640x480 15 1000
480P_3 42 480x480 15 800
480P_4 43 640x480 30 1500
480P_6 45 480x480 30 1200
480P_8 47 848x480 15 1200
480P_9 48 848x480 30 1800
720P 50 1280x720 15 2400
720P_3 52 1280x720 30 3699
720P_5 54 960x720 15 1920
720P_6 55 960x720 30 2880
1080P 60 1920×1080 15 4200
1080P_3 60 1920×1080 30 6300
1080P_5 60 1920×1080 60 9560
*/
export default class VideoProfile {
static VP120P = 0
static VP120P_3 = 2
static VP180P = 10
static VP180P_3 = 12
static VP180P_4 = 13
static VP240P = 20
static VP240P_3 = 22
static VP240P_4 = 23
static VP360P = 30
static VP360P_3 = 32
static VP360P_4 = 33
static VP360P_6 = 35
static VP360P_7 = 36
static VP360P_8 = 37
static VP480P = 40
static VP480P_3 = 42
static VP480P_4 = 43
static VP480P_6 = 45
static VP480P_8 = 47
static VP480P_9 = 48
static VP720P = 50
static VP720P_3 = 52
static VP720P_5 = 54
static VP720P_6 = 55
static VP1080P = 60
static VP1080P_3 = 62
static VP1080P_5 = 64
static VPDEFAULT = VideoProfile.VP360P
width
height
fps
bitrate
constructor (width, height, fps, bitrate) {
this.width = width
this.height = height
this.fps = fps
this.bitrate = bitrate
}
static getVideoProfile (videoProfile) {
switch (videoProfile) {
// 120P 0 160x120 15 65
// 120P_3 2 120x120 15 50
case VideoProfile.VP120P:
return new VideoProfile(160, 120, 15, 120)
case VideoProfile.VP120P_3:
return new VideoProfile(120, 120, 15, 100)
// 180P 10 320x180 15 140
// 180P_3 12 180x180 15 100
// 180P_4 13 240x180 15 120
case VideoProfile.VP180P:
return new VideoProfile(320, 180, 15, 280)
case VideoProfile.VP180P_3:
return new VideoProfile(180, 180, 15, 200)
case VideoProfile.VP180P_4:
return new VideoProfile(240, 180, 15, 240)
// 240P 20 320x240 15 200
// 240P_3 22 240x240 15 140
// 240P_4 24 424x240 15 220
case VideoProfile.VP240P:
return new VideoProfile(320, 240, 15, 360)
case VideoProfile.VP240P_3:
return new VideoProfile(240, 240, 15, 240)
case VideoProfile.VP240P_4:
return new VideoProfile(424, 240, 15, 400)
// 360P 30 640x360 15 400
// 360P_3 32 360x360 15 260
// 360P_4 33 640x360 30 600
// 360P_6 35 360x360 30 400
// 360P_7 36 480x360 15 320
// 360P_8 37 480x360 30 490
case VideoProfile.VP360P:
return new VideoProfile(640, 360, 15, 800)
case VideoProfile.VP360P_3:
return new VideoProfile(360, 360, 15, 520)
case VideoProfile.VP360P_4:
return new VideoProfile(640, 360, 30, 1200)
case VideoProfile.VP360P_6:
return new VideoProfile(360, 360, 30, 780)
case VideoProfile.VP360P_7:
return new VideoProfile(480, 360, 15, 1000)
case VideoProfile.VP360P_8:
return new VideoProfile(480, 360, 30, 1500)
// 480P 40 640x480 15 500
// 480P_3 42 480x480 15 400
// 480P_4 43 640x480 30 750
// 480P_6 45 480x480 30 600
// 480P_8 47 848x480 15 610
// 480P_9 48 848x480 30 930
case VideoProfile.VP480P:
return new VideoProfile(640, 480, 15, 1000)
case VideoProfile.VP480P_3:
return new VideoProfile(480, 480, 15, 800)
case VideoProfile.VP480P_4:
return new VideoProfile(640, 480, 30, 1500)
case VideoProfile.VP480P_6:
return new VideoProfile(480, 480, 30, 1200)
case VideoProfile.VP480P_8:
return new VideoProfile(848, 480, 15, 1200)
case VideoProfile.VP480P_9:
return new VideoProfile(848, 480, 30, 1800)
// 720P 50 1280x720 15 1130
// 720P_3 52 1280x720 30 1710
// 720P_5 54 960x720 15 910
// 720P_6 55 960x720 30 1380
case VideoProfile.VP720P:
return new VideoProfile(1280, 720, 15, 2400)
case VideoProfile.VP720P_3:
return new VideoProfile(1280, 720, 30, 3600)
case VideoProfile.VP720P_5:
return new VideoProfile(960, 720, 15, 1920)
case VideoProfile.VP720P_6:
//1080P 60 1920 * 1080 15 2080
//1080P_3 62 1920 * 1080 30 3150
//1080P_5 64 1920 * 1080 60 4780
return new VideoProfile(960, 720, 30, 2880)
case VideoProfile.VP1080P:
return new VideoProfile(1920, 1080, 15, 4200)
case VideoProfile.VP1080P_3:
return new VideoProfile(1920, 1080, 30, 6300)
case VideoProfile.VP1080P_5:
return new VideoProfile(1920, 1080, 60, 9560)
default:
return VideoProfile.getVideoProfile(VideoProfile.VPDEFAULT)
}
}
}
+8
View File
@@ -0,0 +1,8 @@
export default class VideoType{
// 不订阅视频流
static NONE = 0;
// 订阅大流
static BIG_STREAM = 1;
// 订阅小流
static SMALL_STREAM = 2;
}
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from "../../messages/notification/notificationMessageContent";
import MessageContentType from "../../messages/messageContentType";
import wfc from "../../client/wfc"
class ParticipantStatus {
userId;
acceptTime;
joinTime;
videoMuted;
}
export default class AddParticipantsMessageContent extends NotificationMessageContent {
callId;
initiator;
pin;
participants;
existParticipants;
audioOnly;
autoAnswer;
clientId;
constructor() {
super(MessageContentType.VOIP_CONTENT_TYPE_ADD_PARTICIPANT);
}
formatNotification(message) {
let desc = '';
if (this.fromSelf){
desc = '您邀请'
}else {
desc = wfc.getGroupMemberDisplayName(message.conversation.target, this.initiator)
desc += "邀请"
}
if (this.participants){
this.participants.forEach(p => {
desc += ' ';
if (p === wfc.getUserId()){
desc += '您';
}else {
desc += wfc.getGroupMemberDisplayName(message.conversation.target, p);
}
})
}
desc += ' 加入了通话';
return desc;
}
encode() {
let payload = super.encode();
payload.content = this.callId;
let obj = {
initiator: this.initiator,
audioOnly: this.audioOnly ? 1 : 0,
pin: this.pin,
participants: this.participants,
existParticipants: this.existParticipants,
autoAnswer: this.autoAnswer,
clientId: this.clientId,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
let epids = this.existParticipants.map(p => p.userId);
let pushData = {
callId:this.callId,
audioOnly:this.audioOnly,
participants:this.participants,
existParticipants: epids,
}
payload.pushData = JSON.stringify(pushData);
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.initiator = obj.initiator;
this.audioOnly = obj.audioOnly === 1;
this.pin = obj.pin;
this.participants = obj.participants;
this.existParticipants = obj.existParticipants;
this.autoAnswer = obj.autoAnswer;
this.clientId = obj.clientId;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import wfc from "../../client/wfc"
import {_patchToJavaLong, _reverseToJsLongString, longValue, stringValue} from '../../util/longUtil'
import MessageContentType from '../../messages/messageContentType';
export default class CallAnswerMessageContent extends MessageContent {
callId;
audioOnly;
inviteMessageUid;
constructor(mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.VOIP_CONTENT_TYPE_ACCEPT, mentionedType, mentionedTargets);
}
digest() {
return '';
}
encode() {
let payload = super.encode();
payload.content = this.callId;
var obj;
if (this.audioOnly) {
obj = '1';
} else {
obj = '0';
}
payload.binaryContent = wfc.utf8_to_b64(obj);
let obj2 = {
u: stringValue(this.inviteMessageUid),
}
let str = JSON.stringify(obj2);
str = _patchToJavaLong(str, 'u');
payload.extra = str;
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let str = wfc.b64_to_utf8(payload.binaryContent);
this.audioOnly = (str === '1');
str = payload.extra;
if (str) {
str = _reverseToJsLongString(str, 'u');
this.inviteMessageUid = longValue(JSON.parse(str).u);
}
}
}
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import MessageContentType from '../../messages/messageContentType';
import wfc from "../../client/wfc"
export default class CallAnswerTMessageContent extends MessageContent {
callId;
audioOnly;
constructor(mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.VOIP_CONTENT_TYPE_ACCEPT_T, mentionedType, mentionedTargets);
}
digest() {
return '';
}
encode() {
let payload = super.encode();
payload.content = this.callId;
var obj;
if (this.audioOnly) {
obj = '1';
} else {
obj = '0';
}
payload.binaryContent = wfc.utf8_to_b64(obj);
return payload;
};
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let str = wfc.b64_to_utf8(payload.binaryContent);
this.audioOnly = (str === '1');
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import MessageContentType from '../../messages/messageContentType';
import wfc from "../../client/wfc"
import {_patchToJavaLong, _reverseToJsLongString, longValue, stringValue} from "../../util/longUtil"
export default class CallByeMessageContent extends MessageContent {
callId;
reason;
inviteMsgUid;
constructor(mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.VOIP_CONTENT_TYPE_END, mentionedType, mentionedTargets);
}
digest() {
return '';
}
encode() {
let payload = super.encode();
payload.content = this.callId;
let obj = {
r: this.reason,
u: this.inviteMsgUid ? stringValue(this.inviteMsgUid) : undefined,
};
let str = JSON.stringify(obj)
str = _patchToJavaLong(str, 'u');
payload.binaryContent = wfc.utf8_to_b64(str);
payload.pushData = str;
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let str = wfc.b64_to_utf8(payload.binaryContent);
str = _reverseToJsLongString(str, 'u');
let obj = JSON.parse(str);
this.reason = obj.r;
this.inviteMsgUid = obj.u ? longValue(obj.u) : undefined;
}
}
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import wfc from "../../client/wfc"
import MessageContentType from '../../messages/messageContentType';
export default class CallModifyMessageContent extends MessageContent {
callId;
audioOnly;
constructor(mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.VOIP_CONTENT_TYPE_MODIFY, mentionedType, mentionedTargets);
}
digest() {
return '';
}
encode() {
let payload = super.encode();
payload.content = this.callId;
var obj;
if (this.audioOnly) {
obj = '1';
} else {
obj = '0';
}
payload.binaryContent = wfc.utf8_to_b64(obj);
return payload;
};
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let str = wfc.b64_to_utf8(payload.binaryContent);
this.audioOnly = (str === '1');
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import MessageContentType from '../../messages/messageContentType';
import wfc from "../../client/wfc"
export default class CallSignalMessageContent extends MessageContent {
callId;
payload;
constructor(mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.VOIP_CONTENT_TYPE_SIGNAL, mentionedType, mentionedTargets);
}
digest() {
return '';
}
encode() {
let payload = super.encode();
payload.content = this.callId;
payload.binaryContent = wfc.utf8_to_b64(this.payload);
return payload;
};
decode(payload) {
super.decode(payload);
this.callId = payload.content;
this.payload = wfc.b64_to_utf8(payload.binaryContent);
}
}
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import MessageContentType from '../../messages/messageContentType';
import wfc from "../../client/wfc"
export default class CallStartMessageContent extends MessageContent {
callId;
targetIds = [];
connectTime;
endTime;
/**
* 0, UnKnown,
* 1, Busy,
* 2, SignalError,
* 3, Hangup,
* 4, MediaError,
* 5, RemoteHangup,
* 6, OpenCameraFailure,
* 7, Timeout,
* 8, AcceptByOtherClient
*/
status = 0;
audioOnly;
pin;
// 0,未知;1,多人版音视频;2,高级版音视频
sdkType = 0;
constructor(mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.VOIP_CONTENT_TYPE_START, mentionedType, mentionedTargets);
}
digest() {
if (this.audioOnly) {
return '[语音通话]';
} else {
return '[视频通话]';
}
}
encode() {
let payload = super.encode();
payload.content = this.callId;
payload.pushContent = '音视频通话邀请';
let obj = {
c: this.connectTime,
e: this.endTime,
s: this.status,
a: this.audioOnly ? 1 : 0,
ts: this.targetIds,
t: this.targetIds[0],
p: this.pin,
ty: this.sdkType
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
let pushData = {
callId: this.callId,
audioOnly: this.audioOnly,
participants: this.targetIds,
}
payload.pushData = JSON.stringify(pushData);
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.connectTime = obj.c;
this.endTime = obj.e;
this.status = obj.s;
this.audioOnly = (obj.a === 1);
this.targetIds = obj.ts;
if (!this.targetIds) {
this.targetIds = [obj.t];
}
this.pin = obj.p;
this.sdkType = obj.ty
}
}
@@ -0,0 +1,32 @@
import MessageContent from "../../messages/messageContent";
import MessageContentType from "../../messages/messageContentType";
import wfc from "../../client/wfc";
export default class ConferenceChangeModeContent extends MessageContent {
callId;
audience;
constructor(callId, audience) {
super(MessageContentType.CONFERENCE_CONTENT_TYPE_CHANGE_MODE);
this.callId = callId;
this.audience = audience;
}
encode() {
let payload = super.encode();
payload.content = this.callId;
let obj = {'a': this.audience};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj))
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
if (payload.binaryContent) {
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.audience = !!obj.a;
}
}
}
@@ -0,0 +1,99 @@
import MessageContent from "../../messages/messageContent";
import MessageContentType from "../../messages/messageContentType";
import wfc from "../../client/wfc";
export default class ConferenceCommandMessageContent extends MessageContent {
conferenceId;
commandType;
targetUserId;
boolValue;
constructor(conferenceId, commandType, targetUserId, boolValue) {
super(MessageContentType.CONFERENCE_CONTENT_TYPE_COMMAND);
this.conferenceId = conferenceId;
this.commandType = commandType;
this.targetUserId = targetUserId;
this.boolValue = boolValue;
}
encode() {
let payload = super.encode();
payload.content = this.conferenceId;
let obj = {
t: this.commandType,
u: this.targetUserId,
};
if (this.boolValue) {
obj['b'] = this.boolValue;
}
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
if (payload.binaryContent) {
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.commandType = obj.t;
this.boolValue = !!obj.b;
this.targetUserId = obj.u;
}
this.conferenceId = payload.content;
}
// TODO Object.freeze
static ConferenceCommandType = Object.freeze({
//全体静音,只有主持人可以操作,结果写入conference profile中。带有参数是否允许成员自主解除静音。
MUTE_ALL_AUDIO: 0,
//取消全体静音,只有主持人可以操作,结果写入conference profile中。带有参数是否邀请成员解除静音。
CANCEL_MUTE_ALL_AUDIO: 1,
//要求某个用户更改静音状态,只有主持人可以操作。带有参数是否静音/解除静音。
REQUEST_MUTE_AUDIO: 2,
//拒绝UNMUTE要求。(如果同意不需要通知对方同意)
REJECT_UNMUTE_AUDIO_REQUEST: 3,
//普通用户申请解除静音,带有参数是请求,还是取消请求。
APPLY_UNMUTE_AUDIO: 4,
//管理员批准解除静音申请,带有参数是同意,还是拒绝申请。
APPROVE_UNMUTE_AUDIO: 5,
//管理员批准全部解除静音申请,带有参数是同意,还是拒绝申请。
APPROVE_ALL_UNMUTE_AUDIO: 6,
//举手,带有参数是举手还是放下举手
HANDUP: 7,
//主持人放下成员的举手
PUT_HAND_DOWN: 8,
//主持人放下全体成员的举手
PUT_ALL_HAND_DOWN: 9,
//录制,有参数是录制还是取消录制
RECORDING: 10,
// 设置焦点用户
FOCUS: 11,
// 取消设置焦点用户
CANCEL_FOCUS: 12,
//全体静音,只有主持人可以操作,结果写入conference profile中。带有参数是否允许成员自主解除静音。
MUTE_ALL_VIDEO: 13,
//取消全体静音,只有主持人可以操作,结果写入conference profile中。带有参数是否邀请成员解除静音。
CANCEL_MUTE_ALL_VIDEO: 14,
//要求某个用户更改静音状态,只有主持人可以操作。带有参数是否静音/解除静音。
REQUEST_MUTE_VIDEO: 15,
//拒绝UNMUTE要求。(如果同意不需要通知对方同意)
REJECT_UNMUTE_VIDEO_REQUEST: 16,
//普通用户申请解除静音,带有参数是请求,还是取消请求。
APPLY_UNMUTE_VIDEO: 17,
//管理员批准解除静音申请,带有参数是同意,还是拒绝申请。
APPROVE_UNMUTE_VIDEO: 18,
//管理员批准全部解除静音申请,带有参数是同意,还是拒绝申请。
APPROVE_ALL_UNMUTE_VIDEO: 19,
});
}
@@ -0,0 +1,69 @@
import MessageContent from "../../messages/messageContent";
import MessageContentType from "../../messages/messageContentType";
import wfc from "../../client/wfc";
export default class ConferenceInviteMessageContent extends MessageContent {
callId;
host;
title;
desc;
startTime;
audioOnly;
audience;
pin;
advanced;
constructor(callId, host, title, desc, startTime, audioOnly, audience, advance, pin) {
super(MessageContentType.CONFERENCE_CONTENT_TYPE_INVITE);
this.callId = callId;
this.host = host;
this.title = title;
this.desc = desc;
this.startTime = startTime;
this.audioOnly = audioOnly;
this.audience = audience;
this.advanced = advance;
this.pin = pin;
}
digest(message) {
let str = '[会议邀请]'
return str;
}
encode() {
let payload = super.encode();
payload.content = this.callId;
payload.pushContent = '会议邀请';
let obj = {
h: this.host,
s: this.startTime,
t: this.title,
d: this.desc,
audience: this.audience ? 1 : 0,
advanced: this.advanced ? 1 : 0,
a: this.audioOnly ? 1 : 0,
p: this.pin,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
if (payload.binaryContent) {
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.host = obj.h;
this.startTime = obj.s;
this.title = obj.t;
this.desc = obj.d;
this.audience = obj.audience > 0;
this.advanced = obj.advanced > 0;
this.audioOnly = obj.a > 0;
this.pin = obj.p;
}
this.callId = payload.content;
}
}
@@ -0,0 +1,23 @@
import MessageContent from "../../messages/messageContent";
import MessageContentType from "../../messages/messageContentType";
export default class ConferenceKickoffMemberMessageContent extends MessageContent {
callId;
constructor(callId) {
super(MessageContentType.CONFERENCE_CONTENT_TYPE_KICKOFF_MEMBER)
this.callId = callId;
}
encode() {
let payload = super.encode();
payload.content = this.callId;
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
}
}
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import wfc from "../../client/wfc"
import MessageContentType from '../../messages/messageContentType';
export default class JoinCallRequestMessageContent extends MessageContent {
callId;
clientId;
constructor(callId, clientId) {
super(MessageContentType.VOIP_Join_Call_Request);
this.callId = callId;
this.clientId = clientId;
}
digest() {
return '';
}
encode() {
let payload = super.encode();
payload.content = this.callId;
let obj = {
clientId: this.clientId
}
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.clientId = obj.clientId;
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from '../../messages/messageContent';
import wfc from "../../client/wfc"
import MessageContentType from '../../messages/messageContentType';
export default class MultiCallOngoingMessageContent extends MessageContent {
callId;
initiator;
audioOnly;
targets;
constructor(callId, initiator, audioOnly, targets) {
super(MessageContentType.VOIP_Multi_Call_Ongoing);
this.callId = callId;
this.initiator = initiator;
this.audioOnly = audioOnly;
this.targets = targets;
}
digest(message) {
let displayName = wfc.getGroupMemberDisplayName(message.conversation.target, this.initiator);
return displayName + ' 发起的通话';
}
encode() {
let payload = super.encode();
payload.content = this.callId;
let obj = {
initiator: this.initiator,
audioOnly: this.audioOnly ? 1 : 0,
targets: this.targets
}
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.initiator = obj.initiator;
this.audioOnly = obj.audioOnly === 1;
this.targets = obj.targets;
}
}
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from "../../messages/notification/notificationMessageContent";
import MessageContentType from "../../messages/messageContentType";
import wfc from "../../client/wfc"
class ParticipantStatus {
userId;
acceptTime;
joinTime;
videoMuted;
}
export default class MuteVideoMessageContent extends NotificationMessageContent {
callId;
videoMuted;
existParticipants;
constructor(mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.VOIP_CONTENT_TYPE_MUTE_VIDEO, mentionedType, mentionedTargets);
}
formatNotification(message) {
// TODO
return "mute video";
}
encode() {
let payload = super.encode();
payload.content = this.callId;
let obj = {
existParticipants: this.existParticipants,
videoMuted: this.videoMuted,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
this.callId = payload.content;
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.existParticipants = obj.existParticipants;
this.videoMuted = obj.videoMuted;
}
}
+23
View File
@@ -0,0 +1,23 @@
export default class ConferenceInfo {
conferenceId;
conferenceTitle;
password;
pin;
owner;
managers = [];
focus;
// 秒
startTime;
endTime;
audience;
advance;
//@SerializedName("allowSwitchMode")
allowSwitchMode; // 其实更新allowTurnOnMic;
noJoinBeforeStart = false;
recording = false;
isAllowTurnOnMic() {
return this.allowSwitchMode;
}
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class ConnectionStatus {
static ConnectionStatusTimeInconsistent = -9;
static ConnectionStatusNotLicensed = -8;
static ConnectionStatusKickedOff = -7;
static ConnectionStatusSecretKeyMismatch = -6;
static ConnectionStatusTokenIncorrect = -5;
static ConnectionStatusServerDown = -4;
static ConnectionStatusRejected = -3;
static ConnectionStatusLogout = -2;
static ConnectionStatusUnconnected = -1;
static ConnectionStatusConnecting = 0;
static ConnectionStatusConnected = 1;
static ConnectionStatusReceiveing = 2;
static desc(status) {
const desc = {
'-9': '客户端和IM 服务端时间不同步,请进行时钟同步',
'-8': 'IM 服务未授权或已过期,专业版IM-Server 是绑定域名或者 ip 的,只能通过所绑定的域名去连接',
'-7': '被踢下线',
'-6': '会话密钥错误,请参考 https://docs.wildfirechat.cn/faq/general.html 第12个问题排查',
'-5': 'token错误',
'-4': 'IM Server服务无法连通,请检查服务器是否宕机或者网络出现问题',
'-3': '连接被服务器拒绝,一般是用户被封禁',
'-2': '退出登录',
'-1': '连接失败',
'0': '连接中',
'1': '连接成功,正常状态,所有业务可用',
'2': '正在同步信息,登录以后要先同步消息,可能同步数据量比较大,这时可以选择等待连接状态变为1时来统一更新UI'
};
return desc[status]
}
}
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class ErrorCode {
//server error code
static kEcServerSecrectKeyMismatch = 1;
static kEcServerInvalidData = 2;
static kEcServerServerError = 4;
static kEcServerNotModified = 5;
static kEcServerTokenIncorrect = 6;
static kConnectionStatusKickedOff = 7;
static kEcServerUserForbidden = 8;
static kEcServerNotInGroup = 9;
static kEcServerInvalidMessage = 10;
static kEcServerGroupAlreadyExist = 11;
static kEcServerPasswordIncorrect = 15;
static kEcServerFriendAlreadyRequested = 16;
static kEcServerFriendRequestOverFrequency = 17;
static kEcServerFriendRquestBlocked = 18;
static kEcServerFriendRequestOvertime = 19;
static kEcServerNotInChatroom = 20;
static kEcServerNotLicensed = 22;
static kEcServerTimeInconsistent = 30;
static kEcServerUserIsBlocked = 245;
static kEcServerInBlacklist = 246;
static kEcServerForbidden_send_msg = 247;
static kEcServerNotRight = 248;
static kEcServerTimeout = 249;
static kEcServerOverFrequence = 250;
static kEcServerInvalidParameter = 251;
static kEcServerNotExist = 253;
static kEcServerNotImplement = 254;
}
+500
View File
@@ -0,0 +1,500 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import TextMessageContent from '../messages/textMessageContent'
import PTextMessageContent from '../messages/ptextMessageContent'
import ImageMessageContent from '../messages/imageMessageContent';
import MessageContentType from '../messages/messageContentType';
import PersistFlag from '../messages/persistFlag';
import TipNotificationMessageContent from '../messages/notification/tipNotification';
import UnknownMessageContent from '../messages/unknownMessageContent';
import UnsupportMessageContent from '../messages/unsupportMessageConten';
import ChangeGroupNameNotification from '../messages/notification/changeGroupNameNotification';
import KickoffGroupMemberNotification from '../messages/notification/kickoffGroupMemberNotification';
import KickoffGroupMemberVisiableNotification from '../messages/notification/kickoffGroupMemberVisiableNotification';
import AddGroupMemberNotification from '../messages/notification/addGroupMemberNotification';
import ChangeGroupPortraitNotification from '../messages/notification/changeGroupPortraitNotification';
import CreateGroupNotification from '../messages/notification/createGroupNotification';
import DismissGroupNotification from '../messages/notification/dismissGroupNotification';
import ModifyGroupAliasNotification from '../messages/notification/modifyGroupAliasNotification';
import ModifyGroupExtraNotification from '../messages/notification/modifyGroupExtraNotification';
import ModifyGroupMemberExtraNotification from '../messages/notification/modifyGroupMemberExtraNotification';
import QuitGroupNotification from '../messages/notification/quitGroupNotification';
import QuitGroupVisiableNotification from '../messages/notification/quitGroupVisiableNotification';
import TransferGroupOwnerNotification from '../messages/notification/transferGroupOwnerNotification';
import FileMessageContent from '../messages/fileMessageContent';
import VideoMessageContent from '../messages/videoMessageContent';
import StickerMessageContent from '../messages/stickerMessageContent';
import SoundMessageContent from '../messages/soundMessageContent';
import TypingMessageContent from '../messages/typingMessageContent';
import RecallMessageNotification from '../messages/notification/recallMessageNotification';
import DeleteMessageContent from '../messages/deleteMessageContent';
import CallStartMessageContent from '../av/messages/callStartMessageContent';
import CallAnswerMessageContent from '../av/messages/callAnswerMessageContent';
import CallAnswerTMessageContent from '../av/messages/callAnswerTMessageContent';
import CallByeMessageContent from '../av/messages/callByeMessageContent';
import CallSignalMessageContent from '../av/messages/callSignalMessageContent';
import CallModifyMessageContent from '../av/messages/callModifyMessageContent';
import AddParticipantsMessageContent from "../av/messages/addParticipantsMessageContent";
import MuteVideoMessageContent from "../av/messages/muteVideoMessageContent";
import GroupJoinTypeNotificationContent from "../messages/notification/groupJoinTypeNotificationContent";
import GroupMuteNotificationContent from "../messages/notification/groupMuteNotificationContent";
import GroupSetManagerNotificationContent from "../messages/notification/groupSetManagerNotificationContent";
import GroupPrivateChatNotificationContent from "../messages/notification/groupPrivateChatNotificationContent";
import LocationMessageContent from "../messages/locationMessageContent";
import MuteGroupMemberNotification from '../messages/notification/muteGroupMemberNotification'
import AllowGroupMemberNotification from '../messages/notification/allowGroupMemberNotification'
import CardMessageContent from '../messages/cardMessageContent'
import CompositeMessageContent from "../messages/compositeMessageContent";
import ConferenceInviteMessageContent from "../av/messages/conferenceInviteMessageContent";
import ConferenceChangeModeContent from "../av/messages/conferenceChangeModeContent";
import ConferenceKickoffMemberMessageContent from "../av/messages/conferenceKickoffMemberMessageContent";
import MarkUnreadMessageContent from "../messages/markUnreadMessageContent";
import LinkMessageContent from "../messages/linkMessageContent";
import FriendAddedNotification from "../messages/notification/friendAddedNotification";
import FriendGreetingNotification from "../messages/notification/friendGreetingNotification";
import PcLoginRequestMessageContent from "../messages/pcLoginRequestMessageContent";
import StartSecretChatNotification from "../messages/notification/startSecretChatNotification";
import MultiCallOngoingMessageContent from "../av/messages/multiCallOngoingMessageContent";
import JoinCallRequestMessageContent from "../av/messages/joinCallRequestMessageContent";
import RichNotificationMessageContent from "../messages/notification/richNotificationMessageContent";
import ArticlesMessageContent from "../messages/articlesMessageContent";
import ChannelMenuEventMessageContent from "../messages/channelMenuEventMessageContent";
import EnterChannelChatMessageContent from "../messages/enterChannelChatMessageContent";
import LeaveChannelChatMessageContent from "../messages/leaveChannelChatMessageContent";
import ConferenceCommandMessageContent from "../av/messages/conferenceCommandMessageContent";
import StreamingTextGeneratingMessageContent from "../messages/streamingTextGeneratingMessageContent";
import StreamingTextGeneratedMessageContent from "../messages/streamingTextGeneratedMessageContent";
export default class MessageConfig {
static getMessageContentClazz(type) {
for (const content of MessageConfig.MessageContents) {
if (content.type === type) {
if (content.contentClazz) {
return content.contentClazz;
} else {
return UnsupportMessageContent;
}
}
}
console.error(`message type ${type} is unknown`);
return UnknownMessageContent;
}
static getMessageContentFlag(type) {
let flag = PersistFlag.No_Persist;
for (const content of MessageConfig.MessageContents) {
if (content.type === type) {
flag = content.flag;
}
}
return flag;
}
static getMessageContentPersitFlag(type) {
for (const content of MessageConfig.MessageContents) {
if (content.type === type) {
return content.flag;
}
}
return -1;
}
static getMessageContentType(messageContent) {
for (const content of MessageConfig.MessageContents) {
if (content.contentClazz && messageContent instanceof content.contentClazz) {
return content.type;
}
}
return MessageContentType.Unknown;
}
static registerMessageContent(name, flag, type, clazz) {
// TODO validate args
MessageConfig.MessageContents.push(
{
name: name,
flag: flag,
type: type,
contentClazz: clazz,
}
);
}
static MessageContents = [
{
name: 'unknown',
flag: PersistFlag.Persist,
type: MessageContentType.Unknown,
contentClazz: UnknownMessageContent,
},
{
name: 'text',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Text,
contentClazz: TextMessageContent,
},
{
name: 'ptext',
flag: PersistFlag.Persist,
type: MessageContentType.P_Text,
contentClazz: PTextMessageContent,
},
{
name: 'voice',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Voice,
contentClazz: SoundMessageContent,
},
{
name: 'image',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Image,
contentClazz: ImageMessageContent,
},
{
name: 'location',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Location,
contentClazz: LocationMessageContent,
},
{
name: 'file',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.File,
contentClazz: FileMessageContent,
},
{
name: 'video',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Video,
contentClazz: VideoMessageContent,
},
{
name: 'sticker',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Sticker,
contentClazz: StickerMessageContent,
},
{
name: 'link',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Link,
contentClazz: LinkMessageContent,
},
{
name: 'userCard',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.UserCard,
contentClazz: CardMessageContent,
},
{
name: 'compositeMessage',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Composite_Message,
contentClazz: CompositeMessageContent,
},
{
name: 'tip',
flag: PersistFlag.Persist,
type: MessageContentType.Tip_Notification,
contentClazz: TipNotificationMessageContent,
},
{
name: 'typing',
flag: PersistFlag.Transparent,
type: MessageContentType.Typing,
contentClazz: TypingMessageContent,
},
{
name: 'friendGreeting',
flag: PersistFlag.Persist,
type: MessageContentType.Friend_Added,
contentClazz: FriendGreetingNotification,
},
{
name: 'friendAdded',
flag: PersistFlag.Persist,
type: MessageContentType.Friend_Greeting,
contentClazz: FriendAddedNotification,
},
{
name: 'addGroupMemberNotification',
flag: PersistFlag.Persist,
type: MessageContentType.AddGroupMember_Notification,
contentClazz: AddGroupMemberNotification,
},
{
name: 'changeGroupNameNotification',
flag: PersistFlag.Persist,
type: MessageContentType.ChangeGroupName_Notification,
contentClazz: ChangeGroupNameNotification,
},
{
name: 'changeGroupPortraitNotification',
flag: PersistFlag.Persist,
type: MessageContentType.ChangeGroupPortrait_Notification,
contentClazz: ChangeGroupPortraitNotification,
},
{
name: 'createGroupNotification',
flag: PersistFlag.Persist,
type: MessageContentType.CreateGroup_Notification,
contentClazz: CreateGroupNotification,
},
{
name: 'dismissGroupNotification',
flag: PersistFlag.Persist,
type: MessageContentType.DismissGroup_Notification,
contentClazz: DismissGroupNotification,
},
{
name: 'kickoffGroupMemberNotification',
flag: PersistFlag.Persist,
type: MessageContentType.KickOffGroupMember_Notification,
contentClazz: KickoffGroupMemberNotification,
},
{
name: 'kickoffGroupMemberVisiableNotification',
flag: PersistFlag.Persist,
type: MessageContentType.KickOffGroupMember_Visible_Notification,
contentClazz: KickoffGroupMemberVisiableNotification,
},
{
name: 'modifyGroupAliasNotification',
flag: PersistFlag.Persist,
type: MessageContentType.ModifyGroupAlias_Notification,
contentClazz: ModifyGroupAliasNotification,
},
{
name: 'modifyGroupExtraNotification',
flag: PersistFlag.Persist,
type: MessageContentType.ModifyGroupExtra_Notification,
contentClazz: ModifyGroupExtraNotification,
},
{
name: 'modifyGroupMemberExtraNotification',
flag: PersistFlag.Persist,
type: MessageContentType.ModifyGroupMemberExtra_Notification,
contentClazz: ModifyGroupMemberExtraNotification,
},
{
name: 'quitGroupNotification',
flag: PersistFlag.Persist,
type: MessageContentType.QuitGroup_Notification,
contentClazz: QuitGroupNotification,
},
{
name: 'quitGroupVisiableNotification',
flag: PersistFlag.Persist,
type: MessageContentType.QuitGroup_Visible_Notification,
contentClazz: QuitGroupVisiableNotification,
},
{
name: 'transferGroupOwnerNotification',
flag: PersistFlag.Persist,
type: MessageContentType.TransferGroupOwner_Notification,
contentClazz: TransferGroupOwnerNotification,
},
{
name: 'groupJoinTypeNotificationContent',
flag: PersistFlag.Persist,
type: MessageContentType.ChangeJoinType_Notification,
contentClazz: GroupJoinTypeNotificationContent,
},
{
name: 'groupMuteNotificationContent',
flag: PersistFlag.Persist,
type: MessageContentType.MuteGroup_Notification,
contentClazz: GroupMuteNotificationContent,
},
{
name: 'groupPrivateChatNotificationContent',
flag: PersistFlag.Persist,
type: MessageContentType.ChangePrivateChat_Notification,
contentClazz: GroupPrivateChatNotificationContent,
},
{
name: 'groupSetManagerNotificationContent',
flag: PersistFlag.Persist,
type: MessageContentType.SetGroupManager_Notification,
contentClazz: GroupSetManagerNotificationContent,
},
{
name: 'muteGroupMemberNotificationContent',
flag: PersistFlag.Persist,
type: MessageContentType.MuteGroupMember_Notification,
contentClazz: MuteGroupMemberNotification,
},
{
name: 'allowGroupMemberNotificationContent',
flag: PersistFlag.Persist,
type: MessageContentType.AllowGroupMember_Notification,
contentClazz: AllowGroupMemberNotification,
},
{
name: 'recall',
flag: PersistFlag.Persist,
type: MessageContentType.RecallMessage_Notification,
contentClazz: RecallMessageNotification,
},
{
name: 'delete',
flag: PersistFlag.No_Persist,
type: MessageContentType.DeleteMessage_Notification,
contentClazz: DeleteMessageContent,
},
{
name: 'streamingTextGenerating',
flag: PersistFlag.Transparent,
type: MessageContentType.Streaming_Text_Generating,
contentClazz: StreamingTextGeneratingMessageContent,
},
{
name: 'streamingTextGenerated',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Streaming_Text_Generated,
contentClazz: StreamingTextGeneratedMessageContent,
},
{
name: 'callStartMessageContent',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.VOIP_CONTENT_TYPE_START,
contentClazz: CallStartMessageContent,
},
{
name: 'callAnswerMessageContent',
flag: PersistFlag.No_Persist,
type: MessageContentType.VOIP_CONTENT_TYPE_ACCEPT,
contentClazz: CallAnswerMessageContent,
},
{
name: 'callAnswerTMessageContent',
flag: PersistFlag.Transparent,
type: MessageContentType.VOIP_CONTENT_TYPE_ACCEPT_T,
contentClazz: CallAnswerTMessageContent,
},
{
name: 'callByeMessageContent',
flag: PersistFlag.No_Persist,
type: MessageContentType.VOIP_CONTENT_TYPE_END,
contentClazz: CallByeMessageContent,
},
{
name: 'callSignalMessageContent',
flag: PersistFlag.Transparent,
type: MessageContentType.VOIP_CONTENT_TYPE_SIGNAL,
contentClazz: CallSignalMessageContent,
},
{
name: 'callModifyMessageContent',
flag: PersistFlag.No_Persist,
type: MessageContentType.VOIP_CONTENT_TYPE_MODIFY,
contentClazz: CallModifyMessageContent,
},
{
name: 'callAddParticipant',
flag: PersistFlag.Persist,
type: MessageContentType.VOIP_CONTENT_TYPE_ADD_PARTICIPANT,
contentClazz: AddParticipantsMessageContent,
},
{
name: 'callMuteVideo',
flag: PersistFlag.No_Persist,
type: MessageContentType.VOIP_CONTENT_TYPE_MUTE_VIDEO,
contentClazz: MuteVideoMessageContent,
},
{
name: 'conferenceInvite',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.CONFERENCE_CONTENT_TYPE_INVITE,
contentClazz: ConferenceInviteMessageContent,
},
{
name: 'conferenceChangeMode',
flag: PersistFlag.Transparent,
type: MessageContentType.CONFERENCE_CONTENT_TYPE_CHANGE_MODE,
contentClazz: ConferenceChangeModeContent,
},
{
name: 'conferenceKickoffMember',
flag: PersistFlag.Transparent,
type: MessageContentType.CONFERENCE_CONTENT_TYPE_KICKOFF_MEMBER,
contentClazz: ConferenceKickoffMemberMessageContent,
},
{
name: 'multiCallOngoing',
flag: PersistFlag.Transparent,
type: MessageContentType.VOIP_Multi_Call_Ongoing,
contentClazz: MultiCallOngoingMessageContent,
},
{
name: 'joinCallRequest',
flag: PersistFlag.Transparent,
type: MessageContentType.VOIP_Join_Call_Request,
contentClazz: JoinCallRequestMessageContent,
},
{
name: 'markUnreadMessage',
flag: PersistFlag.No_Persist,
type: MessageContentType.Mark_Unread_Sync,
contentClazz: MarkUnreadMessageContent,
},
{
name: 'pcLoginRequest',
flag: PersistFlag.No_Persist,
type: MessageContentType.PC_Login_Request,
contentClazz: PcLoginRequestMessageContent,
},
{
name: 'startSecretChat',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.StartSecretChat_Notification,
contentClazz: StartSecretChatNotification,
},
{
name: 'richNotification',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Rich_Notification,
contentClazz: RichNotificationMessageContent,
},
{
name: 'articlesMessageContent',
flag: PersistFlag.Persist_And_Count,
type: MessageContentType.Articles,
contentClazz: ArticlesMessageContent,
},
{
name: 'channelMenuEventMessageContent',
flag: PersistFlag.Transparent,
type: MessageContentType.Channel_Menu_Event,
contentClazz: ChannelMenuEventMessageContent,
},
{
name: 'enterChannelChatMessageContent',
flag: PersistFlag.Transparent,
type: MessageContentType.Enter_Channel_Chat,
contentClazz: EnterChannelChatMessageContent,
},
{
name: 'leaveChannelChatMessageContent',
flag: PersistFlag.Transparent,
type: MessageContentType.Leave_Channel_Chat,
contentClazz: LeaveChannelChatMessageContent,
},
{
name: 'conferenceCommandMessageContent',
flag: PersistFlag.Transparent,
type: MessageContentType.CONFERENCE_CONTENT_TYPE_COMMAND,
contentClazz: ConferenceCommandMessageContent,
}
];
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class UserSettingScope {
//不能直接使用,调用setConversation:silent:方法会使用到此值。
static ConversationSilent = 1;
static GlobalSilent = 2;
//不能直接使用,调用setConversation:top:方法会使用到此值。
static ConversationTop = 3;
static HiddenNotificationDetail = 4;
static GroupHideNickname = 5;
static FavoriteGroup = 6;
//不能直接使用,协议栈内会使用此值
static Conversation_Sync = 7;
//不能直接使用,协议栈内会使用此值
static My_Channel = 8;
//不能直接使用,协议栈内会使用此值
static Listened_Channel = 9;
static PCOnline = 10;
static UserSettingConversationReaded = 11;
static WebOnline = 12;
static DisableReceipt = 13;
static FavoriteUser = 14;
static MuteWhenPCOnline = 15;
static LinesReaded = 16;
static NoDisturbing = 17;
static ConversationClearMessage = 18;
static ConversationDraft = 19;
static DisableSyncDraft = 20;
static VoipSilent = 21;
static PttReserved = 22;
static CustomState = 23;
static DisableSecretChat = 24;
static PttSilent = 25;
static GroupRemark = 26;
// 不能直接使用,协议栈内部会使用此致
static Privacy_Searchable = 27;
// 不能直接使用,协议栈内部会使用此致
static AddFriend_NoVerify = 28;
// 用户自定义的scope需从1000开始,以防冲突
static kUserSettingCustomBegin = 1000;
}
File diff suppressed because it is too large. Load diff
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class EventType {
// function (message) {}
static SendMessage = 'sendMsg';
// function (message, hasMore) {}
/**
* @deprecated 请使用 ReceiveMessages
* @type {string}
*/
static ReceiveMessage = 'receiveMsg';
// function ([message], hasMore) {}
static ReceiveMessages = 'receiveMsgs';
// function (Map(userId, receiveTime)) {}
static MessageReceived = 'msgReceived';
// function ([readEntry]) {}
static MessageRead = 'msgRead';
// 主动调用recallMessage时,也会触发
// function (operator, messageUid) {}
static RecallMessage = 'recallMsg';
// 远程删除消息时触发
// function (messageUid) {}
static MessageDeleted = 'msgDeleted'
// function (messageId) {}
// 本地主动删除消息时触发
static DeleteMessage = 'deleteMsg';
// function (message) {}
static MessageStatusUpdate = 'msgStatusUpdate';
// function (connectionStatus) {}
static ConnectionStatusChanged = 'connectionStatusChanged';
// function (host/ip/port) {}
static ConnectToServer = 'connectToServer';
// function (userInfos) {}
static UserInfosUpdate = 'userInfosUpdate';
// function (channelInfos) {}
static ChannelInfosUpdate = 'channelInfosUpdate';
// function (groupInfos) {}
static GroupInfosUpdate = 'groupInfosUpdate';
// function (updatedFriendIds) {}
static FriendListUpdate = 'friendListUpdate';
// function ([newFriendRequests]) {}
static FriendRequestUpdate = 'friendRequestUpdate';
// function (conversationInfo) {}
static ConversationInfoUpdate = 'conversationInfoUpdate';
// function () {}
static SettingUpdate = 'settingUpdate';
// function (groupId, GroupMember[]) {}
static GroupMembersUpdate = 'groupMembersUpdate';
// function (event) {}
static ConferenceEvent = 'conferenceEvent';
// function (UserOnlineState[]) {}
static UserOnlineEvent = 'onlineEvent';
// function (targetId, playedMessageId) {}
static SecretChatStartBurn = 'secretChatStartBurn';
// function ([messageId]) {}
static SecretChatMessageBurned = 'secretChatMessageBurned';
// function (targetId) {}
static SecretChatStateChange = 'secretChatStateChange';
}
+10
View File
@@ -0,0 +1,10 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class ModifyChannelInfoType {
static Modify_Channel_Name = 0;
static Modify_Channel_Portrait = 1;
static Modify_Channel_Desc = 2;
static Modify_Channel_Extra = 3;
}
@@ -0,0 +1,96 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
import wfc from "../client/wfc";
import LinkMessageContent from "./linkMessageContent";
export default class ArticlesMessageContent extends MessageContent {
topArticle;
subArticles;
constructor() {
super(MessageContentType.Articles);
}
digest(message) {
return this.topArticle.title;
}
encode() {
let payload = super.encode();
let obj = {
top: this.topArticle.toJson(),
}
if (this.subArticles) {
obj['subArticles'] = this.subArticles.map(article => article.toJson());
}
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.topArticle = new Article();
this.topArticle.fromJson(obj.top);
if (obj.subArticles) {
this.subArticles = [];
obj.subArticles.forEach(article => {
let tmp = new Article();
tmp.fromJson(article);
this.subArticles.push(tmp);
})
}
}
toLinkMessageContent() {
let contents = [];
contents.push(this.topArticle.toLinkMessageContent())
if (this.subArticles) {
this.subArticles.forEach(article => {
contents.push(article.toLinkMessageContent())
})
}
return contents;
}
}
class Article {
articleId;
cover;
title;
digest;
url;
readReport;
toJson() {
let obj = {
id: this.articleId,
cover: this.cover,
title: this.title,
url: this.url,
digest: this.digest,
rr: this.readReport
}
return obj;
}
fromJson(obj) {
this.articleId = obj.id;
this.cover = obj.cover;
this.title = obj.title;
this.digest = obj.digest;
this.url = obj.url;
this.readReport = obj.rr;
}
toLinkMessageContent() {
let content = new LinkMessageContent();
content.url = this.url;
content.title = this.title;
content.contentDigest = this.digest;
content.thumbnail = this.cover;
return content;
}
}
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
/*
* Copyright © 2020 WildFireChat. All rights reserved.
*/
import MessageContent from './messageContent'
import MessageContentType from './messageContentType'
import wfc from '../client/wfc'
import Config from '../../config'
export default class CardMessageContent extends MessageContent {
/**
* 0,用户;1,群组;2,聊天室;3,频道
*/
cardType;
target;
name;
displayName;
portrait;
from;
constructor(cardType, target, displayName, portrait, from) {
super(MessageContentType.UserCard);
this.cardType = cardType;
this.target = target;
this.displayName = displayName;
this.portrait = portrait;
this.from = from;
}
encode() {
let payload = super.encode()
payload.content = this.target;
let obj = {
t: this.cardType,
n: this.name,
d: this.displayName,
p: this.portrait,
f: this.from,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload)
this.target = payload.content;
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.cardType = obj.t;
this.name = obj.n;
this.displayName = obj.d;
this.portrait = obj.p;
if (Config.urlRedirect){
this.portrait = Config.urlRedirect(obj.p);
}
this.from = obj.f;
}
digest() {
let msg = '[名片]';
switch (this.cardType) {
case 0:
msg = '[个人名片]'
break;
case 1:
msg = '[群组名片]'
break;
case 2:
msg = '[聊天室名]'
break;
case 3:
msg = '[频道名片]'
break;
default:
break;
}
return msg + this.displayName;
}
}
@@ -0,0 +1,17 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
export default class ChannelMenuEventMessageContent extends MessageContent {
menu
constructor(menu) {
super(MessageContentType.Channel_Menu_Event);
this.menu = menu;
}
encode() {
let payload = super.encode();
payload.content = JSON.stringify(this.menu);
return payload;
}
}
+194
View File
@@ -0,0 +1,194 @@
import MessageContentType from "../messages/messageContentType";
import wfc from "../client/wfc";
import MediaMessageContent from "../messages/mediaMessageContent";
import {stringValue} from "../util/longUtil";
import Message from "../messages/message";
import Conversation from "../model/conversation";
import Long from "long";
import {compare} from "../util/longUtil";
import MessagePayload from "../messages/messagePayload";
import ArticlesMessageContent from "./articlesMessageContent";
import MessageContentMediaType from "./messageContentMediaType";
export default class CompositeMessageContent extends MediaMessageContent {
title = '';
messages = [];
// web 端有效,仅仅是用来标识 mediaCompositeMessage 是否已加载
loaded = false;
constructor() {
super(MessageContentType.Composite_Message, MessageContentMediaType.General, '')
}
setMessages(msgs) {
this.messages = [];
msgs.forEach(m => {
if (m.messageContent instanceof ArticlesMessageContent) {
let linkMessageContents = m.messageContent.toLinkMessageContent();
linkMessageContents.forEach(lm => {
let msg = Object.assign(new Message(), m);
msg.messageContent = lm;
this.messages.push(msg);
})
} else {
this.messages.push(m)
}
})
this.messages = this.messages.sort((m1, m2) => {
return compare(m1.messageUid, m2.messageUid);
})
}
digest(message) {
return '[聊天记录]' + this.title;
}
encode() {
let payload = super.encode();
payload.content = this.title;
let arr = [];
let binArr;
let size = 0;
this.messages.forEach(msg => {
let msgPayload = msg.messageContent.encode();
let o = {
uid: stringValue(msg.messageUid),
type: msg.conversation.type,
target: msg.conversation.target,
line: msg.conversation.line,
from: msg.from,
tos: msg.to,
direction: msg.direction,
status: msg.status,
serverTime: stringValue(msg.timestamp),
ctype: msgPayload.type,
csc: msgPayload.searchableContent,
cpc: msgPayload.pushContent,
cpd: msgPayload.pushData,
cc: msgPayload.content,
cmt: msgPayload.mentionedType,
cmts: msgPayload.mentionedTargets,
ce: msgPayload.extra,
};
if (msgPayload.searchableContent) {
payload.searchableContent = payload.searchableContent + msgPayload.searchableContent + ' ';
}
if (msgPayload.binaryContent) {
o.cbc = msgPayload.binaryContent;
}
if (msg.messageContent instanceof MediaMessageContent) {
o.mt = msg.messageContent.mediaType;
o.mru = msg.messageContent.remotePath;
}
if (!binArr) {
size += JSON.stringify(o).length;
if (size > 20480 && arr.length > 0) {
binArr = arr.map((value) => value);
}
}
arr.push(o);
});
let obj;
if (binArr && !this.file) {
obj = {
ms: arr,
}
let str = JSON.stringify(obj);
str = str.replace(/"uid":"([0-9]+)"/, "\"uid\":$1");
str = str.replace(/"serverTime":"([0-9]+)"/, "\"serverTime\":$1");
let blob = new Blob([str]);
let fileName = 'wcf-' + new Date().getTime() + '.data';
this.file = new File([blob], fileName);
obj = {
ms: binArr,
}
} else {
if (binArr) {
obj = {
ms: binArr,
}
} else {
obj = {
ms: arr,
}
}
}
let str = JSON.stringify(obj);
str = str.replace(/"uid":"([0-9]+)"/, "\"uid\":$1");
str = str.replace(/"serverTime":"([0-9]+)"/, "\"serverTime\":$1");
payload.binaryContent = wfc.utf8_to_b64(str)
return payload;
}
decode(payload) {
super.decode(payload);
this.title = payload.content;
let str;
if (this.file) {
// web
let fileReader = new FileReader();
fileReader.onload(ev => {
this._decodeMessages(ev.target.result);
});
fileReader.readAsBinaryString(this.file);
} else if (this.localPath) {
}
if (!str) {
str = wfc.b64_to_utf8(payload.binaryContent);
this._decodeMessages(str);
}
}
_decodeMessages(str) {
if (this.loaded) {
return;
}
this.messages = [];
// FIXME node 环境,decodeURIComponent 方法,有时候会在最后添加上@字符,目前尚未找到原因,先规避
str = str.substring(0, str.lastIndexOf('}') + 1);
str = str.replace(/"uid":([0-9]+)/g, "\"uid\":\"$1\"");
str = str.replace(/"serverTime":([0-9]+)/g, "\"serverTime\":\"$1\"");
let obj = JSON.parse(str);
obj.ms.forEach(o => {
let conv = new Conversation(o.type, o.target, o.line);
let msg = new Message()
msg.messageUid = Long.fromValue(o.uid);
msg.conversation = conv;
msg.from = o.from;
msg.to = o.tos;
msg.direction = o.direction;
msg.status = o.status;
msg.timestamp = Long.fromValue(o.serverTime);
let payload = new MessagePayload();
payload.type = o.ctype;
payload.searchableContent = o.csc;
payload.pushContent = o.cpc;
payload.pushData = o.cpd;
payload.content = o.cc;
payload.mentionedType = o.cmt;
payload.mentionedTargets = o.cmts;
payload.extra = o.ce;
payload.binaryContent = o.cbc;
payload.mediaType = o.mt;
payload.remoteMediaUrl = o.mru;
msg.messageContent = Message.messageContentFromMessagePayload(payload, msg.from);
this.messages.push(msg);
});
console.log('cp ms', this.messages)
}
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from './messageContent'
import MessageContentType from './messageContentType';
import wfc from '../client/wfc'
import Long from 'long'
// 本消息由调用server api删除消息触发,请勿直接发送本消息
export default class DeleteMessageContent extends MessageContent {
operatorId = '';
messageUid = new Long(0);
constructor(operatorId, messageUid) {
super(MessageContentType.DeleteMessage_Notification);
this.operatorId = operatorId;
this.messageUid = messageUid;
}
formatNotification(message) {
return "消息已删除";
}
encode() {
let payload = super.encode();
payload.content = this.operatorId;
payload.binaryContent = wfc.utf8_to_b64(this.messageUid.toString());
return payload;
}
decode(payload) {
super.decode(payload);
this.operatorId = payload.content;
this.messageUid = Long.fromString(wfc.b64_to_utf8(payload.binaryContent));
}
}
@@ -0,0 +1,9 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
export default class EnterChannelChatMessageContent extends MessageContent {
constructor() {
super(MessageContentType.Enter_Channel_Chat);
}
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContentMediaType from "./messageContentMediaType";
import MediaMessageContent from "./mediaMessageContent";
import MessageContentType from "./messageContentType";
export default class FileMessageContent extends MediaMessageContent {
name = '';
size = 0;
constructor(fileOrLocalPath, remotePath, name, size) {
super(MessageContentType.File, MessageContentMediaType.File, fileOrLocalPath, remotePath);
if (fileOrLocalPath && fileOrLocalPath.name) {
this.name = fileOrLocalPath.name;
this.size = fileOrLocalPath.size;
} else if (remotePath) {
this.name = name ? name : remotePath.substring(remotePath.lastIndexOf('/') + 1)
this.size = size ? size : 0;
}
}
digest() {
return '[文件]' + this.name;
}
encode() {
let payload = super.encode();
payload.searchableContent = this.name;
payload.content = this.size + '';
return payload;
}
decode(payload) {
super.decode(payload);
if (payload.searchableContent) {
this.name = payload.searchableContent;
this.size = Number(payload.content);
}
}
}
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MediaMessageContent from './mediaMessageContent';
import MessageContentMediaType from './messageContentMediaType';
import MessageContentType from './messageContentType';
export default class ImageMessageContent extends MediaMessageContent {
// base64 encoded, 不包含头部:data:image/png;base64,
thumbnail;
imageWidth;
imageHeight;
constructor(fileOrLocalPath, remotePath, thumbnail) {
super(MessageContentType.Image, MessageContentMediaType.Image, fileOrLocalPath, remotePath);
this.thumbnail = thumbnail;
}
digest() {
return '[图片]';
}
encode() {
let payload = super.encode();
payload.mediaType = MessageContentMediaType.Image;
payload.binaryContent = this.thumbnail;
if (this.imageWidth) {
let obj = {
w: this.imageWidth,
h: this.imageHeight
}
payload.content = JSON.stringify(obj)
}
return payload;
}
decode(payload) {
super.decode(payload);
this.thumbnail = payload.binaryContent;
if (payload.content) {
let obj = JSON.parse(payload.content)
this.imageWidth = obj['w'];
this.imageHeight = obj['h'];
}
}
}
@@ -0,0 +1,9 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
export default class LeaveChannelChatMessageContent extends MessageContent {
constructor() {
super(MessageContentType.Leave_Channel_Chat);
}
}
+42
View File
@@ -0,0 +1,42 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
import wfc from "../client/wfc";
export default class LinkMessageContent extends MessageContent {
title;
contentDigest;
url;
thumbnail;
constructor() {
super(MessageContentType.Link);
}
encode() {
let payload = super.encode();
let obj = {
d: this.contentDigest,
u: this.url,
t: this.thumbnail
}
payload.searchableContent = this.title;
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
this.title = payload.searchableContent;
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.contentDigest = obj.d;
this.url = obj.u;
this.thumbnail = obj.t;
}
digest(message) {
let tmp = this.title ? this.title.trim() : this.contentDigest ? this.contentDigest.trim() : null;
return tmp ? tmp : this.url;
}
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from './messageContent'
export default class LocationMessageContent extends MessageContent {
title;
// base64 encoded, 不包含头部:data:image/png;base64,
thumbnail;
lat;
long;
digest() {
return '位置'
}
encode() {
let payload = super.encode();
payload.searchableContent = this.title;
payload.binaryContent = this.thumbnail;
let location = {
lat: this.lat,
long: this.long
};
payload.content = JSON.stringify(location);
return payload;
}
decode(payload) {
super.decode(payload);
this.title = payload.searchableContent;
this.thumbnail = payload.binaryContent;
let location = JSON.parse(payload.content);
this.lat = location.lat;
this.long = location.long;
}
}
@@ -0,0 +1,40 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
import {_patchToJavaLong, _reverseToJsLongString, longValue, stringValue} from "../util/longUtil";
import wfc from "../client/wfc";
export default class MarkUnreadMessageContent extends MessageContent {
messageUid;
timestamp;
constructor(messageUid) {
super(MessageContentType.Mark_Unread_Sync);
this.messageUid = messageUid;
}
encode() {
let payload = super.encode();
let obj = {
u: stringValue(this.messageUid),
t: stringValue(this.timestamp),
}
let str = JSON.stringify(obj)
str = _patchToJavaLong(str, 'u');
str = _patchToJavaLong(str, 't');
payload.binaryContent = wfc.utf8_to_b64(str);
return payload;
}
decode(payload) {
super.decode(payload);
let str = wfc.b64_to_utf8(payload.binaryContent);
str = _reverseToJsLongString(str, 'u');
str = _reverseToJsLongString(str, 't');
let obj = JSON.parse(str);
this.messageUid = obj.u ? longValue(obj.u) : undefined;
this.timestamp = obj.t ? longValue(obj.t) : undefined;
}
}
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from './messageContent'
import Config from '../../config'
export default class MediaMessageContent extends MessageContent {
file;
remotePath = '';
localPath = '';
mediaType = 0;
/**
*
* @param {number} messageType 消息类型
* @param {number} mediaType 媒体类型
* @param {File | string} fileOrLocalPath File类型,或者dataUri或者本地路径,本地路径是必须是绝对路径
* @param {string} remotePath 远端地址
*/
constructor(messageType, mediaType = 0, fileOrLocalPath, remotePath) {
super(messageType);
this.mediaType = mediaType;
if (!fileOrLocalPath) {
this.localPath = '';
this.remotePath = remotePath;
} else if (typeof fileOrLocalPath === "string" && !fileOrLocalPath.startsWith("http")) {
this.localPath = fileOrLocalPath;
this.remotePath = remotePath;
} else {
this.file = fileOrLocalPath;
if (fileOrLocalPath && fileOrLocalPath.path) {
this.localPath = fileOrLocalPath.path;
// attention: 粘贴的时候,path是空字符串,故采用了这个trick
if (this.localPath.indexOf(fileOrLocalPath.name) < 0) {
this.localPath += fileOrLocalPath.name;
}
}
}
}
encode() {
let payload = super.encode();
payload.localMediaPath = this.localPath;
payload.remoteMediaUrl = this.remotePath ? this.remotePath : '';
payload.mediaType = this.mediaType;
return payload;
}
decode(payload) {
super.decode(payload);
this.localPath = payload.localMediaPath;
this.remotePath = payload.remoteMediaUrl;
if (Config.urlRedirect){
this.remotePath = Config.urlRedirect(payload.remoteMediaUrl);
}
this.mediaType = payload.mediaType;
}
}
+218
View File
@@ -0,0 +1,218 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
/**
*
message in json format
{
"conversation":{
"conversationType": 0,
"target": "UZUWUWuu",
"line": 0,
}
"from": "UZUWUWuu",
"content": {
"type": 1,
"searchableContent": "1234",
"pushContent": "",
"content": "",
"binaryContent": "",
"localContent": "",
"mediaType": 0,
"remoteMediaUrl": "",
"localMediaPath": "",
"mentionedType": 0,
"mentionedTargets": [ ]
},
"messageId": 52,
"direction": 1,
"status": 5,
"messageUid": 75735276990792720,
"timestamp": 1550849394256,
"to": ""
}
*/
import Conversation from '../model/conversation'
import NotificationMessageContent from './notification/notificationMessageContent'
import wfc from '../client/wfc'
import MessageConfig from '../client/messageConfig';
import UnknownMessageContent from './unknownMessageContent';
import PersistFlag from './persistFlag';
import MessageStatus from './messageStatus';
import ConversationType from '../model/conversationType';
import {encode} from 'base64-arraybuffer';
import Config from '../../config.js';
import Long from 'long'
import UnsupportMessageContent from "../messages/unsupportMessageConten";
import RecallMessageNotification from "../messages/notification/recallMessageNotification";
export default class Message {
conversation = {};
from = '';
content = {}; // 实际是payload
messageContent = {};
messageId = 0;
direction = 0;
status = 0;
messageUid = -1;
timestamp = 0;
to = '';
localExtra = '';
constructor(conversation, messageContent) {
this.conversation = conversation;
this.messageContent = messageContent;
}
static fromProtoMessage(obj) {
if (!obj) {
return null;
}
if (!obj.conversation.target) {
return null;
}
// iOS,Android,Windows,OSX,Harmony
if ([1, 2, 3, 4, 7, 8, 9, 10, 11, 12].indexOf(Config.getWFCPlatform()) >= 0) {
let msg = Object.assign(new Message(), obj);
// big integer to number
msg.messageId = Number(msg.messageId);
if (msg.messageId === -1) {
return null;
}
msg.messageUid = Long.fromValue(msg.messageUid);
if (msg.timestamp){
msg.timestamp = Long.fromValue(msg.timestamp).toNumber();
} else {
// 移动端
msg.timestamp = Long.fromValue(msg.serverTime).toNumber();
}
msg.localExtra = obj.localExtra;
if (!msg.from) {
// 移动端
msg.from = obj.sender;
}
msg.conversation = new Conversation(obj.conversation.conversationType !== undefined ? obj.conversation.conversationType : obj.conversation.type, obj.conversation.target, obj.conversation.line);
let contentClazz = MessageConfig.getMessageContentClazz(msg.content.type !== undefined ? msg.content.type : msg.content.messageContentType);
if (contentClazz) {
let content = new contentClazz();
try {
content.decode(msg.content);
if (content instanceof NotificationMessageContent) {
content.fromSelf = msg.from === wfc.getUserId();
}
} catch (error) {
console.error('decode message payload failed, fallback to unkownMessage', msg.content, error);
let flag = MessageConfig.getMessageContentPersitFlag(msg.content.type);
if (PersistFlag.Persist === flag || PersistFlag.Persist_And_Count === flag) {
content = new UnknownMessageContent(msg.content);
} else {
return null;
}
}
msg.messageContent = content;
if (content instanceof UnknownMessageContent) {
console.log('unknownMessage Content', obj)
}
} else {
console.error('message content not register', obj);
}
return msg;
} else {
let msg = new Message();
msg.from = obj.fromUser;
msg.content = obj.content;
msg.messageUid = obj.messageId;
msg.localExtra = obj.localExtra;
msg.timestamp = obj.serverTimestamp;
let contentClazz = MessageConfig.getMessageContentClazz(obj.content.type);
if (contentClazz) {
let content = new contentClazz();
try {
if (obj.content.data && obj.content.data.length > 0) {
obj.content.binaryContent = encode(obj.content.data);
}
content.decode(obj.content);
content.extra = obj.content.extra;
if (content instanceof NotificationMessageContent) {
content.fromSelf = msg.from === wfc.getUserId();
}
} catch (error) {
console.error('decode message payload failed, fallback to unkownMessage', obj.content, error);
let flag = MessageConfig.getMessageContentPersitFlag(obj.content.type);
if (PersistFlag.Persist === flag || PersistFlag.Persist_And_Count === flag) {
content = new UnknownMessageContent(obj.content);
} else {
return null;
}
}
msg.messageContent = content;
if (content instanceof UnknownMessageContent) {
console.log('unknownMessage Content', obj)
}
} else {
console.error('message content not register', obj);
}
if (msg.from === wfc.getUserId()) {
msg.conversation = new Conversation(obj.conversation.type, obj.conversation.target, obj.conversation.line);
// out
msg.direction = 0;
msg.status = MessageStatus.Sent;
} else {
if (obj.conversation.type === ConversationType.Single) {
msg.conversation = new Conversation(obj.conversation.type, obj.fromUser, obj.conversation.line);
} else {
msg.conversation = new Conversation(obj.conversation.type, obj.conversation.target, obj.conversation.line);
}
// in
msg.direction = 1;
msg.status = MessageStatus.Unread;
if (msg.content.mentionedType === 2) {
msg.status = MessageStatus.AllMentioned;
} else if (msg.content.mentionedType === 1) {
for (const target of msg.content.mentionedTarget) {
if (target === wfc.getUserId()) {
msg.status = MessageStatus.Mentioned;
break;
}
}
}
}
return msg;
}
}
static messageContentFromMessagePayload(payload, from) {
let contentClazz = MessageConfig.getMessageContentClazz(payload.type);
contentClazz = contentClazz ? contentClazz : UnsupportMessageContent;
let content = new contentClazz();
content.decode(payload);
let selfUid = wfc.getUserId();
if (content instanceof NotificationMessageContent) {
if (content instanceof RecallMessageNotification) {
if (content.operatorId === selfUid) {
content.fromSelf = true;
}
} else if (from === selfUid) {
content.fromSelf = true;
}
}
return content;
}
static toMessagePayload(message) {
return message.messageContent.encode();
}
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessagePayload from "./messagePayload";
export default class MessageContent {
type;
//0 普通消息, 1 部分提醒, 2 提醒全部
mentionedType = 0;
//提醒对象,mentionedType 1时有效
mentionedTargets = [];
extra;
pushContent;
constructor(type, mentionedType = 0, mentionedTargets = []) {
this.type = type;
this.mentionedType = mentionedType;
this.mentionedTargets = mentionedTargets;
}
digest(message) {
return '...digest...';
}
/**
* return MessagePayload in json format
*/
encode() {
let payload = new MessagePayload();
payload.type = this.type;
payload.mentionedType = this.mentionedType;
payload.mentionedTargets = this.mentionedTargets;
payload.extra = this.extra;
return payload;
}
/**
*
* @param {object} payload object json.parse from message#content
*/
decode(payload) {
this.type = payload.type;
this.mentionedType = payload.mentionedType;
if (payload.hasOwnProperty('mentionedTarget')) {
// web
this.mentionedTargets = payload.mentionedTarget;
} else {
// pc
this.mentionedTargets = payload.mentionedTargets;
}
this.extra = payload.extra;
this.pushContent = payload.pushContent;
}
}
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class MessageContentMediaType {
static General = 0;
static Image = 1;
static Voice = 2;
static Video = 3;
static File = 4;
static Portrait = 5;
static Favorite = 6;
static Sticker = 7;
static Moments = 8;
}
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class MessageContentType {
// 基本消息类型
static Unknown = 0;
static Text = 1;
static Voice = 2;
static Image = 3;
static Location = 4;
static File = 5;
static Video = 6;
static Sticker = 7;
static Link = 8;
static P_Text = 9;
static UserCard = 10;
static Composite_Message = 11;
static Rich_Notification = 12;
static Articles = 13;
//流式文本正在生成消息
static Streaming_Text_Generating = 14;
//流式文本消息
static Streaming_Text_Generated = 15;
static Mark_Unread_Sync = 31;
static StartSecretChat_Notification = 40;
//频道进出消息
static Enter_Channel_Chat = 71;
static Leave_Channel_Chat = 72;
static Channel_Menu_Event = 73
// 提醒消息
static RecallMessage_Notification = 80;
static DeleteMessage_Notification = 81; //不存储的
static Tip_Notification = 90;
static Typing = 91;
// //以上是打招呼的内容
// int ContentType_Friend_Greeting = 92;
// //您已经添加XXX为好友了,可以愉快地聊天了
// int ContentType_Friend_Added = 93;
//
// int ContentType_PC_LOGIN_REQUSET = 94;
static Friend_Greeting = 92;
static Friend_Added = 93;
static PC_Login_Request = 94;
// 群相关消息
static CreateGroup_Notification = 104;
static AddGroupMember_Notification = 105;
static KickOffGroupMember_Notification = 106;
static QuitGroup_Notification = 107;
static DismissGroup_Notification = 108;
static TransferGroupOwner_Notification = 109;
static ChangeGroupName_Notification = 110;
static ModifyGroupAlias_Notification = 111;
static ChangeGroupPortrait_Notification = 112;
static MuteGroup_Notification = 113;
static ChangeJoinType_Notification = 114;
static ChangePrivateChat_Notification = 115;
static ChangeSearchable_Notification = 116;
static SetGroupManager_Notification = 117;
//禁言/取消禁言群成员的通知消息
static MuteGroupMember_Notification = 118;
// 全局禁言之后,允许群成员发言的通知消息
static AllowGroupMember_Notification = 119;
//踢出群成员的可见通知消息
static KickOffGroupMember_Visible_Notification = 120;
//退群的可见通知消息
static QuitGroup_Visible_Notification = 121;
static ModifyGroupExtra_Notification = 122;
static ModifyGroupMemberExtra_Notification = 123;
static VOIP_CONTENT_TYPE_START = 400;
static VOIP_CONTENT_TYPE_END = 402;
static VOIP_CONTENT_TYPE_ACCEPT = 401;
static VOIP_CONTENT_TYPE_SIGNAL = 403;
static VOIP_CONTENT_TYPE_MODIFY = 404;
static VOIP_CONTENT_TYPE_ACCEPT_T = 405;
static VOIP_CONTENT_TYPE_ADD_PARTICIPANT = 406;
static VOIP_CONTENT_TYPE_MUTE_VIDEO = 407;
static CONFERENCE_CONTENT_TYPE_INVITE = 408;
static CONFERENCE_CONTENT_TYPE_CHANGE_MODE = 410;
static CONFERENCE_CONTENT_TYPE_KICKOFF_MEMBER = 411;
static CONFERENCE_CONTENT_TYPE_COMMAND = 412;
static VOIP_Multi_Call_Ongoing = 416;
static VOIP_Join_Call_Request = 417;
static MESSAGE_CONTENT_TYPE_FEED = 501;
static MESSAGE_CONTENT_TYPE_COMMENT = 502;
}
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
/**
*
"content": {
"type": 1,
"searchableContent": "1234",
"pushContent": "",
"content": "",
"binaryContent": "",
"localContent": "",
"mediaType": 0,
"remoteMediaUrl": "",
"localMediaPath": "",
"mentionedType": 0,
"mentionedTargets": [ ]
},
*/
export default class MessagePayload {
type;
searchableContent;
pushContent;
pushData;
content;
binaryContent; // base64 string, 图片时,不包含头部信息:data:image/png;base64,
localContent;
mediaType;
remoteMediaUrl;
localMediaPath;
mentionedType = 0;
mentionedTargets = [];
extra;
}
+15
View File
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class MessageStatus {
static All = -1;
static Sending = 0;
static Sent = 1;
static SendFailure = 2;
static Mentioned = 3;
static AllMentioned = 4;
static Unread = 5;
static Readed = 6;
static Played = 7;
}
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class AddGroupMemberNotification extends GroupNotificationContent {
invitor = '';
invitees = [];
constructor(invitor, invitees) {
super(MessageContentType.AddGroupMember_Notification);
this.invitor = invitor;
this.invitees = invitees;
}
formatNotification() {
let notifyStr;
if (this.invitees.length === 1 && this.invitees[0] === this.invitor) {
if (this.fromSelf) {
return '您加入了群组';
} else {
return wfc.getGroupMemberDisplayName(this.groupId, this.invitor) + ' 加入了群组';
}
}
if (this.fromSelf) {
notifyStr = '您邀请:';
} else {
notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.invitor) + '邀请:';
}
let membersStr = '';
let userInfos = wfc.getUserInfos(this.invitees, this.groupId);
userInfos.forEach(m => {
membersStr += ' ' + m.displayName;
});
return notifyStr + membersStr + '加入了群组';
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.invitor,
ms: this.invitees,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent);
let obj = JSON.parse(json);
this.groupId = obj.g;
this.invitor = obj.o;
this.invitees = obj.ms;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import GroupNotificationContent from './groupNotification'
import MessageContentType from '../messageContentType'
import wfc from '../../client/wfc'
export default class AllowGroupMemberNotification extends GroupNotificationContent {
groupId
operator
// 操作类型,1允许发言,0禁止发言
type
memberIds
constructor(operator, type, memberIds) {
super(MessageContentType.MuteGroupMember_Notification)
this.operator = operator
this.type = type
this.memberIds = memberIds
}
formatNotification(message) {
let notifyStr = ''
if (this.fromSelf) {
notifyStr += '您'
} else {
notifyStr += wfc.getGroupMemberDisplayName(this.groupId,
this.operator)
}
notifyStr += '把'
if (this.memberIds) {
this.memberIds.forEach((memberId) => {
notifyStr += ' '
notifyStr += wfc.getGroupMemberDisplayName(this.groupId,
memberId)
})
}
if (this.type === 0) {
notifyStr += '取消群禁言时发言权限'
} else {
notifyStr += '允许群禁言时发言'
}
return notifyStr
}
encode() {
let payload = super.encode()
let obj = {
g: this.groupId,
o: this.operator,
n: this.type + '',
ms: this.memberIds,
}
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj))
return payload
}
decode(payload) {
super.decode(payload)
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json)
this.groupId = obj.g
this.operator = obj.o
this.type = parseInt(obj.n)
this.memberIds = obj.ms
}
}
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from "../messageContentType";
import GroupNotificationContent from "./groupNotification";
export default class ChangeGroupNameNotification extends GroupNotificationContent {
operator = '';
name = '';
constructor(operator, name) {
super(MessageContentType.ChangeGroupName_Notification);
this.operator = operator;
this.name = name;
}
formatNotification() {
if (this.fromSelf) {
return '您修改群名称为:' + this.name;
} else {
return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '修改群名称为:' + this.name;
}
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
n: this.name,
o: this.operator,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
this.name = obj.n;
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from "../messageContentType";
import GroupNotificationContent from "./groupNotification";
export default class ChangeGroupPortraitNotification extends GroupNotificationContent {
operator = '';
constructor(operator) {
super(MessageContentType.ChangeGroupPortrait_Notification);
this.operator = operator;
}
formatNotification() {
if (this.fromSelf) {
return '您修改群头像';
} else {
return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '修改了群头像';
}
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
n: this.name,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
}
}
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from "./notificationMessageContent";
export default class ChatRoomWelcomeNotificationContent extends NotificationMessageContent {
welcome;
formatNotification(message) {
return this.welcome;
}
encode() {
return super.encode();
}
decode(payload) {
super.decode(payload);
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class CreateGroupNotification extends GroupNotificationContent {
creator = '';
groupName = '';
constructor(creator, groupName) {
super(MessageContentType.CreateGroup_Notification);
this.creator = creator;
this.groupName = groupName;
}
formatNotification() {
if (this.fromSelf) {
return '您创建了群组 ' + this.groupName;
} else {
return wfc.getUserDisplayName(this.creator) + '创建了群组 ' + this.groupName;
}
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
n: this.groupName,
o: this.creator,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.creator = obj.o;
this.groupName = obj.n;
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class DismissGroupNotification extends GroupNotificationContent {
operator = '';
constructor(operator) {
super(MessageContentType.DismissGroup_Notification);
this.operator = operator;
}
formatNotification() {
if (this.fromSelf) {
return '您解散了群组';
} else {
return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '解散了群组';
}
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
}
}
@@ -0,0 +1,17 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from "./notificationMessageContent";
import MessageContentType from "../messageContentType";
export default class FriendAddedNotification extends NotificationMessageContent {
constructor() {
super(MessageContentType.Friend_Added);
}
formatNotification() {
return "你们已经是好友了,可以开始聊天了。";
}
}
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2022 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from "./notificationMessageContent";
import MessageContentType from "../messageContentType";
export default class FriendGreetingNotification extends NotificationMessageContent {
constructor() {
super(MessageContentType.Friend_Greeting);
}
formatNotification(message) {
return "以上是打招呼的内容";
}
}
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import GroupNotificationContent from "./groupNotification";
import wfc from "../../client/wfc";
import MessageContentType from "../messageContentType";
export default class GroupJoinTypeNotificationContent extends GroupNotificationContent {
operator;
//在group type为Restricted时,0 开放加入权限(群成员可以拉人,用户也可以主动加入);1 只能群成员拉人入群;2 只能群管理拉人入群
joinType;
constructor(operator, joinType) {
super(MessageContentType.ChangeJoinType_Notification);
this.operator = operator;
this.type = joinType;
}
formatNotification(message) {
let notifyStr;
if (this.fromSelf) {
notifyStr = '您';
} else {
notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.operator);
}
switch (this.joinType) {
case 0:
notifyStr += ' 开放了加入群组功能';
break;
case 1:
notifyStr += ' 仅允许群成员邀请加入群组';
break;
case 2:
notifyStr += " 关闭了加入群组功能";
break;
default:
break;
}
return notifyStr;
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
n: (this.joinType + '')
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return super.encode();
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.groupId = obj.g;
this.operator = obj.o;
this.joinType = parseInt(obj.n);
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import GroupNotificationContent from "./groupNotification";
import MessageContentType from "../messageContentType";
import wfc from "../../client/wfc";
export default class GroupMuteNotificationContent extends GroupNotificationContent {
operator;
//0 正常;1 全局禁言
muteType;
constructor(operator, muteType) {
super(MessageContentType.MuteGroup_Notification);
this.operator = operator;
this.muteType = muteType;
}
formatNotification(message) {
// return sb.toString();
let notifyStr = this.fromSelf ? '您' : wfc.getGroupMemberDisplayName(this.groupId, this.operator);
notifyStr += this.muteType === 0 ? ' 关闭了全员禁言' : ' 开启了全员禁言';
return notifyStr;
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
n: this.muteType + ''
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.groupId = obj.g;
this.operator = obj.o;
this.muteType = parseInt(obj.n);
}
}
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from "./notificationMessageContent";
export default class GroupNotificationContent extends NotificationMessageContent {
groupId = '';
constructor(type) {
super(type);
}
}
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import GroupNotificationContent from "./groupNotification";
import MessageContentType from "../messageContentType";
import wfc from "../../client/wfc";
export default class GroupPrivateChatNotificationContent extends GroupNotificationContent {
operator;
//是否运行群中普通成员私聊。0 允许,1不允许
privateChatType;
constructor(operator, privateChatType) {
super(MessageContentType.ChangePrivateChat_Notification);
this.operator = operator;
this.privateChatType = privateChatType;
}
formatNotification(message) {
// return sb.toString();
let notifyStr = this.fromSelf ? '您' : wfc.getGroupMemberDisplayName(this.groupId, this.operator);
notifyStr += this.privateChatType === 0 ? ' 开启了成员私聊' : ' 关闭了成员私聊';
return notifyStr;
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
n: this.privateChatType + ''
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.groupId = obj.g;
this.operator = obj.o;
this.privateChatType = parseInt(obj.n);
}
}
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import GroupNotificationContent from "./groupNotification";
import MessageContentType from "../messageContentType";
import wfc from "../../client/wfc";
export default class GroupSetManagerNotificationContent extends GroupNotificationContent {
operator;
// 1, 设置为管理员;0,取消管理员
setManagerType;
memberIds = [];
constructor(operator, setManagerType, memberIds) {
super(MessageContentType.SetGroupManager_Notification);
this.operator = operator;
this.setManagerType = setManagerType;
this.memberIds = memberIds;
}
formatNotification(message) {
let notifyStr = this.fromSelf ? '您' : wfc.getGroupMemberDisplayName(this.groupId, this.operator)
notifyStr += '把 ';
this.memberIds.forEach((memberId) => {
notifyStr += ' ';
notifyStr += wfc.getGroupMemberDisplayName(this.groupId, memberId);
})
notifyStr += ' ';
notifyStr += this.setManagerType === 0 ? '取消了管理员' : '设置为了管理员';
return notifyStr;
}
encode() {
// MessagePayload payload = new MessagePayload();
// try {
// JSONObject objWrite = new JSONObject();
// objWrite.put("g", groupId);
// objWrite.put("o", operator);
// objWrite.put("n", type + "");
// JSONArray objArray = new JSONArray();
// for (String id : memberIds) {
// objArray.put(id);
// }
// objWrite.put("ms", objArray);
// payload.binaryContent = objWrite.toString().getBytes();
// } catch (JSONException e) {
// e.printStackTrace();
// }
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
n: this.setManagerType + '',
ms: this.memberIds,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.groupId = obj.g;
this.operator = obj.o;
this.setManagerType = parseInt(obj.n);
this.memberIds = obj.ms;
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from "../messageContentType";
import GroupNotificationContent from "./groupNotification";
export default class KickoffGroupMemberNotification extends GroupNotificationContent {
operator = '';
kickedMembers = [];
constructor(operator, kickedMembers) {
super(MessageContentType.KickOffGroupMember_Notification);
this.operator = operator;
this.kickedMembers = kickedMembers;
}
formatNotification() {
let notifyStr;
if (this.fromSelf) {
notifyStr = '您把 ';
} else {
notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '把 ';
}
let kickedMembersStr = '';
let userInfos = wfc.getUserInfos(this.kickedMembers, this.groupId);
userInfos.forEach(userInfo => {
if (userInfo.uid === wfc.getUserId()) {
kickedMembersStr += ' 您';
} else {
kickedMembersStr += ' ' + userInfo.displayName;
}
});
return notifyStr + kickedMembersStr + ' 移除了群组';
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
ms: this.kickedMembers,
o: this.operateUser,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
this.kickedMembers = obj.ms;
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from "../messageContentType";
import GroupNotificationContent from "./groupNotification";
export default class KickoffGroupMemberVisiableNotification extends GroupNotificationContent {
operator = '';
kickedMembers = [];
constructor(operator, kickedMembers) {
super(MessageContentType.KickOffGroupMember_Visible_Notification);
this.operator = operator;
this.kickedMembers = kickedMembers;
}
formatNotification() {
let notifyStr;
if (this.fromSelf) {
notifyStr = '您把 ';
} else {
notifyStr = wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '把 ';
}
let kickedMembersStr = '';
let userInfos = wfc.getUserInfos(this.kickedMembers, this.groupId);
userInfos.forEach(userInfo => {
if (userInfo.uid === wfc.getUserId()) {
kickedMembersStr += ' 您';
} else {
kickedMembersStr += ' ' + userInfo.displayName;
}
});
return notifyStr + kickedMembersStr + ' 移除了群组';
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
ms: this.kickedMembers,
o: this.operateUser,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
this.kickedMembers = obj.ms;
}
}
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class ModifyGroupAliasNotification extends GroupNotificationContent {
operator = '';
alias = '';
memberId = '';
constructor(creator, alias) {
super(MessageContentType.ModifyGroupAlias_Notification);
this.operator = creator;
this.alias = alias;
}
formatNotification() {
let notificationStr = '';
if (this.fromSelf) {
notificationStr += '你';
} else {
let userInfo = wfc.getUserInfo(this.operator, false, this.groupId)
if (userInfo.friendAlias) {
notificationStr += userInfo.friendAlias;
} else if (userInfo.displayName) {
notificationStr += userInfo.displayName;
} else {
notificationStr += this.operator;
}
}
notificationStr += '修改';
if (this.memberId) {
let userInfo = wfc.getUserInfo(this.memberId, false);
if (userInfo.friendAlias) {
notificationStr += userInfo.friendAlias;
} else if (userInfo.displayName) {
notificationStr += userInfo.displayName;
} else {
notificationStr += this.memberId;
}
notificationStr += '的';
}
notificationStr += '群昵称为';
notificationStr += this.alias;
return notificationStr;
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
n: this.alias,
o: this.operator,
m: this.memberId,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
this.alias = obj.n;
this.memberId = obj.m;
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class ModifyGroupExtraNotification extends GroupNotificationContent {
operator = '';
groupExtra = '';
constructor(creator, groupExtra) {
super(MessageContentType.ModifyGroupExtra_Notification);
this.operator = creator;
this.groupExtra = groupExtra;
}
formatNotification() {
let notificationStr = '';
if (this.fromSelf) {
notificationStr += '你';
} else {
let userInfo = wfc.getUserInfo(this.operator, false, this.groupId)
if (userInfo.friendAlias) {
notificationStr += userInfo.friendAlias;
} else if (userInfo.displayName) {
notificationStr += userInfo.displayName;
} else {
notificationStr += this.operator;
}
}
notificationStr += '修改';
notificationStr += '群附加信息为';
notificationStr += this.groupExtra;
return notificationStr;
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
n: this.groupExtra,
o: this.operator,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
this.groupExtra = obj.n;
}
}
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class ModifyGroupMemberExtraNotification extends GroupNotificationContent {
operator = '';
groupMemberExtra = '';
memberId = '';
constructor(creator, groupMemberExtra) {
super(MessageContentType.ModifyGroupMemberExtra_Notification);
this.operator = creator;
this.groupMemberExtra = groupMemberExtra;
}
formatNotification() {
let notificationStr = '';
if (this.fromSelf) {
notificationStr += '你';
} else {
let userInfo = wfc.getUserInfo(this.operator, false, this.groupId)
if (userInfo.friendAlias) {
notificationStr += userInfo.friendAlias;
} else if (userInfo.displayName) {
notificationStr += userInfo.displayName;
} else {
notificationStr += this.operator;
}
}
notificationStr += '修改';
if (this.memberId) {
let userInfo = wfc.getUserInfo(this.memberId, false);
if (userInfo.friendAlias) {
notificationStr += userInfo.friendAlias;
} else if (userInfo.displayName) {
notificationStr += userInfo.displayName;
} else {
notificationStr += this.memberId;
}
notificationStr += '的';
}
notificationStr += '群成员信息为';
notificationStr += this.groupMemberExtra;
return notificationStr;
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
n: this.groupMemberExtra,
o: this.operator,
m: this.memberId,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
this.groupMemberExtra = obj.n;
this.memberId = obj.m;
}
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import GroupNotificationContent from './groupNotification'
import MessageContentType from '../messageContentType'
import wfc from '../../client/wfc'
export default class MuteGroupMemberNotification extends GroupNotificationContent {
groupId
operator
// 操作类型,1禁言,0取消禁言
muteType
memberIds
constructor(operator, muteType, memberIds) {
super(MessageContentType.MuteGroupMember_Notification)
this.operator = operator
this.muteType = muteType
this.memberIds = memberIds
}
formatNotification(message) {
let notifyStr = ''
if (this.fromSelf) {
notifyStr += '您'
} else {
notifyStr += wfc.getGroupMemberDisplayName(this.groupId,
this.operator)
}
notifyStr += '把'
if (this.memberIds) {
this.memberIds.forEach((memberId) => {
notifyStr += ' '
notifyStr += wfc.getGroupMemberDisplayName(this.groupId,
memberId)
})
}
if (this.muteType === 1) {
notifyStr += '设置了禁言'
} else {
notifyStr += '取消了禁言'
}
return notifyStr
}
encode() {
let payload = super.encode()
let obj = {
g: this.groupId,
o: this.operator,
n: this.muteType + '',
ms: this.memberIds,
}
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj))
return payload
}
decode(payload) {
super.decode(payload)
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json)
this.groupId = obj.g
this.operator = obj.o
this.muteType = parseInt(obj.n)
this.memberIds = obj.ms
}
}
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from "../messageContent";
export default class NotificationMessageContent extends MessageContent {
// message#protoMessageToMessage时设置
fromSelf = false;
constructor(type) {
super(type);
}
digest(message) {
var desc = '';
try {
desc = this.formatNotification(message);
} catch (error) {
console.log('disgest', error);
}
return desc;
}
formatNotification(message) {
return '..nofication..';
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class QuitGroupNotification extends GroupNotificationContent {
operator = '';
constructor(operator) {
super(MessageContentType.QuitGroup_Notification);
this.operator = operator;
}
formatNotification() {
if (this.fromSelf) {
return '您退出了群组';
} else {
return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '退出了群组';
}
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
}
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class QuitVisiableGroupNotification extends GroupNotificationContent {
operator = '';
constructor(operator) {
super(MessageContentType.QuitGroup_Visible_Notification);
this.operator = operator;
}
formatNotification() {
if (this.fromSelf) {
return '您退出了群组';
} else {
return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '退出了群组';
}
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
}
}
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from './notificationMessageContent'
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import Long from 'long';
import ConversationType from "../../model/conversationType";
export default class RecallMessageNotification extends NotificationMessageContent {
operatorId = '';
messageUid = new Long(0);
originalSender;
originalContentType;
originalSearchableContent;
originalContent;
originalExtra;
originalMessageTimestamp;
constructor(operatorId, messageUid) {
super(MessageContentType.RecallMessage_Notification);
this.operatorId = operatorId;
this.messageUid = messageUid;
}
formatNotification(message) {
if (this.operatorId === wfc.getUserId()){
return "你撤回了一条消息";
}
if (message.conversation.type === ConversationType.Group) {
return wfc.getGroupMemberDisplayName(message.conversation.target, this.operatorId) + "撤回了一条消息";
} else {
return wfc.getUserDisplayName(this.operatorId) + "撤回了一条消息";
}
}
encode() {
let payload = super.encode();
payload.content = this.operatorId;
payload.binaryContent = wfc.utf8_to_b64(this.messageUid.toString());
return payload;
}
decode(payload) {
super.decode(payload);
this.operatorId = payload.content;
this.messageUid = Long.fromString(wfc.b64_to_utf8(payload.binaryContent));
try {
this.setExtra(payload.extra);
} catch (e) {
console.error('decode recallMessage extra error', e)
}
}
setExtra(extra) {
if (extra) {
extra =extra.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
let obj = JSON.parse(extra);
this.originalSender = obj["s"];
this.originalContentType = obj["t"];
this.originalSearchableContent = obj["sc"];
this.originalContent = obj["c"];
this.originalExtra = obj["e"];
this.originalMessageTimestamp = Long.fromValue(obj["ts"]);
}
}
}
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import NotificationMessageContent from "./notificationMessageContent";
export default class RichNotificationMessageContent extends NotificationMessageContent {
// 富通知消息
title;
desc;
remark;
// @[@{@"key":@"登陆账户", @"value":@"野火IM", @"color":@"#173155"}, @{@"key":@"登陆地点", @"value":@"北京", @"color":@"#173155"}]
datas;
// 附加信息
exName;
exPortrait;
exUrl;
// 应用信息
appId;
constructor() {
super(MessageContentType.Rich_Notification);
}
formatNotification() {
return this.title;
}
encode() {
let payload = super.encode();
payload.pushContent = this.title;
payload.content = this.desc;
let obj = {
remark: this.remark,
exName: this.exName,
exPortrait: this.exPortrait,
exUrl: this.exUrl,
appId: this.appId,
datas: this.datas,
}
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj))
return payload;
}
decode(payload) {
super.decode(payload);
this.title = payload.pushContent;
this.desc = payload.content;
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.remark = obj.remark;
this.exName = obj.exName;
this.exPortrait = obj.exPortrait;
this.exUrl = obj.exUrl;
this.appId = obj.appId;
this.datas = obj.datas;
}
}
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from './notificationMessageContent'
import MessageContentType from "../messageContentType";
import wfc from "../../client/wfc";
import SecretChatState from "../../model/secretChatState";
export default class StartSecretChatNotification extends NotificationMessageContent {
constructor() {
super(MessageContentType.StartSecretChat_Notification);
}
formatNotification(message) {
let state = wfc.getSecretChatInfo(message.conversation.target).state;
if (state === SecretChatState.Starting) {
return "等待对方响应";
} else if (state === SecretChatState.Accepting) {
return "密聊会话建立中";
} else if (state === SecretChatState.Established) {
return "密聊会话已建立";
} else if (state === SecretChatState.Canceled) {
return "密聊会话已取消";
} else {
return "密聊会话不可用";
}
}
encode() {
return super.encode();
}
decode(payload) {
super.decode(payload);
}
}
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from './notificationMessageContent'
export default class TemplateNotification extends NotificationMessageContent {
tip = '';
constructor(type) {
super(type)
this.tip = '';
}
formatNotification() {
return this.tip;
}
digest() {
return this.tip;
}
encode() {
let payload = super.encode();
payload.content = this.tip;
return payload;
};
decode(payload) {
super.decode(payload);
this.tip = payload.content;
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import NotificationMessageContent from './notificationMessageContent'
import MessageContentType from '../messageContentType';
export default class TipNotificationMessageContent extends NotificationMessageContent {
tip = '';
constructor(tip) {
super(MessageContentType.Tip_Notification);
this.tip = tip;
}
formatNotification() {
return this.tip;
}
digest() {
return this.tip;
}
encode() {
let payload = super.encode();
payload.content = this.tip;
return payload;
};
decode(payload) {
super.decode(payload);
this.tip = payload.content;
}
}
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import wfc from '../../client/wfc'
import MessageContentType from '../messageContentType';
import GroupNotificationContent from './groupNotification';
export default class TransferGroupOwnerNotification extends GroupNotificationContent {
operator = '';
newOwner = '';
constructor(operator, newOwner) {
super(MessageContentType.TransferGroupOwner_Notification);
this.operator = operator;
this.newOwner = newOwner;
}
formatNotification() {
if (this.fromSelf) {
return '您把群转让给了 ' + wfc.getGroupMemberDisplayName(this.groupId, this.newOwner);
} else {
return wfc.getGroupMemberDisplayName(this.groupId, this.operator) + '把群转让给了 ' + wfc.getGroupMemberDisplayName(this.groupId, this.newOwner)
}
}
encode() {
let payload = super.encode();
let obj = {
g: this.groupId,
o: this.operator,
m: this.newOwner,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let json = wfc.b64_to_utf8(payload.binaryContent)
let obj = JSON.parse(json);
this.groupId = obj.g;
this.operator = obj.o;
this.newOwner = obj.m;
}
}
@@ -0,0 +1,37 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
import MessageContentMediaType from "./messageContentMediaType";
import wfc from "../client/wfc";
export default class PcLoginRequestMessageContent extends MessageContent{
platform;
sessionId;
constructor() {
super(MessageContentType.PC_Login_Request);
}
digest() {
return '[PC请求登录]';
}
encode() {
let payload = super.encode();
payload.mediaType = MessageContentMediaType.File;
let obj = {
p : this.platform,
t: this.sessionId,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.platform = obj.p;
this.sessionId = obj.t;
}
}
+11
View File
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class PersistFlag {
static No_Persist = 0;
static Persist = 1;
static Persist_And_Count = 3;
static Transparent = 4;
}
+16
View File
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContentType from './messageContentType';
import TextMessageContent from './textMessageContent';
export default class PTextMessageContent extends TextMessageContent {
constructor(content, mentionedType = 0, mentionedTargets = []) {
super(content, mentionedType, mentionedTargets);
this.type = MessageContentType.P_Text;
}
}
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MediaMessageContent from './mediaMessageContent'
import MessageContentMediaType from './messageContentMediaType';
import MessageContentType from './messageContentType';
export default class SoundMessageContent extends MediaMessageContent {
duration;
constructor(fileOrLocalPath, remotePath, duration) {
super(MessageContentType.Voice, MessageContentMediaType.Voice, fileOrLocalPath, remotePath);
this.duration = duration;
}
digest() {
return '[语音]';
}
encode() {
let payload = super.encode();
payload.mediaType = MessageContentMediaType.Voice;
let obj = {
duration: this.duration,
};
payload.content = JSON.stringify(obj);
return payload;
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(payload.content);
this.duration = obj.duration;
}
}
+43
View File
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContentMediaType from "./messageContentMediaType";
import MediaMessageContent from "./mediaMessageContent";
import MessageContentType from "./messageContentType";
import wfc from "../client/wfc"
export default class StickerMessageContent extends MediaMessageContent {
width = 200;
height = 200;
constructor(filerOrLocalPath, remotePath, width, height) {
super(MessageContentType.Sticker, MessageContentMediaType.Sticker, filerOrLocalPath, remotePath);
this.width = width;
this.height = height;
}
digest() {
return '[表情]';
}
encode() {
let payload = super.encode();
payload.mediaType = MessageContentMediaType.File;
let obj = {
x: this.width,
y: this.height,
};
payload.binaryContent = wfc.utf8_to_b64(JSON.stringify(obj));
return payload;
}
decode(payload) {
super.decode(payload);
let obj = JSON.parse(wfc.b64_to_utf8(payload.binaryContent));
this.width = obj.x;
this.height = obj.y;
}
}
@@ -0,0 +1,28 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
export default class StreamingTextGeneratedMessageContent extends MessageContent {
text = '';
streamId = '';
constructor() {
super(MessageContentType.Streaming_Text_Generated);
}
digest(message) {
return this.text;
}
encode() {
let payload = super.encode();
payload.searchableContent = this.text;
payload.content = this.streamId;
return payload;
}
decode(payload) {
super.decode(payload);
this.text = payload.searchableContent;
this.streamId = payload.content;
}
}
@@ -0,0 +1,28 @@
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
export default class StreamingTextGeneratingMessageContent extends MessageContent {
text = '';
streamId = '';
constructor() {
super(MessageContentType.Streaming_Text_Generating);
}
digest(message) {
return this.text;
}
encode() {
let payload = super.encode();
payload.searchableContent = this.text;
payload.content = this.streamId;
return payload;
}
decode(payload) {
super.decode(payload);
this.text = payload.searchableContent;
this.streamId = payload.content;
}
}
+60
View File
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from './messageContent'
import MessageContentType from './messageContentType';
import wfc from '../client/wfc'
import QuoteInfo from "../model/quoteInfo";
export default class TextMessageContent extends MessageContent {
content;
quoteInfo;
constructor(content, mentionedType = 0, mentionedTargets = []) {
super(MessageContentType.Text, mentionedType, mentionedTargets);
this.content = content;
}
digest() {
return this.content;
}
encode() {
let payload = super.encode();
payload.searchableContent = this.content;
if (this.quoteInfo) {
let obj = {
"quote": this.quoteInfo.encode()
}
// JSON.parse 和 JSON.stringify 不能处理java long
let orgStr = JSON.stringify(obj);
let str = orgStr.replace(/"u":"([0-9]+)"/, "\"u\":$1");
payload.binaryContent = wfc.utf8_to_b64(str);
}
return payload;
}
decode(payload) {
super.decode(payload);
this.content = payload.searchableContent;
if (payload.binaryContent && payload.binaryContent.length > 0) {
// JSON.parse 和 JSON.stringify 不能处理java long
let quoteInfoStr = wfc.b64_to_utf8(payload.binaryContent)
// FIXME node 环境,decodeURIComponent 方法,有时候会在最后添加上@字符,目前尚未找到原因,先规避
quoteInfoStr = quoteInfoStr.substring(0, quoteInfoStr.lastIndexOf('}') + 1)
quoteInfoStr = quoteInfoStr.replace(/"u":([0-9]+),/, '"u":"$1",')
let obj = JSON.parse(quoteInfoStr).quote
if(obj){
this.quoteInfo = new QuoteInfo();
this.quoteInfo.decode(obj);
}
}
}
setQuoteInfo(quoteInfo) {
this.quoteInfo = quoteInfo;
}
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
export default class TypingMessageContent extends MessageContent {
static TYPING_TEXT = 0;
static TYPING_VOICE = 1;
static TYPING_CAMERA = 2;
static TYPING_LOCATION = 3;
static TYPING_FILE = 4;
typingType = TypingMessageContent.TYPING_TEXT;
constructor(type) {
super(MessageContentType.Typing);
this.typingType = type;
}
digest() {
return this.content;
}
encode() {
let payload = super.encode();
payload.content = this.typingType + '';
return payload;
}
decode(payload) {
super.decode(payload);
this.typingType = parseInt(payload.content);
}
}
+27
View File
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from "./messageContent";
import MessageContentType from "./messageContentType";
export default class UnknownMessageContent extends MessageContent {
originalPayload;
constructor(originalPayload) {
super(MessageContentType.Unknown);
this.originalPayload = originalPayload;
}
encode() {
return this.originalPayload;
}
decode(paylaod) {
this.originalPayload = paylaod;
}
digest() {
return '未知类型消息';
}
}
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MessageContent from "./messageContent";
export default class UnsupportMessageContent extends MessageContent {
digest() {
return '尚不支持该类型消息, 请手机查看 : ' + this.type;
}
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import MediaMessageContent from './mediaMessageContent'
import MessageContentMediaType from './messageContentMediaType';
import MessageContentType from './messageContentType';
export default class VideoMessageContent extends MediaMessageContent {
// base64 encoded
thumbnail;
duration;
constructor(fileOrLocalPath, remotePath, thumbnail, duration = 0) {
super(MessageContentType.Video, MessageContentMediaType.Video, fileOrLocalPath, remotePath);
this.thumbnail = thumbnail;
this.duration = duration;
}
digest() {
return '[视频]';
}
encode() {
let payload = super.encode();
payload.binaryContent = this.thumbnail;
let obj = {
d: this.duration,
duration: this.duration
}
payload.content = JSON.stringify(obj);
payload.mediaType = MessageContentMediaType.Video;
return payload;
}
decode(payload) {
super.decode(payload);
this.thumbnail = payload.binaryContent;
if (payload.content) {
let obj = JSON.parse(payload.content)
this.duration = obj.d;
if (this.duration === undefined) {
this.duration = obj.duration;
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
import ChannelInfo from "./channelInfo";
export default class NullChannelInfo extends ChannelInfo {
constructor(channelId) {
super()
this.channelId = channelId;
this.name = `<${channelId}>`
}
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2020 WildFireChat. All rights reserved.
*/
export default class ChannelInfo {
channelId;
name;
portrait;
desc;
owner;
// 0, public; 1, private; 2, destoryed
status;
extra;
updateDt;
menus;
//第0位表示是否允许查看用户所有信息,还是只允许看用户id,用户名称,用户昵称和用户头像
static StatusMaskFullInfo = 0x01;
//第1位表示是否允许查看非订阅用户信息
static StatusMaskUnsubscribedUserAccess = 0x02;
//第2位表示是否允许主动添加用户订阅关系
static StatusMaskActiveSubscribe = 0x04;
//第3位表示是否允许给非订阅用户发送消息
static StatusMaskMessageUnsubscribed = 0x08;
//第4位表示是否私有
static StatusMaskPrivate = 0x10;
//第6位表示是否删除
static StatusMaskDeleted = 0x40;
//第8位表示是否全局频道,全局平道发送消息时,会广播给系统所有人
static StatusMaskGlobal = 0x80;
}
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff. Show more