mdm-im-v3 2.1.0 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/{FilePreview-dpnc9m3Z.js → FilePreview-Cz0KMA_m.js} +2 -2
- package/dist/core.es.js +2 -2
- package/dist/{index-CsaYx_7b.js → index-C8koozDu.js} +2 -2
- package/dist/{index-CNxeqkio.js → index-GiaKeCU7.js} +47 -47
- package/dist/{index-D5S79LNp.js → index-P9_HILzo.js} +599 -319
- package/dist/index.es.js +1 -1
- package/dist/style/index.css +1 -1
- package/dist-h5/{ChatHistoryH5-BhrGF5WR.js → ChatHistoryH5-CKDqKPl-.js} +2 -2
- package/dist-h5/{ChatPageH5-B3azJu7O.js → ChatPageH5-FXZxtcQr.js} +3 -3
- package/dist-h5/{ChatSettingsH5-CFr9Bn69.js → ChatSettingsH5-PackrlPt.js} +1 -1
- package/dist-h5/{CreateGroupH5-a16jkObH.js → CreateGroupH5-CO_ZH36_.js} +2 -2
- package/dist-h5/{GroupAnnouncementH5-B-Qfzoy2.js → GroupAnnouncementH5-yUDR5kYW.js} +1 -1
- package/dist-h5/{GroupInfoDialogH5-BHLKs62Z.js → GroupInfoDialogH5-BRk-_mEn.js} +1 -1
- package/dist-h5/{GroupMembersH5-D_f1RFjO.js → GroupMembersH5-BVHUF2mG.js} +1 -1
- package/dist-h5/{GroupNoticeH5-46ZjBe92.js → GroupNoticeH5-KA-L2h9r.js} +1 -1
- package/dist-h5/{MemberDetailH5-B7nlr8ZT.js → MemberDetailH5-BfAE0nx-.js} +2 -2
- package/dist-h5/{SearchPageH5-hYxNItvz.js → SearchPageH5-B6B_U4hW.js} +2 -2
- package/dist-h5/{SelectMembersH5-DQIfX_w4.js → SelectMembersH5-CrPoBnYp.js} +2 -2
- package/dist-h5/{imChat-Bfl2JS8Q.js → imChat-pGlpr8Vj.js} +40 -7
- package/dist-h5/index.es.js +2 -2
- package/dist-h5/{indexH5-DAnvVyZ1.js → indexH5-CCvF1MV7.js} +413 -128
- package/dist-h5/{indexH5-CUQe-Ize.js → indexH5-sKvS7t3k.js} +7 -3
- package/package.json +72 -71
- package/dist-h5/request-CK8gkCRf.js +0 -44
|
@@ -2,9 +2,77 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { ref, computed } from "vue";
|
|
5
|
-
import { defineStore } from "pinia";
|
|
6
5
|
import axios from "axios";
|
|
7
6
|
import { ElMessage } from "element-plus";
|
|
7
|
+
import { defineStore } from "pinia";
|
|
8
|
+
function normalizeIMIdentity(config = {}) {
|
|
9
|
+
const version = Number(config.imIdentityVersion || 1);
|
|
10
|
+
const tenantID = String(config.tenantID || "");
|
|
11
|
+
const userID = version === 2 ? String(config.imUserID || "") : String(config.userID || "");
|
|
12
|
+
if (![1, 2].includes(version)) throw new Error("不支持的 IM 身份版本");
|
|
13
|
+
if (version === 2 && (!tenantID || !/^mdm2u_[a-f0-9]{48}$/.test(userID))) {
|
|
14
|
+
throw new Error("租户 IM 身份信息不完整");
|
|
15
|
+
}
|
|
16
|
+
return { imIdentityVersion: version, tenantID, userID, imUserID: version === 2 ? userID : "" };
|
|
17
|
+
}
|
|
18
|
+
function imSessionScope(config = {}) {
|
|
19
|
+
if (!config.userID && !config.imUserID) return "";
|
|
20
|
+
const identity = normalizeIMIdentity(config);
|
|
21
|
+
return JSON.stringify([
|
|
22
|
+
config.apiUrl || "",
|
|
23
|
+
config.wsUrl || "",
|
|
24
|
+
identity.tenantID,
|
|
25
|
+
identity.imIdentityVersion,
|
|
26
|
+
identity.userID,
|
|
27
|
+
config.platformID ?? 5
|
|
28
|
+
]);
|
|
29
|
+
}
|
|
30
|
+
function imCacheNamespace(config = {}) {
|
|
31
|
+
if (!config.tenantID || !config.userID && !config.imUserID) return "";
|
|
32
|
+
return `scope2:${imSessionScope(config)}`;
|
|
33
|
+
}
|
|
34
|
+
function nextIMSession(current, input = {}) {
|
|
35
|
+
const merged = { ...current, ...input };
|
|
36
|
+
if (Number(merged.imIdentityVersion) === 2 && String(current.tenantID || "") !== String(merged.tenantID || "") && !Object.hasOwn(input, "imUserID")) {
|
|
37
|
+
throw new Error("切换租户必须提供目标 IM 身份");
|
|
38
|
+
}
|
|
39
|
+
const next = { ...merged, ...normalizeIMIdentity(merged) };
|
|
40
|
+
if (imSessionScope(current) !== imSessionScope(next)) {
|
|
41
|
+
for (const key of ["imToken", "satoken", "chatToken", "nickname", "faceURL", "remoteConnectUrl", "remoteConnectToken", "businessUserID", "loginCode"]) {
|
|
42
|
+
next[key] = Object.hasOwn(input, key) ? input[key] : "";
|
|
43
|
+
}
|
|
44
|
+
next.loginStatus = 1;
|
|
45
|
+
next.groupStatus = 0;
|
|
46
|
+
next.currentChatId = "";
|
|
47
|
+
next.unReadCount = 0;
|
|
48
|
+
next.isViewingChat = false;
|
|
49
|
+
}
|
|
50
|
+
return next;
|
|
51
|
+
}
|
|
52
|
+
function parseIMBusinessData(value) {
|
|
53
|
+
try {
|
|
54
|
+
const result = typeof value === "string" ? JSON.parse(value) : value;
|
|
55
|
+
return result && typeof result === "object" && !Array.isArray(result) ? result : null;
|
|
56
|
+
} catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function shouldHandleLoginNotice(notice, session) {
|
|
61
|
+
if (Number(session.imIdentityVersion) === 2) return false;
|
|
62
|
+
if (!notice || notice.event !== "LOGIN_NOTICE") return false;
|
|
63
|
+
if (notice.tenantID != null && String(notice.tenantID) !== String(session.tenantID)) return false;
|
|
64
|
+
return Boolean(notice.sendUserID && notice.imToken && session.imToken && notice.sendUserID === session.userID && notice.imToken !== session.imToken);
|
|
65
|
+
}
|
|
66
|
+
function assertIMTarget(value, kind = "user") {
|
|
67
|
+
const pattern = kind === "group" ? /^mdm2g_[a-f0-9]{48}$/ : /^mdm2u_[a-f0-9]{48}$/;
|
|
68
|
+
if (!pattern.test(String(value || ""))) throw new Error(kind === "group" ? "请先通过服务端预留租户群组身份" : "消息目标缺少租户 IM 身份");
|
|
69
|
+
}
|
|
70
|
+
function shouldHandleRemoteNotice(notice, session) {
|
|
71
|
+
if (!notice) return false;
|
|
72
|
+
if (Number(session.imIdentityVersion) !== 2) return notice.sendUserID !== session.userID;
|
|
73
|
+
const own = session.imUserID || session.userID;
|
|
74
|
+
return Boolean(own && String(notice.tenantID || "") === String(session.tenantID || "") && /^mdm2u_[a-f0-9]{48}$/.test(notice.sendIMUserID || "") && notice.recvIMUserID === own && notice.sendIMUserID !== own);
|
|
75
|
+
}
|
|
8
76
|
const CbEvents = {
|
|
9
77
|
OnConnectFailed: "OnConnectFailed",
|
|
10
78
|
OnConnectSuccess: "OnConnectSuccess",
|
|
@@ -9786,6 +9854,227 @@ class EventEmitter {
|
|
|
9786
9854
|
this.emitter.all.clear();
|
|
9787
9855
|
}
|
|
9788
9856
|
}
|
|
9857
|
+
const useChatStore = defineStore("chatMessage", {
|
|
9858
|
+
state: () => {
|
|
9859
|
+
return {
|
|
9860
|
+
userID: "",
|
|
9861
|
+
// SDK IM identity (legacy hosts still supply loginCode)
|
|
9862
|
+
imUserID: "",
|
|
9863
|
+
businessUserID: "",
|
|
9864
|
+
loginCode: "",
|
|
9865
|
+
imIdentityVersion: 1,
|
|
9866
|
+
nickname: "",
|
|
9867
|
+
// 用户昵称
|
|
9868
|
+
faceURL: "",
|
|
9869
|
+
// 用户头像
|
|
9870
|
+
platformID: IM_LOGIN_PLATFORM.Web,
|
|
9871
|
+
loginStatus: IM_LOGIN_STATUS.Logout,
|
|
9872
|
+
// 登录状态
|
|
9873
|
+
groupStatus: IM_GROUP_STATUS.Nomal,
|
|
9874
|
+
// 群组状态
|
|
9875
|
+
apiUrl: "",
|
|
9876
|
+
wsUrl: "",
|
|
9877
|
+
tenantID: "",
|
|
9878
|
+
satoken: "",
|
|
9879
|
+
// 系统Token
|
|
9880
|
+
imToken: "",
|
|
9881
|
+
// IM token
|
|
9882
|
+
chatToken: "",
|
|
9883
|
+
// 聊天token
|
|
9884
|
+
unReadCount: 0,
|
|
9885
|
+
// 本账号所有未读消息
|
|
9886
|
+
currentChatId: "",
|
|
9887
|
+
// 当前会话ID
|
|
9888
|
+
isFocused: true,
|
|
9889
|
+
// 窗口是否聚焦
|
|
9890
|
+
remoteConnectUrl: "",
|
|
9891
|
+
// 向日葵被控端连接地址
|
|
9892
|
+
remoteConnectToken: "",
|
|
9893
|
+
// 被控端连接token(session)
|
|
9894
|
+
isViewingChat: false
|
|
9895
|
+
// 是否在H5聊天详情页(控制自动标记已读)
|
|
9896
|
+
};
|
|
9897
|
+
},
|
|
9898
|
+
getters: {
|
|
9899
|
+
// 获取当前会话ID
|
|
9900
|
+
getCurrentChatId(state) {
|
|
9901
|
+
return state.currentChatId;
|
|
9902
|
+
},
|
|
9903
|
+
// 获取用户登录状态
|
|
9904
|
+
getLoginStatus(state) {
|
|
9905
|
+
return state.loginStatus;
|
|
9906
|
+
},
|
|
9907
|
+
// 获取基本地址路径
|
|
9908
|
+
getBaseUrl(state) {
|
|
9909
|
+
return state.apiUrl;
|
|
9910
|
+
},
|
|
9911
|
+
// 获取socket链接路径
|
|
9912
|
+
getWsUrl(state) {
|
|
9913
|
+
return state.wsUrl;
|
|
9914
|
+
},
|
|
9915
|
+
// 获取系统token
|
|
9916
|
+
getToken(state) {
|
|
9917
|
+
return state.satoken;
|
|
9918
|
+
},
|
|
9919
|
+
// 获取租户ID
|
|
9920
|
+
getTenantID(state) {
|
|
9921
|
+
return state.tenantID;
|
|
9922
|
+
},
|
|
9923
|
+
// 获取用户登录信息
|
|
9924
|
+
getUserInfo(state) {
|
|
9925
|
+
return {
|
|
9926
|
+
userID: state.userID,
|
|
9927
|
+
imUserID: state.imUserID,
|
|
9928
|
+
businessUserID: state.businessUserID,
|
|
9929
|
+
loginCode: state.loginCode,
|
|
9930
|
+
imIdentityVersion: state.imIdentityVersion,
|
|
9931
|
+
nickname: state.nickname,
|
|
9932
|
+
faceURL: state.faceURL,
|
|
9933
|
+
loginStatus: state.loginStatus,
|
|
9934
|
+
platformID: state.platformID,
|
|
9935
|
+
satoken: state.satoken,
|
|
9936
|
+
tenantID: state.tenantID,
|
|
9937
|
+
imToken: state.imToken,
|
|
9938
|
+
chatToken: state.chatToken
|
|
9939
|
+
};
|
|
9940
|
+
},
|
|
9941
|
+
// 获取未读消息总数
|
|
9942
|
+
getUnReadCount(state) {
|
|
9943
|
+
return state.unReadCount;
|
|
9944
|
+
},
|
|
9945
|
+
// 获取窗口是否聚焦
|
|
9946
|
+
getIsFocused(state) {
|
|
9947
|
+
return state.isFocused;
|
|
9948
|
+
},
|
|
9949
|
+
// 获取被控端连接地址
|
|
9950
|
+
getRemoteConnectUrl(state) {
|
|
9951
|
+
return state.remoteConnectUrl;
|
|
9952
|
+
},
|
|
9953
|
+
// 获取被控端连接token
|
|
9954
|
+
getRemoteConnectToken(state) {
|
|
9955
|
+
return state.remoteConnectToken;
|
|
9956
|
+
},
|
|
9957
|
+
// 获取是否在查看H5聊天详情
|
|
9958
|
+
getIsViewingChat(state) {
|
|
9959
|
+
return state.isViewingChat;
|
|
9960
|
+
}
|
|
9961
|
+
},
|
|
9962
|
+
actions: {
|
|
9963
|
+
// 设置当前会话ID
|
|
9964
|
+
setCurrentChatId(id) {
|
|
9965
|
+
this.currentChatId = id;
|
|
9966
|
+
},
|
|
9967
|
+
// 更新未读总数
|
|
9968
|
+
setUnReadCount(count = 0) {
|
|
9969
|
+
this.unReadCount = count;
|
|
9970
|
+
},
|
|
9971
|
+
// 更新用户的登录状态
|
|
9972
|
+
setLoginStatus(val) {
|
|
9973
|
+
this.loginStatus = val;
|
|
9974
|
+
},
|
|
9975
|
+
// 更新群组状态
|
|
9976
|
+
setGroupStatus(val) {
|
|
9977
|
+
this.groupStatus = val;
|
|
9978
|
+
},
|
|
9979
|
+
// 保存登录用户信息
|
|
9980
|
+
setUserInfo(obj) {
|
|
9981
|
+
const next = nextIMSession(this.$state, obj);
|
|
9982
|
+
this.$patch(next);
|
|
9983
|
+
},
|
|
9984
|
+
// 设置窗口聚焦状态
|
|
9985
|
+
setIsFocused(val) {
|
|
9986
|
+
this.isFocused = val;
|
|
9987
|
+
},
|
|
9988
|
+
// 设置被控端连接地址
|
|
9989
|
+
setRemoteConnectUrl(url) {
|
|
9990
|
+
this.remoteConnectUrl = url;
|
|
9991
|
+
},
|
|
9992
|
+
// 设置被控端连接token
|
|
9993
|
+
setRemoteConnectToken(token) {
|
|
9994
|
+
this.remoteConnectToken = token;
|
|
9995
|
+
},
|
|
9996
|
+
// 设置是否在查看H5聊天详情
|
|
9997
|
+
setIsViewingChat(val) {
|
|
9998
|
+
this.isViewingChat = val;
|
|
9999
|
+
}
|
|
10000
|
+
},
|
|
10001
|
+
persist: {
|
|
10002
|
+
enabled: true,
|
|
10003
|
+
// 开启持久化
|
|
10004
|
+
strategies: [
|
|
10005
|
+
{
|
|
10006
|
+
key: "MDM_CHAT_MESSAGE",
|
|
10007
|
+
// 存储的 key 名(默认 store id)
|
|
10008
|
+
storage: localStorage,
|
|
10009
|
+
// 存储位置(默认 localStorage)
|
|
10010
|
+
// HttpOnly Cookie 认证:satoken 和 imToken 不再持久化到 localStorage,仅保留在 Pinia 内存中
|
|
10011
|
+
paths: ["userID", "nickname", "faceURL", "platformID", "apiUrl", "wsUrl", "tenantID", "imUserID", "businessUserID", "loginCode", "imIdentityVersion"]
|
|
10012
|
+
}
|
|
10013
|
+
]
|
|
10014
|
+
}
|
|
10015
|
+
});
|
|
10016
|
+
const requestInstance = axios.create({
|
|
10017
|
+
baseURL: "",
|
|
10018
|
+
timeout: 6e4,
|
|
10019
|
+
withCredentials: true
|
|
10020
|
+
// HttpOnly Cookie 认证:自动携带会话 Cookie
|
|
10021
|
+
});
|
|
10022
|
+
requestInstance.defaults.headers.post["Content-Type"] = "application/json; charset=utf-8";
|
|
10023
|
+
requestInstance.interceptors.request.use(
|
|
10024
|
+
function(config) {
|
|
10025
|
+
config.headers["X-Login-Type"] = "3";
|
|
10026
|
+
const chatStore = useChatStore();
|
|
10027
|
+
if (chatStore.satoken) {
|
|
10028
|
+
config.headers["satoken"] = chatStore.satoken;
|
|
10029
|
+
}
|
|
10030
|
+
return config;
|
|
10031
|
+
},
|
|
10032
|
+
function(error) {
|
|
10033
|
+
return Promise.reject(error);
|
|
10034
|
+
}
|
|
10035
|
+
);
|
|
10036
|
+
requestInstance.interceptors.response.use(
|
|
10037
|
+
function(response) {
|
|
10038
|
+
if ((response == null ? void 0 : response.status) == 200) {
|
|
10039
|
+
const code = response == null ? void 0 : response.data.code;
|
|
10040
|
+
if (EXIT_CODE.values.includes(code)) {
|
|
10041
|
+
if (EXIT_CODE[code] !== "token") {
|
|
10042
|
+
ElMessage.error(EXIT_CODE.label[code]);
|
|
10043
|
+
}
|
|
10044
|
+
}
|
|
10045
|
+
} else {
|
|
10046
|
+
ElMessage.error("接口出错,请检查网络后重试");
|
|
10047
|
+
}
|
|
10048
|
+
return response;
|
|
10049
|
+
},
|
|
10050
|
+
function(error) {
|
|
10051
|
+
return Promise.reject(error);
|
|
10052
|
+
}
|
|
10053
|
+
);
|
|
10054
|
+
class IMSessionChangedError extends Error {
|
|
10055
|
+
constructor() {
|
|
10056
|
+
super("IM 会话已切换,请重试");
|
|
10057
|
+
this.name = "IMSessionChangedError";
|
|
10058
|
+
}
|
|
10059
|
+
}
|
|
10060
|
+
function guardIMSDK(sdk, isCurrent) {
|
|
10061
|
+
const lifecycle = /* @__PURE__ */ new Set(["on", "off", "logout"]);
|
|
10062
|
+
return new Proxy(sdk, {
|
|
10063
|
+
get(target, key) {
|
|
10064
|
+
const value = Reflect.get(target, key);
|
|
10065
|
+
if (typeof value !== "function") return value;
|
|
10066
|
+
return (...args) => {
|
|
10067
|
+
if (!lifecycle.has(key) && !isCurrent()) return Promise.reject(new IMSessionChangedError());
|
|
10068
|
+
const result = Reflect.apply(value, target, args);
|
|
10069
|
+
if (!result || typeof result.then !== "function" || lifecycle.has(key)) return result;
|
|
10070
|
+
return result.then((data) => {
|
|
10071
|
+
if (!isCurrent()) throw new IMSessionChangedError();
|
|
10072
|
+
return data;
|
|
10073
|
+
});
|
|
10074
|
+
};
|
|
10075
|
+
}
|
|
10076
|
+
});
|
|
10077
|
+
}
|
|
9789
10078
|
const HEX = "0123456789abcdef";
|
|
9790
10079
|
function randomBytes(length) {
|
|
9791
10080
|
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
@@ -9819,7 +10108,9 @@ class ImKit extends EventEmitter {
|
|
|
9819
10108
|
dataDir = "./",
|
|
9820
10109
|
userID,
|
|
9821
10110
|
imToken,
|
|
9822
|
-
chatToken
|
|
10111
|
+
chatToken,
|
|
10112
|
+
imIdentityVersion = 1,
|
|
10113
|
+
isCurrentSession = () => true
|
|
9823
10114
|
}) {
|
|
9824
10115
|
super();
|
|
9825
10116
|
__publicField(this, "apiUrl", "");
|
|
@@ -9843,6 +10134,11 @@ class ImKit extends EventEmitter {
|
|
|
9843
10134
|
__publicField(this, "loginStatus", IM_LOGIN_STATUS.Logout);
|
|
9844
10135
|
// 1 未登录 2 登录中 3 已登录
|
|
9845
10136
|
__publicField(this, "groupStatus", IM_GROUP_STATUS.Nomal);
|
|
10137
|
+
this.imIdentityVersion = Number(imIdentityVersion);
|
|
10138
|
+
this.isCurrentSession = isCurrentSession;
|
|
10139
|
+
this.disposed = false;
|
|
10140
|
+
this.pendingGroupCreates = /* @__PURE__ */ new Map();
|
|
10141
|
+
this.businessApiUrl = apiUrl;
|
|
9846
10142
|
this.apiUrl = `${apiUrl}/imapi`;
|
|
9847
10143
|
this.wsUrl = `${wsUrl}/imws`;
|
|
9848
10144
|
this.platformID = platformID;
|
|
@@ -9878,7 +10174,8 @@ class ImKit extends EventEmitter {
|
|
|
9878
10174
|
// @openim/client-sdk和@openim/wasm-client-sdk 不需要初始化,直接调用 login 即可。
|
|
9879
10175
|
initSDK() {
|
|
9880
10176
|
try {
|
|
9881
|
-
this.
|
|
10177
|
+
this.disposed = false;
|
|
10178
|
+
this.IMSDK = guardIMSDK(Ot(), () => !this.disposed && this.isCurrentSession());
|
|
9882
10179
|
this.bindEvent();
|
|
9883
10180
|
} catch (err) {
|
|
9884
10181
|
console.error(err);
|
|
@@ -9918,6 +10215,7 @@ class ImKit extends EventEmitter {
|
|
|
9918
10215
|
}
|
|
9919
10216
|
// 清空即时通信实例
|
|
9920
10217
|
clearSDK() {
|
|
10218
|
+
this.disposed = true;
|
|
9921
10219
|
this.unbindEvent();
|
|
9922
10220
|
this.IMSDK = null;
|
|
9923
10221
|
}
|
|
@@ -10147,8 +10445,9 @@ class ImKit extends EventEmitter {
|
|
|
10147
10445
|
console.log("请先初始化SDK");
|
|
10148
10446
|
return;
|
|
10149
10447
|
}
|
|
10150
|
-
this.IMSDK.logout().then(() => {
|
|
10151
|
-
this.
|
|
10448
|
+
return this.IMSDK.logout().then(() => {
|
|
10449
|
+
this.loginStatus = IM_LOGIN_STATUS.Logout;
|
|
10450
|
+
this.emit("updateStatus", this.loginStatus);
|
|
10152
10451
|
return true;
|
|
10153
10452
|
}).catch((error) => {
|
|
10154
10453
|
console.log("IM登出异常:", error);
|
|
@@ -10821,6 +11120,10 @@ class ImKit extends EventEmitter {
|
|
|
10821
11120
|
}
|
|
10822
11121
|
// 发送消息,发送通过 create***Message 创建的消息,offlinePushInfo-离线消息体,groupID-发送单聊消息时传空字符串
|
|
10823
11122
|
async sendMessage({ recvID, groupID, offlinePushInfo, message }, operationID = uuidv4()) {
|
|
11123
|
+
if (this.imIdentityVersion === 2) {
|
|
11124
|
+
if (groupID) assertIMTarget(groupID, "group");
|
|
11125
|
+
else assertIMTarget(recvID);
|
|
11126
|
+
}
|
|
10824
11127
|
try {
|
|
10825
11128
|
const res = await this.IMSDK.sendMessage({ recvID, groupID, offlinePushInfo, message }, operationID);
|
|
10826
11129
|
if (res.data) {
|
|
@@ -10995,9 +11298,26 @@ class ImKit extends EventEmitter {
|
|
|
10995
11298
|
* @param {String} operationID
|
|
10996
11299
|
*/
|
|
10997
11300
|
async createGroup({ groupInfo, memberUserIDs, ownerUserID, adminUserIDs }, operationID = uuidv4()) {
|
|
10998
|
-
var _a;
|
|
11301
|
+
var _a, _b, _c;
|
|
11302
|
+
if (this.imIdentityVersion === 2) {
|
|
11303
|
+
if (this.disposed || !this.isCurrentSession()) throw new IMSessionChangedError();
|
|
11304
|
+
if (ownerUserID !== this.userID) throw new Error("群主必须是当前用户");
|
|
11305
|
+
if (adminUserIDs == null ? void 0 : adminUserIDs.length) throw new Error("请在建群后设置管理员");
|
|
11306
|
+
const spec = JSON.stringify([groupInfo == null ? void 0 : groupInfo.groupName, ownerUserID, [...memberUserIDs || []].sort()]);
|
|
11307
|
+
const requestID = String((groupInfo == null ? void 0 : groupInfo.groupID) || this.pendingGroupCreates.get(spec) || operationID);
|
|
11308
|
+
this.pendingGroupCreates.set(spec, requestID);
|
|
11309
|
+
const result = await requestInstance.post(`${this.businessApiUrl}/api/v1/openim/createTenantGroup`, {
|
|
11310
|
+
requestID,
|
|
11311
|
+
groupName: groupInfo == null ? void 0 : groupInfo.groupName,
|
|
11312
|
+
members: memberUserIDs || []
|
|
11313
|
+
});
|
|
11314
|
+
if (this.disposed || !this.isCurrentSession()) throw new IMSessionChangedError();
|
|
11315
|
+
if (((_a = result.data) == null ? void 0 : _a.code) !== 200) throw new Error(((_b = result.data) == null ? void 0 : _b.msg) || "建群失败");
|
|
11316
|
+
this.pendingGroupCreates.delete(spec);
|
|
11317
|
+
return true;
|
|
11318
|
+
}
|
|
10999
11319
|
try {
|
|
11000
|
-
const res = await ((
|
|
11320
|
+
const res = await ((_c = this.IMSDK) == null ? void 0 : _c.createGroup(
|
|
11001
11321
|
{
|
|
11002
11322
|
groupInfo,
|
|
11003
11323
|
memberUserIDs,
|
|
@@ -11066,6 +11386,10 @@ class ImKit extends EventEmitter {
|
|
|
11066
11386
|
* @param {String} operationID
|
|
11067
11387
|
*/
|
|
11068
11388
|
async inviteUserToGroup({ groupID, userIDList: userIDList2, reason }, operationID = uuidv4()) {
|
|
11389
|
+
if (this.imIdentityVersion === 2) {
|
|
11390
|
+
assertIMTarget(groupID, "group");
|
|
11391
|
+
for (const id of userIDList2 || []) assertIMTarget(id);
|
|
11392
|
+
}
|
|
11069
11393
|
if (!groupID || !this.IMSDK) return;
|
|
11070
11394
|
try {
|
|
11071
11395
|
const res = await this.IMSDK.inviteUserToGroup({ groupID, userIDList: userIDList2, reason }, operationID);
|
|
@@ -11412,165 +11736,6 @@ class ImKit extends EventEmitter {
|
|
|
11412
11736
|
}
|
|
11413
11737
|
}
|
|
11414
11738
|
}
|
|
11415
|
-
const useChatStore = defineStore("chatMessage", {
|
|
11416
|
-
state: () => {
|
|
11417
|
-
return {
|
|
11418
|
-
userID: "",
|
|
11419
|
-
// 用户ID
|
|
11420
|
-
nickname: "",
|
|
11421
|
-
// 用户昵称
|
|
11422
|
-
faceURL: "",
|
|
11423
|
-
// 用户头像
|
|
11424
|
-
platformID: IM_LOGIN_PLATFORM.Web,
|
|
11425
|
-
loginStatus: IM_LOGIN_STATUS.Logout,
|
|
11426
|
-
// 登录状态
|
|
11427
|
-
groupStatus: IM_GROUP_STATUS.Nomal,
|
|
11428
|
-
// 群组状态
|
|
11429
|
-
apiUrl: "",
|
|
11430
|
-
wsUrl: "",
|
|
11431
|
-
tenantID: "",
|
|
11432
|
-
satoken: "",
|
|
11433
|
-
// 系统Token
|
|
11434
|
-
imToken: "",
|
|
11435
|
-
// IM token
|
|
11436
|
-
chatToken: "",
|
|
11437
|
-
// 聊天token
|
|
11438
|
-
unReadCount: 0,
|
|
11439
|
-
// 本账号所有未读消息
|
|
11440
|
-
currentChatId: "",
|
|
11441
|
-
// 当前会话ID
|
|
11442
|
-
isFocused: true,
|
|
11443
|
-
// 窗口是否聚焦
|
|
11444
|
-
remoteConnectUrl: "",
|
|
11445
|
-
// 向日葵被控端连接地址
|
|
11446
|
-
remoteConnectToken: "",
|
|
11447
|
-
// 被控端连接token(session)
|
|
11448
|
-
isViewingChat: false
|
|
11449
|
-
// 是否在H5聊天详情页(控制自动标记已读)
|
|
11450
|
-
};
|
|
11451
|
-
},
|
|
11452
|
-
getters: {
|
|
11453
|
-
// 获取当前会话ID
|
|
11454
|
-
getCurrentChatId(state) {
|
|
11455
|
-
return state.currentChatId;
|
|
11456
|
-
},
|
|
11457
|
-
// 获取用户登录状态
|
|
11458
|
-
getLoginStatus(state) {
|
|
11459
|
-
return state.loginStatus;
|
|
11460
|
-
},
|
|
11461
|
-
// 获取基本地址路径
|
|
11462
|
-
getBaseUrl(state) {
|
|
11463
|
-
return state.apiUrl;
|
|
11464
|
-
},
|
|
11465
|
-
// 获取socket链接路径
|
|
11466
|
-
getWsUrl(state) {
|
|
11467
|
-
return state.wsUrl;
|
|
11468
|
-
},
|
|
11469
|
-
// 获取系统token
|
|
11470
|
-
getToken(state) {
|
|
11471
|
-
return state.satoken;
|
|
11472
|
-
},
|
|
11473
|
-
// 获取租户ID
|
|
11474
|
-
getTenantID(state) {
|
|
11475
|
-
return state.tenantID;
|
|
11476
|
-
},
|
|
11477
|
-
// 获取用户登录信息
|
|
11478
|
-
getUserInfo(state) {
|
|
11479
|
-
return {
|
|
11480
|
-
userID: state.userID,
|
|
11481
|
-
nickname: state.nickname,
|
|
11482
|
-
faceURL: state.faceURL,
|
|
11483
|
-
loginStatus: state.loginStatus,
|
|
11484
|
-
platformID: state.platformID,
|
|
11485
|
-
satoken: state.satoken,
|
|
11486
|
-
tenantID: state.tenantID,
|
|
11487
|
-
imToken: state.imToken,
|
|
11488
|
-
chatToken: state.chatToken
|
|
11489
|
-
};
|
|
11490
|
-
},
|
|
11491
|
-
// 获取未读消息总数
|
|
11492
|
-
getUnReadCount(state) {
|
|
11493
|
-
return state.unReadCount;
|
|
11494
|
-
},
|
|
11495
|
-
// 获取窗口是否聚焦
|
|
11496
|
-
getIsFocused(state) {
|
|
11497
|
-
return state.isFocused;
|
|
11498
|
-
},
|
|
11499
|
-
// 获取被控端连接地址
|
|
11500
|
-
getRemoteConnectUrl(state) {
|
|
11501
|
-
return state.remoteConnectUrl;
|
|
11502
|
-
},
|
|
11503
|
-
// 获取被控端连接token
|
|
11504
|
-
getRemoteConnectToken(state) {
|
|
11505
|
-
return state.remoteConnectToken;
|
|
11506
|
-
},
|
|
11507
|
-
// 获取是否在查看H5聊天详情
|
|
11508
|
-
getIsViewingChat(state) {
|
|
11509
|
-
return state.isViewingChat;
|
|
11510
|
-
}
|
|
11511
|
-
},
|
|
11512
|
-
actions: {
|
|
11513
|
-
// 设置当前会话ID
|
|
11514
|
-
setCurrentChatId(id) {
|
|
11515
|
-
this.currentChatId = id;
|
|
11516
|
-
},
|
|
11517
|
-
// 更新未读总数
|
|
11518
|
-
setUnReadCount(count = 0) {
|
|
11519
|
-
this.unReadCount = count;
|
|
11520
|
-
},
|
|
11521
|
-
// 更新用户的登录状态
|
|
11522
|
-
setLoginStatus(val) {
|
|
11523
|
-
this.loginStatus = val;
|
|
11524
|
-
},
|
|
11525
|
-
// 更新群组状态
|
|
11526
|
-
setGroupStatus(val) {
|
|
11527
|
-
this.groupStatus = val;
|
|
11528
|
-
},
|
|
11529
|
-
// 保存登录用户信息
|
|
11530
|
-
setUserInfo(obj) {
|
|
11531
|
-
this.userID = (obj == null ? void 0 : obj.userID) || this.userID;
|
|
11532
|
-
this.nickname = (obj == null ? void 0 : obj.nickname) || this.nickname;
|
|
11533
|
-
this.faceURL = (obj == null ? void 0 : obj.faceURL) || this.faceURL;
|
|
11534
|
-
this.imToken = (obj == null ? void 0 : obj.imToken) || this.imToken;
|
|
11535
|
-
this.chatToken = (obj == null ? void 0 : obj.chatToken) || this.chatToken;
|
|
11536
|
-
this.satoken = (obj == null ? void 0 : obj.satoken) || this.satoken;
|
|
11537
|
-
this.apiUrl = (obj == null ? void 0 : obj.apiUrl) || this.apiUrl;
|
|
11538
|
-
this.wsUrl = (obj == null ? void 0 : obj.wsUrl) || this.wsUrl;
|
|
11539
|
-
this.tenantID = (obj == null ? void 0 : obj.tenantID) || this.tenantID;
|
|
11540
|
-
this.platformID = obj.platformID || this.platformID;
|
|
11541
|
-
},
|
|
11542
|
-
// 设置窗口聚焦状态
|
|
11543
|
-
setIsFocused(val) {
|
|
11544
|
-
this.isFocused = val;
|
|
11545
|
-
},
|
|
11546
|
-
// 设置被控端连接地址
|
|
11547
|
-
setRemoteConnectUrl(url) {
|
|
11548
|
-
this.remoteConnectUrl = url;
|
|
11549
|
-
},
|
|
11550
|
-
// 设置被控端连接token
|
|
11551
|
-
setRemoteConnectToken(token) {
|
|
11552
|
-
this.remoteConnectToken = token;
|
|
11553
|
-
},
|
|
11554
|
-
// 设置是否在查看H5聊天详情
|
|
11555
|
-
setIsViewingChat(val) {
|
|
11556
|
-
this.isViewingChat = val;
|
|
11557
|
-
}
|
|
11558
|
-
},
|
|
11559
|
-
persist: {
|
|
11560
|
-
enabled: true,
|
|
11561
|
-
// 开启持久化
|
|
11562
|
-
strategies: [
|
|
11563
|
-
{
|
|
11564
|
-
key: "MDM_CHAT_MESSAGE",
|
|
11565
|
-
// 存储的 key 名(默认 store id)
|
|
11566
|
-
storage: localStorage,
|
|
11567
|
-
// 存储位置(默认 localStorage)
|
|
11568
|
-
// HttpOnly Cookie 认证:satoken 和 imToken 不再持久化到 localStorage,仅保留在 Pinia 内存中
|
|
11569
|
-
paths: ["userID", "nickname", "faceURL", "platformID", "apiUrl", "wsUrl", "tenantID"]
|
|
11570
|
-
}
|
|
11571
|
-
]
|
|
11572
|
-
}
|
|
11573
|
-
});
|
|
11574
11739
|
const userList = ref([]);
|
|
11575
11740
|
const userIDList = ref([]);
|
|
11576
11741
|
const userOnlineStatus = ref({});
|
|
@@ -11608,7 +11773,12 @@ const useUsers = () => {
|
|
|
11608
11773
|
const getAllUserStatus = () => {
|
|
11609
11774
|
return userOnlineStatus.value;
|
|
11610
11775
|
};
|
|
11611
|
-
|
|
11776
|
+
const resetUsers = () => {
|
|
11777
|
+
userList.value = [];
|
|
11778
|
+
userIDList.value = [];
|
|
11779
|
+
userOnlineStatus.value = {};
|
|
11780
|
+
};
|
|
11781
|
+
return { resetUsers, updateUserList, getUserIds, updateUserStatus, getCurrentUserInfo, getAllUserStatus, getUserStatus };
|
|
11612
11782
|
};
|
|
11613
11783
|
function getDefaultExportFromCjs(x3) {
|
|
11614
11784
|
return x3 && x3.__esModule && Object.prototype.hasOwnProperty.call(x3, "default") ? x3["default"] : x3;
|
|
@@ -36257,7 +36427,7 @@ const toPinyin = (text) => {
|
|
|
36257
36427
|
const conversationList = ref([]);
|
|
36258
36428
|
const skipSortIds = /* @__PURE__ */ new Set();
|
|
36259
36429
|
const currentConversation = ref({});
|
|
36260
|
-
ref([]);
|
|
36430
|
+
const currentConversationUsers = ref([]);
|
|
36261
36431
|
const useConversations = () => {
|
|
36262
36432
|
const chatMessage = useChatStore();
|
|
36263
36433
|
const baseUrl = chatMessage.getBaseUrl;
|
|
@@ -36446,6 +36616,8 @@ const useConversations = () => {
|
|
|
36446
36616
|
if (id) skipSortIds.add(id);
|
|
36447
36617
|
};
|
|
36448
36618
|
const clearConversationList = () => {
|
|
36619
|
+
skipSortIds.clear();
|
|
36620
|
+
currentConversationUsers.value = [];
|
|
36449
36621
|
conversationList.value = [];
|
|
36450
36622
|
currentConversation.value = {};
|
|
36451
36623
|
chatMessage.setUnReadCount(0);
|
|
@@ -37141,7 +37313,14 @@ const useMsgList = () => {
|
|
|
37141
37313
|
}
|
|
37142
37314
|
return obj.sessionType === IM_CVS_TYPE.Group ? `${obj.senderNickname}: [未知消息]` : `${obj.senderNickname}发送了消息`;
|
|
37143
37315
|
};
|
|
37316
|
+
const clearMessageList = () => {
|
|
37317
|
+
messageList.value = [];
|
|
37318
|
+
startClientMsgID.value = "";
|
|
37319
|
+
isLastMessage.value = true;
|
|
37320
|
+
isFirstMessage.value = false;
|
|
37321
|
+
};
|
|
37144
37322
|
return {
|
|
37323
|
+
clearMessageList,
|
|
37145
37324
|
messageList,
|
|
37146
37325
|
startClientMsgID,
|
|
37147
37326
|
isLastMessage,
|
|
@@ -37322,7 +37501,7 @@ const useBurnAfterReading = () => {
|
|
|
37322
37501
|
const origin = Number(startAt) || Date.now();
|
|
37323
37502
|
const deadline = origin + duration * 1e3;
|
|
37324
37503
|
if (deadline <= Date.now()) {
|
|
37325
|
-
setTimeout(() =>
|
|
37504
|
+
timers.set(key, setTimeout(() => fireBurn(conversationID, msg.clientMsgID), 0));
|
|
37326
37505
|
return;
|
|
37327
37506
|
}
|
|
37328
37507
|
deadlines.set(key, deadline);
|
|
@@ -39575,13 +39754,14 @@ async function clearCache(userID) {
|
|
|
39575
39754
|
function useMessageCache() {
|
|
39576
39755
|
const chatMessage = useChatStore();
|
|
39577
39756
|
function _getUserID() {
|
|
39578
|
-
return chatMessage
|
|
39757
|
+
return imCacheNamespace(chatMessage);
|
|
39579
39758
|
}
|
|
39580
39759
|
async function loadConversationsFromCache() {
|
|
39581
39760
|
const userID = _getUserID();
|
|
39582
39761
|
if (!userID) return null;
|
|
39583
39762
|
try {
|
|
39584
39763
|
const list = await loadConversations(userID);
|
|
39764
|
+
if (userID !== _getUserID()) return null;
|
|
39585
39765
|
if (list && Array.isArray(list) && list.length > 0) {
|
|
39586
39766
|
console.log(
|
|
39587
39767
|
`[MessageCache] Loaded ${list.length} conversations from IndexedDB cache`
|
|
@@ -39609,6 +39789,7 @@ function useMessageCache() {
|
|
|
39609
39789
|
if (!userID || !conversationID) return null;
|
|
39610
39790
|
try {
|
|
39611
39791
|
const list = await loadMessages(userID, conversationID);
|
|
39792
|
+
if (userID !== _getUserID()) return null;
|
|
39612
39793
|
if (list && Array.isArray(list) && list.length > 0) {
|
|
39613
39794
|
console.log(
|
|
39614
39795
|
`[MessageCache] Loaded ${list.length} messages for ${conversationID} from IndexedDB cache`
|
|
@@ -39652,6 +39833,19 @@ function useMessageCache() {
|
|
|
39652
39833
|
const mittBus = mitt();
|
|
39653
39834
|
const newMsgAudioUrl = "data:audio/mpeg;base64,SUQzAwAAAAAgAFRJVDMAAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSlUUFVCAAAAGAAAANW+s6TL2LLEKHNjLmNoaW5hei5jb20pV09BUgAAABcAANW+s6TL2LLEKHNjLmNoaW5hei5jb20pVEVOQwAAABgAAADVvrOky9iyxChzYy5jaGluYXouY29tKVRBTEIAAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSlUWUVSAAAABQAAADIwMjBUUEUyAAAAGAAAANW+s6TL2LLEKHNjLmNoaW5hei5jb20pVElUMgAAABgAAADVvrOky9iyxChzYy5jaGluYXouY29tKVRDT04AAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSlDT01NAAAAHAAAAGNoaQDVvrOky9iyxChzYy5jaGluYXouY29tKVRQRTEAAAAYAAAA1b6zpMvYssQoc2MuY2hpbmF6LmNvbSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABJRDMEAAAAADYkVFhYWAAAAAsAAANUREFUADMwMDYAVFhYWAAAAAsAAANUSU1FADIxMzEAVFhYWAAAAAoAAANjb21tZW50AABQUklWAAA1OQAAWE1QADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQzIDc5LjE2MTIxMCwgMjAxNy8wOC8xMS0xMDoyODozNiAgICAgICAgIj4KIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIgogICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIgogICAgeG1sbnM6eG1wRE09Imh0dHA6Ly9ucy5hZG9iZS5jb20veG1wLzEuMC9EeW5hbWljTWVkaWEvIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6Y3JlYXRvckF0b209Imh0dHA6Ly9ucy5hZG9iZS5jb20vY3JlYXRvckF0b20vMS4wLyIKICAgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3YjdlYjE0OC03ZTllLTA3NDctYTNlNS05NzlmN2IzZTQ4ODEiCiAgIHhtcE1NOkRvY3VtZW50SUQ9ImU4YTMzOWUyLWI5YjQtM2I5MC02OTFkLWMwZWMwMDAwMDAzZCIKICAgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjM2ZDgxZDUxLWYxM2QtMWQ0MS1hODYxLWIxZTlmZDEyMzgxOCIKICAgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMC0wNi0zMFQyMTozMTozNCswODowMCIKICAgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDYtMzBUMjE6MzE6MzQrMDg6MDAiCiAgIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUHJlbWllcmUgUHJvIENDIDIwMTguMCAoV2luZG93cykiCiAgIHhtcDpDcmVhdGVEYXRlPSIyMDIwLTA2LTMwVDIxOjMxOjA0KzA4OjAwIgogICB4bXBETTphdWRpb1NhbXBsZVJhdGU9Ii0xIgogICB4bXBETTphdWRpb1NhbXBsZVR5cGU9IjE2SW50IgogICB4bXBETTphdWRpb0NoYW5uZWxUeXBlPSJTdGVyZW8iCiAgIHhtcERNOnN0YXJ0VGltZVNjYWxlPSIzMDAwMCIKICAgeG1wRE06c3RhcnRUaW1lU2FtcGxlU2l6ZT0iMTAwMSIKICAgZGM6Zm9ybWF0PSJNUDMiPgogICA8eG1wTU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0iZDEwNTQ1NzMtNjlmMS02Y2M2LTJhYTItNzk0ZDAwMDAwMDZhIgogICAgICBzdEV2dDp3aGVuPSIyMDIwLTA2LTMwVDIxOjMxOjM0KzA4OjAwIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQcmVtaWVyZSBQcm8gQ0MgMjAxOC4wIChXaW5kb3dzKSIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIvPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjIwYWNhNWE3LTAwMzQtNDM0OC05ZWQ4LTBlMWY3Y2IwOGVhZCIKICAgICAgc3RFdnQ6d2hlbj0iMjAyMC0wNi0zMFQyMTozMTozNCswODowMCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUHJlbWllcmUgUHJvIENDIDIwMTguMCAoV2luZG93cykiLz4KICAgICA8cmRmOmxpCiAgICAgIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiCiAgICAgIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6ZmYxY2M1NmItMmUyMS1kMTRlLThhMGEtYTZlYWVjY2ZjODVmIgogICAgICBzdEV2dDp3aGVuPSIyMDIwLTA2LTMwVDIxOjMxOjM0KzA4OjAwIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQcmVtaWVyZSBQcm8gQ0MgMjAxOC4wIChXaW5kb3dzKSIKICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIvPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo3YjdlYjE0OC03ZTllLTA3NDctYTNlNS05NzlmN2IzZTQ4ODEiCiAgICAgIHN0RXZ0OndoZW49IjIwMjAtMDYtMzBUMjE6MzE6MzQrMDg6MDAiCiAgICAgIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFByZW1pZXJlIFBybyBDQyAyMDE4LjAgKFdpbmRvd3MpIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvbWV0YWRhdGEiLz4KICAgIDwvcmRmOlNlcT4KICAgPC94bXBNTTpIaXN0b3J5PgogICA8eG1wTU06SW5ncmVkaWVudHM+CiAgICA8cmRmOkJhZz4KICAgICA8cmRmOmxpCiAgICAgIHN0UmVmOmluc3RhbmNlSUQ9IjBmODZjODFiLTgxYzAtOTY2Mi1lNGZlLTcyOTMwMDAwMDA2YSIKICAgICAgc3RSZWY6ZG9jdW1lbnRJRD0iZjNjYTE3ZDItZjhlNi1lNjY1LTMyZmEtYTI3ZDAwMDAwMDNkIgogICAgICBzdFJlZjpmcm9tUGFydD0idGltZTo1MDU1NzM4NjQ5NTBmMjU0MDE2MDAwMDAwZDIwOTIwMjk3ODYwMGYyNTQwMTYwMDAwMDAiCiAgICAgIHN0UmVmOnRvUGFydD0idGltZTowZDIwOTIwMjk3ODYwMGYyNTQwMTYwMDAwMDAiCiAgICAgIHN0UmVmOmZpbGVQYXRoPSLlvq7kv6HmnaXkv6Hmga8ubXA0IgogICAgICBzdFJlZjptYXNrTWFya2Vycz0iTm9uZSIvPgogICAgPC9yZGY6QmFnPgogICA8L3htcE1NOkluZ3JlZGllbnRzPgogICA8eG1wTU06UGFudHJ5PgogICAgPHJkZjpCYWc+CiAgICAgPHJkZjpsaT4KICAgICAgPHJkZjpEZXNjcmlwdGlvbgogICAgICAgeG1wOkNyZWF0ZURhdGU9IjE5MDQtMDEtMDFUMDA6MDBaIgogICAgICAgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDYtMzBUMjE6MzA6MzQrMDg6MDAiCiAgICAgICB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTA2LTMwVDIxOjMwOjM0KzA4OjAwIgogICAgICAgeG1wRE06bG9nQ29tbWVudD0i5pys6KeG6aKR55Sx5rmW5Y2X5LiA5ZSv5L+h5oGv56eR5oqA5byA5Y+R55qERVblvZXlsY/ova/ku7blvZXliLbvvIx3d3cuaWV3YXkuY24iCiAgICAgICB4bXBNTTpJbnN0YW5jZUlEPSIwZjg2YzgxYi04MWMwLTk2NjItZTRmZS03MjkzMDAwMDAwNmEiCiAgICAgICB4bXBNTTpEb2N1bWVudElEPSJmM2NhMTdkMi1mOGU2LWU2NjUtMzJmYS1hMjdkMDAwMDAwM2QiCiAgICAgICB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6OTk4YTUwOGUtY2IxMC01ODQ1LWI3YmItYzBhMTg2Yjk5YmJkIj4KICAgICAgPHhtcERNOmR1cmF0aW9uCiAgICAgICB4bXBETTp2YWx1ZT0iMTAyMTkiCiAgICAgICB4bXBETTpzY2FsZT0iMS8xMDAwIi8+CiAgICAgIDxkYzp0aXRsZT4KICAgICAgIDxyZGY6QWx0PgogICAgICAgIDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+RVblvZXlsY8zLjkuN+i9r+S7tuW9leWItjwvcmRmOmxpPgogICAgICAgPC9yZGY6QWx0PgogICAgICA8L2RjOnRpdGxlPgogICAgICA8eG1wTU06SGlzdG9yeT4KICAgICAgIDxyZGY6U2VxPgogICAgICAgIDxyZGY6bGkKICAgICAgICAgc3RFdnQ6YWN0aW9uPSJzYXZlZCIKICAgICAgICAgc3RFdnQ6aW5zdGFuY2VJRD0iMGY4NmM4MWItODFjMC05NjYyLWU0ZmUtNzI5MzAwMDAwMDZhIgogICAgICAgICBzdEV2dDp3aGVuPSIyMDIwLTA2LTMwVDIxOjMwOjM0KzA4OjAwIgogICAgICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQcmVtaWVyZSBQcm8gQ0MgMjAxOC4wIChXaW5kb3dzKSIKICAgICAgICAgc3RFdnQ6Y2hhbmdlZD0iLyIvPgogICAgICAgPC9yZGY6U2VxPgogICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICAgIDwvcmRmOmxpPgogICAgPC9yZGY6QmFnPgogICA8L3htcE1NOlBhbnRyeT4KICAgPHhtcE1NOkRlcml2ZWRGcm9tCiAgICBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjIwYWNhNWE3LTAwMzQtNDM0OC05ZWQ4LTBlMWY3Y2IwOGVhZCIKICAgIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MjBhY2E1YTctMDAzNC00MzQ4LTllZDgtMGUxZjdjYjA4ZWFkIgogICAgc3RSZWY6b3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOjIwYWNhNWE3LTAwMzQtNDM0OC05ZWQ4LTBlMWY3Y2IwOGVhZCIvPgogICA8Y3JlYXRvckF0b206d2luZG93c0F0b20KICAgIGNyZWF0b3JBdG9tOmV4dGVuc2lvbj0iLnBycHJvaiIKICAgIGNyZWF0b3JBdG9tOmludm9jYXRpb25GbGFncz0iL0wiCiAgICBjcmVhdG9yQXRvbTp1bmNQcm9qZWN0UGF0aD0iXFw/XEM6XFVzZXJzXEFkbWluaXN0cmF0b3JcRGVza3RvcFzpn7PmlYgucHJwcm9qIi8+CiAgIDxjcmVhdG9yQXRvbTptYWNBdG9tCiAgICBjcmVhdG9yQXRvbTphcHBsaWNhdGlvbkNvZGU9IjEzNDc0NDk0NTUiCiAgICBjcmVhdG9yQXRvbTppbnZvY2F0aW9uQXBwbGVFdmVudD0iMTEyOTQ2ODAxOCIvPgogICA8eG1wRE06cHJvamVjdFJlZgogICAgeG1wRE06dHlwZT0ibW92aWUiLz4KICAgPHhtcERNOmR1cmF0aW9uCiAgICB4bXBETTp2YWx1ZT0iMjQiCiAgICB4bXBETTpzY2FsZT0iMTAwMS8zMDAwMCIvPgogICA8eG1wRE06c3RhcnRUaW1lY29kZQogICAgeG1wRE06dGltZUZvcm1hdD0iMjk5N0Ryb3BUaW1lY29kZSIKICAgIHhtcERNOnRpbWVWYWx1ZT0iMDA7MDA7MDA7MDAiLz4KICAgPHhtcERNOmFsdFRpbWVjb2RlCiAgICB4bXBETTp0aW1lVmFsdWU9IjAwOzAwOzAwOzAwIgogICAgeG1wRE06dGltZUZvcm1hdD0iMjk5N0Ryb3BUaW1lY29kZSIvPgogIDwvcmRmOkRlc2NyaXB0aW9uPgogPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIAo8P3hwYWNrZXQgZW5kPSJ3Ij8+AFRTU0UAAAAPAAADTGF2ZjU4LjI5LjEwMAAAAAAAAAAAAAAA//tUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAAmAAAlaAAHBxQUFBkZHBwcICAgIyMnJyczMzM7O0NDQ0tLUFBQVlZWXl5kZGRpaWlwcH19fYSEjIyMkpKSmZmfn5+mpqarq7CwsLi4uL6+xsbGzc3U1NTc3Nzi4ujo6O7u7vj4/f39//8AAAAATGF2YzU4LjU0AAAAAAAAAAAAAAAAJAJAAAAAAAAAJWjf6z1f//sURAAP8AAAf4AAAAgAAA/wAAABAAAB/gAAACAAAD/AAAAEhDRCABQDzOiGQIAGkK2f+m0xFBeAgB2e//65w07/0//17a3gSSj4AADRmRiCpZ6TS8Xa9XmGk0IWlm+l//ukZB4BUAAAf4AAAAgAAA/wAAABAoAVK4eEQGA7AGSYkAAA3//////11QAYA23f/9t+lCeKaU8gVsWiyotFmopjjbH9RwKMBGx3oG4r///+4ABSK4Y1/ZIS5xnmnFXOFjLC5yWcl+nqaAQQ6AAGdEH0TKsazW+3qOBAfLqqj0bv+1X91FqEgFiAAPLCEGTrIgHM/9GTPPnP+omkBz8cdXAoIAmALO0qZAXJBJSYgUkzKHHD////0kqoDOAZhKRgUACcATn3TNDtTChcc3/+pdRAEekAAREoqCWAYszVTdrpPmguGDXrukEeZgAAVQCEIigRNBdw7ueVJ/Wz8+t/Z0dppEI1BlhAgqNDyQ0BAmQ6DQe6ufXI///RhNBA8BA01AzJU4IeZ/3UgwZAA18Qkwox5EIBYAAHRDRw+YOZo7+eRoQorWSVpQIwBZUbccUMCg+2pMqQQ2v2DVoUp7XJqhlCwBShHA4NMHnhS76QPECb//d///9TqCCSMIgDZMUk1e/p/90u44aezIAIAkYKSLAgxOAYaCTmAUG3IXQfN/QVCRaZ/hSGdZC3/7hkAAtrP9X6mFVSZHlEf/Zr/+gYFlK4AD8wxQk0FwqBigDIAPdDx+GBgbg8EFAFzgPPEf9T//tEZOqBEP8CykkmCAAJ4BlFBAABA5gbKSeMYABeACTkAAAAv+S/6kf+jf///3///9dgSGVgVQQAMAXCCQBAEAgDNfzfLmpYX0LmLy2fwtYEulxKA4P0BcZA/xH4yQWELt/FKCdzCTv/3KxOBcIHoAFgdv//c8MeSRcKpJf/+VDQlCZRGMFgHX///kuOYbNLjLFzl/////J80AwHA4AAoHA4HAoAAQA+//skRP2BEOEDychJABAVIElJFSAAA7QJKSCkAABegSTkJIAAfwMA8A//0/8cZS/9AkCKbEv//YJGFvC/o//+VkNaZh///v////5gaKIKJQgQByYQAZLAACBZv7wEhIKgYyTAyYA5odmiRZsBxv0ZnFBEoQHuwbVW//s0RPQBENYDSckjEAAYYDkoJEAAAtgFKSGAAABfgeVkIIgMbcqZVudwSpZo1xBJA04MZXJ0R1t4ZDABgiTDEexg4uxm8SQoMiFXuaUSw527zjz16DYHj6AdNctoMhZdDTKmsQqKU0OXraXkIYYqR1HvFgY0UeFpTyYf/65Xl7sQIxOLysywowQByWUyVhYM//skRPkBEKICykkjAAgYwIk4JCIBAvQJKSGMAAA9AOUgFIAEZnLAIOyK3UpL/ZfizSXxe868QnFL2lBQOjomsmkqZL5k81Z3nnRalGrrT+/3fzWbO43Ev//3udkjlas/+H/////Lq8vzz/////7kfiDz1qQlQlAY//s0ZPkA0S4ESkkmEAASQBkiBAAABRANJzRgAAAdgGTCgAAAMbMiYtX3DHGnULh2AaG/TNHecesz/PzibutNi4TQnla92pl80atkzQly9dqavYvlI1CRGSa6Wu+ptbd9ToKqvtQYwAC4ot79YNmSzp9LCh470fpo9imhrYIEgskAcQEoC10AWZgoMqZ+mBMo//ukZPsAAz5ZT/4+ABA2KTn9wTQAHOVrVfmtAAFrGSu/HtIAXM41A2FOF9XJihRMU1rQPqRSSSUZj1CIZI+cWgrWha62q0lmpiJ6UTFGtFaaz1Kkuvep6nRMTUyJocLpLVS5NHilS9FS1s7DtLB7v+KAzQys5gqKsdrdCAFgaPFRYROBUFYKukHQVBXb2S3/rBXq//yXnaC6yQaXhP73YBEASkEDXEJP10Pklo5hnHf8m0ZOUlCfMdpvCtNu9fShMdZNP5Bzv1lBlRnNGV2m2WmnXXgwRqYVCOoSYEVu/YLpnIDFKiGlQHQADAoMcKUBuUdLhHKYs/V///RnP+pgd4YGRBA6cmASoRwiB6ZIBIZeVOJQZ3GWtM94CJFtJG/Va7hWwv50exkgCTG7LZvv6Tr+tEqMUWpVf/qf/sH4iHjdgwqvwAPEiD/LWIAIAKIiffYACDQcUbBB0SiWQKRqUhDh1bCSnyv21qY3Ff1TvtAEYAAAHAAACxi5jqn07+Dg6u6B1dOk9y2WrvGIJh5hq+I+ghf2QP1TUtXliiw7ymfRrZlD67I2C2OF//01IiaIECmF5NnHHE3//9HKCCE8RQBEqKZII9SI9TC8swA1pAZOHEAAmnxdz0MQuhd8H4St//t0ZOkAAys72u9hoAgjoAqv4AABCTjPd+eEVmh1AGo8AAAEtERM6IpLqQjkY+Zf/+xptwJDS3/8l9QACAANAcAAAEIAF2DAsEDqBiBoOoEJgHUmz9YZNJSxwyD8agumsp4lKM7dKrbtU954GaUn/8DN8Ys0rBFhvUUP/21sXS8M4X0Lr7///+gVBIAlwIODwPAcJmPxCcWoAAAgAD4AAAFtsMiuetkRojMadDclwXWzeoqCt9DXgQp///1FgAoAGELiMybg1I4rK0oKsPVgQibAm+OhXarCOUZUKvOCxGBgtVeUUeLxWDEYCHJYmQMnRojIEqaEn//fRZEh4uIXE/b///1pC2BfQfY+yyoyQAACsQQ4YAGTlU9L8z+9VqQE//t0ZO8AAmE12XstHOglYFpPYCIBC5TbS65pR+CrD6j08Klsclwy/9///p6mBoLVR//rQAhjAzRhQ+0AFhH0YOD0hj84syQNicITROvQoQHsfyiPxUMSOvZrmT5ixP8bsLd4pfKBZ//+YnTUz9////Ubh2TJxgPYOBWi2RZmHwAAAFFiLWASQ3pIbk0/+m/A/6YGACD4gAAUqTLZsevISUDltDxbojCXbbtPLGFjO1K2xKCHesKGbCoXEyyOSBDDwGJByqf/9bq+shpPkW9v///mYn4UGQh0tolI1bgNgcAEdDv/oxFV4/7CfgnYAAAjACoV2z9Hw4G2ZOlQqLrHcyM6eNKIE0yr6I0iOb+rzHAgx4XOb4+JDMgkGI3mnmC3//t0ZPCBAvAx0eu6afgkI9ntJKKDChzDS67qY+CED6i0YKIk////54Rkxx0UsFgDDDgAAAQLzWT/Tg11n////wQUBVlAzgwpOCAG6CoWAD8tmKW2lObIGYN+rZ1osWHs8JhcVXLTQ5hHnHi9ibeE7PJ6fk/M6ij5vlkbr6/l9oAbGnzJ0///pIUYgBCTw3RODOAAQQPMBQkPyrvR0CrOtmf9v/7eSaAkABIE7wAAokKgLsnJNZICGMCAKAYbZ0l0t2B68OtxaQ1vF+KNeBniEFCsGjAIDSBgXan+ZhGc7OH/iK0HZf5ccgijE5t4JTKozDrliIiDpU4UwLjEyS7RdZE1bDZVbF9tB7jp53//KLOFURQiQQwrgPDUgfJFu9uR//tUZPSAUi4v1vtvamoZAKpfBCYDSVDHTU4OEGAngCh0AAAAoZo/IABpU0ELiBOb818Iv2Rjf/b8rQBUAAAAOlUIQFQA4mACoAaWYrGutZXa8ThR+ZeSchqijNKKGI8sOm5ymeiM8szVujU/ZpJbuJWqt7lWr2rJqhKQMn2o7i4ug8IpD0//9C6nIPDI6JAAosLvRgwAjgEBPAgAAHWFsWzaJmt9LlS3+Cfx5x19X//9B6BLYAEEF0wBLUvnJN9b//tkZOiAEg4vV2tJOyoUgiodBAJFCbS7W+0wrehbgKk8IAAEFSpqyiJ6xH+bcFymHlBKVNFZNIIgcabZiRNtRejAWicSU+k/SYdQccb3obm57q///pPoViEx1kzUxccFskSRgABDggAVliDz0l/+p+o9ib//kaAIgAGLFwAA6RaJlhqcsXBOkEESZeuhdkIfyzXfuGbkN5SksBC73W1yUf/D+UVrydrmk3r/P/hXJWGqf6scYQHQUDvRv///UQgCm7sSbDglAAhAW+In4l//v7NCYDqAAZZHKAFMsE+pmkmVTQxJDUqdtnjoLXnp+SwP//t0ZPEBA7gx1et4VMgYoBptBAAAC0i9Va3g6+h4lqj8IAuEhXlFPgSgQL+2soo7b798vR0tMcXll/0OEIImm9yk1vR////UbDQlCGLOAAAAACgAAAfD////Xy8ACVCIAG/eHABE1grQhYixOEJZNErGGLQSmyZW3jG/SRB3nE3Yxhg7lxr/8Rz5Z9p4XRv////ziMqJspqAAHqh7////KWgGwAAAscAAN1C4hkYU+hZiYxsLawMZQmEloqZep5nWY8BhA5Q8TGiQ/cYCZqt/6AaBQSRzpli3VP///x0aCxND2AAAAMBgABr/8Rij//65AFdVQBU5zlABSgFBIHFGSYgLGhgRyF+rmXa6PHjgCRQJLnTKyWNTFzQT84ggs6i//tkZOsAEkkxVutMgioW4AqPAAABCaC7Va288Sg6gCe0AAAAdW6aaadlp7ZPFE8ebWxsO8uIbVN1W//oLTMzM25MffSRkI50MAACwfWD4IOUCDi4P7sAKBDlw+Jw+P//rD8QKgAAEGA9FgI6ocmUgMADBSCMsFwCng1LdV/GHxCaWByQxiwApmFAbZ2hQwNhzRUBY8BBEC9xUDcAVHLzjKzQhCKABmXIZorrfMQw7SFbn0g2mupIFo1ryqOJbsVeOIxxHmGb6EcsmpguOwO9bs54pgtTZ3P9XXR3DIEUIYOaA1uYjkPqUsGoYv2UxrjE//tUZPMAcjsu1WtvPCoOgCo9GAAAB3C7Z+y9RSglAKfQ8AAA6Iyig4gvGoOy8DGIBKf////8sOfhh9hkheNdcXyjE44n////////////+hpLb3/3ebX5GCgExCNfuVZb5IgKAABhCbYjUzaSMm19viTQ8dQmJdRss/uvk8qcPHrSpnPza1TfgaVXXUD3aUULCwkULlKUf8Y4AEAA2gGMlAUA2gA0uT3ABhJi1NxECDsmpebJaoDCeYsfC68QFMjo//tkZPOAAggvVWtPOWoOQAnMAAAACby9XfWmgCiEAGi2ggAEPCF4DR5LuKqt6DYSsJnrml2ARcr5A4/MV+uCCpnmdlfCpgsKqrRQ7HLLpNxaw6sMRiXoiqmvP6zBuM9D8PMjgYxBWK0d2IwMHXwbAuWDGS3EmmpqMw5G5x3aiAaGrjX3hU2ZLUuU9+pWtOLASwypobpWQsXiO6eDrtLxRu++tPDv/WdEoZ5z//bwMEa8yXL///yy+/l0gKIBACsssAUCeBDAMFAAAOCHO7KUnSeqkj/WB9AKbPRPa74b2Z7amUHuzcbrf12gAGZHZA8Y//ukZPoABf1LVm5zJIBBJFrdwayQF60dYfmcgAC6Cet/AtJADfAWFTzyWHZSgoVEJJsEdhlbHrl2RxG/SpmKA8E1rQUIUShMYIaRkomIxFLLqLGqa2pJUloo/qfSRhpBSR4mt6z3Sbo11F57qVZ3SWjSuqj/5KjBOYNglmCshAHAEbADHvUk9Yh39zP/5V34mdKgqHeQkABRJiABIQhEFwNkBCEOBogpJAF2bSoo3eFaj8WdCLXL2UQezW9asOiUGedbW7DFc6TltP3kdqh1TR/UloLRA+gusmhk1t2U62rWXanU9LrWs1Seitv+ZGsSUZIMN0EAo/HHCAAAwE+oN7FPD/1g8iy//8T+teAGCwAAwPwArAwOEmKhojCjWw0wFgKX9ocTYXFpl8YIiFuHtbao2blzCmvqyBg7bvtkBYKpmSz//Jsb5scR/U7GazMILE6zda6/R6NLY6bFg8XmgXJ+V2R2gQSPQBAAJUZdL60YhwAp3/NymfcAcKCw7/9Rj1u6KAAUTQABLMbgBsZbylBxQZCmXFCEwP5h/mmNG2jtZWnSe10wm7fzuRnI+8rNNDUy2VKITv/QMQWCqsv7TnQCUTjEM0//5wXAJj0hHRoOh4JlAhphg4FgIA8gpyhM//t0ZOGBAus9W39hoAoboAqP4AABC7jzX+0xtGhfAKk0IAAEG2v+id//48t/zeSVwwCUx1M5/puAIyg1YSjlKJFwrir+bC/EMOxFL7vfpeI/7M40M8er1bIyJKVf/FYtPI/80gyAYTNcnt//8bjESdooSBgGAVAJYAgY0JOKIpBJqAAO/er//lXEf9euAAHKHMEu6VwAk6+PYqp0lSwsjWA2VwtcMhWmL5ur3Dsj9A6O8GYpS8cj+J0xuRSA/+iao/+s3RULI0NTIwuutV1pf8zIV0zScNzQAARAIAHggAAwryTca5G5//nX//Py9E//+r+oNqACCgAHwWwBB6VE8HGy9hLeAKiJsw/0+MlAYU7Osrap9D5L1vPrEHukqtWJ//t0ZOgAArsuVetplQof4motCAuRCgzHXe09R+BegOowIIAEqsaoMycMg0f+sagxlJH/nS4UEwqY2jiKA/ms3ucPoHTH/QHaJ0X5qYoMasAAEdAB8CAAOKBBHB+Ezvy6TCfyv/N/8zlXWAAprxMA3juACcoiKp0zU2xAASyjcTE4bWi9mS+Z9QSC2k+I4JBimhtMRgxrblhCvKEB6Z/8mBZE8pUf2Mx6mpiBvGw8dJZaV//9iaUjJNE2JiI7nAAMRaAABxR/RziRoSBOEzPx37dP//2/8GqgAIMpQiT4AQAgUSB3wUSZQGeRy2EiiBoWH6E43lC+UKvD/dbMErJN0y5VErGbnKEznokUBvJqCP9SR8wT/6JuiiDCMGYG5oio//tkZPYAAgIuW/sMOmocgEpvFMAACUDHZ+yxpyB1GSj8EAtE6///MW5qkOAHYDGAHAAAEwt7oZHJ9af7ls/VKyAAxmzghvR3AEXX3bLQofGNAlWeNFiUs5ujafjJUBZYkSkRWpXX+2ooGdvu5OuBo6Qx4ElD5fXwgcp///7dKA+hKiQb1Ur//7JP2+4axsbDSADQAATAOChwALLgoqCzWaOsNf/+qoAAcRYAFPATgBsKQuYCBKHmtBEuliAXpc5itse5qIlsKLeniavr3ukhnrbivs3b27HxQ8Ym7ptv7gMlBr///KOeaZqE1iab1//9//tkZPoAErsyVWtvafgZwLodAAMDCpTJYeytryBikij8cAnUdYiUtbi0jtfUAHkgewMD3cKRQcKAACAAAVfLLOjg67Jf//8t5AEKVKZy8LYAIOmI+KgMEqwEjVWKW9JgbfCUAGlolW6BbM5vtjL4vv9VE8gQ7I7cinCf+9QVB17877KpVojEczFLDOUA5kDBKGAWPTiEruy8j5jBAMY9REdpO4AgwYHguaOKWkiyZDetwZ4zX6jUHNc5OfX0Eh1/8vMbb7Jey+BFppoK8cW+//0IkIDzOPe+AggDT8s/DaADootH2AAAn6kY5HXD/wf+//tkZPCAEoQw1ntPafoUYQodACYlCljDW+09Z6hLgym8ACRM6vQAHQ7ZTv5TAAXkOF9pMeQvKpykDFIYNhK1XBaE8Q+R5tTTV9tVKlNZgql5lSH63vIDirZt/4c4H/9lcUABlEM58CkoQJGYCoYyU+eYGhAS9531fVu/pvEQhVt3J7p8ACqMg4yKDVhlFSjJDGwsnG49itHqfMbXZFIz5r/BQOs0razSInILN/jQ8Ft/5kUg4Bqc/xUAAMAOBh6OQAADE8Q0I63+QX9X1eT0gCETVYn5ZgAGckhrKetKmw6JSUiEQbGuUTKd7KUOKMDr//tkZPEAEsox1ftPWfoUoAp/AAABCHDJZ+wwSaA+gCi4AAAEL2N+2IGpdGYUhoTiogN2/1V3M/tID44FBHjQZPRKNH3EB8EBYAH7nckc9/5o1/9eipAAURoSJ5AHgBqiSGSRyiSCOCCNanQ+hVX5UM4WpkPf9eaNRqbchBjJeMz17OYJ+KskqFdnxr/IKM//dTkCQ1xVnd0YiCBKN/+JmFJMgcDhAAAAHgABivFBAA6gJEPsdqb5/tNf+p1EAAIAUBgGQFwAosoZbEAmBxakVCQblTokjPqPjdnPja3WF/yOQJTWs92mFKTkilMOogyb//tUZPaAEiEkWXsGLRgSIMpdBAYFCEyRY+w8SeBQgCh8AAAAFNGiRs11U9zM66///ng+0Hy6TQz+Wnna8bZO5+nLWiT1oNDEE2U5gDHakMMMV5NFoo1ZOC0KVlQFAgACVSUEJS9GenF/lNrQx/90kJ6AAHMaJQfQJYAmldZJTNHTEIDh91NR9GRQrckc5fN6A/zj0Dyqza/uSnOXJilrUEZl0t/duNVsbqdCih/62WiSIe0TEw9SKoZZ1oZF71Co//tUZO4AgeciWXsPKfoVYCpfCAABCEChY+w856BBAGh0AAAAEHBCFlDuKlkAG6KqLe3YAAEAXiYkbjAi5GNeJUpc+akN9dX1qU76rEAhDtDF7MvgB9VAsmFyhPkkIRJT4fR0oVDgkE3IuoQiHby2iKG0PSq8j02VWLMe230yHOv/nu0jCNEVq9j9F3cwxf6HGtQfDQVwIUZYIRpcAJQStezQSGtaO0WYvFuQ0Z2ur+X6quMgt22CR/t3ACBwcnJh//t0ZOmAAoo1VXtPKnoWYBovAAABDODbT+0t9WBkguh0AIgMD4JrpTNqzqjd5qeMlakuqw9C/iAj2Z50LRIWzle1VVGfWab6Xd2NkDT/6zZpND1UmkyNaLsYKtSczVP4IECOAHCMuYGaObI38bAAFQOYCDwtEIrxPgHt4Yt9ljt2g/P8553ofq/8PIozCXbWRN9pMAF4XHIkaTA/B9OY10y+LXSZPsx3AqtUX0dvGvWCKnLOyMjxJ60y2f6fVypSnqUmhrQ0XrLpofMAzJ0XU1PfZt6a0U0rKg1zUiCQHlHaYu1AACklREXkbQAgW5YbC1sApJZuEvOfP9e78v7/+r/3/X/eyv/U5DQVSrEQiY5XSfVxgAzhb+XRrGoRoiyv//tkZPOAErE11XstHiggIMpfDCMTCTjRW+wtS+hxBKg8xBgsflzFqV4iqKH6XgZF+E8dmHu/xoAzKqnXhKCxUfX135nNtrOM5/dFIXuESoe75jdq3o6HkbLT2OoZTPt1BAVtppDvmtgAto5BSMgxbU5gd3q3Vt20f9f7/2/6+n96v/273+UWOKONoSCXaRM7vWlAGIH/on6QHpO4HuOo/yes0ZcoBYmRPqlmyLPhUE0jRI6uoRqcbKX//Oiq2r//3sUY4gwlqG1zfMs+7UdbpPQ95xolTm0oz0SgpPBo5J+AkAARJC3J8IrXxksXTq3B//t0ZOsAAn0r1/sMa8ol4XoPPGYKCvDZXee02OCiHKi8gIl9ClOqKW/+v9kVSe7PuMXAAHVMYAXrICAUbYx7KMlEWRlJlL25mbEswmqL1jGDLc/U1nH9oRa2TadiRMTbTcGme+VuagigtdXl/P0mG5DKJYg9Asfv702UxRKWvGO21ny41gC1egXWMgATHigsPwSO/z9GnWj9mP/RZmExHMh3dNtgFtCsqLeepIBpiqJPHF1PCRSB5S0gvZsqQ2tXtWrWV9p8RLSuZgR1kZnaoAGCwf/vWIYIKMPpo66v/04lEul5Ulaltu4J90N7UAAEgDBYVUgAI1+hK2yWg/w3Vn/oZ8kLJ0ZqSfQgyHsVTf+R4BRQmJgnRpfqbbFmrrjZ//t0ZO4AAn4t1vnsU9oqRwpPBYVBSfzTV+esT+iPCOf8FYjMSxSvBDeP1T1fUECzijoPkiR2LsgpNaOH3/t/N2S6Pub37DjjZd4tGO+jkdVHp+VOkRPNhn6R+Rmju0sjZ8EikNACpoF5AAMhP94+mmq+oyfbrY4sBcK/DqP5D+xCUX2QA6JQoF9aQQBCIO1pHOac8q9XEvtwzENvFB6BIOyP2kId7fXOLoQUL5N1nA8OGlB47lpc5p6Uaiv2Tcu4aanBFCykKu+Erm6qPiZYce0euvm2pmEoP0iAH7IAGDYHIUCoZBVTTu9R4wLHj2//6MRQt30yL76VsCDQdLNXETU2LAX4UHrRRjt58KeN0rWPIhD/PsGLBuHbLzYmWUU+//tkZPUAApQiU/sPSloXYMn9BAMTCiTZV+eJFqhvA6e8EBhUv/ujyFXS19TFL3TzaA/jGlXTX81FN3vaCSvH163SLYySMg5ymXBAFjlmzAAAYKGOWsF67L5ZaQzQrOs0yJhKNJAM8hQADS2eezd9VIEGSZifKwzoN7g8DJ2w0NN0YDn5dZEHTAgE2JJE+D52Tv/7aQd8xct4/lsi0hWy2OO+ZvrIeR+kNcghBi1+IFoAAB3hXWzwBNq18bhuot6qe1qvqADNSpWAtm1AXf12AB0VkcVKoAwhSglBQqcwEDSQyA/Qi8Jmf92Lg643TftJ//t0ZO+AErc8VfsLG/gewsmsBSJBCzy1S+wxaehSAybwEBgc8pFhtX//pKq///C6xBRjM/+cV266PapNZKF4SHMSlTtYr4ICAC6pMAAAT6VdnVdO3OVO+pfWZkhB1XAAbfESAE5FbdNT65xISTmMcgBJxvcbrUmTw5AeVF3egJREImuKxGEup/+DKcWqfynKwUQCPWZ5t/fZ09zUMurHDhCGF0UoABS4My7fC6hnAQTgs2p80SZIwVczwSBTqOWjYJScN2n+aIAdBLv2gyVTBmJTVEh9GqWbjY0ugy+P4HhqPU2I2LrmY7ibAuLlAj/40ayqdvrIkwqS3y9cdS32091yjWzvb5A+oiTqIAAB0EBGzoSkoJEhI49npJWVVUd9//tkZPuAEqE31XsLG/oXADntDAABCfTFS+wsb+hahKg8kIwsP1f16ZJggnoUW/FJACQpn4MmYYgFiBPSlwuxsX0TRZGMD0+YjitzqFpaoRz26TJVU6jX/1l/+xVCAY41bLT2VrshnMa5yqpIiwoRBFQa7epGFgLLrQCwoss9vuhoQ5YDb/IqpFARaSFN+WAABCBRofgIEoyLrIQQ+VYhKG7Wo6zN/HchzdZFHRuwsw3DULoaMmO4nkZJSlpppqU1SFSv+7mCAgw9UEDZZupkF/3e11Mt2Uks8zrNzFxU4a1vLIa2/PWoAAOnQcCBvDhG//tkZPiAElc01PnrGvoU4CnNJAABCSzVSeycTuhqAyg8ECQMfH96NDghCwMYEcABAIn5RySBEo7DFSEKYCAS6MqwpOp+zNMBAAAAP6IShRU0E1LmmCCY6PuacWjAEGMqMYCAQ/GTOEwyIKUvMEFcWrM8OAACpCJ/kfWopsC0krE0WlOtq3xoD9s8Z6ypl1vm95uateYfxg7R1pLGh9wrneu/Ka9uKOO406/b/T2VNarb/H8ce/uv3Ddampt5Vvyz/H/7/26eny/Pv02PK2P1qv//////595vvP7hzHVWyIQ0Cv8MFHAgUDATBUqdEs7///tUZPyAEjYiU3sJK0oeQMm9MCkDCXjTR+ysrWhKgCe0AAAE////qEyAWeDSGdWZw2wAAAAAAA7PDy2vdviCQp8RAEQmECDyBc0BSO/M6dMN+qqSJlakAAgAYNLPMBcAqVkgNNRfSGxEAVUdCVoDEYqqM/kx96JCmFQDo5y2hvcRYcEUqljw70MeUb1TjyqNJFYy0te9HIr9amt56hKwQlBiAAOqUP+gJNVXC8qDUFX/yj2/T///9cUqAUFriUAu//uUZOiAAs400H1poAomobnNpAgBFw0hSfm8AkCqBqi/DDABgrUeDsQ1TEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVMQU1FMy4xMDBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//tUZOSD8lwZSU8kYAAbgTk54YAAAWwBJwAAACAAAD/AAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZOGP8AAAf4AAAAgAAA/wAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV";
|
|
39654
39835
|
let imInstance = null;
|
|
39836
|
+
let failedLogoutClient = null;
|
|
39837
|
+
let sessionRevision = 0;
|
|
39838
|
+
let sessionQueue = Promise.resolve();
|
|
39839
|
+
let pendingSessionKey = "";
|
|
39840
|
+
const subscribedStores = /* @__PURE__ */ new WeakSet();
|
|
39841
|
+
let activeSessionScope = "";
|
|
39842
|
+
let reloginTimer = null;
|
|
39843
|
+
const enqueueSession = (operation) => {
|
|
39844
|
+
const result = sessionQueue.then(operation, operation);
|
|
39845
|
+
sessionQueue = result.catch(() => {
|
|
39846
|
+
});
|
|
39847
|
+
return result;
|
|
39848
|
+
};
|
|
39655
39849
|
let initPromise = null;
|
|
39656
39850
|
let httpAuthBroken = false;
|
|
39657
39851
|
let syncFinished = false;
|
|
@@ -39671,7 +39865,8 @@ const resolveSyncWaiters = (ok) => {
|
|
|
39671
39865
|
};
|
|
39672
39866
|
const resetSyncState = () => {
|
|
39673
39867
|
syncFinished = false;
|
|
39674
|
-
|
|
39868
|
+
const waiters = syncWaiters.splice(0);
|
|
39869
|
+
waiters.forEach((done) => done(false));
|
|
39675
39870
|
};
|
|
39676
39871
|
const buildConversationFromMessage = (msg, selfUserID) => {
|
|
39677
39872
|
if (!msg) return null;
|
|
@@ -39749,13 +39944,14 @@ const useMessage = (config = {}) => {
|
|
|
39749
39944
|
}
|
|
39750
39945
|
const loginStatus = computed(() => messageStore.loginStatus);
|
|
39751
39946
|
let msgAudioEl = null;
|
|
39947
|
+
let initTimer = null;
|
|
39752
39948
|
const getMsgAudio = () => {
|
|
39753
39949
|
if (!msgAudioEl) {
|
|
39754
39950
|
msgAudioEl = new Audio(newMsgAudioUrl);
|
|
39755
39951
|
}
|
|
39756
39952
|
return msgAudioEl;
|
|
39757
39953
|
};
|
|
39758
|
-
const { updateUserStatus } = useUsers();
|
|
39954
|
+
const { updateUserStatus, resetUsers } = useUsers();
|
|
39759
39955
|
const {
|
|
39760
39956
|
conversationList: conversationList2,
|
|
39761
39957
|
currentConversation: currentConversation2,
|
|
@@ -39767,6 +39963,7 @@ const useMessage = (config = {}) => {
|
|
|
39767
39963
|
} = useConversations();
|
|
39768
39964
|
const {
|
|
39769
39965
|
messageList: messageList2,
|
|
39966
|
+
clearMessageList,
|
|
39770
39967
|
updateMessageList,
|
|
39771
39968
|
updateMessageIsRead,
|
|
39772
39969
|
handleMessage,
|
|
@@ -39781,6 +39978,8 @@ const useMessage = (config = {}) => {
|
|
|
39781
39978
|
onBurn(async (conversationID, clientMsgID) => {
|
|
39782
39979
|
var _a;
|
|
39783
39980
|
if (!conversationID || !clientMsgID) return;
|
|
39981
|
+
const burnScope = imSessionScope(messageStore);
|
|
39982
|
+
const burnRevision = sessionRevision;
|
|
39784
39983
|
const inCurrentList = messageList2.value.some((item) => item.clientMsgID === clientMsgID);
|
|
39785
39984
|
if (inCurrentList) deleteMessageById(clientMsgID);
|
|
39786
39985
|
try {
|
|
@@ -39788,6 +39987,7 @@ const useMessage = (config = {}) => {
|
|
|
39788
39987
|
} catch (error) {
|
|
39789
39988
|
console.error("[IM] 删除焚毁消息失败:", error);
|
|
39790
39989
|
}
|
|
39990
|
+
if (burnRevision !== sessionRevision || burnScope !== imSessionScope(messageStore)) return;
|
|
39791
39991
|
if (inCurrentList) {
|
|
39792
39992
|
const rest = JSON.parse(JSON.stringify(messageList2.value));
|
|
39793
39993
|
saveMessagesToCache(conversationID, rest);
|
|
@@ -39797,6 +39997,7 @@ const useMessage = (config = {}) => {
|
|
|
39797
39997
|
}
|
|
39798
39998
|
try {
|
|
39799
39999
|
const cached = await loadMessagesFromCache(conversationID);
|
|
40000
|
+
if (burnRevision !== sessionRevision || burnScope !== imSessionScope(messageStore)) return;
|
|
39800
40001
|
if ((_a = cached == null ? void 0 : cached.list) == null ? void 0 : _a.length) {
|
|
39801
40002
|
const rest = cached.list.filter((item) => item.clientMsgID !== clientMsgID);
|
|
39802
40003
|
saveMessagesToCache(conversationID, rest);
|
|
@@ -39823,7 +40024,10 @@ const useMessage = (config = {}) => {
|
|
|
39823
40024
|
const getUnReadMessageCount = async (bool = false) => {
|
|
39824
40025
|
if (bool) {
|
|
39825
40026
|
if (!imInstance) return;
|
|
40027
|
+
const countScope = imSessionScope(messageStore);
|
|
40028
|
+
const countRevision = sessionRevision;
|
|
39826
40029
|
const count = await (imInstance == null ? void 0 : imInstance.getTotalUnreadMsgCount());
|
|
40030
|
+
if (countRevision !== sessionRevision || countScope !== imSessionScope(messageStore)) return;
|
|
39827
40031
|
messageStore.setUnReadCount(count || 0);
|
|
39828
40032
|
} else {
|
|
39829
40033
|
const count = conversationList2.value.reduce((pre, cur) => {
|
|
@@ -39853,47 +40057,90 @@ const useMessage = (config = {}) => {
|
|
|
39853
40057
|
}
|
|
39854
40058
|
return bool;
|
|
39855
40059
|
};
|
|
39856
|
-
const
|
|
39857
|
-
if (
|
|
39858
|
-
|
|
39859
|
-
if (
|
|
39860
|
-
|
|
39861
|
-
|
|
39862
|
-
|
|
39863
|
-
|
|
39864
|
-
|
|
39865
|
-
|
|
40060
|
+
const disposeInstance = async (clearData = true) => {
|
|
40061
|
+
if (reloginTimer) clearTimeout(reloginTimer);
|
|
40062
|
+
reloginTimer = null;
|
|
40063
|
+
if (initTimer) clearTimeout(initTimer);
|
|
40064
|
+
initTimer = null;
|
|
40065
|
+
unbindMessageEvent();
|
|
40066
|
+
cancelAllBurns();
|
|
40067
|
+
const previous = imInstance || failedLogoutClient;
|
|
40068
|
+
previous == null ? void 0 : previous.removeAllListeners();
|
|
40069
|
+
let loggedOut = false;
|
|
40070
|
+
try {
|
|
40071
|
+
const result = await (previous == null ? void 0 : previous.logout());
|
|
40072
|
+
if (result === false) throw new Error("IM 退出失败,请重试后再切换");
|
|
40073
|
+
loggedOut = true;
|
|
40074
|
+
} catch (error) {
|
|
40075
|
+
failedLogoutClient = previous;
|
|
40076
|
+
throw error;
|
|
40077
|
+
} finally {
|
|
40078
|
+
if (loggedOut) {
|
|
40079
|
+
previous == null ? void 0 : previous.clearSDK();
|
|
40080
|
+
if (failedLogoutClient === previous) failedLogoutClient = null;
|
|
39866
40081
|
}
|
|
40082
|
+
if (imInstance === previous) imInstance = null;
|
|
40083
|
+
if (typeof window !== "undefined" && window.imInstance === previous) window.imInstance = null;
|
|
39867
40084
|
resetSyncState();
|
|
39868
|
-
if (
|
|
39869
|
-
|
|
39870
|
-
|
|
39871
|
-
|
|
39872
|
-
|
|
39873
|
-
|
|
39874
|
-
|
|
39875
|
-
|
|
39876
|
-
}
|
|
39877
|
-
|
|
39878
|
-
|
|
39879
|
-
|
|
39880
|
-
|
|
39881
|
-
|
|
40085
|
+
if (clearData) {
|
|
40086
|
+
clearConversationList();
|
|
40087
|
+
clearMessageList();
|
|
40088
|
+
resetUsers();
|
|
40089
|
+
messageStore.currentChatId = "";
|
|
40090
|
+
messageStore.remoteConnectUrl = "";
|
|
40091
|
+
messageStore.remoteConnectToken = "";
|
|
40092
|
+
messageStore.isViewingChat = false;
|
|
40093
|
+
}
|
|
40094
|
+
messageStore.setLoginStatus(IM_LOGIN_STATUS.Logout);
|
|
40095
|
+
}
|
|
40096
|
+
};
|
|
40097
|
+
const initIMSDK = async (force = false) => {
|
|
40098
|
+
const snapshot = { ...messageStore.$state, ...normalizeIMIdentity(messageStore) };
|
|
40099
|
+
const scope = imSessionScope(snapshot);
|
|
40100
|
+
if (!scope || !snapshot.imToken) return false;
|
|
40101
|
+
const key = JSON.stringify([scope, snapshot.imToken]);
|
|
40102
|
+
if (initPromise && pendingSessionKey === key) return initPromise;
|
|
40103
|
+
const sameSession = !force && imInstance && activeSessionScope === scope && messageStore.loginStatus === IM_LOGIN_STATUS.Logged && imInstance.imToken === snapshot.imToken;
|
|
40104
|
+
if (sameSession && !initPromise) return true;
|
|
40105
|
+
const revision = ++sessionRevision;
|
|
40106
|
+
pendingSessionKey = key;
|
|
40107
|
+
const operation = enqueueSession(async () => {
|
|
40108
|
+
if (revision !== sessionRevision || imSessionScope(messageStore) !== scope) return false;
|
|
40109
|
+
await disposeInstance(activeSessionScope !== scope);
|
|
40110
|
+
if (revision !== sessionRevision || imSessionScope(messageStore) !== scope) return false;
|
|
40111
|
+
activeSessionScope = scope;
|
|
40112
|
+
const client = new ImKit({
|
|
40113
|
+
userID: snapshot.userID,
|
|
40114
|
+
imToken: snapshot.imToken,
|
|
40115
|
+
chatToken: snapshot.chatToken,
|
|
40116
|
+
imIdentityVersion: snapshot.imIdentityVersion,
|
|
40117
|
+
apiUrl: snapshot.apiUrl,
|
|
40118
|
+
wsUrl: snapshot.wsUrl,
|
|
40119
|
+
platformID: snapshot.platformID,
|
|
40120
|
+
isCurrentSession: () => revision === sessionRevision && imSessionScope(messageStore) === scope
|
|
40121
|
+
});
|
|
40122
|
+
imInstance = client;
|
|
40123
|
+
client.initSDK();
|
|
40124
|
+
bindMessageEvent(client, revision, scope);
|
|
40125
|
+
const loginOk = await client.login();
|
|
40126
|
+
if (revision !== sessionRevision || imSessionScope(messageStore) !== scope) {
|
|
40127
|
+
await disposeInstance(true);
|
|
40128
|
+
return false;
|
|
39882
40129
|
}
|
|
39883
|
-
imInstance == null ? void 0 : imInstance.initSDK();
|
|
39884
|
-
bindMessageEvent();
|
|
39885
|
-
const loginOk = await (imInstance == null ? void 0 : imInstance.login());
|
|
39886
40130
|
if (loginOk !== false) httpAuthBroken = false;
|
|
39887
|
-
window
|
|
40131
|
+
if (typeof window !== "undefined") window.imInstance = client;
|
|
39888
40132
|
return loginOk !== false;
|
|
39889
|
-
})
|
|
40133
|
+
});
|
|
40134
|
+
initPromise = operation;
|
|
39890
40135
|
try {
|
|
39891
|
-
return await
|
|
40136
|
+
return await operation;
|
|
39892
40137
|
} finally {
|
|
39893
|
-
initPromise
|
|
40138
|
+
if (initPromise === operation) {
|
|
40139
|
+
initPromise = null;
|
|
40140
|
+
pendingSessionKey = "";
|
|
40141
|
+
}
|
|
39894
40142
|
}
|
|
39895
40143
|
};
|
|
39896
|
-
let reloginTimer = null;
|
|
39897
40144
|
let reloginAttempts = 0;
|
|
39898
40145
|
let tokenInvalidNotified = false;
|
|
39899
40146
|
let recoveredToken = "";
|
|
@@ -39910,11 +40157,17 @@ const useMessage = (config = {}) => {
|
|
|
39910
40157
|
notifyTokenInvalid({ errMsg: "auto relogin exhausted" });
|
|
39911
40158
|
return;
|
|
39912
40159
|
}
|
|
40160
|
+
const recoveryScope = imSessionScope(messageStore);
|
|
40161
|
+
const recoveryRevision = sessionRevision;
|
|
39913
40162
|
reloginTimer = setTimeout(async () => {
|
|
39914
40163
|
reloginTimer = null;
|
|
40164
|
+
if (recoveryRevision !== sessionRevision || recoveryScope !== imSessionScope(messageStore)) return;
|
|
39915
40165
|
reloginAttempts += 1;
|
|
39916
40166
|
console.warn(`[IM] token 已失效,自动重新登录(第 ${reloginAttempts} 次)`);
|
|
39917
40167
|
const ok = await initIMSDK(true);
|
|
40168
|
+
const recoveryClient = imInstance;
|
|
40169
|
+
const currentRevision = sessionRevision;
|
|
40170
|
+
if (recoveryScope !== imSessionScope(messageStore) || !recoveryClient) return;
|
|
39918
40171
|
if (!ok) {
|
|
39919
40172
|
tryRelogin();
|
|
39920
40173
|
return;
|
|
@@ -39923,7 +40176,9 @@ const useMessage = (config = {}) => {
|
|
|
39923
40176
|
tokenInvalidNotified = false;
|
|
39924
40177
|
try {
|
|
39925
40178
|
await waitForSyncFinish(8e3);
|
|
39926
|
-
|
|
40179
|
+
if (currentRevision !== sessionRevision || recoveryScope !== imSessionScope(messageStore)) return;
|
|
40180
|
+
const list = await recoveryClient.getConversationListSplit(0, 200);
|
|
40181
|
+
if (currentRevision !== sessionRevision || recoveryScope !== imSessionScope(messageStore)) return;
|
|
39927
40182
|
if (list == null ? void 0 : list.length) {
|
|
39928
40183
|
handleConversationList(list, "init", handleMessage);
|
|
39929
40184
|
}
|
|
@@ -39957,34 +40212,31 @@ const useMessage = (config = {}) => {
|
|
|
39957
40212
|
tokenInvalidNotified = false;
|
|
39958
40213
|
tryRelogin();
|
|
39959
40214
|
};
|
|
39960
|
-
const clearInstance = async (
|
|
39961
|
-
|
|
39962
|
-
|
|
39963
|
-
|
|
39964
|
-
|
|
39965
|
-
|
|
39966
|
-
|
|
39967
|
-
|
|
39968
|
-
}
|
|
39969
|
-
resetSyncState();
|
|
39970
|
-
if (bool) {
|
|
39971
|
-
imInstance = null;
|
|
39972
|
-
window.imInstance = null;
|
|
39973
|
-
clearConversationList();
|
|
39974
|
-
}
|
|
39975
|
-
messageStore.setLoginStatus(IM_LOGIN_STATUS.Logout);
|
|
40215
|
+
const clearInstance = async () => {
|
|
40216
|
+
++sessionRevision;
|
|
40217
|
+
pendingSessionKey = "";
|
|
40218
|
+
if (reloginTimer) clearTimeout(reloginTimer);
|
|
40219
|
+
reloginTimer = null;
|
|
40220
|
+
return enqueueSession(async () => {
|
|
40221
|
+
await disposeInstance(true);
|
|
40222
|
+
activeSessionScope = "";
|
|
40223
|
+
});
|
|
39976
40224
|
};
|
|
39977
|
-
const bindMessageEvent = () => {
|
|
39978
|
-
|
|
39979
|
-
|
|
40225
|
+
const bindMessageEvent = (client, revision, scope) => {
|
|
40226
|
+
const isActive = () => revision === sessionRevision && client === imInstance && imSessionScope(messageStore) === scope;
|
|
40227
|
+
const onSessionEvent = (event, handler) => client.on(event, (...args) => {
|
|
40228
|
+
if (isActive()) return handler(...args);
|
|
40229
|
+
});
|
|
40230
|
+
if (!client || !client.on) return;
|
|
40231
|
+
onSessionEvent("im-error", handleImError);
|
|
39980
40232
|
bindUnhandledRejection(handleImError);
|
|
39981
|
-
|
|
40233
|
+
onSessionEvent(CbEvents.OnUserTokenExpired, () => {
|
|
39982
40234
|
console.log("用户授权信息过期,重新登录");
|
|
39983
40235
|
});
|
|
39984
|
-
|
|
40236
|
+
onSessionEvent(CbEvents.OnSelfInfoUpdated, (data) => {
|
|
39985
40237
|
console.log("用户资料更新:", data);
|
|
39986
40238
|
});
|
|
39987
|
-
|
|
40239
|
+
onSessionEvent(CbEvents.OnUserStatusChanged, (data) => {
|
|
39988
40240
|
console.log("用户在线状态变化:", data);
|
|
39989
40241
|
if (data == null ? void 0 : data.userID) {
|
|
39990
40242
|
updateUserStatus([data]);
|
|
@@ -40006,11 +40258,10 @@ const useMessage = (config = {}) => {
|
|
|
40006
40258
|
}
|
|
40007
40259
|
});
|
|
40008
40260
|
const handleSunloginEvent = (data) => {
|
|
40009
|
-
|
|
40010
|
-
|
|
40261
|
+
const info = parseIMBusinessData(data.data);
|
|
40262
|
+
if (!info) return;
|
|
40011
40263
|
const { event, sendUserID, recvUserID, sendUserName, address, session } = info;
|
|
40012
|
-
|
|
40013
|
-
if (sendUserID === currentUserId) return;
|
|
40264
|
+
if (!shouldHandleRemoteNotice(info, messageStore.getUserInfo)) return;
|
|
40014
40265
|
const SUN_EVENTS = {
|
|
40015
40266
|
"create-sl-remote": () => mittBus.emit("createSLRemote", { address, session }),
|
|
40016
40267
|
"apply-sl-control": () => mittBus.emit("applySLControl", { sendUserName, sendUserID, recvUserID }),
|
|
@@ -40024,17 +40275,13 @@ const useMessage = (config = {}) => {
|
|
|
40024
40275
|
if (handler) handler();
|
|
40025
40276
|
};
|
|
40026
40277
|
const handleImNoticeEvent = (data) => {
|
|
40027
|
-
|
|
40028
|
-
|
|
40029
|
-
|
|
40030
|
-
if (event !== "LOGIN_NOTICE") return;
|
|
40031
|
-
const currentUserId = (_a = messageStore.getUserInfo) == null ? void 0 : _a.userID;
|
|
40032
|
-
const curImToken = (_b = messageStore.getUserInfo) == null ? void 0 : _b.imToken;
|
|
40033
|
-
if (sendUserID === currentUserId && imToken !== curImToken) {
|
|
40278
|
+
const info = parseIMBusinessData(data.data);
|
|
40279
|
+
if (!info) return;
|
|
40280
|
+
if (shouldHandleLoginNotice(info, messageStore.getUserInfo)) {
|
|
40034
40281
|
mittBus.emit("LOGOUT_NOTICE");
|
|
40035
40282
|
}
|
|
40036
40283
|
};
|
|
40037
|
-
|
|
40284
|
+
onSessionEvent(CbEvents.OnRecvCustomBusinessMessage, (data) => {
|
|
40038
40285
|
if (data.key === "sunlogin") {
|
|
40039
40286
|
handleSunloginEvent(data);
|
|
40040
40287
|
} else if (data.key === "imNotice") {
|
|
@@ -40044,13 +40291,14 @@ const useMessage = (config = {}) => {
|
|
|
40044
40291
|
const resolveConversationIDs = async (list) => {
|
|
40045
40292
|
var _a;
|
|
40046
40293
|
for (let i3 = 0; i3 < list.length; i3++) {
|
|
40294
|
+
if (!isActive()) return;
|
|
40047
40295
|
const item = list[i3];
|
|
40048
40296
|
let cvsId = getConversationIDBySessionType(item, "sendID");
|
|
40049
40297
|
if (!cvsId) {
|
|
40050
40298
|
let info = null;
|
|
40051
40299
|
if (!httpAuthBroken) {
|
|
40052
40300
|
try {
|
|
40053
|
-
info = await (
|
|
40301
|
+
info = await (client == null ? void 0 : client.getOneConversation(
|
|
40054
40302
|
item.sessionType === IM_CVS_TYPE.Single ? item.sendID : item.groupID,
|
|
40055
40303
|
item == null ? void 0 : item.sessionType
|
|
40056
40304
|
));
|
|
@@ -40058,6 +40306,7 @@ const useMessage = (config = {}) => {
|
|
|
40058
40306
|
console.warn("[IM] 获取会话信息失败,改用消息数据兜底:", error);
|
|
40059
40307
|
}
|
|
40060
40308
|
}
|
|
40309
|
+
if (!isActive()) return;
|
|
40061
40310
|
if (info == null ? void 0 : info.conversationID) {
|
|
40062
40311
|
item.showName = info.showName;
|
|
40063
40312
|
item.faceURL = info.faceURL;
|
|
@@ -40066,7 +40315,8 @@ const useMessage = (config = {}) => {
|
|
|
40066
40315
|
handleConversationList([info], "add", handleMessage);
|
|
40067
40316
|
if (info.ex) {
|
|
40068
40317
|
const clearedEx = preserveBurnInEx("", info.ex);
|
|
40069
|
-
await (
|
|
40318
|
+
await (client == null ? void 0 : client.setConversation({ conversationID: cvsId, ex: clearedEx }));
|
|
40319
|
+
if (!isActive()) return;
|
|
40070
40320
|
info.ex = clearedEx;
|
|
40071
40321
|
}
|
|
40072
40322
|
} else {
|
|
@@ -40101,6 +40351,7 @@ const useMessage = (config = {}) => {
|
|
|
40101
40351
|
for (const [cvsID, items] of grouped) {
|
|
40102
40352
|
try {
|
|
40103
40353
|
const cached = ((_a = await loadMessagesFromCache(cvsID)) == null ? void 0 : _a.list) || [];
|
|
40354
|
+
if (!isActive()) return;
|
|
40104
40355
|
saveMessagesToCache(cvsID, dedupeMessages([...cached, ...items]));
|
|
40105
40356
|
} catch (error) {
|
|
40106
40357
|
console.warn("[IM] 兜底会话消息写入缓存失败:", error);
|
|
@@ -40111,6 +40362,7 @@ const useMessage = (config = {}) => {
|
|
|
40111
40362
|
const curMsgList = [];
|
|
40112
40363
|
const cvs = currentConversation2.value;
|
|
40113
40364
|
for (let i3 = 0; i3 < list.length; i3++) {
|
|
40365
|
+
if (!isActive()) return;
|
|
40114
40366
|
const item = list[i3];
|
|
40115
40367
|
const cvsId = item.conversationID;
|
|
40116
40368
|
if (item.sessionType === IM_CVS_TYPE.Single && (cvs == null ? void 0 : cvs.userID) === item.sendID || item.groupID && cvs.groupID === item.groupID) {
|
|
@@ -40128,11 +40380,13 @@ const useMessage = (config = {}) => {
|
|
|
40128
40380
|
}
|
|
40129
40381
|
return curMsgList;
|
|
40130
40382
|
};
|
|
40131
|
-
|
|
40383
|
+
onSessionEvent(CbEvents.OnRecvNewMessages, async (list) => {
|
|
40132
40384
|
console.log("批量接收消息:", list);
|
|
40133
40385
|
if ((list == null ? void 0 : list.length) > 0) {
|
|
40134
40386
|
await resolveConversationIDs(list);
|
|
40387
|
+
if (!isActive()) return;
|
|
40135
40388
|
await cacheFallbackMessages(list);
|
|
40389
|
+
if (!isActive()) return;
|
|
40136
40390
|
const curMsgList = routeMessages(list);
|
|
40137
40391
|
if (curMsgList.length > 0) {
|
|
40138
40392
|
const cvs = currentConversation2.value;
|
|
@@ -40143,7 +40397,7 @@ const useMessage = (config = {}) => {
|
|
|
40143
40397
|
}
|
|
40144
40398
|
}
|
|
40145
40399
|
});
|
|
40146
|
-
|
|
40400
|
+
onSessionEvent(CbEvents.OnRecvC2CReadReceipt, async (list) => {
|
|
40147
40401
|
if ((list == null ? void 0 : list.length) > 0) {
|
|
40148
40402
|
const cvs = currentConversation2.value;
|
|
40149
40403
|
const curList = list.filter((item) => item.userID === (cvs == null ? void 0 : cvs.userID) && item.sessionType === IM_CVS_TYPE.Single);
|
|
@@ -40158,45 +40412,50 @@ const useMessage = (config = {}) => {
|
|
|
40158
40412
|
setConversationMsgAsRead(cvs.conversationID);
|
|
40159
40413
|
}
|
|
40160
40414
|
});
|
|
40161
|
-
|
|
40415
|
+
onSessionEvent(CbEvents.OnNewRecvMessageRevoked, (data) => {
|
|
40162
40416
|
if (data == null ? void 0 : data.clientMsgID) {
|
|
40163
40417
|
revokeMessage(data);
|
|
40164
40418
|
}
|
|
40165
40419
|
});
|
|
40166
|
-
|
|
40420
|
+
onSessionEvent("updateStatus", (val = 1) => {
|
|
40167
40421
|
console.log("登录状态", val);
|
|
40168
40422
|
messageStore.setLoginStatus(val);
|
|
40169
40423
|
if (val === IM_LOGIN_STATUS.Logged) {
|
|
40170
|
-
setTimeout(() => {
|
|
40424
|
+
initTimer = setTimeout(() => {
|
|
40425
|
+
if (!isActive()) return;
|
|
40171
40426
|
getUnReadMessageCount();
|
|
40172
40427
|
}, 1e3);
|
|
40173
40428
|
} else if (val === IM_LOGIN_STATUS.Logout) {
|
|
40174
40429
|
mittBus.emit("IM_LOGOUT");
|
|
40175
40430
|
}
|
|
40176
40431
|
});
|
|
40177
|
-
|
|
40432
|
+
onSessionEvent(CbEvents.OnSyncServerStart, () => {
|
|
40178
40433
|
console.log("IM 服务端同步开始");
|
|
40179
40434
|
syncFinished = false;
|
|
40180
40435
|
});
|
|
40181
|
-
|
|
40436
|
+
onSessionEvent(CbEvents.OnSyncServerFinish, () => {
|
|
40182
40437
|
console.log("IM 服务端同步完成");
|
|
40183
40438
|
resolveSyncWaiters(true);
|
|
40184
40439
|
mittBus.emit("IM_SYNC_SERVER_FINISH", true);
|
|
40185
40440
|
});
|
|
40186
|
-
|
|
40441
|
+
onSessionEvent(CbEvents.OnSyncServerFailed, (data) => {
|
|
40187
40442
|
console.warn("IM 服务端同步失败:", data);
|
|
40188
40443
|
resolveSyncWaiters(false);
|
|
40189
40444
|
mittBus.emit("IM_SYNC_SERVER_FINISH", false);
|
|
40190
40445
|
});
|
|
40191
|
-
|
|
40446
|
+
onSessionEvent("im-error", async (err) => {
|
|
40447
|
+
if (initTimer) {
|
|
40448
|
+
clearTimeout(initTimer);
|
|
40449
|
+
initTimer = null;
|
|
40450
|
+
}
|
|
40192
40451
|
});
|
|
40193
|
-
|
|
40452
|
+
onSessionEvent(CbEvents.OnConversationChanged, (data) => {
|
|
40194
40453
|
if (Array.isArray(data) && (data == null ? void 0 : data.length)) {
|
|
40195
40454
|
console.log("会话状态改变:", data);
|
|
40196
40455
|
handleConversationList(data, "update", handleMessage);
|
|
40197
40456
|
}
|
|
40198
40457
|
});
|
|
40199
|
-
|
|
40458
|
+
onSessionEvent(CbEvents.OnNewConversation, async (data) => {
|
|
40200
40459
|
console.log("新会话:", data);
|
|
40201
40460
|
if (data == null ? void 0 : data.length) {
|
|
40202
40461
|
const cvsIds = conversationList2.value.map((item) => item.conversationID);
|
|
@@ -40204,7 +40463,8 @@ const useMessage = (config = {}) => {
|
|
|
40204
40463
|
const userIds = newList.filter((item) => item.conversationType === IM_CVS_TYPE.Single).map((item) => item.userID);
|
|
40205
40464
|
let statusInfo = {};
|
|
40206
40465
|
if (userIds.length > 0) {
|
|
40207
|
-
const statusList = await (
|
|
40466
|
+
const statusList = await (client == null ? void 0 : client.subscribeUsersStatus(userIds));
|
|
40467
|
+
if (!isActive()) return;
|
|
40208
40468
|
statusInfo = updateUserStatus(statusList);
|
|
40209
40469
|
}
|
|
40210
40470
|
newList.forEach((item) => {
|
|
@@ -40220,48 +40480,48 @@ const useMessage = (config = {}) => {
|
|
|
40220
40480
|
mittBus.emit("OnNewConversationCreated", data);
|
|
40221
40481
|
}
|
|
40222
40482
|
});
|
|
40223
|
-
|
|
40483
|
+
onSessionEvent(CbEvents.OnGroupInfoChanged, (data) => {
|
|
40224
40484
|
if (data == null ? void 0 : data.groupID) {
|
|
40225
40485
|
mittBus.emit("OnGroupInfoChanged", data);
|
|
40226
40486
|
}
|
|
40227
40487
|
});
|
|
40228
|
-
|
|
40488
|
+
onSessionEvent(CbEvents.OnGroupMemberInfoChanged, (data) => {
|
|
40229
40489
|
if (data == null ? void 0 : data.groupID) {
|
|
40230
40490
|
updateMessageSenderInfo(data);
|
|
40231
40491
|
mittBus.emit("OnGroupMemberInfoChanged", data);
|
|
40232
40492
|
}
|
|
40233
40493
|
});
|
|
40234
|
-
|
|
40494
|
+
onSessionEvent(CbEvents.OnJoinedGroupAdded, (data) => {
|
|
40235
40495
|
if (data == null ? void 0 : data.groupID) {
|
|
40236
40496
|
mittBus.emit("OnJoinedGroupAdded", data.groupID);
|
|
40237
40497
|
}
|
|
40238
40498
|
});
|
|
40239
|
-
|
|
40499
|
+
onSessionEvent(CbEvents.OnGroupMemberAdded, (data) => {
|
|
40240
40500
|
if (data == null ? void 0 : data.groupID) {
|
|
40241
40501
|
mittBus.emit("OnGroupMemberAdded", data);
|
|
40242
40502
|
}
|
|
40243
40503
|
});
|
|
40244
|
-
|
|
40504
|
+
onSessionEvent(CbEvents.OnGroupApplicationAdded, (data) => {
|
|
40245
40505
|
console.log("收到入群申请通知:", data);
|
|
40246
40506
|
mittBus.emit("OnGroupApplicationAdded", data);
|
|
40247
40507
|
});
|
|
40248
|
-
|
|
40508
|
+
onSessionEvent(CbEvents.OnGroupApplicationAccepted, (data) => {
|
|
40249
40509
|
console.log("入群申请被同意:", data);
|
|
40250
40510
|
mittBus.emit("OnGroupApplicationAccepted", data);
|
|
40251
40511
|
});
|
|
40252
|
-
|
|
40512
|
+
onSessionEvent(CbEvents.OnGroupApplicationRejected, (data) => {
|
|
40253
40513
|
console.log("入群申请被拒绝:", data);
|
|
40254
40514
|
mittBus.emit("OnGroupApplicationRejected", data);
|
|
40255
40515
|
});
|
|
40256
|
-
|
|
40516
|
+
onSessionEvent(CbEvents.OnJoinedGroupDeleted, (data) => {
|
|
40257
40517
|
if (data.groupID) {
|
|
40258
40518
|
mittBus.emit("OnJoinedGroupDeleted", data.groupID);
|
|
40259
40519
|
}
|
|
40260
40520
|
});
|
|
40261
|
-
|
|
40521
|
+
onSessionEvent(CbEvents.OnGroupMemberDeleted, (data) => {
|
|
40262
40522
|
mittBus.emit("OnGroupMemberDeleted", data);
|
|
40263
40523
|
});
|
|
40264
|
-
|
|
40524
|
+
onSessionEvent(CbEvents.OnGroupDismissed, (data) => {
|
|
40265
40525
|
if (data && data.groupID) {
|
|
40266
40526
|
data.status = IM_GROUP_STATUS.Dismissed;
|
|
40267
40527
|
mittBus.emit("OnGroupInfoChanged", data);
|
|
@@ -40296,6 +40556,24 @@ const useMessage = (config = {}) => {
|
|
|
40296
40556
|
imInstance.off(CbEvents.OnGroupApplicationAccepted);
|
|
40297
40557
|
imInstance.off(CbEvents.OnGroupApplicationRejected);
|
|
40298
40558
|
};
|
|
40559
|
+
if (!subscribedStores.has(messageStore)) {
|
|
40560
|
+
subscribedStores.add(messageStore);
|
|
40561
|
+
let previousScope = imSessionScope(messageStore);
|
|
40562
|
+
messageStore.$subscribe((_mutation, state) => {
|
|
40563
|
+
let nextScope = "";
|
|
40564
|
+
try {
|
|
40565
|
+
nextScope = imSessionScope(state);
|
|
40566
|
+
} catch {
|
|
40567
|
+
}
|
|
40568
|
+
if (previousScope === nextScope) return;
|
|
40569
|
+
previousScope = nextScope;
|
|
40570
|
+
clearConversationList();
|
|
40571
|
+
clearMessageList();
|
|
40572
|
+
resetUsers();
|
|
40573
|
+
cancelAllBurns();
|
|
40574
|
+
void clearInstance().catch((error) => console.error("[IM] 会话切换清理失败:", error));
|
|
40575
|
+
}, { detached: true, flush: "sync" });
|
|
40576
|
+
}
|
|
40299
40577
|
return {
|
|
40300
40578
|
messageStore,
|
|
40301
40579
|
loginStatus,
|
|
@@ -40308,63 +40586,65 @@ const useMessage = (config = {}) => {
|
|
|
40308
40586
|
};
|
|
40309
40587
|
};
|
|
40310
40588
|
export {
|
|
40311
|
-
|
|
40312
|
-
|
|
40589
|
+
uuidv4 as $,
|
|
40590
|
+
getReplyDetail as A,
|
|
40313
40591
|
BURN_DEFAULT as B,
|
|
40314
|
-
|
|
40315
|
-
|
|
40316
|
-
|
|
40317
|
-
|
|
40318
|
-
|
|
40319
|
-
|
|
40320
|
-
|
|
40321
|
-
|
|
40322
|
-
|
|
40323
|
-
|
|
40324
|
-
|
|
40325
|
-
|
|
40326
|
-
|
|
40327
|
-
|
|
40328
|
-
|
|
40329
|
-
|
|
40330
|
-
|
|
40331
|
-
|
|
40332
|
-
|
|
40333
|
-
|
|
40334
|
-
|
|
40335
|
-
|
|
40336
|
-
|
|
40337
|
-
|
|
40338
|
-
|
|
40339
|
-
|
|
40340
|
-
|
|
40341
|
-
|
|
40342
|
-
|
|
40343
|
-
|
|
40344
|
-
|
|
40345
|
-
|
|
40346
|
-
|
|
40347
|
-
|
|
40348
|
-
|
|
40349
|
-
|
|
40592
|
+
useMsgList as C,
|
|
40593
|
+
throttle as D,
|
|
40594
|
+
isBurnMessage as E,
|
|
40595
|
+
formatBurnRemain as F,
|
|
40596
|
+
isBurned as G,
|
|
40597
|
+
smoothScrollTo as H,
|
|
40598
|
+
IMSessionChangedError as I,
|
|
40599
|
+
getJsonDetail as J,
|
|
40600
|
+
getSelectionText as K,
|
|
40601
|
+
useBurnAfterReading as L,
|
|
40602
|
+
createCvsId as M,
|
|
40603
|
+
dedupeMessages as N,
|
|
40604
|
+
handleUrl as O,
|
|
40605
|
+
handleDate as P,
|
|
40606
|
+
GROUP_JOIN_SOURCE as Q,
|
|
40607
|
+
GROUP_APPLICATION_STATUS as R,
|
|
40608
|
+
useMessage as S,
|
|
40609
|
+
useUsers as T,
|
|
40610
|
+
useConversations as U,
|
|
40611
|
+
useMessageCache as V,
|
|
40612
|
+
mittBus as W,
|
|
40613
|
+
IM_LOGIN_STATUS as X,
|
|
40614
|
+
preserveBurnInEx as Y,
|
|
40615
|
+
buildBurnEx as Z,
|
|
40616
|
+
sleep as _,
|
|
40617
|
+
IM_CVS_TYPE as a,
|
|
40618
|
+
GROUP_VERIFICATION_TYPE as a0,
|
|
40619
|
+
getDefaultExportFromCjs as a1,
|
|
40620
|
+
getMediaDuration as a2,
|
|
40621
|
+
IM_FONT_SIZE as a3,
|
|
40622
|
+
IM_FONT_FAMILY as a4,
|
|
40623
|
+
IM_FONT_STYLE as a5,
|
|
40624
|
+
formatFileSize as a6,
|
|
40625
|
+
isDefaultAvatar as b,
|
|
40626
|
+
getAvatarBg as c,
|
|
40627
|
+
getAvatarText as d,
|
|
40628
|
+
cloneDeep as e,
|
|
40629
|
+
getConversationBurnSetting as f,
|
|
40350
40630
|
getGroupAvatarBg as g,
|
|
40351
|
-
|
|
40352
|
-
|
|
40353
|
-
|
|
40354
|
-
|
|
40355
|
-
|
|
40356
|
-
|
|
40357
|
-
|
|
40358
|
-
|
|
40359
|
-
|
|
40360
|
-
|
|
40361
|
-
|
|
40362
|
-
|
|
40363
|
-
|
|
40631
|
+
useDate as h,
|
|
40632
|
+
imSessionScope as i,
|
|
40633
|
+
isNoticeAgentConversation as j,
|
|
40634
|
+
IM_GROUP_MEMBER_ROLE as k,
|
|
40635
|
+
IM_MSG_TYPE as l,
|
|
40636
|
+
debounce as m,
|
|
40637
|
+
IM_GROUP_STATUS as n,
|
|
40638
|
+
IM_LOGIN_PLATFORM as o,
|
|
40639
|
+
BURN_PRESETS as p,
|
|
40640
|
+
formatBurnDuration as q,
|
|
40641
|
+
requestInstance as r,
|
|
40642
|
+
BURN_MAX as s,
|
|
40643
|
+
BURN_MIN as t,
|
|
40364
40644
|
useChatStore as u,
|
|
40365
|
-
|
|
40366
|
-
|
|
40367
|
-
|
|
40368
|
-
|
|
40369
|
-
|
|
40645
|
+
handleLinks as v,
|
|
40646
|
+
clampBurnDuration as w,
|
|
40647
|
+
copyToClipboard as x,
|
|
40648
|
+
downloadFileByBlob as y,
|
|
40649
|
+
formatSeconds as z
|
|
40370
40650
|
};
|