Files
IM-web-new/dist-local/js/app.js
T

1045 lines
667 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
/******/ (function() { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&setup=true&lang=js":
/*!*************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&setup=true&lang=js ***!
\*************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _components_LoginView_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./components/LoginView.vue */ \"./src/components/LoginView.vue\");\n/* harmony import */ var _components_ChatShell_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./components/ChatShell.vue */ \"./src/components/ChatShell.vue\");\n/* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./stores/session */ \"./src/stores/session.js\");\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'App',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_3__.useSessionStore)();\n (0,vue__WEBPACK_IMPORTED_MODULE_0__.onMounted)(() => {\n session.restore();\n });\n const __returned__ = {\n session,\n onMounted: vue__WEBPACK_IMPORTED_MODULE_0__.onMounted,\n LoginView: _components_LoginView_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n ChatShell: _components_ChatShell_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n get useSessionStore() {\n return _stores_session__WEBPACK_IMPORTED_MODULE_3__.useSessionStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/App.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ChatShell.vue?vue&type=script&setup=true&lang=js":
/*!******************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ChatShell.vue?vue&type=script&setup=true&lang=js ***!
\******************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _sidebar_NavigationRail_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sidebar/NavigationRail.vue */ \"./src/components/sidebar/NavigationRail.vue\");\n/* harmony import */ var _sidebar_ConversationList_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sidebar/ConversationList.vue */ \"./src/components/sidebar/ConversationList.vue\");\n/* harmony import */ var _sidebar_ContactList_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sidebar/ContactList.vue */ \"./src/components/sidebar/ContactList.vue\");\n/* harmony import */ var _chat_ChatPanel_vue__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./chat/ChatPanel.vue */ \"./src/components/chat/ChatPanel.vue\");\n/* harmony import */ var _contacts_ContactPanel_vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./contacts/ContactPanel.vue */ \"./src/components/contacts/ContactPanel.vue\");\n/* harmony import */ var _favorites_FavoriteList_vue__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./favorites/FavoriteList.vue */ \"./src/components/favorites/FavoriteList.vue\");\n/* harmony import */ var _favorites_FavoritePanel_vue__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./favorites/FavoritePanel.vue */ \"./src/components/favorites/FavoritePanel.vue\");\n/* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/stores/conversations */ \"./src/stores/conversations.js\");\n/* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @/stores/navigation */ \"./src/stores/navigation.js\");\n/* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @/stores/contacts */ \"./src/stores/contacts.js\");\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'ChatShell',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_8__.useConversationStore)();\n const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_9__.useNavigationStore)();\n const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_10__.useContactStore)();\n (0,vue__WEBPACK_IMPORTED_MODULE_0__.onMounted)(() => {\n conversations.refreshRemoteConversations();\n contacts.refreshContacts();\n });\n const __returned__ = {\n conversations,\n navigation,\n contacts,\n onMounted: vue__WEBPACK_IMPORTED_MODULE_0__.onMounted,\n NavigationRail: _sidebar_NavigationRail_vue__WEBPACK_IMPORTED_MODULE_1__[\"default\"],\n ConversationList: _sidebar_ConversationList_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n ContactList: _sidebar_ContactList_vue__WEBPACK_IMPORTED_MODULE_3__[\"default\"],\n ChatPanel: _chat_ChatPanel_vue__WEBPACK_IMPORTED_MODULE_4__[\"default\"],\n ContactPanel: _contacts_ContactPanel_vue__WEBPACK_IMPORTED_MODULE_5__[\"default\"],\n FavoriteList: _favorites_FavoriteList_vue__WEBPACK_IMPORTED_MODULE_6__[\"default\"],\n FavoritePanel: _favorites_FavoritePanel_vue__WEBPACK_IMPORTED_MODULE_7__[\"default\"],\n get useConversationStore() {\n return _stores_conversations__WEBPACK_IMPORTED_MODULE_8__.useConversationStore;\n },\n get useNavigationStore() {\n return _stores_navigation__WEBPACK_IMPORTED_MODULE_9__.useNavigationStore;\n },\n get useContactStore() {\n return _stores_contacts__WEBPACK_IMPORTED_MODULE_10__.useContactStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/ChatShell.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/LoginView.vue?vue&type=script&setup=true&lang=js":
/*!******************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/LoginView.vue?vue&type=script&setup=true&lang=js ***!
\******************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! axios */ \"./node_modules/axios/lib/axios.js\");\n/* harmony import */ var jr_qrcode__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! jr-qrcode */ \"./node_modules/jr-qrcode/dist/jr-qrcode.js\");\n/* harmony import */ var jr_qrcode__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(jr_qrcode__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n/* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @/stores/session */ \"./src/stores/session.js\");\n/* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @/services/imClient */ \"./src/services/imClient.js\");\n\n\n\n\n\n\n\nconst QR_CODE_PREFIX_PC_SESSION = 'wildfirechat://pcsession/';\nconst defaultPlatformLogo = '/favicon.ico';\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'LoginView',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_5__.useSessionStore)();\n const view = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('login');\n const loginMode = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('phone');\n const loginAccount = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const loginPassword = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const registerType = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(1);\n const registerForm = (0,vue__WEBPACK_IMPORTED_MODULE_3__.reactive)({\n number: '',\n code: '',\n password: '',\n confirmPassword: '',\n invitationCode: ''\n });\n const sendingCode = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n const info = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const qrStatus = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('idle');\n const qrCodeImage = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const qrSessionToken = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const qrUserName = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const qrUserPortrait = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n let qrGeneration = 0;\n let qrExpireTimer = null;\n const defaultPlatformName = _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.appName;\n const platformName = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(defaultPlatformName);\n const platformLogo = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(defaultPlatformLogo);\n const canSubmitLogin = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => loginAccount.value.length >= 3 && loginPassword.value.length >= 1);\n const canRequestEmailCode = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => registerType.value === 2 && /\\S+@\\S+\\.\\S+/.test(registerForm.number));\n const canSubmitRegister = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (registerForm.password.length < 1 || registerForm.password !== registerForm.confirmPassword) {\n return false;\n }\n if (registerType.value === 2) {\n return canRequestEmailCode.value && registerForm.code.length >= 1;\n }\n return registerForm.number.length >= 5;\n });\n const qrUserInitial = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => String(qrUserName.value || 'U').slice(0, 1).toUpperCase());\n const qrStatusTitle = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (session.connecting || qrStatus.value === 'confirmed') {\n return '正在进入';\n }\n if (qrStatus.value === 'loading') {\n return '正在生成二维码';\n }\n if (qrStatus.value === 'scanned') {\n return qrUserName.value ? `${qrUserName.value} 已扫码` : '已扫码,待确认';\n }\n if (qrStatus.value === 'expired') {\n return '二维码已过期';\n }\n if (qrStatus.value === 'error') {\n return '二维码加载失败';\n }\n return '扫码登录';\n });\n const qrStatusText = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (session.connecting || qrStatus.value === 'confirmed') {\n return '登录信息已确认,正在建立连接';\n }\n if (qrStatus.value === 'loading') {\n return '正在创建扫码登录会话';\n }\n if (qrStatus.value === 'scanned') {\n return '请在手机 App 上确认登录';\n }\n if (qrStatus.value === 'expired') {\n return '请刷新二维码后重新扫码';\n }\n if (qrStatus.value === 'error') {\n return '请稍后重试';\n }\n return '使用已登录的手机 App 扫描二维码';\n });\n const qrRefreshText = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n if (qrStatus.value === 'loading') {\n return '生成中...';\n }\n if (qrStatus.value === 'expired' || qrStatus.value === 'error') {\n return '重新生成二维码';\n }\n return '刷新二维码';\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onMounted)(() => {\n loadPlatformConfig();\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_3__.onBeforeUnmount)(() => {\n stopQrLogin();\n });\n function clearFormMessage() {\n session.error = '';\n info.value = '';\n }\n function setLoginMode(mode) {\n loginMode.value = mode;\n loginAccount.value = '';\n loginPassword.value = '';\n clearFormMessage();\n if (mode === 'qr') {\n startQrLogin();\n return;\n }\n stopQrLogin();\n }\n async function submitLogin() {\n clearFormMessage();\n const type = loginMode.value === 'email' ? 2 : 1;\n await session.loginWithPassword(loginAccount.value, loginPassword.value, type);\n }\n function switchRegisterType(type) {\n registerType.value = type;\n registerForm.number = '';\n registerForm.code = '';\n registerForm.password = '';\n registerForm.confirmPassword = '';\n registerForm.invitationCode = '';\n clearFormMessage();\n }\n async function requestEmailCode() {\n clearFormMessage();\n sendingCode.value = true;\n try {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_6__.imClient.requestAuthCode(registerForm.number);\n info.value = '邮箱验证码已发送,请在当前注册表单中填写后继续。';\n } catch (error) {\n session.error = error.message || '验证码发送失败';\n } finally {\n sendingCode.value = false;\n }\n }\n async function submitRegister() {\n clearFormMessage();\n if (registerForm.password !== registerForm.confirmPassword) {\n session.error = '两次输入的密码不一致';\n return;\n }\n const result = await session.register({\n type: registerType.value,\n number: registerForm.number,\n code: registerType.value === 2 ? registerForm.code : '',\n password: registerForm.password,\n invitationCode: registerForm.invitationCode\n });\n if (result) {\n info.value = '注册成功,正在进入系统。';\n }\n }\n function openRegister() {\n clearFormMessage();\n stopQrLogin();\n view.value = 'register';\n }\n function backToLogin() {\n clearFormMessage();\n loginMode.value = 'phone';\n stopQrLogin();\n view.value = 'login';\n }\n function resetQrState() {\n qrStatus.value = 'idle';\n qrCodeImage.value = '';\n qrSessionToken.value = '';\n qrUserName.value = '';\n qrUserPortrait.value = '';\n }\n function clearQrExpireTimer() {\n if (qrExpireTimer) {\n window.clearTimeout(qrExpireTimer);\n qrExpireTimer = null;\n }\n }\n function stopQrLogin() {\n qrGeneration += 1;\n clearQrExpireTimer();\n resetQrState();\n }\n function refreshQrLogin() {\n startQrLogin(true);\n }\n async function startQrLogin(force = false) {\n if (loginMode.value !== 'qr') {\n return;\n }\n if (!force && qrSessionToken.value && qrCodeImage.value && !['expired', 'error'].includes(qrStatus.value)) {\n return;\n }\n qrGeneration += 1;\n const generation = qrGeneration;\n clearQrExpireTimer();\n clearFormMessage();\n qrStatus.value = 'loading';\n qrCodeImage.value = '';\n qrSessionToken.value = '';\n qrUserName.value = '';\n qrUserPortrait.value = '';\n try {\n const pcSession = await _services_imClient__WEBPACK_IMPORTED_MODULE_6__.imClient.createPcSession();\n if (generation !== qrGeneration || loginMode.value !== 'qr') {\n return;\n }\n const token = String(pcSession.token || '');\n if (!token) {\n throw new Error('服务端没有返回扫码 token');\n }\n qrSessionToken.value = token;\n qrCodeImage.value = jr_qrcode__WEBPACK_IMPORTED_MODULE_2___default().getQrBase64(QR_CODE_PREFIX_PC_SESSION + token);\n qrStatus.value = 'waiting';\n const expireMs = Math.max(30000, Math.min(Number(pcSession.expired || 300000), 300000));\n qrExpireTimer = window.setTimeout(() => {\n if (generation === qrGeneration && qrStatus.value !== 'confirmed' && !session.isAuthenticated) {\n qrStatus.value = 'expired';\n }\n }, expireMs);\n pollQrLogin(generation, token);\n } catch (error) {\n if (generation !== qrGeneration) {\n return;\n }\n qrStatus.value = 'error';\n session.error = error.message || '二维码加载失败';\n }\n }\n async function pollQrLogin(generation, token) {\n try {\n while (generation === qrGeneration && loginMode.value === 'qr' && !session.isAuthenticated) {\n const payload = await _services_imClient__WEBPACK_IMPORTED_MODULE_6__.imClient.loginWithPcSession(token);\n if (generation !== qrGeneration || loginMode.value !== 'qr') {\n return;\n }\n const code = Number(payload.code);\n const data = payload.data || payload.result || {};\n const status = Number(data.status);\n if (code === 0 && data.imToken) {\n qrStatus.value = 'confirmed';\n clearQrExpireTimer();\n await session.completePcSessionLogin(data);\n return;\n }\n if (code === 20042 || status === 1 || status === 3) {\n qrStatus.value = 'scanned';\n qrUserName.value = data.userName || data.displayName || qrUserName.value;\n qrUserPortrait.value = data.portrait || qrUserPortrait.value;\n await delay(1000);\n continue;\n }\n if (status === 0 || code === 13) {\n qrStatus.value = 'waiting';\n await delay(1000);\n continue;\n }\n if (status === 4) {\n qrStatus.value = 'expired';\n session.error = payload.message || '扫码登录已取消';\n return;\n }\n if (payload.message) {\n throw new Error(payload.message);\n }\n await delay(1000);\n }\n } catch (error) {\n if (generation === qrGeneration && loginMode.value === 'qr' && !session.isAuthenticated) {\n qrStatus.value = 'error';\n session.error = error.message || '扫码登录失败';\n }\n }\n }\n function delay(ms) {\n return new Promise(resolve => window.setTimeout(resolve, ms));\n }\n async function loadPlatformConfig() {\n try {\n const response = await axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"].get(_config__WEBPACK_IMPORTED_MODULE_4__.appConfig.platformConfigApi, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '平台配置加载失败');\n }\n const config = response.data?.result || {};\n const name = String(config.platformName || '').trim();\n const logo = String(config.logoUrl || config.logo || '').trim();\n const version = String(config.version || '').trim();\n platformName.value = name || defaultPlatformName;\n platformLogo.value = resolveBrandLogo(logo, version);\n } catch (error) {\n platformName.value = defaultPlatformName;\n platformLogo.value = defaultPlatformLogo;\n }\n applyDocumentBrand();\n }\n function resolveBrandLogo(value, version = '') {\n const logo = String(value || '').trim();\n if (!logo) {\n return defaultPlatformLogo;\n }\n if (/^(https?:|data:|blob:)/i.test(logo)) {\n return appendBrandVersion(logo, version);\n }\n if (logo.startsWith('//')) {\n return appendBrandVersion(`${window.location.protocol}${logo}`, version);\n }\n const base = logo.startsWith('/') ? _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.adminServer : `${_config__WEBPACK_IMPORTED_MODULE_4__.appConfig.adminServer}/`;\n return appendBrandVersion(new URL(logo, base).toString(), version);\n }\n function appendBrandVersion(url, version) {\n if (!version || /^(data:|blob:)/i.test(url)) {\n return url;\n }\n const parsed = new URL(url, window.location.href);\n parsed.searchParams.set('v', version);\n return parsed.toString();\n }\n function applyDocumentBrand() {\n if (typeof document === 'undefined') {\n return;\n }\n document.title = platformName.value || defaultPlatformName;\n let icon = document.querySelector('link[rel=\"icon\"]');\n if (!icon) {\n icon = document.createElement('link');\n icon.setAttribute('rel', 'icon');\n document.head.appendChild(icon);\n }\n icon.setAttribute('href', platformLogo.value || defaultPlatformLogo);\n }\n function handleBrandLogoError() {\n if (platformLogo.value !== defaultPlatformLogo) {\n platformLogo.value = defaultPlatformLogo;\n applyDocumentBrand();\n }\n }\n const __returned__ = {\n session,\n view,\n loginMode,\n loginAccount,\n loginPassword,\n registerType,\n registerForm,\n sendingCode,\n info,\n QR_CODE_PREFIX_PC_SESSION,\n qrStatus,\n qrCodeImage,\n qrSessionToken,\n qrUserName,\n qrUserPortrait,\n get qrGeneration() {\n return qrGeneration;\n },\n set qrGeneration(v) {\n qrGeneration = v;\n },\n get qrExpireTimer() {\n return qrExpireTimer;\n },\n set qrExpireTimer(v) {\n qrExpireTimer = v;\n },\n defaultPlatformName,\n defaultPlatformLogo,\n platformName,\n platformLogo,\n canSubmitLogin,\n canRequestEmailCode,\n canSubmitRegister,\n qrUserInitial,\n qrStatusTitle,\n qrStatusText,\n qrRefreshText,\n clearFormMessage,\n setLoginMode,\n submitLogin,\n switchRegisterType,\n requestEmailCode,\n submitRegister,\n openRegister,\n backToLogin,\n resetQrState,\n clearQrExpireTimer,\n stopQrLogin,\n refreshQrLogin,\n startQrLogin,\n pollQrLogin,\n delay,\n loadPlatformConfig,\n resolveBrandLogo,\n appendBrandVersion,\n applyDocumentBrand,\n handleBrandLogoError,\n get axios() {\n return axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"];\n },\n get jrQRCode() {\n return (jr_qrcode__WEBPACK_IMPORTED_MODULE_2___default());\n },\n computed: vue__WEBPACK_IMPORTED_MODULE_3__.computed,\n onBeforeUnmount: vue__WEBPACK_IMPORTED_MODULE_3__.onBeforeUnmount,\n onMounted: vue__WEBPACK_IMPORTED_MODULE_3__.onMounted,\n reactive: vue__WEBPACK_IMPORTED_MODULE_3__.reactive,\n ref: vue__WEBPACK_IMPORTED_MODULE_3__.ref,\n get appConfig() {\n return _config__WEBPACK_IMPORTED_MODULE_4__.appConfig;\n },\n get useSessionStore() {\n return _stores_session__WEBPACK_IMPORTED_MODULE_5__.useSessionStore;\n },\n get imClient() {\n return _services_imClient__WEBPACK_IMPORTED_MODULE_6__.imClient;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/LoginView.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/ChatPanel.vue?vue&type=script&setup=true&lang=js":
/*!***********************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/ChatPanel.vue?vue&type=script&setup=true&lang=js ***!
\***********************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.set.difference.v2.js */ \"./node_modules/core-js/modules/es.set.difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/es.set.intersection.v2.js */ \"./node_modules/core-js/modules/es.set.intersection.v2.js\");\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/es.set.is-disjoint-from.v2.js */ \"./node_modules/core-js/modules/es.set.is-disjoint-from.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! core-js/modules/es.set.is-subset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-subset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! core-js/modules/es.set.is-superset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-superset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! core-js/modules/es.set.symmetric-difference.v2.js */ \"./node_modules/core-js/modules/es.set.symmetric-difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_10__);\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! core-js/modules/es.set.union.v2.js */ \"./node_modules/core-js/modules/es.set.union.v2.js\");\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _MessageList_vue__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./MessageList.vue */ \"./src/components/chat/MessageList.vue\");\n/* harmony import */ var _MessageComposer_vue__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./MessageComposer.vue */ \"./src/components/chat/MessageComposer.vue\");\n/* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @/services/imClient */ \"./src/services/imClient.js\");\n/* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @/stores/conversations */ \"./src/stores/conversations.js\");\n/* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @/stores/contacts */ \"./src/stores/contacts.js\");\n/* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @/stores/session */ \"./src/stores/session.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'ChatPanel',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_16__.useConversationStore)();\n const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_17__.useContactStore)();\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_18__.useSessionStore)();\n const activeConversation = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => conversations.activeConversation);\n const groupMenuOpen = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)(false);\n const singleProfileOpen = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)(false);\n const singleAliasDraft = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const singleProfileSaving = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)(false);\n const singleProfileNotice = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const singleProfileError = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const groupPanel = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const groupBusy = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)(false);\n const groupDetail = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)(null);\n const groupMembers = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)([]);\n const groupAliasDraft = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const manageSection = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const selectedAdminIds = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)([]);\n const selectedKickIds = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)([]);\n const transferTargetId = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const profileDraft = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)({\n name: '',\n announcement: '',\n welcomeText: ''\n });\n const muteDraft = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)({\n mode: 'off',\n scheduleType: 'once',\n startsAtLocal: '',\n endsAtLocal: '',\n dailyStart: '09:00',\n dailyEnd: '18:00'\n });\n const muteSaveNotice = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const muteSaveError = (0,vue__WEBPACK_IMPORTED_MODULE_12__.ref)('');\n const singlePeerId = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n if (!activeConversation.value || isGroupConversation.value) {\n return '';\n }\n return String(activeConversation.value.target || activeConversation.value.raw?.target || activeConversation.value.id?.replace(/^single-/, '') || '');\n });\n const singleContact = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n const peerId = singlePeerId.value;\n if (!peerId) {\n return null;\n }\n return contacts.contacts.find(contact => String(contact.uid || contact.id || '') === peerId) || null;\n });\n const singleProfile = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n const contact = singleContact.value;\n const conversation = activeConversation.value || {};\n const rawUser = contact?.rawUser || {};\n const displayName = contact?.alias || rawUser.displayName || rawUser.name || contact?.title || conversation.title || singlePeerId.value || '未知用户';\n const rawName = rawUser.displayName || rawUser.name || contact?.title || conversation.title || '';\n return {\n uid: singlePeerId.value,\n displayName,\n rawName,\n mobile: rawUser.mobile || conversation.raw?.mobile || '',\n address: rawUser.address || conversation.raw?.address || '',\n portrait: contact?.portrait || conversation.portrait || '',\n avatarText: String(displayName || '?').slice(0, 1).toUpperCase(),\n alias: contact?.alias || ''\n };\n });\n const isGroupConversation = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n return ['group', 'channel'].includes(activeConversation.value?.type) || activeConversation.value?.raw?.type === 'group';\n });\n const currentGroupRole = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n return groupDetail.value?.myRole || activeConversation.value?.role || activeConversation.value?.raw?.role || '';\n });\n const isGroupOwner = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => currentGroupRole.value === 'owner');\n const canManageGroup = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => ['owner', 'admin'].includes(currentGroupRole.value));\n const adminCandidateMembers = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => groupMembers.value.filter(member => member.role !== 'owner'));\n const transferableMembers = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => groupMembers.value.filter(member => member.role !== 'owner'));\n const messageDetail = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => conversations.messageDetail || null);\n const messageDetailGroup = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => messageDetail.value?.group || null);\n const isMessageDetailGroup = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n return messageDetail.value?.conversationType === 'group' || Boolean(messageDetail.value?.group);\n });\n const messageDetailCounts = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n return messageDetailGroup.value?.counts || {\n read: 0,\n unread: 0,\n undelivered: 0,\n total: 0\n };\n });\n const kickCandidateMembers = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n return groupMembers.value.filter(member => {\n if (member.uid === session.userId || member.role === 'owner') {\n return false;\n }\n if (currentGroupRole.value === 'admin') {\n return member.role === 'member';\n }\n return currentGroupRole.value === 'owner';\n });\n });\n const statusText = (0,vue__WEBPACK_IMPORTED_MODULE_12__.computed)(() => {\n if (activeConversation.value?.type === 'channel' && !conversations.canSendActiveConversation) {\n return '公告群,仅管理员可发言';\n }\n return session.connectionStatusText || (session.connected ? '已连接' : '未连接');\n });\n function formatDetailTime(value) {\n const timestamp = Number(value || 0);\n if (!timestamp) {\n return '暂无';\n }\n return new Intl.DateTimeFormat('zh-CN', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false,\n timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone\n }).format(timestamp);\n }\n function detailMemberName(member) {\n return member?.name || member?.displayName || member?.rawName || member?.uid || '-';\n }\n function detailMemberAvatar(member) {\n return String(detailMemberName(member) || '?').slice(0, 1).toUpperCase();\n }\n function detailRoleLabel(role) {\n if (role === 'owner') {\n return '群主';\n }\n if (role === 'admin') {\n return '管理员';\n }\n return '';\n }\n function closeGroupMenu() {\n groupMenuOpen.value = false;\n }\n function toggleGroupMenu() {\n if (!isGroupConversation.value) {\n return;\n }\n groupMenuOpen.value = !groupMenuOpen.value;\n }\n async function openSingleProfile() {\n if (!activeConversation.value || isGroupConversation.value) {\n return;\n }\n closeGroupMenu();\n singleProfileNotice.value = '';\n singleProfileError.value = '';\n singleAliasDraft.value = singleProfile.value.alias || '';\n singleProfileOpen.value = true;\n contacts.refreshContacts().then(() => {\n if (singleProfileOpen.value) {\n singleAliasDraft.value = singleProfile.value.alias || '';\n }\n }).catch(() => {});\n }\n function closeSingleProfile() {\n if (singleProfileSaving.value) {\n return;\n }\n singleProfileOpen.value = false;\n singleProfileNotice.value = '';\n singleProfileError.value = '';\n }\n async function saveSingleAlias() {\n const peerId = singleProfile.value.uid;\n if (!peerId || singleProfileSaving.value) {\n return;\n }\n singleProfileSaving.value = true;\n singleProfileNotice.value = '';\n singleProfileError.value = '';\n try {\n const ok = await contacts.updateContactAlias(peerId, singleAliasDraft.value);\n if (!ok) {\n singleProfileError.value = contacts.actionError || '备注名修改失败';\n return;\n }\n await contacts.refreshContacts({\n force: true\n }).catch(() => {});\n const refreshedContact = contacts.contacts.find(contact => String(contact.uid || contact.id || '') === peerId) || singleContact.value;\n const nextTitle = refreshedContact?.title || singleAliasDraft.value || singleProfile.value.rawName || singleProfile.value.displayName || peerId;\n conversations.upsertConversation({\n ...activeConversation.value,\n title: nextTitle,\n portrait: refreshedContact?.portrait || activeConversation.value?.portrait || '',\n avatarText: String(nextTitle || '?').slice(0, 1).toUpperCase(),\n raw: {\n ...(activeConversation.value?.raw || {}),\n target: peerId,\n mobile: refreshedContact?.rawUser?.mobile || activeConversation.value?.raw?.mobile || '',\n address: refreshedContact?.rawUser?.address || activeConversation.value?.raw?.address || '',\n alias: refreshedContact?.alias || singleAliasDraft.value\n }\n });\n singleAliasDraft.value = refreshedContact?.alias || singleAliasDraft.value;\n singleProfileNotice.value = '备注名已保存';\n } catch (error) {\n singleProfileError.value = error.message || '备注名修改失败';\n } finally {\n singleProfileSaving.value = false;\n }\n }\n function handleSenderProfileUpdated() {\n contacts.refreshContacts({\n force: true\n }).catch(() => {});\n conversations.syncActiveMessages({\n allowReadReceipt: true\n });\n if (groupPanel.value === 'members') {\n loadGroupMembers();\n }\n }\n function closeGroupPanel() {\n groupPanel.value = '';\n groupBusy.value = false;\n clearMuteSaveFeedback();\n }\n async function loadGroupDetail() {\n if (!session.userId || !activeConversation.value?.target) {\n return null;\n }\n groupBusy.value = true;\n try {\n groupDetail.value = await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.getGroupDetail(session.userId, activeConversation.value.target);\n return groupDetail.value;\n } catch (error) {\n conversations.setActionError(error.message || '群资料加载失败');\n return null;\n } finally {\n groupBusy.value = false;\n }\n }\n async function openGroupOverview() {\n if (!isGroupConversation.value) {\n return;\n }\n closeGroupMenu();\n groupPanel.value = 'overview';\n await loadGroupDetail();\n }\n async function openGroupMembers() {\n closeGroupMenu();\n groupPanel.value = 'members';\n await loadGroupMembers();\n }\n async function loadGroupMembers() {\n groupBusy.value = true;\n try {\n groupMembers.value = await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.getGroupMembers(session.userId, activeConversation.value.target);\n selectedAdminIds.value = groupMembers.value.filter(member => member.role === 'admin').map(member => member.uid);\n return groupMembers.value;\n } catch (error) {\n conversations.setActionError(error.message || '群员加载失败');\n return [];\n } finally {\n groupBusy.value = false;\n }\n }\n async function openGroupAlias() {\n closeGroupMenu();\n groupPanel.value = 'alias';\n const detail = await loadGroupDetail();\n groupAliasDraft.value = detail?.myAlias || '';\n }\n function msToLocalInput(value) {\n const timestamp = Number(value || 0);\n if (!timestamp) {\n return '';\n }\n const date = new Date(timestamp);\n const local = new Date(date.getTime() - date.getTimezoneOffset() * 60000);\n return local.toISOString().slice(0, 16);\n }\n function localInputToMs(value) {\n return value ? new Date(value).getTime() : 0;\n }\n function prepareManagementDrafts() {\n clearMuteSaveFeedback();\n profileDraft.value = {\n name: groupDetail.value?.name || activeConversation.value?.title || '',\n announcement: groupDetail.value?.announcement || '',\n welcomeText: groupDetail.value?.welcomeText || ''\n };\n const setting = groupDetail.value?.muteSetting || {};\n muteDraft.value = {\n mode: setting.mode || 'off',\n scheduleType: setting.scheduleType || 'once',\n startsAtLocal: msToLocalInput(setting.startsAtMs),\n endsAtLocal: msToLocalInput(setting.endsAtMs),\n dailyStart: setting.dailyStart || '09:00',\n dailyEnd: setting.dailyEnd || '18:00'\n };\n }\n function clearMuteSaveFeedback() {\n muteSaveNotice.value = '';\n muteSaveError.value = '';\n }\n async function openGroupManage() {\n if (!canManageGroup.value) {\n return;\n }\n closeGroupMenu();\n groupPanel.value = 'manage';\n manageSection.value = isGroupOwner.value ? 'admins' : 'profile';\n await loadGroupDetail();\n prepareManagementDrafts();\n await loadGroupMembers();\n }\n async function openTransferGroup() {\n groupPanel.value = 'transfer';\n transferTargetId.value = '';\n await loadGroupMembers();\n }\n async function saveGroupAlias() {\n if (!activeConversation.value?.target || groupBusy.value) {\n return;\n }\n groupBusy.value = true;\n try {\n const alias = await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.updateGroupAlias(session.userId, activeConversation.value.target, groupAliasDraft.value);\n groupDetail.value = {\n ...(groupDetail.value || {}),\n myAlias: alias\n };\n conversations.setActionNotice('本群昵称已保存');\n closeGroupPanel();\n } catch (error) {\n conversations.setActionError(error.message || '本群昵称保存失败');\n } finally {\n groupBusy.value = false;\n }\n }\n function toggleAdmin(userId) {\n const selected = new Set(selectedAdminIds.value);\n if (selected.has(userId)) {\n selected.delete(userId);\n } else {\n selected.add(userId);\n }\n selectedAdminIds.value = Array.from(selected);\n }\n function toggleKick(userId) {\n const selected = new Set(selectedKickIds.value);\n if (selected.has(userId)) {\n selected.delete(userId);\n } else {\n selected.add(userId);\n }\n selectedKickIds.value = Array.from(selected);\n }\n async function saveGroupAdmins() {\n if (!activeConversation.value?.target || groupBusy.value) {\n return;\n }\n groupBusy.value = true;\n try {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.setGroupAdmins(session.userId, activeConversation.value.target, selectedAdminIds.value);\n groupMembers.value = groupMembers.value.map(member => {\n if (member.role === 'owner') {\n return member;\n }\n return {\n ...member,\n role: selectedAdminIds.value.includes(member.uid) ? 'admin' : 'member'\n };\n });\n conversations.setActionNotice('管理员已更新');\n } catch (error) {\n conversations.setActionError(error.message || '管理员设置失败');\n } finally {\n groupBusy.value = false;\n }\n }\n async function saveGroupProfile() {\n if (!activeConversation.value?.target || groupBusy.value) {\n return;\n }\n groupBusy.value = true;\n try {\n const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.updateGroupProfile(session.userId, activeConversation.value.target, profileDraft.value);\n groupDetail.value = {\n ...(groupDetail.value || {}),\n name: result.name,\n announcement: result.announcement,\n welcomeText: result.welcomeText\n };\n conversations.upsertConversation({\n ...activeConversation.value,\n title: result.name,\n avatarText: String(result.name || '?').slice(0, 1).toUpperCase(),\n updatedAt: Number(result.updatedAt || Date.now())\n });\n conversations.setActionNotice('群资料已保存');\n } catch (error) {\n conversations.setActionError(error.message || '群资料保存失败');\n } finally {\n groupBusy.value = false;\n }\n }\n async function kickSelectedMembers() {\n if (!selectedKickIds.value.length || groupBusy.value) {\n return;\n }\n if (!window.confirm('确认将所选成员移出群组?')) {\n return;\n }\n groupBusy.value = true;\n try {\n const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.kickGroupMembers(session.userId, activeConversation.value.target, selectedKickIds.value);\n const removed = new Set(result.removedIds || selectedKickIds.value);\n groupMembers.value = groupMembers.value.filter(member => !removed.has(member.uid));\n selectedKickIds.value = [];\n conversations.setActionNotice('已移出群组');\n } catch (error) {\n conversations.setActionError(error.message || '踢人失败');\n } finally {\n groupBusy.value = false;\n }\n }\n async function saveMuteSetting() {\n if (!activeConversation.value?.target || groupBusy.value) {\n return;\n }\n clearMuteSaveFeedback();\n groupBusy.value = true;\n try {\n const setting = await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.updateGroupMuteSetting(session.userId, activeConversation.value.target, {\n mode: muteDraft.value.mode,\n scheduleType: muteDraft.value.scheduleType,\n startsAtMs: localInputToMs(muteDraft.value.startsAtLocal),\n endsAtMs: localInputToMs(muteDraft.value.endsAtLocal),\n dailyStart: muteDraft.value.dailyStart,\n dailyEnd: muteDraft.value.dailyEnd\n });\n groupDetail.value = {\n ...(groupDetail.value || {}),\n muteSetting: setting\n };\n muteSaveNotice.value = '禁言设置已保存';\n } catch (error) {\n muteSaveError.value = error.message || '禁言设置保存失败';\n } finally {\n groupBusy.value = false;\n }\n }\n async function leaveCurrentGroup() {\n if (!activeConversation.value || groupBusy.value) {\n return;\n }\n if (!window.confirm('确认退出该群组?')) {\n return;\n }\n groupBusy.value = true;\n const ok = await conversations.leaveGroup(activeConversation.value);\n groupBusy.value = false;\n if (ok) {\n closeGroupPanel();\n }\n }\n async function dismissCurrentGroup() {\n if (!activeConversation.value || groupBusy.value) {\n return;\n }\n if (!window.confirm('确认解散该群组?所有成员都将不可继续使用该群。')) {\n return;\n }\n groupBusy.value = true;\n const ok = await conversations.dismissGroup(activeConversation.value);\n groupBusy.value = false;\n if (ok) {\n closeGroupPanel();\n }\n }\n async function transferCurrentGroup() {\n if (!activeConversation.value?.target || !transferTargetId.value || groupBusy.value) {\n return;\n }\n if (!window.confirm('确认将群主转让给该成员?')) {\n return;\n }\n groupBusy.value = true;\n try {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient.transferGroup(session.userId, activeConversation.value.target, transferTargetId.value);\n groupDetail.value = {\n ...(groupDetail.value || {}),\n myRole: 'member'\n };\n activeConversation.value.role = 'member';\n if (activeConversation.value.raw) {\n activeConversation.value.raw.role = 'member';\n }\n conversations.setActionNotice('群组已转让');\n closeGroupPanel();\n conversations.refreshRemoteConversations();\n } catch (error) {\n conversations.setActionError(error.message || '转让群组失败');\n } finally {\n groupBusy.value = false;\n }\n }\n function memberAvatar(member) {\n return String(member.displayName || member.uid || '?').slice(0, 1).toUpperCase();\n }\n document.addEventListener('click', closeGroupMenu);\n (0,vue__WEBPACK_IMPORTED_MODULE_12__.onBeforeUnmount)(() => {\n document.removeEventListener('click', closeGroupMenu);\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_12__.watch)(() => activeConversation.value?.id, () => {\n closeGroupMenu();\n closeSingleProfile();\n closeGroupPanel();\n groupDetail.value = null;\n groupMembers.value = [];\n groupAliasDraft.value = '';\n selectedAdminIds.value = [];\n selectedKickIds.value = [];\n transferTargetId.value = '';\n manageSection.value = '';\n });\n const __returned__ = {\n conversations,\n contacts,\n session,\n activeConversation,\n groupMenuOpen,\n singleProfileOpen,\n singleAliasDraft,\n singleProfileSaving,\n singleProfileNotice,\n singleProfileError,\n groupPanel,\n groupBusy,\n groupDetail,\n groupMembers,\n groupAliasDraft,\n manageSection,\n selectedAdminIds,\n selectedKickIds,\n transferTargetId,\n profileDraft,\n muteDraft,\n muteSaveNotice,\n muteSaveError,\n singlePeerId,\n singleContact,\n singleProfile,\n isGroupConversation,\n currentGroupRole,\n isGroupOwner,\n canManageGroup,\n adminCandidateMembers,\n transferableMembers,\n messageDetail,\n messageDetailGroup,\n isMessageDetailGroup,\n messageDetailCounts,\n kickCandidateMembers,\n statusText,\n formatDetailTime,\n detailMemberName,\n detailMemberAvatar,\n detailRoleLabel,\n closeGroupMenu,\n toggleGroupMenu,\n openSingleProfile,\n closeSingleProfile,\n saveSingleAlias,\n handleSenderProfileUpdated,\n closeGroupPanel,\n loadGroupDetail,\n openGroupOverview,\n openGroupMembers,\n loadGroupMembers,\n openGroupAlias,\n msToLocalInput,\n localInputToMs,\n prepareManagementDrafts,\n clearMuteSaveFeedback,\n openGroupManage,\n openTransferGroup,\n saveGroupAlias,\n toggleAdmin,\n toggleKick,\n saveGroupAdmins,\n saveGroupProfile,\n kickSelectedMembers,\n saveMuteSetting,\n leaveCurrentGroup,\n dismissCurrentGroup,\n transferCurrentGroup,\n memberAvatar,\n computed: vue__WEBPACK_IMPORTED_MODULE_12__.computed,\n onBeforeUnmount: vue__WEBPACK_IMPORTED_MODULE_12__.onBeforeUnmount,\n ref: vue__WEBPACK_IMPORTED_MODULE_12__.ref,\n watch: vue__WEBPACK_IMPORTED_MODULE_12__.watch,\n MessageList: _MessageList_vue__WEBPACK_IMPORTED_MODULE_13__[\"default\"],\n MessageComposer: _MessageComposer_vue__WEBPACK_IMPORTED_MODULE_14__[\"default\"],\n get imClient() {\n return _services_imClient__WEBPACK_IMPORTED_MODULE_15__.imClient;\n },\n get useConversationStore() {\n return _stores_conversations__WEBPACK_IMPORTED_MODULE_16__.useConversationStore;\n },\n get useContactStore() {\n return _stores_contacts__WEBPACK_IMPORTED_MODULE_17__.useContactStore;\n },\n get useSessionStore() {\n return _stores_session__WEBPACK_IMPORTED_MODULE_18__.useSessionStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/ChatPanel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageComposer.vue?vue&type=script&setup=true&lang=js":
/*!*****************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageComposer.vue?vue&type=script&setup=true&lang=js ***!
\*****************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'MessageComposer',\n props: {\n disabled: {\n type: Boolean,\n default: false\n },\n quoteMessage: {\n type: Object,\n default: null\n }\n },\n emits: ['send', 'send-attachment', 'cancel-quote'],\n setup(__props, {\n expose: __expose,\n emit: __emit\n }) {\n __expose();\n const props = __props;\n const emit = __emit;\n const text = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)('');\n const emojiOpen = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)(false);\n const dropActive = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)(false);\n const textareaEl = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)(null);\n const imageInput = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)(null);\n const fileInput = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)(null);\n let dragDepth = 0;\n const emojiList = ['😀', '😄', '😂', '😊', '😍', '😘', '😎', '😢', '😡', '👍', '🙏', '👏', '💪', '🎉', '❤️', '🔥', '🌹', '☕', '✅', '⭐', '💰', '🎁', '🤝', '👌'];\n function submit() {\n const value = text.value.trim();\n if (!value) {\n return;\n }\n emit('send', value);\n text.value = '';\n emojiOpen.value = false;\n }\n function toggleEmojiPicker() {\n emojiOpen.value = !emojiOpen.value;\n }\n function insertEmoji(emoji) {\n const element = textareaEl.value;\n if (!element) {\n text.value += emoji;\n return;\n }\n const start = element.selectionStart ?? text.value.length;\n const end = element.selectionEnd ?? text.value.length;\n text.value = `${text.value.slice(0, start)}${emoji}${text.value.slice(end)}`;\n requestAnimationFrame(() => {\n element.focus();\n const cursor = start + emoji.length;\n element.setSelectionRange(cursor, cursor);\n });\n }\n function chooseImage() {\n imageInput.value?.click();\n }\n function chooseFile() {\n fileInput.value?.click();\n }\n function attachmentTypeForFile(file, fallbackType = 'file') {\n if (file?.type?.startsWith('image/')) {\n return 'image';\n }\n return fallbackType === 'image' ? 'image' : 'file';\n }\n function emitFiles(files, fallbackType = 'file') {\n if (props.disabled) {\n return;\n }\n const validFiles = Array.from(files || []).filter(file => file instanceof File && file.size > 0);\n if (!validFiles.length) {\n return;\n }\n const caption = text.value.trim();\n validFiles.forEach((file, index) => {\n emit('send-attachment', {\n type: attachmentTypeForFile(file, fallbackType),\n file,\n text: index === 0 ? caption : ''\n });\n });\n text.value = '';\n emojiOpen.value = false;\n }\n function selectAttachment(event, type) {\n const input = event.target;\n const files = input.files ? Array.from(input.files) : [];\n input.value = '';\n if (!files.length || props.disabled) {\n return;\n }\n emitFiles(files, type);\n }\n function hasDraggedFiles(event) {\n const types = Array.from(event.dataTransfer?.types || []);\n return types.includes('Files');\n }\n function handleDragEnter(event) {\n if (props.disabled || !hasDraggedFiles(event)) {\n return;\n }\n dragDepth += 1;\n dropActive.value = true;\n event.dataTransfer.dropEffect = 'copy';\n }\n function handleDragOver(event) {\n if (props.disabled || !hasDraggedFiles(event)) {\n return;\n }\n dropActive.value = true;\n event.dataTransfer.dropEffect = 'copy';\n }\n function handleDragLeave() {\n dragDepth = Math.max(0, dragDepth - 1);\n if (dragDepth === 0) {\n dropActive.value = false;\n }\n }\n function filesFromDataTransfer(dataTransfer) {\n const items = Array.from(dataTransfer?.items || []);\n const files = items.filter(item => item.kind === 'file' && !item.webkitGetAsEntry?.()?.isDirectory).map(item => item.getAsFile()).filter(Boolean);\n if (files.length) {\n return files;\n }\n return Array.from(dataTransfer?.files || []);\n }\n function handleDrop(event) {\n dragDepth = 0;\n dropActive.value = false;\n if (props.disabled) {\n return;\n }\n emitFiles(filesFromDataTransfer(event.dataTransfer));\n }\n function imageFilesFromClipboard(clipboardData) {\n return Array.from(clipboardData?.items || []).filter(item => item.kind === 'file' && item.type.startsWith('image/')).map(item => item.getAsFile()).filter(Boolean);\n }\n function handlePaste(event) {\n if (props.disabled) {\n return;\n }\n const imageFiles = imageFilesFromClipboard(event.clipboardData);\n if (!imageFiles.length) {\n return;\n }\n event.preventDefault();\n emitFiles(imageFiles, 'image');\n }\n const __returned__ = {\n props,\n emit,\n text,\n emojiOpen,\n dropActive,\n textareaEl,\n imageInput,\n fileInput,\n get dragDepth() {\n return dragDepth;\n },\n set dragDepth(v) {\n dragDepth = v;\n },\n emojiList,\n submit,\n toggleEmojiPicker,\n insertEmoji,\n chooseImage,\n chooseFile,\n attachmentTypeForFile,\n emitFiles,\n selectAttachment,\n hasDraggedFiles,\n handleDragEnter,\n handleDragOver,\n handleDragLeave,\n filesFromDataTransfer,\n handleDrop,\n imageFilesFromClipboard,\n handlePaste,\n ref: vue__WEBPACK_IMPORTED_MODULE_5__.ref\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageComposer.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageList.vue?vue&type=script&setup=true&lang=js":
/*!*************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageList.vue?vue&type=script&setup=true&lang=js ***!
\*************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @/stores/contacts */ \"./src/stores/contacts.js\");\n/* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/services/mediaProxy */ \"./src/services/mediaProxy.js\");\n\n\n\n\n\n\n\n\nconst IMAGE_MIN_SCALE = 0.5;\nconst IMAGE_MAX_SCALE = 6;\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'MessageList',\n props: {\n messages: {\n type: Array,\n default: () => []\n },\n selectionMode: {\n type: Boolean,\n default: false\n },\n selectedMessageIds: {\n type: Array,\n default: () => []\n },\n favoriteMessageIds: {\n type: Array,\n default: () => []\n },\n attentionMessageId: {\n type: String,\n default: ''\n },\n canRecallOthers: {\n type: Boolean,\n default: false\n }\n },\n emits: ['message-action', 'toggle-select', 'sender-profile-updated'],\n setup(__props, {\n expose: __expose,\n emit: __emit\n }) {\n __expose();\n const props = __props;\n const emit = __emit;\n const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_6__.useContactStore)();\n const listEl = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)(null);\n const viewerStage = (0,vue__WEBPACK_IMPORTED_MODULE_5__.ref)(null);\n const contextMenu = (0,vue__WEBPACK_IMPORTED_MODULE_5__.reactive)({\n visible: false,\n x: 0,\n y: 0,\n message: null\n });\n const imageViewer = (0,vue__WEBPACK_IMPORTED_MODULE_5__.reactive)({\n visible: false,\n url: '',\n name: '',\n scale: 1,\n rotation: 0,\n offsetX: 0,\n offsetY: 0,\n dragging: false,\n dragStartX: 0,\n dragStartY: 0,\n dragOffsetX: 0,\n dragOffsetY: 0\n });\n const senderProfile = (0,vue__WEBPACK_IMPORTED_MODULE_5__.reactive)({\n visible: false,\n uid: '',\n displayName: '',\n rawName: '',\n mobile: '',\n address: '',\n portrait: '',\n avatarText: '',\n role: '',\n roleLabel: '',\n contactAlias: '',\n groupAlias: '',\n isContact: false,\n aliasDraft: '',\n saving: false,\n adding: false,\n notice: '',\n error: ''\n });\n const imageViewerStyle = (0,vue__WEBPACK_IMPORTED_MODULE_5__.computed)(() => ({\n transform: `translate3d(${imageViewer.offsetX}px, ${imageViewer.offsetY}px, 0) scale(${imageViewer.scale}) rotate(${imageViewer.rotation}deg)`\n }));\n const menuItems = (0,vue__WEBPACK_IMPORTED_MODULE_5__.computed)(() => {\n if (!contextMenu.message) {\n return [];\n }\n const isOwnMessage = contextMenu.message.direction === 'out';\n if (isRecalledMessage(contextMenu.message)) {\n return [...(isOwnMessage ? [{\n action: 'edit',\n label: '编辑'\n }] : []), {\n action: 'copy',\n label: '复制'\n }, {\n action: 'delete',\n label: '删除'\n }, {\n action: 'detail',\n label: '详情'\n }];\n }\n const favoriteLabel = isFavorite(contextMenu.message) ? '取消收藏' : '收藏';\n const items = [{\n action: 'copy',\n label: '复制'\n }, {\n action: 'delete',\n label: '删除'\n }, {\n action: 'forward',\n label: '转发'\n }, {\n action: 'favorite',\n label: favoriteLabel\n }, {\n action: 'quote',\n label: '引用'\n }, {\n action: 'select',\n label: '多选'\n }, {\n action: 'detail',\n label: '详情'\n }];\n if (isOwnMessage) {\n items.unshift({\n action: 'edit',\n label: '编辑'\n });\n items.push({\n action: 'recall',\n label: '撤回'\n });\n } else if (props.canRecallOthers) {\n items.push({\n action: 'recall',\n label: '撤回'\n });\n }\n return items;\n });\n function scrollToBottom() {\n (0,vue__WEBPACK_IMPORTED_MODULE_5__.nextTick)(() => {\n if (listEl.value) {\n listEl.value.scrollTop = listEl.value.scrollHeight;\n }\n });\n }\n function scrollToMessage(messageId) {\n (0,vue__WEBPACK_IMPORTED_MODULE_5__.nextTick)(() => {\n if (!listEl.value || !messageId) {\n return;\n }\n const row = Array.from(listEl.value.querySelectorAll('.message-row')).find(element => element.dataset.messageKey === messageId);\n if (row) {\n row.scrollIntoView({\n block: 'center',\n behavior: 'smooth'\n });\n }\n });\n }\n (0,vue__WEBPACK_IMPORTED_MODULE_5__.watch)(() => props.messages.map(message => `${message.id}:${message.status}:${message.deliveryStatus || ''}:${message.messageUid || ''}:${message.recalled ? '1' : ''}`).join('|'), scrollToBottom, {\n immediate: true\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_5__.watch)(() => props.attentionMessageId, scrollToMessage);\n (0,vue__WEBPACK_IMPORTED_MODULE_5__.onMounted)(() => {\n document.addEventListener('click', closeMenu);\n document.addEventListener('keydown', closeMenuOnEscape);\n document.addEventListener('pointermove', moveImageDrag);\n document.addEventListener('pointerup', stopImageDrag);\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_5__.onBeforeUnmount)(() => {\n document.removeEventListener('click', closeMenu);\n document.removeEventListener('keydown', closeMenuOnEscape);\n document.removeEventListener('pointermove', moveImageDrag);\n document.removeEventListener('pointerup', stopImageDrag);\n });\n function messageIdentity(message) {\n return String(message.messageUid || message.id || '');\n }\n function canOpenMessageMenu(message) {\n return message && message.status !== 'failed' && message.status !== 'sending';\n }\n function isSelected(message) {\n return props.selectedMessageIds.includes(messageIdentity(message));\n }\n function isFavorite(message) {\n return props.favoriteMessageIds.includes(messageIdentity(message));\n }\n function isAttention(message) {\n return props.attentionMessageId === messageIdentity(message);\n }\n function isRecallNotice(message) {\n return message.direction === 'out' && (message.recalled || message.status === 'recalled');\n }\n function isRecalledMessage(message) {\n return message.recalled || message.status === 'recalled';\n }\n function isImageMessage(message) {\n return message?.type === 'image' && message?.attachment?.url;\n }\n function isFileMessage(message) {\n return message?.type === 'file' && message?.attachment?.url;\n }\n function isGroupMessage(message) {\n return ['group', 'channel'].includes(message?.conversationType || '');\n }\n function showGroupSender(message) {\n return isGroupMessage(message) && message?.direction === 'in';\n }\n function senderRoleLabel(message) {\n const role = message?.senderProfile?.role || message?.senderRole || '';\n if (role === 'owner') {\n return '群主';\n }\n if (role === 'admin') {\n return '管理员';\n }\n return '';\n }\n function groupSenderName(message) {\n return message?.senderName || message?.senderProfile?.displayName || message?.from || '未知用户';\n }\n function groupSenderAvatarText(message) {\n return String(groupSenderName(message) || '?').slice(0, 1).toUpperCase();\n }\n function openSenderProfile(message) {\n const profile = message?.senderProfile || {};\n const uid = profile.uid || message?.from || '';\n const cachedContact = contacts.contacts.find(contact => String(contact.uid || contact.id || '') === uid) || null;\n const cachedAlias = String(cachedContact?.alias || '').trim();\n const contactAlias = String(profile.contactAlias || cachedAlias || profile.remarkAlias || '').trim();\n const groupAlias = String(profile.groupAlias || '').trim();\n const rawName = profile.rawName || cachedContact?.rawUser?.displayName || cachedContact?.rawUser?.name || cachedContact?.title || groupSenderName(message);\n const displayName = contactAlias || groupAlias || rawName || uid;\n senderProfile.visible = true;\n senderProfile.uid = uid;\n senderProfile.displayName = displayName;\n senderProfile.rawName = rawName || '';\n senderProfile.mobile = profile.mobile || cachedContact?.rawUser?.mobile || '';\n senderProfile.address = profile.address || cachedContact?.address || cachedContact?.rawUser?.address || '';\n senderProfile.portrait = profile.portrait || cachedContact?.portrait || message?.senderPortrait || '';\n senderProfile.avatarText = String(displayName || senderProfile.uid || '?').slice(0, 1).toUpperCase();\n senderProfile.role = profile.role || message?.senderRole || '';\n senderProfile.roleLabel = senderRoleLabel(message);\n senderProfile.contactAlias = contactAlias;\n senderProfile.groupAlias = groupAlias;\n senderProfile.isContact = Boolean(profile.isContact || cachedContact);\n senderProfile.aliasDraft = contactAlias;\n senderProfile.saving = false;\n senderProfile.adding = false;\n senderProfile.notice = '';\n senderProfile.error = '';\n closeMenu();\n }\n function closeSenderProfile() {\n if (senderProfile.saving || senderProfile.adding) {\n return;\n }\n senderProfile.visible = false;\n }\n async function addSenderAsContact() {\n if (!senderProfile.uid || senderProfile.adding || senderProfile.saving) {\n return;\n }\n senderProfile.adding = true;\n senderProfile.notice = '';\n senderProfile.error = '';\n const ok = await contacts.addContact(senderProfile.uid);\n if (ok || String(contacts.actionError || '').includes('已经是联系人')) {\n senderProfile.isContact = true;\n const alias = senderProfile.aliasDraft.trim();\n let aliasSaved = false;\n if (alias) {\n aliasSaved = await contacts.updateContactAlias(senderProfile.uid, alias);\n if (aliasSaved) {\n senderProfile.contactAlias = alias;\n senderProfile.displayName = alias;\n senderProfile.avatarText = String(alias || senderProfile.uid || '?').slice(0, 1).toUpperCase();\n }\n }\n await contacts.refreshContacts({\n force: true\n }).catch(() => {});\n if (alias && !aliasSaved) {\n senderProfile.notice = '';\n senderProfile.error = contacts.actionError ? `已添加为好友,但${contacts.actionError}` : '已添加为好友,但备注名同步失败';\n } else {\n senderProfile.notice = alias ? '已添加为好友,备注名已保存' : ok ? '已添加为好友' : '已是好友';\n }\n emit('sender-profile-updated', {\n userId: senderProfile.uid\n });\n } else {\n senderProfile.error = contacts.actionError || '添加好友失败';\n }\n senderProfile.adding = false;\n }\n async function saveSenderAlias() {\n if (!senderProfile.uid || senderProfile.saving || senderProfile.adding) {\n return;\n }\n senderProfile.saving = true;\n senderProfile.notice = '';\n senderProfile.error = '';\n const ok = await contacts.updateContactAlias(senderProfile.uid, senderProfile.aliasDraft);\n if (ok) {\n await contacts.refreshContacts({\n force: true\n }).catch(() => {});\n const alias = senderProfile.aliasDraft.trim();\n senderProfile.contactAlias = alias;\n senderProfile.displayName = alias || senderProfile.groupAlias || senderProfile.rawName || senderProfile.uid;\n senderProfile.avatarText = String(senderProfile.displayName || senderProfile.uid || '?').slice(0, 1).toUpperCase();\n senderProfile.notice = '备注名已保存';\n emit('sender-profile-updated', {\n userId: senderProfile.uid\n });\n } else {\n senderProfile.error = contacts.actionError || '备注名修改失败';\n }\n senderProfile.saving = false;\n }\n function roleBubbleClass(message) {\n const role = message?.senderRole || '';\n if (role === 'owner') {\n return 'role-bubble-owner';\n }\n if (role === 'admin') {\n return 'role-bubble-admin';\n }\n return '';\n }\n function formatFileSize(size) {\n const bytes = Number(size || 0);\n if (bytes >= 1024 * 1024) {\n return `${(bytes / 1024 / 1024).toFixed(bytes >= 10 * 1024 * 1024 ? 0 : 1)} MB`;\n }\n if (bytes >= 1024) {\n return `${(bytes / 1024).toFixed(bytes >= 10 * 1024 ? 0 : 1)} KB`;\n }\n return bytes > 0 ? `${bytes} B` : '';\n }\n function handleMessageClick(message) {\n if (props.selectionMode) {\n emit('toggle-select', message);\n }\n }\n function handleImageClick(message) {\n if (props.selectionMode) {\n emit('toggle-select', message);\n return;\n }\n openImageViewer(message);\n }\n function openImageViewer(message) {\n const attachment = message?.attachment || {};\n if (!attachment.url) {\n return;\n }\n closeMenu();\n imageViewer.visible = true;\n imageViewer.url = (0,_services_mediaProxy__WEBPACK_IMPORTED_MODULE_7__.imageDisplayUrl)(attachment.url);\n imageViewer.name = attachment.name || 'image';\n resetImageViewer();\n }\n function closeImageViewer() {\n imageViewer.visible = false;\n imageViewer.dragging = false;\n }\n function resetImageViewer() {\n imageViewer.scale = 1;\n imageViewer.rotation = 0;\n imageViewer.offsetX = 0;\n imageViewer.offsetY = 0;\n }\n function clampImageScale(value) {\n return Math.min(IMAGE_MAX_SCALE, Math.max(IMAGE_MIN_SCALE, Number(value.toFixed(2))));\n }\n function setImageScale(value, originX = null, originY = null) {\n const previousScale = imageViewer.scale;\n const nextScale = clampImageScale(value);\n if (nextScale === previousScale) {\n return;\n }\n if (originX !== null && originY !== null && viewerStage.value) {\n const rect = viewerStage.value.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const ratio = nextScale / previousScale - 1;\n imageViewer.offsetX -= (originX - centerX - imageViewer.offsetX) * ratio;\n imageViewer.offsetY -= (originY - centerY - imageViewer.offsetY) * ratio;\n }\n imageViewer.scale = nextScale;\n if (nextScale <= 1) {\n imageViewer.offsetX = 0;\n imageViewer.offsetY = 0;\n }\n }\n function zoomImage(delta) {\n setImageScale(imageViewer.scale + delta);\n }\n function rotateImage() {\n imageViewer.rotation = (imageViewer.rotation + 90) % 360;\n }\n function handleImageWheel(event) {\n const factor = event.deltaY < 0 ? 1.12 : 1 / 1.12;\n setImageScale(imageViewer.scale * factor, event.clientX, event.clientY);\n }\n function startImageDrag(event) {\n if (!imageViewer.visible || imageViewer.scale <= 1) {\n return;\n }\n imageViewer.dragging = true;\n imageViewer.dragStartX = event.clientX;\n imageViewer.dragStartY = event.clientY;\n imageViewer.dragOffsetX = imageViewer.offsetX;\n imageViewer.dragOffsetY = imageViewer.offsetY;\n }\n function moveImageDrag(event) {\n if (!imageViewer.dragging) {\n return;\n }\n imageViewer.offsetX = imageViewer.dragOffsetX + event.clientX - imageViewer.dragStartX;\n imageViewer.offsetY = imageViewer.dragOffsetY + event.clientY - imageViewer.dragStartY;\n }\n function stopImageDrag() {\n imageViewer.dragging = false;\n }\n function saveViewerImage() {\n if (!imageViewer.url) {\n return;\n }\n const downloadUrl = new URL('/api/media_download.php', window.location.origin);\n downloadUrl.searchParams.set('url', imageViewer.url);\n downloadUrl.searchParams.set('name', imageViewer.name || 'image');\n const link = document.createElement('a');\n link.href = downloadUrl.toString();\n link.download = imageViewer.name || 'image';\n document.body.appendChild(link);\n link.click();\n link.remove();\n }\n function openMenu(event, message) {\n if (!canOpenMessageMenu(message)) {\n closeMenu();\n return;\n }\n contextMenu.visible = true;\n contextMenu.message = message;\n contextMenu.x = Math.min(event.clientX, window.innerWidth - 148);\n contextMenu.y = Math.min(event.clientY, window.innerHeight - 352);\n }\n function closeMenu() {\n contextMenu.visible = false;\n contextMenu.message = null;\n }\n function closeMenuOnEscape(event) {\n if (event.key === 'Escape') {\n if (senderProfile.visible) {\n closeSenderProfile();\n }\n if (imageViewer.visible) {\n closeImageViewer();\n }\n closeMenu();\n }\n }\n function chooseMenuAction(action) {\n if (contextMenu.message) {\n emit('message-action', {\n action,\n message: contextMenu.message\n });\n }\n closeMenu();\n }\n function formatTime(timestamp) {\n return new Intl.DateTimeFormat('zh-CN', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone\n }).format(timestamp);\n }\n function deliveryState(message) {\n if (message.direction !== 'out' || message.status === 'failed' || message.status === 'recalled' || message.recalled) {\n return '';\n }\n const state = message.deliveryStatus || message.status;\n if (state === 'read') {\n return 'read';\n }\n if (state === 'delivered') {\n return 'delivered';\n }\n if (state === 'sent') {\n return 'sent';\n }\n return '';\n }\n function deliveryTitle(message) {\n const state = deliveryState(message);\n if (state === 'read') {\n return '对方已读';\n }\n if (state === 'delivered') {\n return '已送达对方';\n }\n if (state === 'sent') {\n return '已送出';\n }\n return '';\n }\n function failureText(message) {\n if (message.status === 'failed') {\n if (message.errorCode) {\n return message.error ? `失败:${message.error}(${message.errorCode})` : `失败:${message.errorCode}`;\n }\n return message.error ? `失败:${message.error}` : '失败';\n }\n return '';\n }\n const __returned__ = {\n props,\n emit,\n contacts,\n listEl,\n viewerStage,\n contextMenu,\n IMAGE_MIN_SCALE,\n IMAGE_MAX_SCALE,\n imageViewer,\n senderProfile,\n imageViewerStyle,\n menuItems,\n scrollToBottom,\n scrollToMessage,\n messageIdentity,\n canOpenMessageMenu,\n isSelected,\n isFavorite,\n isAttention,\n isRecallNotice,\n isRecalledMessage,\n isImageMessage,\n isFileMessage,\n isGroupMessage,\n showGroupSender,\n senderRoleLabel,\n groupSenderName,\n groupSenderAvatarText,\n openSenderProfile,\n closeSenderProfile,\n addSenderAsContact,\n saveSenderAlias,\n roleBubbleClass,\n formatFileSize,\n handleMessageClick,\n handleImageClick,\n openImageViewer,\n closeImageViewer,\n resetImageViewer,\n clampImageScale,\n setImageScale,\n zoomImage,\n rotateImage,\n handleImageWheel,\n startImageDrag,\n moveImageDrag,\n stopImageDrag,\n saveViewerImage,\n openMenu,\n closeMenu,\n closeMenuOnEscape,\n chooseMenuAction,\n formatTime,\n deliveryState,\n deliveryTitle,\n failureText,\n computed: vue__WEBPACK_IMPORTED_MODULE_5__.computed,\n nextTick: vue__WEBPACK_IMPORTED_MODULE_5__.nextTick,\n onBeforeUnmount: vue__WEBPACK_IMPORTED_MODULE_5__.onBeforeUnmount,\n onMounted: vue__WEBPACK_IMPORTED_MODULE_5__.onMounted,\n reactive: vue__WEBPACK_IMPORTED_MODULE_5__.reactive,\n ref: vue__WEBPACK_IMPORTED_MODULE_5__.ref,\n watch: vue__WEBPACK_IMPORTED_MODULE_5__.watch,\n get useContactStore() {\n return _stores_contacts__WEBPACK_IMPORTED_MODULE_6__.useContactStore;\n },\n get imageDisplayUrl() {\n return _services_mediaProxy__WEBPACK_IMPORTED_MODULE_7__.imageDisplayUrl;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/contacts/ContactPanel.vue?vue&type=script&setup=true&lang=js":
/*!******************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/contacts/ContactPanel.vue?vue&type=script&setup=true&lang=js ***!
\******************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @/stores/contacts */ \"./src/stores/contacts.js\");\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'ContactPanel',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_1__.useContactStore)();\n const contact = (0,vue__WEBPACK_IMPORTED_MODULE_0__.computed)(() => contacts.activeContact);\n const remarkName = (0,vue__WEBPACK_IMPORTED_MODULE_0__.computed)(() => contact.value?.alias || '未设置');\n const username = (0,vue__WEBPACK_IMPORTED_MODULE_0__.computed)(() => contact.value?.rawUser?.displayName || contact.value?.rawUser?.name || contact.value?.uid || '');\n const mobile = (0,vue__WEBPACK_IMPORTED_MODULE_0__.computed)(() => contact.value?.rawUser?.mobile || '未知');\n const address = (0,vue__WEBPACK_IMPORTED_MODULE_0__.computed)(() => contact.value?.rawUser?.address || '未知');\n const editingAlias = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(false);\n const aliasDraft = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('');\n const aliasSaving = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)(false);\n const aliasError = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)('');\n (0,vue__WEBPACK_IMPORTED_MODULE_0__.watch)(contact, () => {\n editingAlias.value = false;\n aliasError.value = '';\n });\n function openAliasEditor() {\n aliasDraft.value = contact.value?.alias || '';\n aliasError.value = '';\n editingAlias.value = true;\n }\n function closeAliasEditor() {\n if (aliasSaving.value) {\n return;\n }\n editingAlias.value = false;\n aliasError.value = '';\n }\n async function submitAlias() {\n if (!contact.value) {\n return;\n }\n aliasSaving.value = true;\n aliasError.value = '';\n const ok = await contacts.updateContactAlias(contact.value.uid, aliasDraft.value);\n aliasSaving.value = false;\n if (ok) {\n editingAlias.value = false;\n return;\n }\n aliasError.value = contacts.actionError || '备注名修改失败';\n }\n const __returned__ = {\n contacts,\n contact,\n remarkName,\n username,\n mobile,\n address,\n editingAlias,\n aliasDraft,\n aliasSaving,\n aliasError,\n openAliasEditor,\n closeAliasEditor,\n submitAlias,\n computed: vue__WEBPACK_IMPORTED_MODULE_0__.computed,\n ref: vue__WEBPACK_IMPORTED_MODULE_0__.ref,\n watch: vue__WEBPACK_IMPORTED_MODULE_0__.watch,\n get useContactStore() {\n return _stores_contacts__WEBPACK_IMPORTED_MODULE_1__.useContactStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/contacts/ContactPanel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoriteList.vue?vue&type=script&setup=true&lang=js":
/*!*******************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoriteList.vue?vue&type=script&setup=true&lang=js ***!
\*******************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/stores/conversations */ \"./src/stores/conversations.js\");\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'FavoriteList',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_3__.useConversationStore)();\n const activeKey = (0,vue__WEBPACK_IMPORTED_MODULE_2__.computed)(() => conversations.activeFavorite?.key || '');\n function favoriteTitle(item) {\n if (item.conversationTitle) {\n return item.conversationTitle;\n }\n const conversation = conversations.conversations.find(entry => entry.id === item.conversationId);\n return conversation?.title || item.conversationId || '未知会话';\n }\n function favoritePreview(item) {\n if (item.recalled) {\n return `[${item.recallStatus || '已撤回'}]`;\n }\n if (item.preview) {\n return item.preview;\n }\n if (item.text) {\n return item.text;\n }\n if (item.type === 'image') {\n return '[图片]';\n }\n if (item.type === 'file') {\n return `[文件] ${item.attachment?.name || '文件'}`;\n }\n return '(无文字内容)';\n }\n function formatFavoriteTime(timestamp) {\n const value = Number(timestamp || 0);\n if (!value) {\n return '';\n }\n return new Intl.DateTimeFormat('zh-CN', {\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: false\n }).format(value);\n }\n const __returned__ = {\n conversations,\n activeKey,\n favoriteTitle,\n favoritePreview,\n formatFavoriteTime,\n computed: vue__WEBPACK_IMPORTED_MODULE_2__.computed,\n get useConversationStore() {\n return _stores_conversations__WEBPACK_IMPORTED_MODULE_3__.useConversationStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoriteList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoritePanel.vue?vue&type=script&setup=true&lang=js":
/*!********************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoritePanel.vue?vue&type=script&setup=true&lang=js ***!
\********************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/stores/conversations */ \"./src/stores/conversations.js\");\n/* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/stores/navigation */ \"./src/stores/navigation.js\");\n/* harmony import */ var _services_mediaProxy__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @/services/mediaProxy */ \"./src/services/mediaProxy.js\");\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'FavoritePanel',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_3__.useConversationStore)();\n const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_4__.useNavigationStore)();\n const favorite = (0,vue__WEBPACK_IMPORTED_MODULE_2__.computed)(() => conversations.activeFavorite);\n const notice = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('');\n const error = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('');\n function clearFeedback() {\n notice.value = '';\n error.value = '';\n }\n function favoriteTitle(item) {\n if (item.conversationTitle) {\n return item.conversationTitle;\n }\n const conversation = conversations.conversations.find(entry => entry.id === item.conversationId);\n return conversation?.title || item.conversationId || '未知会话';\n }\n function favoriteText(item) {\n return item.text || '';\n }\n function isImageFavorite(item) {\n return item?.type === 'image' && item?.attachment?.url;\n }\n function isFileFavorite(item) {\n return item?.type === 'file' && item?.attachment?.url;\n }\n function favoriteCopyText(item) {\n if (!item) {\n return '';\n }\n if (item.text) {\n return item.text;\n }\n if (item.recalled) {\n return item.recallStatus || '已撤回';\n }\n if (isImageFavorite(item)) {\n return item.attachment.url;\n }\n if (isFileFavorite(item)) {\n return `${item.attachment.name || '文件'} ${item.attachment.url}`.trim();\n }\n return item.preview || '';\n }\n function formatFileSize(size) {\n const bytes = Number(size || 0);\n if (bytes >= 1024 * 1024) {\n return `${(bytes / 1024 / 1024).toFixed(bytes >= 10 * 1024 * 1024 ? 0 : 1)} MB`;\n }\n if (bytes >= 1024) {\n return `${(bytes / 1024).toFixed(bytes >= 10 * 1024 ? 0 : 1)} KB`;\n }\n return bytes > 0 ? `${bytes} B` : '';\n }\n function formatFavoriteTime(timestamp) {\n const value = Number(timestamp || 0);\n if (!value) {\n return '';\n }\n return new Intl.DateTimeFormat('zh-CN', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hour12: false\n }).format(value);\n }\n async function copyFavorite() {\n clearFeedback();\n const text = favoriteCopyText(favorite.value || {}).trim();\n if (!text) {\n error.value = '没有可复制的文字内容';\n return;\n }\n try {\n await writeClipboard(text);\n notice.value = '已复制';\n } catch (copyError) {\n error.value = '复制失败';\n }\n }\n async function writeClipboard(text) {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return;\n }\n const element = document.createElement('textarea');\n element.value = text;\n element.setAttribute('readonly', 'readonly');\n element.style.position = 'fixed';\n element.style.left = '-9999px';\n document.body.appendChild(element);\n element.select();\n document.execCommand('copy');\n document.body.removeChild(element);\n }\n function openConversation() {\n clearFeedback();\n const item = favorite.value;\n if (!item?.conversationId) {\n error.value = '缺少原会话信息';\n return;\n }\n const conversation = conversations.conversations.find(entry => entry.id === item.conversationId);\n if (!conversation) {\n error.value = '原会话暂未加载,请刷新会话后再试';\n conversations.refreshRemoteConversations();\n return;\n }\n navigation.showMessages();\n conversations.setActiveConversation(item.conversationId);\n window.setTimeout(() => {\n conversations.focusMessage({\n id: item.id || item.key,\n messageUid: item.messageUid || item.key\n });\n }, 450);\n }\n function removeFavorite() {\n clearFeedback();\n const key = favorite.value?.key || '';\n if (!key) {\n return;\n }\n conversations.removeFavorite(key);\n notice.value = '已取消收藏';\n }\n const __returned__ = {\n conversations,\n navigation,\n favorite,\n notice,\n error,\n clearFeedback,\n favoriteTitle,\n favoriteText,\n isImageFavorite,\n isFileFavorite,\n favoriteCopyText,\n formatFileSize,\n formatFavoriteTime,\n copyFavorite,\n writeClipboard,\n openConversation,\n removeFavorite,\n computed: vue__WEBPACK_IMPORTED_MODULE_2__.computed,\n ref: vue__WEBPACK_IMPORTED_MODULE_2__.ref,\n get useConversationStore() {\n return _stores_conversations__WEBPACK_IMPORTED_MODULE_3__.useConversationStore;\n },\n get useNavigationStore() {\n return _stores_navigation__WEBPACK_IMPORTED_MODULE_4__.useNavigationStore;\n },\n get imageDisplayUrl() {\n return _services_mediaProxy__WEBPACK_IMPORTED_MODULE_5__.imageDisplayUrl;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoritePanel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ContactList.vue?vue&type=script&setup=true&lang=js":
/*!****************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ContactList.vue?vue&type=script&setup=true&lang=js ***!
\****************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/stores/contacts */ \"./src/stores/contacts.js\");\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'ContactList',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_4__.useContactStore)();\n const keyword = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const addingContact = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)(false);\n const addKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_3__.ref)('');\n const filteredContacts = (0,vue__WEBPACK_IMPORTED_MODULE_3__.computed)(() => {\n const value = keyword.value.toLowerCase();\n if (!value) {\n return contacts.contacts;\n }\n return contacts.contacts.filter(item => {\n return item.title.toLowerCase().includes(value) || item.subtitle.toLowerCase().includes(value) || item.uid.toLowerCase().includes(value);\n });\n });\n function openAddContact() {\n contacts.actionError = '';\n contacts.actionInfo = '';\n addKeyword.value = '';\n addingContact.value = true;\n }\n function closeAddContact() {\n addingContact.value = false;\n }\n async function submitAddContact() {\n const added = await contacts.addContact(addKeyword.value);\n if (added) {\n window.setTimeout(() => {\n addingContact.value = false;\n }, 500);\n }\n }\n const __returned__ = {\n contacts,\n keyword,\n addingContact,\n addKeyword,\n filteredContacts,\n openAddContact,\n closeAddContact,\n submitAddContact,\n computed: vue__WEBPACK_IMPORTED_MODULE_3__.computed,\n ref: vue__WEBPACK_IMPORTED_MODULE_3__.ref,\n get useContactStore() {\n return _stores_contacts__WEBPACK_IMPORTED_MODULE_4__.useContactStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ContactList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ConversationList.vue?vue&type=script&setup=true&lang=js":
/*!*********************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ConversationList.vue?vue&type=script&setup=true&lang=js ***!
\*********************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.flat-map.js */ \"./node_modules/core-js/modules/es.iterator.flat-map.js\");\n/* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/es.iterator.some.js */ \"./node_modules/core-js/modules/es.iterator.some.js\");\n/* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert.js */ \"./node_modules/core-js/modules/es.map.get-or-insert.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert-computed.js */ \"./node_modules/core-js/modules/es.map.get-or-insert-computed.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! core-js/modules/es.set.difference.v2.js */ \"./node_modules/core-js/modules/es.set.difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! core-js/modules/es.set.intersection.v2.js */ \"./node_modules/core-js/modules/es.set.intersection.v2.js\");\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_10__);\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! core-js/modules/es.set.is-disjoint-from.v2.js */ \"./node_modules/core-js/modules/es.set.is-disjoint-from.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! core-js/modules/es.set.is-subset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-subset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_12__);\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! core-js/modules/es.set.is-superset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-superset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__);\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! core-js/modules/es.set.symmetric-difference.v2.js */ \"./node_modules/core-js/modules/es.set.symmetric-difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_14__);\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! core-js/modules/es.set.union.v2.js */ \"./node_modules/core-js/modules/es.set.union.v2.js\");\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_15__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @/stores/conversations */ \"./src/stores/conversations.js\");\n/* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @/stores/contacts */ \"./src/stores/contacts.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'ConversationList',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_17__.useConversationStore)();\n const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_18__.useContactStore)();\n const actionMenuOpen = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)(false);\n const activeAction = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const actionBusy = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)(false);\n const searchKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const addKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const groupName = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const groupAnnouncement = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const groupWelcomeText = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const joinGroupKey = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const broadcastText = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const channelName = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const channelAnnouncement = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const contactKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)('');\n const selectedContactIds = (0,vue__WEBPACK_IMPORTED_MODULE_16__.ref)([]);\n const actionTitles = {\n addContact: '添加联系人',\n createGroup: '新建群组',\n joinGroup: '加入群组',\n broadcast: '群发助手',\n createChannel: '创建频道/公告群'\n };\n const submitLabels = {\n addContact: '添加',\n createGroup: '创建',\n joinGroup: '加入',\n broadcast: '发送',\n createChannel: '创建'\n };\n const actionTitle = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => actionTitles[activeAction.value] || '');\n const submitLabel = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => submitLabels[activeAction.value] || '确定');\n const modalError = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => contacts.actionError || conversations.actionError);\n const modalInfo = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => contacts.actionInfo || conversations.actionNotice);\n const normalizedSearchKeyword = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => searchKeyword.value.trim().toLowerCase());\n const contactsByUid = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => {\n const map = new Map();\n contacts.contacts.forEach(contact => {\n const uid = String(contact.uid || contact.id || '');\n if (uid) {\n map.set(uid, contact);\n }\n });\n return map;\n });\n const filteredConversationItems = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => {\n const keyword = normalizedSearchKeyword.value;\n if (!keyword) {\n return conversations.conversations.map(item => conversationResult(item));\n }\n const conversationResults = conversations.conversations.filter(item => matchesConversation(item, keyword, contactForConversation(item))).map(item => conversationResult(item));\n const conversationTargets = new Set(conversations.conversations.filter(item => item.type === 'single').map(item => conversationTarget(item)));\n const contactResults = contacts.contacts.filter(item => !conversationTargets.has(String(item.uid || item.id || ''))).filter(item => matchesContact(item, keyword)).map(item => contactResult(item));\n return [...conversationResults, ...contactResults];\n });\n const filteredContacts = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => {\n const keyword = contactKeyword.value.toLowerCase();\n if (!keyword) {\n return contacts.contacts;\n }\n return contacts.contacts.filter(item => {\n return String(item.title || '').toLowerCase().includes(keyword) || String(item.subtitle || '').toLowerCase().includes(keyword) || String(item.uid || '').toLowerCase().includes(keyword);\n });\n });\n const submitDisabled = (0,vue__WEBPACK_IMPORTED_MODULE_16__.computed)(() => {\n if (activeAction.value === 'addContact') {\n return !addKeyword.value;\n }\n if (activeAction.value === 'createGroup') {\n return !groupName.value || !selectedContactIds.value.length;\n }\n if (activeAction.value === 'joinGroup') {\n return !joinGroupKey.value;\n }\n if (activeAction.value === 'broadcast') {\n return !broadcastText.value || !selectedContactIds.value.length;\n }\n if (activeAction.value === 'createChannel') {\n return !channelName.value;\n }\n return true;\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_16__.onMounted)(() => {\n contacts.refreshContacts().catch(() => {});\n });\n const ContactPicker = (0,vue__WEBPACK_IMPORTED_MODULE_16__.defineComponent)({\n name: 'ContactPicker',\n props: {\n contacts: {\n type: Array,\n default: () => []\n },\n selectedIds: {\n type: Array,\n default: () => []\n },\n keyword: {\n type: String,\n default: ''\n },\n emptyText: {\n type: String,\n default: '暂无联系人'\n }\n },\n emits: ['toggle', 'update:keyword'],\n setup(props, {\n emit\n }) {\n return () => (0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('div', {\n class: 'contact-picker'\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('input', {\n value: props.keyword,\n placeholder: '搜索联系人',\n onInput: event => emit('update:keyword', event.target.value)\n }), (0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('div', {\n class: 'contact-picker-list'\n }, props.contacts.length ? props.contacts.map(contact => (0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('button', {\n key: contact.uid,\n type: 'button',\n class: ['contact-picker-row', {\n selected: props.selectedIds.includes(contact.uid)\n }],\n onClick: () => emit('toggle', contact.uid)\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('span', {\n class: 'contact-check'\n }, props.selectedIds.includes(contact.uid) ? '✓' : ''), contact.portrait ? (0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('img', {\n class: 'conversation-avatar image-avatar',\n src: contact.portrait,\n alt: ''\n }) : (0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('span', {\n class: 'conversation-avatar'\n }, contact.avatarText), (0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('span', {\n class: 'contact-picker-copy'\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('strong', contact.title), (0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('small', contact.subtitle)])])) : [(0,vue__WEBPACK_IMPORTED_MODULE_16__.h)('div', {\n class: 'contact-picker-empty'\n }, props.emptyText)])]);\n }\n });\n function searchableValues(...values) {\n return values.flatMap(value => {\n if (Array.isArray(value)) {\n return value;\n }\n if (value && typeof value === 'object') {\n return Object.values(value);\n }\n return [value];\n }).map(value => String(value || '').toLowerCase()).filter(Boolean);\n }\n function matchesKeyword(values, keyword) {\n const compactKeyword = keyword.replace(/[^\\p{L}\\p{N}]+/gu, '');\n return searchableValues(values).some(value => {\n if (value.includes(keyword)) {\n return true;\n }\n if (!compactKeyword) {\n return false;\n }\n return value.replace(/[^\\p{L}\\p{N}]+/gu, '').includes(compactKeyword);\n });\n }\n function conversationTarget(item) {\n if (item.type !== 'single') {\n return String(item.target || item.raw?.target || item.id || '');\n }\n return String(item.target || item.raw?.target || item.id.replace(/^single-/, '') || '');\n }\n function contactForConversation(item) {\n const target = conversationTarget(item);\n return target ? contactsByUid.value.get(target) || null : null;\n }\n function matchesConversation(item, keyword, contact = null) {\n return matchesKeyword([item.title, item.subtitle, item.target, item.id, item.type, item.raw?.target, item.raw?.groupId, item.raw?.group_id, item.raw?.owner_uid, item.raw?.name, item.raw?.displayName, item.raw?.mobile, item.raw?.friendAlias, item.raw?.alias, contact?.title, contact?.subtitle, contact?.uid, contact?.id, contact?.alias, contact?.address, contact?.rawUser, contact?.rawFriend], keyword);\n }\n function matchesContact(item, keyword) {\n return matchesKeyword([item.title, item.subtitle, item.uid, item.id, item.alias, item.address, item.rawUser, item.rawFriend], keyword);\n }\n function conversationResult(item) {\n return {\n ...item,\n resultKind: 'conversation',\n resultKey: `conversation-${item.id}`\n };\n }\n function contactResult(contact) {\n return {\n id: contact.id,\n resultKind: 'contact',\n resultKey: `contact-${contact.uid || contact.id}`,\n contact,\n title: contact.title,\n subtitle: contact.subtitle,\n portrait: contact.portrait,\n avatarText: contact.avatarText,\n unread: 0\n };\n }\n function isListItemActive(item) {\n if (item.resultKind === 'conversation') {\n return item.id === conversations.activeId;\n }\n return `single-${item.contact?.uid || item.id}` === conversations.activeId;\n }\n function selectListItem(item) {\n if (item.resultKind === 'contact') {\n contacts.openChat(item.contact);\n return;\n }\n conversations.setActiveConversation(item.id);\n }\n function clearStoreMessages() {\n contacts.actionError = '';\n contacts.actionInfo = '';\n conversations.actionError = '';\n conversations.actionNotice = '';\n }\n function resetActionFields() {\n addKeyword.value = '';\n groupName.value = '';\n groupAnnouncement.value = '';\n groupWelcomeText.value = '';\n joinGroupKey.value = '';\n broadcastText.value = '';\n channelName.value = '';\n channelAnnouncement.value = '';\n contactKeyword.value = '';\n selectedContactIds.value = [];\n clearStoreMessages();\n }\n function toggleActionMenu() {\n actionMenuOpen.value = !actionMenuOpen.value;\n }\n function closeActionMenu() {\n actionMenuOpen.value = false;\n }\n function openAction(action) {\n resetActionFields();\n activeAction.value = action;\n actionMenuOpen.value = false;\n if (['createGroup', 'broadcast', 'createChannel'].includes(action)) {\n contacts.refreshContacts({\n force: true\n });\n }\n }\n function closeActionModal() {\n activeAction.value = '';\n actionBusy.value = false;\n resetActionFields();\n }\n function toggleContact(contactId) {\n const selected = new Set(selectedContactIds.value);\n if (selected.has(contactId)) {\n selected.delete(contactId);\n } else {\n selected.add(contactId);\n }\n selectedContactIds.value = Array.from(selected);\n }\n async function submitAction() {\n if (submitDisabled.value || actionBusy.value) {\n return;\n }\n actionBusy.value = true;\n clearStoreMessages();\n try {\n let ok = false;\n if (activeAction.value === 'addContact') {\n ok = await contacts.addContact(addKeyword.value);\n if (ok && contacts.activeContact) {\n contacts.openChat(contacts.activeContact);\n }\n } else if (activeAction.value === 'createGroup') {\n ok = await conversations.createGroup({\n name: groupName.value,\n announcement: groupAnnouncement.value,\n welcomeText: groupWelcomeText.value,\n memberIds: selectedContactIds.value\n });\n } else if (activeAction.value === 'joinGroup') {\n ok = await conversations.joinGroup(joinGroupKey.value);\n } else if (activeAction.value === 'broadcast') {\n ok = await conversations.broadcastMessage(selectedContactIds.value, broadcastText.value);\n } else if (activeAction.value === 'createChannel') {\n ok = await conversations.createGroup({\n name: channelName.value,\n memberIds: selectedContactIds.value,\n announcement: channelAnnouncement.value,\n channel: true\n });\n }\n if (ok) {\n window.setTimeout(closeActionModal, 450);\n }\n } finally {\n actionBusy.value = false;\n }\n }\n document.addEventListener('click', closeActionMenu);\n (0,vue__WEBPACK_IMPORTED_MODULE_16__.onBeforeUnmount)(() => {\n document.removeEventListener('click', closeActionMenu);\n });\n function formatUnread(value) {\n const count = Number(value || 0);\n return count > 99 ? '99+' : String(count);\n }\n const __returned__ = {\n conversations,\n contacts,\n actionMenuOpen,\n activeAction,\n actionBusy,\n searchKeyword,\n addKeyword,\n groupName,\n groupAnnouncement,\n groupWelcomeText,\n joinGroupKey,\n broadcastText,\n channelName,\n channelAnnouncement,\n contactKeyword,\n selectedContactIds,\n actionTitles,\n submitLabels,\n actionTitle,\n submitLabel,\n modalError,\n modalInfo,\n normalizedSearchKeyword,\n contactsByUid,\n filteredConversationItems,\n filteredContacts,\n submitDisabled,\n ContactPicker,\n searchableValues,\n matchesKeyword,\n conversationTarget,\n contactForConversation,\n matchesConversation,\n matchesContact,\n conversationResult,\n contactResult,\n isListItemActive,\n selectListItem,\n clearStoreMessages,\n resetActionFields,\n toggleActionMenu,\n closeActionMenu,\n openAction,\n closeActionModal,\n toggleContact,\n submitAction,\n formatUnread,\n computed: vue__WEBPACK_IMPORTED_MODULE_16__.computed,\n defineComponent: vue__WEBPACK_IMPORTED_MODULE_16__.defineComponent,\n h: vue__WEBPACK_IMPORTED_MODULE_16__.h,\n onBeforeUnmount: vue__WEBPACK_IMPORTED_MODULE_16__.onBeforeUnmount,\n onMounted: vue__WEBPACK_IMPORTED_MODULE_16__.onMounted,\n ref: vue__WEBPACK_IMPORTED_MODULE_16__.ref,\n get useConversationStore() {\n return _stores_conversations__WEBPACK_IMPORTED_MODULE_17__.useConversationStore;\n },\n get useContactStore() {\n return _stores_contacts__WEBPACK_IMPORTED_MODULE_18__.useContactStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ConversationList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/NavigationRail.vue?vue&type=script&setup=true&lang=js":
/*!*******************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/NavigationRail.vue?vue&type=script&setup=true&lang=js ***!
\*******************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/stores/session */ \"./src/stores/session.js\");\n/* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/stores/navigation */ \"./src/stores/navigation.js\");\n/* harmony import */ var _stores_contacts__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @/stores/contacts */ \"./src/stores/contacts.js\");\n\n\n\n\n\n\nconst CROP_OUTPUT_SIZE = 512;\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n __name: 'NavigationRail',\n setup(__props, {\n expose: __expose\n }) {\n __expose();\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_3__.useSessionStore)();\n const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_4__.useNavigationStore)();\n const contacts = (0,_stores_contacts__WEBPACK_IMPORTED_MODULE_5__.useContactStore)();\n const settingsItems = [{\n key: 'notifications',\n label: '通知设置'\n }, {\n key: 'password',\n label: '更改密码'\n }, {\n key: 'wallet',\n label: '钱包管理'\n }, {\n key: 'language',\n label: '切换语言'\n }, {\n key: 'feedback',\n label: '问题反馈'\n }];\n const initials = (0,vue__WEBPACK_IMPORTED_MODULE_2__.computed)(() => (session.displayName || session.userId || 'Q').slice(0, 1).toUpperCase());\n const settingsOpen = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(false);\n const settingsSection = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('password');\n const passwordSaving = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(false);\n const settingsNotice = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('');\n const settingsError = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('');\n const profileOpen = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(false);\n const profileSaving = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(false);\n const profileNotice = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('');\n const profileError = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('');\n const profileFile = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(null);\n const profilePreview = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)('');\n const portraitInput = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(null);\n const cropperCanvas = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(null);\n const cropperPreviewCanvas = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)(null);\n const profileDraft = (0,vue__WEBPACK_IMPORTED_MODULE_2__.ref)({\n displayName: ''\n });\n const passwordDraft = (0,vue__WEBPACK_IMPORTED_MODULE_2__.reactive)({\n oldPassword: '',\n newPassword: '',\n confirmPassword: ''\n });\n const currentAvatarUrl = (0,vue__WEBPACK_IMPORTED_MODULE_2__.computed)(() => profilePreview.value || session.portrait || '');\n const activeSettingsItem = (0,vue__WEBPACK_IMPORTED_MODULE_2__.computed)(() => settingsItems.find(item => item.key === settingsSection.value) || settingsItems[0]);\n const avatarPreviewViewer = (0,vue__WEBPACK_IMPORTED_MODULE_2__.reactive)({\n open: false,\n url: '',\n scale: 1,\n offsetX: 0,\n offsetY: 0,\n dragging: false,\n dragStartX: 0,\n dragStartY: 0,\n dragOffsetX: 0,\n dragOffsetY: 0\n });\n const avatarCropper = (0,vue__WEBPACK_IMPORTED_MODULE_2__.reactive)({\n open: false,\n loaded: false,\n busy: false,\n error: '',\n objectUrl: '',\n fileName: 'avatar.jpg',\n image: null,\n baseScale: 1,\n scale: 1,\n rotation: 0,\n offsetX: 0,\n offsetY: 0,\n dragging: false,\n dragStartX: 0,\n dragStartY: 0,\n dragOffsetX: 0,\n dragOffsetY: 0\n });\n const avatarPreviewStyle = (0,vue__WEBPACK_IMPORTED_MODULE_2__.computed)(() => ({\n transform: `translate3d(${avatarPreviewViewer.offsetX}px, ${avatarPreviewViewer.offsetY}px, 0) scale(${avatarPreviewViewer.scale})`\n }));\n (0,vue__WEBPACK_IMPORTED_MODULE_2__.onMounted)(() => {\n session.refreshProfile();\n window.addEventListener('resize', drawAvatarCropper);\n });\n (0,vue__WEBPACK_IMPORTED_MODULE_2__.onBeforeUnmount)(() => {\n revokeProfilePreview();\n closeAvatarCropper();\n window.removeEventListener('resize', drawAvatarCropper);\n });\n function showContacts() {\n navigation.showContacts();\n contacts.refreshContacts();\n }\n function clearProfileFeedback() {\n profileNotice.value = '';\n profileError.value = '';\n }\n function clearSettingsFeedback() {\n settingsNotice.value = '';\n settingsError.value = '';\n }\n function resetPasswordDraft() {\n passwordDraft.oldPassword = '';\n passwordDraft.newPassword = '';\n passwordDraft.confirmPassword = '';\n }\n function openSettings() {\n settingsOpen.value = true;\n settingsSection.value = 'password';\n clearSettingsFeedback();\n }\n function closeSettings() {\n if (passwordSaving.value) {\n return;\n }\n settingsOpen.value = false;\n clearSettingsFeedback();\n resetPasswordDraft();\n }\n function selectSettingsSection(section) {\n settingsSection.value = section;\n clearSettingsFeedback();\n }\n function revokeProfilePreview() {\n if (profilePreview.value) {\n URL.revokeObjectURL(profilePreview.value);\n profilePreview.value = '';\n }\n }\n function revokeCropperObjectUrl() {\n if (avatarCropper.objectUrl) {\n URL.revokeObjectURL(avatarCropper.objectUrl);\n avatarCropper.objectUrl = '';\n }\n }\n async function openProfileEditor() {\n profileOpen.value = true;\n clearProfileFeedback();\n profileDraft.value.displayName = session.displayName || session.userId || '';\n const profile = await session.refreshProfile();\n if (profileOpen.value && profile) {\n profileDraft.value.displayName = session.displayName || session.userId || '';\n }\n }\n function closeProfileEditor() {\n profileOpen.value = false;\n profileFile.value = null;\n clearProfileFeedback();\n revokeProfilePreview();\n closeAvatarPreview();\n closeAvatarCropper();\n }\n function selectPortrait(event) {\n const file = event.target.files?.[0] || null;\n event.target.value = '';\n clearProfileFeedback();\n if (file) {\n openAvatarCropper(file);\n }\n }\n function choosePortraitFile() {\n portraitInput.value?.click();\n }\n function openAvatarPreview() {\n if (!currentAvatarUrl.value) {\n return;\n }\n avatarPreviewViewer.open = true;\n avatarPreviewViewer.url = currentAvatarUrl.value;\n resetAvatarPreview();\n }\n function closeAvatarPreview() {\n avatarPreviewViewer.open = false;\n avatarPreviewViewer.dragging = false;\n }\n function resetAvatarPreview() {\n avatarPreviewViewer.scale = 1;\n avatarPreviewViewer.offsetX = 0;\n avatarPreviewViewer.offsetY = 0;\n }\n function zoomAvatarPreview(factor) {\n avatarPreviewViewer.scale = Math.max(0.5, Math.min(6, Number((avatarPreviewViewer.scale * factor).toFixed(2))));\n if (avatarPreviewViewer.scale <= 1) {\n avatarPreviewViewer.offsetX = 0;\n avatarPreviewViewer.offsetY = 0;\n }\n }\n function handleAvatarPreviewWheel(event) {\n zoomAvatarPreview(event.deltaY < 0 ? 1.12 : 1 / 1.12);\n }\n function startAvatarPreviewDrag(event) {\n if (avatarPreviewViewer.scale <= 1) {\n return;\n }\n avatarPreviewViewer.dragging = true;\n avatarPreviewViewer.dragStartX = event.clientX;\n avatarPreviewViewer.dragStartY = event.clientY;\n avatarPreviewViewer.dragOffsetX = avatarPreviewViewer.offsetX;\n avatarPreviewViewer.dragOffsetY = avatarPreviewViewer.offsetY;\n event.currentTarget.setPointerCapture?.(event.pointerId);\n }\n function moveAvatarPreviewDrag(event) {\n if (!avatarPreviewViewer.dragging) {\n return;\n }\n avatarPreviewViewer.offsetX = avatarPreviewViewer.dragOffsetX + event.clientX - avatarPreviewViewer.dragStartX;\n avatarPreviewViewer.offsetY = avatarPreviewViewer.dragOffsetY + event.clientY - avatarPreviewViewer.dragStartY;\n }\n function stopAvatarPreviewDrag() {\n avatarPreviewViewer.dragging = false;\n }\n function dropPortrait(event) {\n const file = Array.from(event.dataTransfer?.files || []).find(item => item.type.startsWith('image/'));\n if (file) {\n clearProfileFeedback();\n openAvatarCropper(file);\n }\n }\n function cropperStageSize() {\n const canvas = cropperCanvas.value;\n const rect = canvas?.getBoundingClientRect();\n const width = Math.max(280, Math.round(rect?.width || 360));\n const height = Math.max(280, Math.round(rect?.height || 360));\n return {\n width,\n height\n };\n }\n function cropperBoxSize() {\n const {\n width,\n height\n } = cropperStageSize();\n return Math.round(Math.min(width, height) * 0.74);\n }\n function rotatedImageSize() {\n const image = avatarCropper.image;\n if (!image) {\n return {\n width: 1,\n height: 1\n };\n }\n const quarterTurn = Math.abs(avatarCropper.rotation % 180) === 90;\n return {\n width: quarterTurn ? image.naturalHeight : image.naturalWidth,\n height: quarterTurn ? image.naturalWidth : image.naturalHeight\n };\n }\n function clampCropperOffset() {\n const cropSize = cropperBoxSize();\n const rotated = rotatedImageSize();\n const scaledWidth = rotated.width * avatarCropper.scale;\n const scaledHeight = rotated.height * avatarCropper.scale;\n const maxX = Math.max(0, (scaledWidth - cropSize) / 2);\n const maxY = Math.max(0, (scaledHeight - cropSize) / 2);\n avatarCropper.offsetX = Math.max(-maxX, Math.min(maxX, avatarCropper.offsetX));\n avatarCropper.offsetY = Math.max(-maxY, Math.min(maxY, avatarCropper.offsetY));\n }\n function updateCropperBaseScale() {\n const cropSize = cropperBoxSize();\n const rotated = rotatedImageSize();\n avatarCropper.baseScale = Math.max(cropSize / rotated.width, cropSize / rotated.height);\n avatarCropper.scale = Math.max(avatarCropper.baseScale, avatarCropper.scale || avatarCropper.baseScale);\n }\n function drawCanvasImage(canvas, width, height, outputScale = 1, cropOnly = false) {\n const image = avatarCropper.image;\n if (!canvas || !image) {\n return;\n }\n const dpr = cropOnly ? 1 : window.devicePixelRatio || 1;\n canvas.width = Math.round(width * dpr);\n canvas.height = Math.round(height * dpr);\n const context = canvas.getContext('2d');\n context.setTransform(dpr, 0, 0, dpr, 0, 0);\n context.clearRect(0, 0, width, height);\n context.fillStyle = '#eef4f7';\n context.fillRect(0, 0, width, height);\n context.save();\n context.translate(width / 2 + avatarCropper.offsetX * outputScale, height / 2 + avatarCropper.offsetY * outputScale);\n context.rotate(avatarCropper.rotation * Math.PI / 180);\n context.scale(avatarCropper.scale * outputScale, avatarCropper.scale * outputScale);\n context.drawImage(image, -image.naturalWidth / 2, -image.naturalHeight / 2);\n context.restore();\n if (!cropOnly) {\n const cropSize = cropperBoxSize();\n context.save();\n context.fillStyle = 'rgba(10, 18, 30, 0.42)';\n context.beginPath();\n context.rect(0, 0, width, height);\n context.rect((width - cropSize) / 2, (height - cropSize) / 2, cropSize, cropSize);\n context.fill('evenodd');\n context.restore();\n }\n }\n function drawAvatarCropper() {\n if (!avatarCropper.open || !avatarCropper.loaded) {\n return;\n }\n clampCropperOffset();\n const {\n width,\n height\n } = cropperStageSize();\n drawCanvasImage(cropperCanvas.value, width, height);\n const previewCanvas = cropperPreviewCanvas.value;\n if (previewCanvas) {\n drawCanvasImage(previewCanvas, 108, 108, 108 / cropperBoxSize(), true);\n }\n }\n function resetCropperTransform() {\n if (!avatarCropper.image) {\n return;\n }\n avatarCropper.rotation = 0;\n avatarCropper.offsetX = 0;\n avatarCropper.offsetY = 0;\n updateCropperBaseScale();\n avatarCropper.scale = avatarCropper.baseScale;\n drawAvatarCropper();\n }\n function openAvatarCropper(file) {\n if (!file.type.startsWith('image/')) {\n profileError.value = '请选择图片文件';\n return;\n }\n if (file.size > 8 * 1024 * 1024) {\n profileError.value = '头像图片不能超过8MB';\n return;\n }\n closeAvatarCropper();\n avatarCropper.open = true;\n avatarCropper.loaded = false;\n avatarCropper.error = '';\n avatarCropper.fileName = file.name || 'avatar.jpg';\n avatarCropper.objectUrl = URL.createObjectURL(file);\n const image = new Image();\n image.onload = () => {\n avatarCropper.image = image;\n avatarCropper.loaded = true;\n (0,vue__WEBPACK_IMPORTED_MODULE_2__.nextTick)(resetCropperTransform);\n };\n image.onerror = () => {\n avatarCropper.error = '图片加载失败';\n avatarCropper.loaded = false;\n };\n image.src = avatarCropper.objectUrl;\n }\n function closeAvatarCropper() {\n avatarCropper.open = false;\n avatarCropper.loaded = false;\n avatarCropper.busy = false;\n avatarCropper.error = '';\n avatarCropper.image = null;\n avatarCropper.dragging = false;\n revokeCropperObjectUrl();\n }\n function zoomCropper(factor) {\n if (!avatarCropper.loaded) {\n return;\n }\n updateCropperBaseScale();\n avatarCropper.scale = Math.max(avatarCropper.baseScale, Math.min(avatarCropper.baseScale * 6, avatarCropper.scale * factor));\n drawAvatarCropper();\n }\n function rotateCropper(degrees) {\n if (!avatarCropper.loaded) {\n return;\n }\n avatarCropper.rotation = (avatarCropper.rotation + degrees + 360) % 360;\n updateCropperBaseScale();\n clampCropperOffset();\n drawAvatarCropper();\n }\n function handleCropperWheel(event) {\n zoomCropper(event.deltaY < 0 ? 1.08 : 1 / 1.08);\n }\n function startCropperDrag(event) {\n if (!avatarCropper.loaded) {\n return;\n }\n avatarCropper.dragging = true;\n avatarCropper.dragStartX = event.clientX;\n avatarCropper.dragStartY = event.clientY;\n avatarCropper.dragOffsetX = avatarCropper.offsetX;\n avatarCropper.dragOffsetY = avatarCropper.offsetY;\n event.currentTarget.setPointerCapture?.(event.pointerId);\n }\n function moveCropperDrag(event) {\n if (!avatarCropper.dragging) {\n return;\n }\n avatarCropper.offsetX = avatarCropper.dragOffsetX + event.clientX - avatarCropper.dragStartX;\n avatarCropper.offsetY = avatarCropper.dragOffsetY + event.clientY - avatarCropper.dragStartY;\n drawAvatarCropper();\n }\n function stopCropperDrag() {\n avatarCropper.dragging = false;\n }\n function canvasToBlob(canvas, type = 'image/jpeg', quality = 0.9) {\n return new Promise((resolve, reject) => {\n canvas.toBlob(blob => {\n if (blob) {\n resolve(blob);\n } else {\n reject(new Error('头像裁切失败'));\n }\n }, type, quality);\n });\n }\n async function confirmAvatarCrop() {\n if (!avatarCropper.loaded || avatarCropper.busy) {\n return;\n }\n avatarCropper.busy = true;\n avatarCropper.error = '';\n try {\n const outputCanvas = document.createElement('canvas');\n drawCanvasImage(outputCanvas, CROP_OUTPUT_SIZE, CROP_OUTPUT_SIZE, CROP_OUTPUT_SIZE / cropperBoxSize(), true);\n const blob = await canvasToBlob(outputCanvas);\n const fileName = avatarCropper.fileName.replace(/\\.[^.]+$/, '') || 'avatar';\n const croppedFile = new File([blob], `${fileName}.jpg`, {\n type: 'image/jpeg'\n });\n profileFile.value = croppedFile;\n revokeProfilePreview();\n profilePreview.value = URL.createObjectURL(croppedFile);\n closeAvatarCropper();\n } catch (error) {\n avatarCropper.error = error.message || '头像裁切失败';\n } finally {\n avatarCropper.busy = false;\n }\n }\n async function saveProfile() {\n if (profileSaving.value || !profileDraft.value.displayName) {\n return;\n }\n clearProfileFeedback();\n profileSaving.value = true;\n try {\n await session.saveProfile({\n displayName: profileDraft.value.displayName,\n portraitFile: profileFile.value\n });\n profileFile.value = null;\n revokeProfilePreview();\n profileNotice.value = '资料已保存';\n contacts.refreshContacts({\n force: true\n });\n } catch (error) {\n profileError.value = error.message || '资料保存失败';\n } finally {\n profileSaving.value = false;\n }\n }\n async function savePassword() {\n if (passwordSaving.value) {\n return;\n }\n clearSettingsFeedback();\n const oldPassword = passwordDraft.oldPassword;\n const newPassword = passwordDraft.newPassword;\n const confirmPassword = passwordDraft.confirmPassword;\n if (!oldPassword || !newPassword || !confirmPassword) {\n settingsError.value = '请填写完整密码';\n return;\n }\n if (newPassword !== confirmPassword) {\n settingsError.value = '两次输入的新密码不一致';\n return;\n }\n if (oldPassword === newPassword) {\n settingsError.value = '新密码不能和当前密码相同';\n return;\n }\n passwordSaving.value = true;\n try {\n await session.changePassword({\n oldPassword,\n newPassword\n });\n resetPasswordDraft();\n settingsNotice.value = '密码已更新';\n } catch (error) {\n settingsError.value = error.message || '密码修改失败';\n } finally {\n passwordSaving.value = false;\n }\n }\n function logout() {\n closeSettings();\n contacts.clearContacts();\n session.logout();\n }\n const __returned__ = {\n session,\n navigation,\n contacts,\n settingsItems,\n initials,\n settingsOpen,\n settingsSection,\n passwordSaving,\n settingsNotice,\n settingsError,\n profileOpen,\n profileSaving,\n profileNotice,\n profileError,\n profileFile,\n profilePreview,\n portraitInput,\n cropperCanvas,\n cropperPreviewCanvas,\n profileDraft,\n passwordDraft,\n currentAvatarUrl,\n activeSettingsItem,\n avatarPreviewViewer,\n avatarCropper,\n avatarPreviewStyle,\n CROP_OUTPUT_SIZE,\n showContacts,\n clearProfileFeedback,\n clearSettingsFeedback,\n resetPasswordDraft,\n openSettings,\n closeSettings,\n selectSettingsSection,\n revokeProfilePreview,\n revokeCropperObjectUrl,\n openProfileEditor,\n closeProfileEditor,\n selectPortrait,\n choosePortraitFile,\n openAvatarPreview,\n closeAvatarPreview,\n resetAvatarPreview,\n zoomAvatarPreview,\n handleAvatarPreviewWheel,\n startAvatarPreviewDrag,\n moveAvatarPreviewDrag,\n stopAvatarPreviewDrag,\n dropPortrait,\n cropperStageSize,\n cropperBoxSize,\n rotatedImageSize,\n clampCropperOffset,\n updateCropperBaseScale,\n drawCanvasImage,\n drawAvatarCropper,\n resetCropperTransform,\n openAvatarCropper,\n closeAvatarCropper,\n zoomCropper,\n rotateCropper,\n handleCropperWheel,\n startCropperDrag,\n moveCropperDrag,\n stopCropperDrag,\n canvasToBlob,\n confirmAvatarCrop,\n saveProfile,\n savePassword,\n logout,\n computed: vue__WEBPACK_IMPORTED_MODULE_2__.computed,\n nextTick: vue__WEBPACK_IMPORTED_MODULE_2__.nextTick,\n onBeforeUnmount: vue__WEBPACK_IMPORTED_MODULE_2__.onBeforeUnmount,\n onMounted: vue__WEBPACK_IMPORTED_MODULE_2__.onMounted,\n reactive: vue__WEBPACK_IMPORTED_MODULE_2__.reactive,\n ref: vue__WEBPACK_IMPORTED_MODULE_2__.ref,\n get useSessionStore() {\n return _stores_session__WEBPACK_IMPORTED_MODULE_3__.useSessionStore;\n },\n get useNavigationStore() {\n return _stores_navigation__WEBPACK_IMPORTED_MODULE_4__.useNavigationStore;\n },\n get useContactStore() {\n return _stores_contacts__WEBPACK_IMPORTED_MODULE_5__.useContactStore;\n }\n };\n Object.defineProperty(__returned__, '__isScriptSetup', {\n enumerable: false,\n value: true\n });\n return __returned__;\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/NavigationRail.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=template&id=7ba5bd90":
/*!******************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=template&id=7ba5bd90 ***!
\******************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return !$setup.session.isAuthenticated ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"LoginView\"], {\n key: 0\n })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"ChatShell\"], {\n key: 1\n }));\n}\n\n//# sourceURL=webpack://jc-web-im/./src/App.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ChatShell.vue?vue&type=template&id=2fe58db8":
/*!***********************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ChatShell.vue?vue&type=template&id=2fe58db8 ***!
\***********************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"app-shell\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"main\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"NavigationRail\"]), $setup.navigation.section === 'messages' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"ConversationList\"], {\n key: 0\n })) : $setup.navigation.section === 'favorites' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"FavoriteList\"], {\n key: 1\n })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"ContactList\"], {\n key: 2\n })), $setup.navigation.section === 'messages' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"ChatPanel\"], {\n key: 3\n })) : $setup.navigation.section === 'favorites' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"FavoritePanel\"], {\n key: 4\n })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup[\"ContactPanel\"], {\n key: 5\n }))]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/ChatShell.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/LoginView.vue?vue&type=template&id=37959aa4":
/*!***********************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/LoginView.vue?vue&type=template&id=37959aa4 ***!
\***********************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"login-page\"\n};\nconst _hoisted_2 = {\n class: \"login-panel\"\n};\nconst _hoisted_3 = {\n class: \"brand-lockup\"\n};\nconst _hoisted_4 = [\"src\", \"alt\"];\nconst _hoisted_5 = {\n class: \"login-tabs register-tabs\",\n style: {\n gridTemplateColumns: 'repeat(3, minmax(0, 1fr))'\n }\n};\nconst _hoisted_6 = [\"disabled\"];\nconst _hoisted_7 = [\"src\"];\nconst _hoisted_8 = {\n key: 1\n};\nconst _hoisted_9 = {\n key: 0,\n class: \"qr-scan-user\"\n};\nconst _hoisted_10 = [\"src\"];\nconst _hoisted_11 = {\n key: 1\n};\nconst _hoisted_12 = {\n class: \"qr-login-status\"\n};\nconst _hoisted_13 = [\"disabled\"];\nconst _hoisted_14 = [\"autocomplete\", \"inputmode\", \"placeholder\"];\nconst _hoisted_15 = [\"disabled\"];\nconst _hoisted_16 = {\n key: 2,\n class: \"form-error\"\n};\nconst _hoisted_17 = {\n key: 3,\n class: \"form-info\"\n};\nconst _hoisted_18 = {\n class: \"login-tabs register-tabs\",\n style: {\n gridTemplateColumns: 'repeat(2, minmax(0, 1fr))'\n }\n};\nconst _hoisted_19 = [\"autocomplete\", \"inputmode\", \"placeholder\"];\nconst _hoisted_20 = {\n key: 0\n};\nconst _hoisted_21 = {\n class: \"code-row\"\n};\nconst _hoisted_22 = [\"disabled\"];\nconst _hoisted_23 = [\"disabled\"];\nconst _hoisted_24 = {\n key: 1,\n class: \"form-error\"\n};\nconst _hoisted_25 = {\n key: 2,\n class: \"form-info\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"main\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"img\", {\n class: \"brand-mark\",\n src: $setup.platformLogo,\n alt: `${$setup.platformName} logo`,\n onError: $setup.handleBrandLogoError\n }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_4), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h1\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.platformName), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\" <p>按照最新 App Server 文档接入的 Web IM 客户端</p> \")])]), $setup.view === 'login' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"form\", {\n key: 0,\n class: \"login-form\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.submitLogin, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n active: $setup.loginMode === 'qr'\n }),\n onClick: _cache[0] || (_cache[0] = $event => $setup.setLoginMode('qr'))\n }, \"扫码登录\", 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n active: $setup.loginMode === 'phone'\n }),\n onClick: _cache[1] || (_cache[1] = $event => $setup.setLoginMode('phone'))\n }, \"手机号\", 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n active: $setup.loginMode === 'email'\n }),\n onClick: _cache[2] || (_cache[2] = $event => $setup.setLoginMode('email'))\n }, \"邮箱\", 2 /* CLASS */)]), $setup.loginMode === 'qr' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 0\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"qr-login-card\", {\n scanned: $setup.qrStatus === 'scanned',\n expired: $setup.qrStatus === 'expired',\n error: $setup.qrStatus === 'error'\n }])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"qr-code-button\",\n disabled: $setup.qrStatus === 'loading' || $setup.session.connecting,\n onClick: $setup.refreshQrLogin\n }, [$setup.qrCodeImage ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n src: $setup.qrCodeImage,\n alt: \"扫码登录二维码\"\n }, null, 8 /* PROPS */, _hoisted_7)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.qrStatus === 'loading' ? '生成中' : '点击刷新'), 1 /* TEXT */))], 8 /* PROPS */, _hoisted_6), $setup.qrStatus === 'scanned' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_9, [$setup.qrUserPortrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n src: $setup.qrUserPortrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_10)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.qrUserInitial), 1 /* TEXT */))])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_12, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.qrStatusTitle), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.qrStatusText), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-action\",\n disabled: $setup.qrStatus === 'loading' || $setup.session.connecting,\n onClick: $setup.refreshQrLogin\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.qrRefreshText), 9 /* TEXT, PROPS */, _hoisted_13)], 64 /* STABLE_FRAGMENT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 1\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.loginMode === 'phone' ? '手机号' : '邮箱'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[3] || (_cache[3] = $event => $setup.loginAccount = $event),\n autocomplete: $setup.loginMode === 'phone' ? 'username' : 'email',\n inputmode: $setup.loginMode === 'phone' ? 'tel' : 'email',\n placeholder: $setup.loginMode === 'phone' ? '请输入手机号' : '请输入邮箱'\n }, null, 8 /* PROPS */, _hoisted_14), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.loginAccount, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[12] || (_cache[12] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"密码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[4] || (_cache[4] = $event => $setup.loginPassword = $event),\n autocomplete: \"current-password\",\n type: \"password\",\n placeholder: \"请输入密码\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.loginPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"primary-action\",\n disabled: $setup.session.connecting || !$setup.canSubmitLogin\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.session.connecting ? '登录中...' : '登录'), 9 /* TEXT, PROPS */, _hoisted_15)], 64 /* STABLE_FRAGMENT */)), $setup.session.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.session.error), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.info ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_17, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.info), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 32 /* NEED_HYDRATION */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"form\", {\n key: 1,\n class: \"login-form\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.submitRegister, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_18, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n active: $setup.registerType === 1\n }),\n onClick: _cache[5] || (_cache[5] = $event => $setup.switchRegisterType(1))\n }, \"手机号注册\", 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n active: $setup.registerType === 2\n }),\n onClick: _cache[6] || (_cache[6] = $event => $setup.switchRegisterType(2))\n }, \"邮箱注册\", 2 /* CLASS */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.registerType === 1 ? '手机号' : '邮箱'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[7] || (_cache[7] = $event => $setup.registerForm.number = $event),\n autocomplete: $setup.registerType === 1 ? 'tel' : 'email',\n inputmode: $setup.registerType === 1 ? 'tel' : 'email',\n placeholder: $setup.registerType === 1 ? '请输入手机号' : '请输入邮箱'\n }, null, 8 /* PROPS */, _hoisted_19), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.registerForm.number, void 0, {\n trim: true\n }]])]), $setup.registerType === 2 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"label\", _hoisted_20, [_cache[13] || (_cache[13] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"邮箱验证码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_21, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[8] || (_cache[8] = $event => $setup.registerForm.code = $event),\n autocomplete: \"one-time-code\",\n inputmode: \"numeric\",\n placeholder: \"请输入邮箱验证码\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.registerForm.code, void 0, {\n trim: true\n }]]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"code-action\",\n disabled: $setup.sendingCode || !$setup.canRequestEmailCode,\n onClick: $setup.requestEmailCode\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.sendingCode ? '发送中' : '发送验证码'), 9 /* TEXT, PROPS */, _hoisted_22)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"密码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[9] || (_cache[9] = $event => $setup.registerForm.password = $event),\n autocomplete: \"new-password\",\n type: \"password\",\n placeholder: \"请输入密码\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.registerForm.password]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[15] || (_cache[15] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"确认密码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[10] || (_cache[10] = $event => $setup.registerForm.confirmPassword = $event),\n autocomplete: \"new-password\",\n type: \"password\",\n placeholder: \"请再次输入密码\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.registerForm.confirmPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[16] || (_cache[16] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"邀请码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[11] || (_cache[11] = $event => $setup.registerForm.invitationCode = $event),\n autocomplete: \"off\",\n placeholder: \"没有可留空\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.registerForm.invitationCode, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"primary-action\",\n disabled: $setup.session.connecting || !$setup.canSubmitRegister\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.session.connecting ? '注册中...' : '注册并登录'), 9 /* TEXT, PROPS */, _hoisted_23), $setup.session.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_24, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.session.error), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.info ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_25, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.info), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 32 /* NEED_HYDRATION */)), $setup.view === 'login' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 2,\n class: \"ghost-action\",\n type: \"button\",\n onClick: $setup.openRegister\n }, \" 新用户注册 \")) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 3,\n class: \"ghost-action\",\n type: \"button\",\n onClick: $setup.backToLogin\n }, \" 返回登录 \"))])]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/LoginView.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/ChatPanel.vue?vue&type=template&id=358a1705":
/*!****************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/ChatPanel.vue?vue&type=template&id=358a1705 ***!
\****************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\n\nconst _hoisted_1 = {\n class: \"chat-panel\"\n};\nconst _hoisted_2 = {\n class: \"chat-header\"\n};\nconst _hoisted_3 = [\"src\"];\nconst _hoisted_4 = {\n key: 1,\n class: \"chat-title-avatar\"\n};\nconst _hoisted_5 = {\n class: \"chat-title-copy\"\n};\nconst _hoisted_6 = [\"src\"];\nconst _hoisted_7 = {\n key: 1,\n class: \"chat-title-avatar\"\n};\nconst _hoisted_8 = {\n class: \"chat-title-copy\"\n};\nconst _hoisted_9 = {\n key: 2\n};\nconst _hoisted_10 = {\n class: \"header-actions chat-header-actions\"\n};\nconst _hoisted_11 = {\n key: 0,\n class: \"empty-chat\"\n};\nconst _hoisted_12 = {\n key: 2,\n class: \"selection-toolbar\"\n};\nconst _hoisted_13 = {\n class: \"forward-dialog\"\n};\nconst _hoisted_14 = [\"onClick\"];\nconst _hoisted_15 = {\n class: \"conversation-avatar\"\n};\nconst _hoisted_16 = {\n type: \"submit\"\n};\nconst _hoisted_17 = {\n class: \"group-dialog message-detail-dialog\"\n};\nconst _hoisted_18 = {\n key: 0,\n class: \"group-loading\"\n};\nconst _hoisted_19 = {\n class: \"group-profile message-detail-meta\"\n};\nconst _hoisted_20 = {\n key: 0\n};\nconst _hoisted_21 = {\n key: 0,\n class: \"inline-save-status error\"\n};\nconst _hoisted_22 = {\n class: \"message-detail-summary\"\n};\nconst _hoisted_23 = {\n class: \"message-detail-groups\"\n};\nconst _hoisted_24 = {\n class: \"message-detail-section\"\n};\nconst _hoisted_25 = {\n key: 0,\n class: \"message-detail-member-list\"\n};\nconst _hoisted_26 = [\"src\"];\nconst _hoisted_27 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_28 = {\n class: \"message-detail-member-main\"\n};\nconst _hoisted_29 = {\n class: \"message-detail-member-time\"\n};\nconst _hoisted_30 = {\n key: 2,\n class: \"message-detail-role\"\n};\nconst _hoisted_31 = {\n key: 1,\n class: \"contact-picker-empty\"\n};\nconst _hoisted_32 = {\n class: \"message-detail-section\"\n};\nconst _hoisted_33 = {\n key: 0,\n class: \"message-detail-member-list\"\n};\nconst _hoisted_34 = [\"src\"];\nconst _hoisted_35 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_36 = {\n class: \"message-detail-member-main\"\n};\nconst _hoisted_37 = {\n class: \"message-detail-member-time\"\n};\nconst _hoisted_38 = {\n key: 2,\n class: \"message-detail-role\"\n};\nconst _hoisted_39 = {\n key: 1,\n class: \"contact-picker-empty\"\n};\nconst _hoisted_40 = {\n class: \"message-detail-section\"\n};\nconst _hoisted_41 = {\n key: 0,\n class: \"message-detail-member-list\"\n};\nconst _hoisted_42 = [\"src\"];\nconst _hoisted_43 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_44 = {\n class: \"message-detail-member-main\"\n};\nconst _hoisted_45 = {\n key: 2,\n class: \"message-detail-role\"\n};\nconst _hoisted_46 = {\n key: 1,\n class: \"contact-picker-empty\"\n};\nconst _hoisted_47 = {\n class: \"group-dialog single-profile-dialog\"\n};\nconst _hoisted_48 = {\n class: \"single-profile-summary\"\n};\nconst _hoisted_49 = [\"src\"];\nconst _hoisted_50 = {\n key: 1,\n class: \"profile-avatar\"\n};\nconst _hoisted_51 = {\n class: \"group-profile\"\n};\nconst _hoisted_52 = {\n class: \"single-profile-footer\"\n};\nconst _hoisted_53 = {\n key: 0,\n class: \"inline-save-status\"\n};\nconst _hoisted_54 = {\n key: 1,\n class: \"inline-save-status error\"\n};\nconst _hoisted_55 = [\"disabled\"];\nconst _hoisted_56 = [\"disabled\"];\nconst _hoisted_57 = {\n key: 0,\n class: \"group-dialog\"\n};\nconst _hoisted_58 = {\n key: 0,\n class: \"group-loading\"\n};\nconst _hoisted_59 = {\n key: 1,\n class: \"group-profile\"\n};\nconst _hoisted_60 = [\"disabled\"];\nconst _hoisted_61 = [\"disabled\"];\nconst _hoisted_62 = [\"disabled\"];\nconst _hoisted_63 = {\n key: 1,\n class: \"group-dialog\"\n};\nconst _hoisted_64 = {\n key: 0,\n class: \"group-loading\"\n};\nconst _hoisted_65 = {\n key: 1,\n class: \"group-member-list\"\n};\nconst _hoisted_66 = [\"src\"];\nconst _hoisted_67 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_68 = {\n key: 0,\n class: \"contact-picker-empty\"\n};\nconst _hoisted_69 = [\"disabled\"];\nconst _hoisted_70 = {\n key: 3,\n class: \"group-dialog\"\n};\nconst _hoisted_71 = {\n key: 0,\n class: \"group-loading\"\n};\nconst _hoisted_72 = {\n key: 1,\n class: \"group-member-list\"\n};\nconst _hoisted_73 = [\"onClick\"];\nconst _hoisted_74 = [\"src\"];\nconst _hoisted_75 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_76 = {\n key: 0,\n class: \"contact-picker-empty\"\n};\nconst _hoisted_77 = [\"disabled\"];\nconst _hoisted_78 = {\n key: 4,\n class: \"group-dialog group-management-dialog\"\n};\nconst _hoisted_79 = {\n class: \"group-management-tabs\"\n};\nconst _hoisted_80 = {\n key: 0,\n class: \"group-loading\"\n};\nconst _hoisted_81 = {\n key: 1,\n class: \"group-manage-section\"\n};\nconst _hoisted_82 = {\n class: \"group-member-list\"\n};\nconst _hoisted_83 = [\"checked\", \"onChange\"];\nconst _hoisted_84 = [\"src\"];\nconst _hoisted_85 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_86 = {\n key: 0,\n class: \"contact-picker-empty\"\n};\nconst _hoisted_87 = {\n key: 2,\n class: \"group-manage-section\"\n};\nconst _hoisted_88 = {\n key: 3,\n class: \"group-manage-section\"\n};\nconst _hoisted_89 = {\n class: \"group-member-list\"\n};\nconst _hoisted_90 = [\"checked\", \"onChange\"];\nconst _hoisted_91 = [\"src\"];\nconst _hoisted_92 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_93 = {\n key: 0,\n class: \"contact-picker-empty\"\n};\nconst _hoisted_94 = [\"disabled\"];\nconst _hoisted_95 = {\n key: 4,\n class: \"group-manage-section\"\n};\nconst _hoisted_96 = {\n key: 0,\n class: \"mute-time-grid\"\n};\nconst _hoisted_97 = {\n key: 1,\n class: \"mute-time-grid\"\n};\nconst _hoisted_98 = {\n class: \"mute-save-footer\"\n};\nconst _hoisted_99 = {\n key: 0,\n class: \"inline-save-status\"\n};\nconst _hoisted_100 = {\n key: 1,\n class: \"inline-save-status error\"\n};\nconst _hoisted_101 = [\"disabled\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [$setup.isGroupConversation ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"button\", {\n key: 0,\n type: \"button\",\n class: \"chat-title-button\",\n onClick: $setup.openGroupOverview\n }, [$setup.activeConversation?.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"chat-title-avatar image-avatar\",\n src: $setup.activeConversation.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_3)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_4, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.activeConversation?.avatarText || '?'), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h2\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.activeConversation?.title || '未选择会话'), 1 /* TEXT */)])])) : $setup.activeConversation ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"button\", {\n key: 1,\n type: \"button\",\n class: \"chat-title-button\",\n onClick: $setup.openSingleProfile\n }, [$setup.singleProfile.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"chat-title-avatar image-avatar\",\n src: $setup.singleProfile.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_6)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_7, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfile.avatarText), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_8, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h2\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.activeConversation?.title || '未选择会话'), 1 /* TEXT */)])])) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"h2\", _hoisted_9, \"未选择会话\")), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.statusText), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_10, [_cache[29] || (_cache[29] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n class: \"icon-button\",\n title: \"搜索\"\n }, \"⌕\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n class: \"icon-button\",\n title: \"更多\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)($setup.toggleGroupMenu, [\"stop\"])\n }, \"⋯\"), $setup.groupMenuOpen && $setup.isGroupConversation ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: 0,\n class: \"quick-action-menu chat-more-menu\",\n onClick: _cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)(() => {}, [\"stop\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: $setup.openGroupMembers\n }, \"查看群员\"), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: $setup.openGroupAlias\n }, \"我在本群的昵称\"), $setup.canManageGroup ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"button\", {\n key: 0,\n type: \"button\",\n onClick: $setup.openGroupManage\n }, \"群组管理\")) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)])]), !$setup.activeConversation ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_11, _cache[30] || (_cache[30] = [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, \"选择一个会话\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"真实会话同步完成后,可以在左侧打开聊天\", -1 /* HOISTED */)]))) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createBlock)($setup[\"MessageList\"], {\n key: 1,\n messages: $setup.conversations.activeMessages,\n \"selection-mode\": $setup.conversations.selectionMode,\n \"selected-message-ids\": $setup.conversations.selectedMessageIds,\n \"favorite-message-ids\": $setup.conversations.favoriteMessageIds,\n \"attention-message-id\": $setup.conversations.attentionMessageId,\n \"can-recall-others\": $setup.canManageGroup && $setup.isGroupConversation,\n onMessageAction: $setup.conversations.handleMessageAction,\n onToggleSelect: $setup.conversations.toggleSelectedMessage,\n onSenderProfileUpdated: $setup.handleSenderProfileUpdated\n }, null, 8 /* PROPS */, [\"messages\", \"selection-mode\", \"selected-message-ids\", \"favorite-message-ids\", \"attention-message-id\", \"can-recall-others\", \"onMessageAction\", \"onToggleSelect\"])), $setup.conversations.selectionMode ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_12, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"已选 \" + (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.conversations.selectedMessageIds.length) + \" 条\", 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[1] || (_cache[1] = (...args) => $setup.conversations.copySelectedMessages && $setup.conversations.copySelectedMessages(...args))\n }, \"复制\"), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[2] || (_cache[2] = (...args) => $setup.conversations.deleteSelectedMessages && $setup.conversations.deleteSelectedMessages(...args))\n }, \"删除\"), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[3] || (_cache[3] = (...args) => $setup.conversations.startForwardSelectedMessages && $setup.conversations.startForwardSelectedMessages(...args))\n }, \"转发\"), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[4] || (_cache[4] = (...args) => $setup.conversations.clearSelection && $setup.conversations.clearSelection(...args))\n }, \"取消\")])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createVNode)($setup[\"MessageComposer\"], {\n disabled: !$setup.activeConversation || !$setup.session.isAuthenticated || !$setup.conversations.canSendActiveConversation,\n \"quote-message\": $setup.conversations.quotedMessage,\n onCancelQuote: $setup.conversations.cancelQuote,\n onSend: $setup.conversations.sendText,\n onSendAttachment: $setup.conversations.sendAttachment\n }, null, 8 /* PROPS */, [\"disabled\", \"quote-message\", \"onCancelQuote\", \"onSend\", \"onSendAttachment\"]), $setup.conversations.forwardingMessages.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: 3,\n class: \"modal-backdrop\",\n onClick: _cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)((...args) => $setup.conversations.cancelForward && $setup.conversations.cancelForward(...args), [\"self\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[31] || (_cache[31] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"转发给\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: _cache[5] || (_cache[5] = (...args) => $setup.conversations.cancelForward && $setup.conversations.cancelForward(...args))\n }, \"×\")]), ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.conversations.conversations, item => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"button\", {\n key: item.id,\n type: \"button\",\n class: \"forward-target\",\n onClick: $event => $setup.conversations.completeForward(item.id)\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_15, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(item.avatarText), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(item.title), 1 /* TEXT */)], 8 /* PROPS */, _hoisted_14);\n }), 128 /* KEYED_FRAGMENT */))])])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), $setup.conversations.editingMessage ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: 4,\n class: \"modal-backdrop\",\n onClick: _cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)((...args) => $setup.conversations.cancelEditMessage && $setup.conversations.cancelEditMessage(...args), [\"self\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"form\", {\n class: \"edit-dialog\",\n onSubmit: _cache[10] || (_cache[10] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)((...args) => $setup.conversations.completeEditMessage && $setup.conversations.completeEditMessage(...args), [\"prevent\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.conversations.editingMode === 'resend' ? '重新编辑' : '编辑消息'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: _cache[7] || (_cache[7] = (...args) => $setup.conversations.cancelEditMessage && $setup.conversations.cancelEditMessage(...args))\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"textarea\", {\n \"onUpdate:modelValue\": _cache[8] || (_cache[8] = $event => $setup.conversations.editingText = $event),\n maxlength: \"5000\",\n rows: \"5\",\n autofocus: \"\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.conversations.editingText]]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[9] || (_cache[9] = (...args) => $setup.conversations.cancelEditMessage && $setup.conversations.cancelEditMessage(...args))\n }, \"取消\"), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.conversations.editingMode === 'resend' ? '发送' : '保存'), 1 /* TEXT */)])], 32 /* NEED_HYDRATION */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), $setup.conversations.messageDetailOpen ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: 5,\n class: \"modal-backdrop\",\n onClick: _cache[13] || (_cache[13] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)((...args) => $setup.conversations.closeMessageDetail && $setup.conversations.closeMessageDetail(...args), [\"self\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_17, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[32] || (_cache[32] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"消息详情\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: _cache[12] || (_cache[12] = (...args) => $setup.conversations.closeMessageDetail && $setup.conversations.closeMessageDetail(...args))\n }, \"×\")]), $setup.conversations.messageDetailLoading ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_18, \"正在加载\")) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n key: 1\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dl\", _hoisted_19, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[33] || (_cache[33] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"发送时间\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.formatDetailTime($setup.messageDetail?.sentAt)), 1 /* TEXT */)]), $setup.messageDetail?.editedAt ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_20, [_cache[34] || (_cache[34] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"编辑时间\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.formatDetailTime($setup.messageDetail.editedAt)), 1 /* TEXT */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[35] || (_cache[35] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"发送人\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberName($setup.messageDetail?.sender)), 1 /* TEXT */)]), !$setup.isMessageDetailGroup ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n key: 1\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[36] || (_cache[36] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"接收人\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberName($setup.messageDetail?.receiver)), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[37] || (_cache[37] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"送达时间\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)({\n 'message-detail-muted': !$setup.messageDetail?.deliveredAt\n })\n }, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetail?.deliveredAt ? $setup.formatDetailTime($setup.messageDetail.deliveredAt) : '未送达'), 3 /* TEXT, CLASS */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[38] || (_cache[38] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"已读时间\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)({\n 'message-detail-muted': !$setup.messageDetail?.readAt\n })\n }, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetail?.readAt ? $setup.formatDetailTime($setup.messageDetail.readAt) : '未读'), 3 /* TEXT, CLASS */)])], 64 /* STABLE_FRAGMENT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]), $setup.conversations.messageDetailError ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_21, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.conversations.messageDetailError), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), $setup.isMessageDetailGroup ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n key: 1\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_22, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [_cache[39] || (_cache[39] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createTextVNode)(\"已读 \")), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetailCounts.read || 0), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [_cache[40] || (_cache[40] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createTextVNode)(\"未读 \")), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetailCounts.unread || 0), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [_cache[41] || (_cache[41] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createTextVNode)(\"未送达 \")), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetailCounts.undelivered || 0), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [_cache[42] || (_cache[42] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createTextVNode)(\"成员 \")), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetailCounts.total || 0), 1 /* TEXT */)])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_23, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_24, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[43] || (_cache[43] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, \"已读\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetailCounts.read || 0) + \" 人\", 1 /* TEXT */)]), $setup.messageDetailGroup?.read?.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_25, [((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.messageDetailGroup.read, member => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: `read-${member.uid}`,\n class: \"message-detail-member-row\"\n }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: member.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_26)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_27, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberAvatar(member)), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_28, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberName(member)), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.uid), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_29, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.formatDetailTime(member.time)), 1 /* TEXT */), $setup.detailRoleLabel(member.role) ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_30, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailRoleLabel(member.role)), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]);\n }), 128 /* KEYED_FRAGMENT */))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_31, \"暂无已读成员\"))]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_32, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[44] || (_cache[44] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, \"未读\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetailCounts.unread || 0) + \" 人\", 1 /* TEXT */)]), $setup.messageDetailGroup?.unread?.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_33, [((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.messageDetailGroup.unread, member => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: `unread-${member.uid}`,\n class: \"message-detail-member-row\"\n }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: member.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_34)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_35, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberAvatar(member)), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_36, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberName(member)), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.uid), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_37, \"送达 \" + (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.formatDetailTime(member.time)), 1 /* TEXT */), $setup.detailRoleLabel(member.role) ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_38, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailRoleLabel(member.role)), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]);\n }), 128 /* KEYED_FRAGMENT */))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_39, \"暂无未读成员\"))]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_40, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[45] || (_cache[45] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, \"未送达\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.messageDetailCounts.undelivered || 0) + \" 人\", 1 /* TEXT */)]), $setup.messageDetailGroup?.undelivered?.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_41, [((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.messageDetailGroup.undelivered, member => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: `undelivered-${member.uid}`,\n class: \"message-detail-member-row\"\n }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: member.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_42)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_43, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberAvatar(member)), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", _hoisted_44, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailMemberName(member)), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.uid), 1 /* TEXT */)]), _cache[46] || (_cache[46] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", {\n class: \"message-detail-member-time message-detail-muted\"\n }, \"未送达\", -1 /* HOISTED */)), $setup.detailRoleLabel(member.role) ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_45, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.detailRoleLabel(member.role)), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]);\n }), 128 /* KEYED_FRAGMENT */))])) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_46, \"暂无未送达成员\"))])])], 64 /* STABLE_FRAGMENT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)], 64 /* STABLE_FRAGMENT */))])])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), $setup.singleProfileOpen ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: 6,\n class: \"modal-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)($setup.closeSingleProfile, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"section\", _hoisted_47, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[47] || (_cache[47] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"联系人资料\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeSingleProfile\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_48, [$setup.singleProfile.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"profile-avatar image-avatar\",\n src: $setup.singleProfile.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_49)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_50, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfile.avatarText), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfile.displayName), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dl\", _hoisted_51, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[48] || (_cache[48] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"用户ID\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfile.uid || '-'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[49] || (_cache[49] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"昵称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfile.rawName || '-'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[50] || (_cache[50] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"手机号\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfile.mobile || '未知'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[51] || (_cache[51] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"地区\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfile.address || '未知'), 1 /* TEXT */)])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[52] || (_cache[52] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"备注名称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[14] || (_cache[14] = $event => $setup.singleAliasDraft = $event),\n maxlength: \"32\",\n autocomplete: \"off\",\n placeholder: \"留空使用对方昵称\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.singleAliasDraft, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", _hoisted_52, [$setup.singleProfileNotice ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_53, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfileNotice), 1 /* TEXT */)) : $setup.singleProfileError ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_54, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfileError), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n disabled: $setup.singleProfileSaving,\n onClick: $setup.closeSingleProfile\n }, \"取消\", 8 /* PROPS */, _hoisted_55), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n disabled: $setup.singleProfileSaving || !$setup.singleProfile.uid,\n onClick: $setup.saveSingleAlias\n }, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.singleProfileSaving ? '保存中...' : '保存备注'), 9 /* TEXT, PROPS */, _hoisted_56)])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), $setup.groupPanel ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: 7,\n class: \"modal-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)($setup.closeGroupPanel, [\"self\"])\n }, [$setup.groupPanel === 'overview' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_57, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[53] || (_cache[53] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"群概况\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeGroupPanel\n }, \"×\")]), $setup.groupBusy ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_58, \"正在加载\")) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"dl\", _hoisted_59, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[54] || (_cache[54] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"群名\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.groupDetail?.name || $setup.activeConversation?.title || '-'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[55] || (_cache[55] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"群ID\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.groupDetail?.groupId || $setup.activeConversation?.target || '-'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[56] || (_cache[56] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"群说明\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.groupDetail?.announcement || '未设置'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", null, [_cache[57] || (_cache[57] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dt\", null, \"群主昵称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.groupDetail?.ownerName || '-'), 1 /* TEXT */)])])), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", null, [$setup.isGroupOwner ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n key: 0\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"danger-inline-action\",\n disabled: $setup.groupBusy,\n onClick: $setup.dismissCurrentGroup\n }, \"解散群组\", 8 /* PROPS */, _hoisted_60), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n disabled: $setup.groupBusy,\n onClick: $setup.openTransferGroup\n }, \"转让群组\", 8 /* PROPS */, _hoisted_61)], 64 /* STABLE_FRAGMENT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"button\", {\n key: 1,\n type: \"button\",\n class: \"danger-inline-action\",\n disabled: $setup.groupBusy,\n onClick: $setup.leaveCurrentGroup\n }, \"退出群组\", 8 /* PROPS */, _hoisted_62))])])) : $setup.groupPanel === 'members' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_63, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[58] || (_cache[58] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"群员\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeGroupPanel\n }, \"×\")]), $setup.groupBusy ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_64, \"正在加载\")) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_65, [((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.groupMembers, member => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: member.uid,\n class: \"group-member-row\"\n }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: member.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_66)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_67, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.memberAvatar(member)), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.displayName), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.role === 'owner' ? '群主' : member.rawDisplayName), 1 /* TEXT */)])]);\n }), 128 /* KEYED_FRAGMENT */)), !$setup.groupMembers.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_68, \"暂无群员\")) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]))])) : $setup.groupPanel === 'alias' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"form\", {\n key: 2,\n class: \"group-dialog\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_1__.withModifiers)($setup.saveGroupAlias, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[59] || (_cache[59] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"我在本群的昵称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeGroupPanel\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[60] || (_cache[60] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"昵称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[15] || (_cache[15] = $event => $setup.groupAliasDraft = $event),\n maxlength: \"64\",\n autocomplete: \"off\",\n placeholder: \"留空使用个人昵称\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.groupAliasDraft, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n onClick: $setup.closeGroupPanel\n }, \"取消\"), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n class: \"primary-inline-action\",\n disabled: $setup.groupBusy\n }, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.groupBusy ? '保存中...' : '保存'), 9 /* TEXT, PROPS */, _hoisted_69)])], 32 /* NEED_HYDRATION */)) : $setup.groupPanel === 'transfer' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_70, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[61] || (_cache[61] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"转让群组\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeGroupPanel\n }, \"×\")]), $setup.groupBusy ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_71, \"正在加载\")) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_72, [((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.transferableMembers, member => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"button\", {\n key: member.uid,\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)([\"group-member-row selectable\", {\n selected: $setup.transferTargetId === member.uid\n }]),\n onClick: $event => $setup.transferTargetId = member.uid\n }, [member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: member.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_74)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_75, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.memberAvatar(member)), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.displayName), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.rawDisplayName), 1 /* TEXT */)])], 10 /* CLASS, PROPS */, _hoisted_73);\n }), 128 /* KEYED_FRAGMENT */)), !$setup.transferableMembers.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_76, \"暂无可转让成员\")) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)])), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n onClick: $setup.closeGroupPanel\n }, \"取消\"), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n disabled: $setup.groupBusy || !$setup.transferTargetId,\n onClick: $setup.transferCurrentGroup\n }, \"确认转让\", 8 /* PROPS */, _hoisted_77)])])) : $setup.groupPanel === 'manage' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_78, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"header\", null, [_cache[62] || (_cache[62] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"h3\", null, \"群组管理\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeGroupPanel\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"nav\", _hoisted_79, [$setup.isGroupOwner ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"button\", {\n key: 0,\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)({\n active: $setup.manageSection === 'admins'\n }),\n onClick: _cache[16] || (_cache[16] = $event => $setup.manageSection = 'admins')\n }, \"管理员设置\", 2 /* CLASS */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)({\n active: $setup.manageSection === 'profile'\n }),\n onClick: _cache[17] || (_cache[17] = $event => $setup.manageSection = 'profile')\n }, \"修改群资料\", 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)({\n active: $setup.manageSection === 'kick'\n }),\n onClick: _cache[18] || (_cache[18] = $event => $setup.manageSection = 'kick')\n }, \"踢人\", 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)({\n active: $setup.manageSection === 'mute'\n }),\n onClick: _cache[19] || (_cache[19] = $event => $setup.manageSection = 'mute')\n }, \"禁言设置\", 2 /* CLASS */)]), $setup.groupBusy ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_80, \"正在加载\")) : $setup.manageSection === 'admins' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_81, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_82, [((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.adminCandidateMembers, member => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"label\", {\n key: member.uid,\n class: \"group-member-row selectable with-check\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n type: \"checkbox\",\n checked: $setup.selectedAdminIds.includes(member.uid),\n onChange: $event => $setup.toggleAdmin(member.uid)\n }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_83), member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: member.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_84)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_85, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.memberAvatar(member)), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.displayName), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.rawDisplayName), 1 /* TEXT */)])]);\n }), 128 /* KEYED_FRAGMENT */)), !$setup.adminCandidateMembers.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_86, \"暂无可设置成员\")) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n onClick: $setup.saveGroupAdmins\n }, \"保存管理员\")])])) : $setup.manageSection === 'profile' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_87, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[63] || (_cache[63] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"群名称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[20] || (_cache[20] = $event => $setup.profileDraft.name = $event),\n maxlength: \"128\",\n autocomplete: \"off\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.profileDraft.name, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[64] || (_cache[64] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"群说明\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"textarea\", {\n \"onUpdate:modelValue\": _cache[21] || (_cache[21] = $event => $setup.profileDraft.announcement = $event),\n maxlength: \"1000\",\n rows: \"3\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.profileDraft.announcement, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[65] || (_cache[65] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"欢迎词\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"textarea\", {\n \"onUpdate:modelValue\": _cache[22] || (_cache[22] = $event => $setup.profileDraft.welcomeText = $event),\n maxlength: \"1000\",\n rows: \"3\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.profileDraft.welcomeText, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n onClick: $setup.saveGroupProfile\n }, \"保存资料\")])])) : $setup.manageSection === 'kick' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_88, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"div\", _hoisted_89, [((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_1__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.renderList)($setup.kickCandidateMembers, member => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"label\", {\n key: member.uid,\n class: \"group-member-row selectable with-check\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n type: \"checkbox\",\n checked: $setup.selectedKickIds.includes(member.uid),\n onChange: $event => $setup.toggleKick(member.uid)\n }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_90), member.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: member.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_91)) : ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_92, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.memberAvatar(member)), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.displayName), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)(member.role === 'admin' ? '管理员' : member.rawDisplayName), 1 /* TEXT */)])]);\n }), 128 /* KEYED_FRAGMENT */)), !$setup.kickCandidateMembers.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_93, \"暂无可移除成员\")) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"danger-inline-action\",\n disabled: !$setup.selectedKickIds.length,\n onClick: $setup.kickSelectedMembers\n }, \"移出群组\", 8 /* PROPS */, _hoisted_94)])])) : $setup.manageSection === 'mute' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"section\", _hoisted_95, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[67] || (_cache[67] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"禁言模式\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"select\", {\n \"onUpdate:modelValue\": _cache[23] || (_cache[23] = $event => $setup.muteDraft.mode = $event),\n onChange: $setup.clearMuteSaveFeedback\n }, _cache[66] || (_cache[66] = [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"option\", {\n value: \"off\"\n }, \"关闭禁言\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"option\", {\n value: \"all_include_admins\"\n }, \"全体禁言包含管理员\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"option\", {\n value: \"all_except_admins\"\n }, \"除管理员外全体禁言\", -1 /* HOISTED */)]), 544 /* NEED_HYDRATION, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelSelect, $setup.muteDraft.mode]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[69] || (_cache[69] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"时段类型\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"select\", {\n \"onUpdate:modelValue\": _cache[24] || (_cache[24] = $event => $setup.muteDraft.scheduleType = $event),\n onChange: $setup.clearMuteSaveFeedback\n }, _cache[68] || (_cache[68] = [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"option\", {\n value: \"manual\"\n }, \"立即禁言直到管理解除\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"option\", {\n value: \"once\"\n }, \"单次\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"option\", {\n value: \"daily\"\n }, \"每天固定时段\", -1 /* HOISTED */)]), 544 /* NEED_HYDRATION, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelSelect, $setup.muteDraft.scheduleType]])]), $setup.muteDraft.mode !== 'off' && $setup.muteDraft.scheduleType === 'once' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_96, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[70] || (_cache[70] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"开始\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[25] || (_cache[25] = $event => $setup.muteDraft.startsAtLocal = $event),\n type: \"datetime-local\",\n onInput: $setup.clearMuteSaveFeedback\n }, null, 544 /* NEED_HYDRATION, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.muteDraft.startsAtLocal]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[71] || (_cache[71] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"结束\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[26] || (_cache[26] = $event => $setup.muteDraft.endsAtLocal = $event),\n type: \"datetime-local\",\n onInput: $setup.clearMuteSaveFeedback\n }, null, 544 /* NEED_HYDRATION, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.muteDraft.endsAtLocal]])])])) : $setup.muteDraft.mode !== 'off' && $setup.muteDraft.scheduleType === 'daily' ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", _hoisted_97, [(0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[72] || (_cache[72] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"开始\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[27] || (_cache[27] = $event => $setup.muteDraft.dailyStart = $event),\n type: \"time\",\n onInput: $setup.clearMuteSaveFeedback\n }, null, 544 /* NEED_HYDRATION, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.muteDraft.dailyStart]])]), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"label\", null, [_cache[73] || (_cache[73] = (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"span\", null, \"结束\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_1__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[28] || (_cache[28] = $event => $setup.muteDraft.dailyEnd = $event),\n type: \"time\",\n onInput: $setup.clearMuteSaveFeedback\n }, null, 544 /* NEED_HYDRATION, NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_1__.vModelText, $setup.muteDraft.dailyEnd]])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"footer\", _hoisted_98, [$setup.muteSaveNotice ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_99, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.muteSaveNotice), 1 /* TEXT */)) : $setup.muteSaveError ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"span\", _hoisted_100, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.muteSaveError), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n disabled: $setup.groupBusy,\n onClick: $setup.saveMuteSetting\n }, \"保存禁言\", 8 /* PROPS */, _hoisted_101)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)])) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true), $setup.conversations.actionNotice || $setup.conversations.actionError ? ((0,vue__WEBPACK_IMPORTED_MODULE_1__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_1__.createElementBlock)(\"div\", {\n key: 8,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_1__.normalizeClass)([\"chat-toast\", {\n error: $setup.conversations.actionError\n }])\n }, (0,vue__WEBPACK_IMPORTED_MODULE_1__.toDisplayString)($setup.conversations.actionError || $setup.conversations.actionNotice), 3 /* TEXT, CLASS */)) : (0,vue__WEBPACK_IMPORTED_MODULE_1__.createCommentVNode)(\"v-if\", true)]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/ChatPanel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageComposer.vue?vue&type=template&id=08eca580":
/*!**********************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageComposer.vue?vue&type=template&id=08eca580 ***!
\**********************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n key: 0,\n class: \"quote-preview\"\n};\nconst _hoisted_2 = {\n class: \"composer-tools\"\n};\nconst _hoisted_3 = [\"disabled\"];\nconst _hoisted_4 = [\"disabled\"];\nconst _hoisted_5 = [\"disabled\"];\nconst _hoisted_6 = [\"onClick\"];\nconst _hoisted_7 = [\"disabled\", \"onKeydown\"];\nconst _hoisted_8 = {\n class: \"composer-footer\"\n};\nconst _hoisted_9 = [\"disabled\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"form\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"message-composer\", {\n 'drop-active': $setup.dropActive\n }]),\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.submit, [\"prevent\"]),\n onDragenter: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handleDragEnter, [\"prevent\"]),\n onDragover: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handleDragOver, [\"prevent\"]),\n onDragleave: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handleDragLeave, [\"prevent\"]),\n onDrop: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handleDrop, [\"prevent\"]),\n onPaste: $setup.handlePaste\n }, [$props.quoteMessage ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, [_cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"引用\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)(\" \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.quoteMessage.quoteText || $props.quoteMessage.text), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"取消引用\",\n onClick: _cache[0] || (_cache[0] = $event => _ctx.$emit('cancel-quote'))\n }, \"×\")])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"表情\",\n disabled: $props.disabled,\n onClick: $setup.toggleEmojiPicker\n }, \"☺\", 8 /* PROPS */, _hoisted_3), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"图片\",\n disabled: $props.disabled,\n onClick: $setup.chooseImage\n }, \"▧\", 8 /* PROPS */, _hoisted_4), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"文件\",\n disabled: $props.disabled,\n onClick: $setup.chooseFile\n }, \"▤\", 8 /* PROPS */, _hoisted_5), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n ref: \"imageInput\",\n type: \"file\",\n accept: \"image/*\",\n multiple: \"\",\n onChange: _cache[1] || (_cache[1] = $event => $setup.selectAttachment($event, 'image'))\n }, null, 544 /* NEED_HYDRATION, NEED_PATCH */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n ref: \"fileInput\",\n type: \"file\",\n multiple: \"\",\n onChange: _cache[2] || (_cache[2] = $event => $setup.selectAttachment($event, 'file'))\n }, null, 544 /* NEED_HYDRATION, NEED_PATCH */), $setup.emojiOpen ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"emoji-picker\",\n onClick: _cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, [\"stop\"]))\n }, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.emojiList, emoji => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n key: emoji,\n type: \"button\",\n onClick: $event => $setup.insertEmoji(emoji)\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(emoji), 9 /* TEXT, PROPS */, _hoisted_6);\n }), 64 /* STABLE_FRAGMENT */))])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"textarea\", {\n ref: \"textareaEl\",\n \"onUpdate:modelValue\": _cache[4] || (_cache[4] = $event => $setup.text = $event),\n disabled: $props.disabled,\n placeholder: \"输入消息\",\n rows: \"3\",\n onKeydown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withKeys)((0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.submit, [\"exact\", \"prevent\"]), [\"enter\"])\n }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_7), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.text]]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_8, [_cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"Enter 发送,Shift + Enter 换行\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"send-button\",\n disabled: $props.disabled || !$setup.text.trim()\n }, \"发送\", 8 /* PROPS */, _hoisted_9)])], 34 /* CLASS, NEED_HYDRATION */);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageComposer.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageList.vue?vue&type=template&id=a39e6c04":
/*!******************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageList.vue?vue&type=template&id=a39e6c04 ***!
\******************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n ref: \"listEl\",\n class: \"message-list\"\n};\nconst _hoisted_2 = [\"data-message-key\", \"onClick\"];\nconst _hoisted_3 = {\n key: 0,\n class: \"message-select\"\n};\nconst _hoisted_4 = [\"checked\", \"onChange\"];\nconst _hoisted_5 = [\"title\", \"onClick\"];\nconst _hoisted_6 = [\"src\"];\nconst _hoisted_7 = {\n key: 1\n};\nconst _hoisted_8 = {\n class: \"message-stack\"\n};\nconst _hoisted_9 = [\"onClick\"];\nconst _hoisted_10 = {\n key: 0,\n class: \"message-sender-role\"\n};\nconst _hoisted_11 = [\"onContextmenu\"];\nconst _hoisted_12 = [\"onClick\"];\nconst _hoisted_13 = [\"src\", \"alt\"];\nconst _hoisted_14 = [\"href\"];\nconst _hoisted_15 = {\n class: \"message-file-main\"\n};\nconst _hoisted_16 = {\n key: 2\n};\nconst _hoisted_17 = {\n key: 0,\n class: \"recall-mark\"\n};\nconst _hoisted_18 = {\n key: 1,\n class: \"edit-mark\"\n};\nconst _hoisted_19 = {\n key: 2,\n class: \"favorite-mark\",\n title: \"已收藏\",\n \"aria-label\": \"已收藏\"\n};\nconst _hoisted_20 = [\"title\", \"aria-label\"];\nconst _hoisted_21 = {\n key: 0,\n class: \"delivery-check delivery-check-second\"\n};\nconst _hoisted_22 = {\n key: 4,\n class: \"delivery-error\"\n};\nconst _hoisted_23 = [\"onClick\"];\nconst _hoisted_24 = {\n class: \"image-viewer-toolbar\"\n};\nconst _hoisted_25 = {\n class: \"image-viewer-title\"\n};\nconst _hoisted_26 = [\"src\", \"alt\"];\nconst _hoisted_27 = {\n class: \"sender-profile-main\"\n};\nconst _hoisted_28 = [\"src\"];\nconst _hoisted_29 = {\n key: 1,\n class: \"profile-avatar\"\n};\nconst _hoisted_30 = {\n key: 2\n};\nconst _hoisted_31 = {\n class: \"sender-profile-fields\"\n};\nconst _hoisted_32 = {\n class: \"sender-profile-alias\"\n};\nconst _hoisted_33 = [\"disabled\"];\nconst _hoisted_34 = {\n class: \"sender-profile-actions\"\n};\nconst _hoisted_35 = {\n key: 0,\n class: \"inline-save-status\"\n};\nconst _hoisted_36 = {\n key: 1,\n class: \"inline-save-status error\"\n};\nconst _hoisted_37 = [\"disabled\"];\nconst _hoisted_38 = [\"disabled\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_1, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.messages, message => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"article\", {\n key: message.id,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"message-row\", [message.direction, {\n selected: $setup.isSelected(message),\n attention: $setup.isAttention(message),\n recalled: message.recalled || message.status === 'recalled'\n }]]),\n \"data-message-key\": $setup.messageIdentity(message),\n onClick: $event => $setup.handleMessageClick(message)\n }, [$props.selectionMode ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"label\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n type: \"checkbox\",\n checked: $setup.isSelected(message),\n onClick: _cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, [\"stop\"])),\n onChange: $event => $setup.emit('toggle-select', message)\n }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_4)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.showGroupSender(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 1,\n type: \"button\",\n class: \"message-sender-avatar\",\n title: $setup.groupSenderName(message),\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.openSenderProfile(message), [\"stop\"])\n }, [message.senderPortrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n src: message.senderPortrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_6)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_7, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.groupSenderAvatarText(message)), 1 /* TEXT */))], 8 /* PROPS */, _hoisted_5)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_8, [$setup.showGroupSender(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 0,\n type: \"button\",\n class: \"message-sender-name\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.openSenderProfile(message), [\"stop\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.groupSenderName(message)) + \" \", 1 /* TEXT */), $setup.senderRoleLabel(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderRoleLabel(message)), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 8 /* PROPS */, _hoisted_9)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"message-bubble\", $setup.roleBubbleClass(message)]),\n onContextmenu: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.openMenu($event, message), [\"prevent\"])\n }, [$setup.isImageMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 0,\n type: \"button\",\n class: \"message-image\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($event => $setup.handleImageClick(message), [\"stop\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"img\", {\n src: $setup.imageDisplayUrl(message.attachment.url),\n alt: message.attachment.name || '图片'\n }, null, 8 /* PROPS */, _hoisted_13)], 8 /* PROPS */, _hoisted_12)) : $setup.isFileMessage(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"a\", {\n key: 1,\n class: \"message-file\",\n href: message.attachment.url,\n target: \"_blank\",\n rel: \"noreferrer\",\n download: \"\"\n }, [_cache[7] || (_cache[7] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"message-file-icon\"\n }, \"▤\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_15, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(message.attachment.name || '文件'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatFileSize(message.attachment.size)), 1 /* TEXT */)])], 8 /* PROPS */, _hoisted_14)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), message.text ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(message.text), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"time\", null, [$setup.isRecallNotice(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_17, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(message.recallStatus || '已撤回'), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime(message.displayTimestamp || message.timestamp)), 1 /* TEXT */), message.editedAt ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_18, \"【edit \" + (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatTime(message.editedAt)) + \"】\", 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.isFavorite(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_19, \"★\")) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.deliveryState(message) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", {\n key: 3,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"delivery-mark\", `delivery-mark-${$setup.deliveryState(message)}`]),\n title: $setup.deliveryTitle(message),\n \"aria-label\": $setup.deliveryTitle(message)\n }, [_cache[8] || (_cache[8] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"delivery-check\"\n }, \"✓\", -1 /* HOISTED */)), $setup.deliveryState(message) !== 'sent' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_21, \"✓\")) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 10 /* CLASS, PROPS */, _hoisted_20)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), message.status === 'failed' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_22, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.failureText(message)), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)])], 42 /* CLASS, PROPS, NEED_HYDRATION */, _hoisted_11)])], 10 /* CLASS, PROPS */, _hoisted_2);\n }), 128 /* KEYED_FRAGMENT */)), $setup.contextMenu.visible ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"message-context-menu\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)({\n left: `${$setup.contextMenu.x}px`,\n top: `${$setup.contextMenu.y}px`\n }),\n onClick: _cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, [\"stop\"]))\n }, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.menuItems, item => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: item.action,\n type: \"button\",\n onClick: $event => $setup.chooseMenuAction(item.action)\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.label), 9 /* TEXT, PROPS */, _hoisted_23);\n }), 128 /* KEYED_FRAGMENT */))], 4 /* STYLE */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Teleport, {\n to: \"body\"\n }, [$setup.imageViewer.visible ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"image-viewer-backdrop\",\n onClick: $setup.closeImageViewer\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"image-viewer-dialog\",\n onClick: _cache[4] || (_cache[4] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, [\"stop\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_24, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_25, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.imageViewer.name || '图片'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"缩小\",\n \"aria-label\": \"缩小\",\n onClick: _cache[2] || (_cache[2] = $event => $setup.zoomImage(-0.25))\n }, \"−\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"放大\",\n \"aria-label\": \"放大\",\n onClick: _cache[3] || (_cache[3] = $event => $setup.zoomImage(0.25))\n }, \"+\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"还原\",\n \"aria-label\": \"还原\",\n onClick: $setup.resetImageViewer\n }, \"1:1\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"旋转\",\n \"aria-label\": \"旋转\",\n onClick: $setup.rotateImage\n }, \"⟳\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"保存\",\n \"aria-label\": \"保存\",\n onClick: $setup.saveViewerImage\n }, \"⇩\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"关闭\",\n \"aria-label\": \"关闭\",\n onClick: $setup.closeImageViewer\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n ref: \"viewerStage\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"image-viewer-stage\", {\n dragging: $setup.imageViewer.dragging,\n zoomed: $setup.imageViewer.scale > 1\n }]),\n onWheel: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handleImageWheel, [\"prevent\"]),\n onPointerdown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.startImageDrag, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"img\", {\n class: \"image-viewer-img\",\n src: $setup.imageViewer.url,\n alt: $setup.imageViewer.name || '图片',\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)($setup.imageViewerStyle),\n draggable: \"false\"\n }, null, 12 /* STYLE, PROPS */, _hoisted_26)], 34 /* CLASS, NEED_HYDRATION */)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)])), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Teleport, {\n to: \"body\"\n }, [$setup.senderProfile.visible ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"sender-profile-backdrop\",\n onClick: $setup.closeSenderProfile\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", {\n class: \"sender-profile-dialog\",\n onClick: _cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, [\"stop\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [_cache[9] || (_cache[9] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"用户资料\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeSenderProfile\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_27, [$setup.senderProfile.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n class: \"profile-avatar image-avatar\",\n src: $setup.senderProfile.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_28)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_29, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.avatarText), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.displayName || $setup.senderProfile.uid), 1 /* TEXT */), $setup.senderProfile.roleLabel ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_30, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.roleLabel), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dl\", _hoisted_31, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[10] || (_cache[10] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dt\", null, \"用户ID\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.uid || '-'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[11] || (_cache[11] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dt\", null, \"昵称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.rawName || $setup.senderProfile.displayName || '-'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[12] || (_cache[12] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dt\", null, \"手机号\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.mobile || '未知'), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[13] || (_cache[13] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dt\", null, \"地区\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.address || '未知'), 1 /* TEXT */)])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", _hoisted_32, [_cache[14] || (_cache[14] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"备注名称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[5] || (_cache[5] = $event => $setup.senderProfile.aliasDraft = $event),\n maxlength: \"32\",\n autocomplete: \"off\",\n placeholder: \"可给群员设置备注\",\n disabled: $setup.senderProfile.saving || $setup.senderProfile.adding\n }, null, 8 /* PROPS */, _hoisted_33), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.senderProfile.aliasDraft, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"footer\", _hoisted_34, [$setup.senderProfile.notice ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_35, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.notice), 1 /* TEXT */)) : $setup.senderProfile.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_36, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.error), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), !$setup.senderProfile.isContact ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: 2,\n type: \"button\",\n class: \"ghost-inline-action\",\n disabled: $setup.senderProfile.adding || $setup.senderProfile.saving || !$setup.senderProfile.uid,\n onClick: $setup.addSenderAsContact\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.adding ? '添加中...' : '添加为好友'), 9 /* TEXT, PROPS */, _hoisted_37)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n disabled: $setup.senderProfile.saving || $setup.senderProfile.adding || !$setup.senderProfile.uid,\n onClick: $setup.saveSenderAlias\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.senderProfile.saving ? '保存中...' : '保存备注'), 9 /* TEXT, PROPS */, _hoisted_38)])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]))], 512 /* NEED_PATCH */);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/contacts/ContactPanel.vue?vue&type=template&id=63d88b80":
/*!***********************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/contacts/ContactPanel.vue?vue&type=template&id=63d88b80 ***!
\***********************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"contact-panel\"\n};\nconst _hoisted_2 = {\n class: \"chat-header\"\n};\nconst _hoisted_3 = {\n class: \"contact-profile\"\n};\nconst _hoisted_4 = [\"src\"];\nconst _hoisted_5 = {\n key: 1,\n class: \"profile-avatar\"\n};\nconst _hoisted_6 = {\n class: \"profile-main\"\n};\nconst _hoisted_7 = {\n class: \"remark-row\"\n};\nconst _hoisted_8 = {\n class: \"profile-fields\"\n};\nconst _hoisted_9 = {\n key: 0,\n class: \"form-error\"\n};\nconst _hoisted_10 = {\n class: \"modal-actions\"\n};\nconst _hoisted_11 = [\"disabled\"];\nconst _hoisted_12 = [\"disabled\"];\nconst _hoisted_13 = {\n key: 1,\n class: \"empty-chat\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"section\", _hoisted_1, [$setup.contact ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 0\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h2\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.remarkName), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.username), 1 /* TEXT */)])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [$setup.contact.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n class: \"profile-avatar image-avatar\",\n src: $setup.contact.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_4)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_5, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.contact.avatarText), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_6, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_7, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h3\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.remarkName), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button remark-edit-button\",\n title: \"编辑备注名\",\n onClick: $setup.openAliasEditor\n }, \"✏️\")])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dl\", _hoisted_8, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[2] || (_cache[2] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dt\", null, \"用户名\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.username), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dt\", null, \"手机号\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.mobile), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[4] || (_cache[4] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dt\", null, \"地区\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"dd\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.address), 1 /* TEXT */)])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"primary-action profile-action\",\n onClick: _cache[0] || (_cache[0] = $event => $setup.contacts.openChat($setup.contact))\n }, \"发消息\")]), $setup.editingAlias ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"modal-backdrop contact-modal-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.closeAliasEditor, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"form\", {\n class: \"modal-panel\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.submitAlias, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [_cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"编辑备注名\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeAliasEditor\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[6] || (_cache[6] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"备注名\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[1] || (_cache[1] = $event => $setup.aliasDraft = $event),\n maxlength: \"32\",\n autocomplete: \"off\",\n autofocus: \"\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.aliasDraft, void 0, {\n trim: true\n }]])]), $setup.aliasError ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.aliasError), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n disabled: $setup.aliasSaving,\n onClick: $setup.closeAliasEditor\n }, \"取消\", 8 /* PROPS */, _hoisted_11), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"submit\",\n class: \"primary-inline-action\",\n disabled: $setup.aliasSaving\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.aliasSaving ? '保存中' : '保存'), 9 /* TEXT, PROPS */, _hoisted_12)])], 32 /* NEED_HYDRATION */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 64 /* STABLE_FRAGMENT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_13, _cache[7] || (_cache[7] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"选择一个联系人\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"好友列表同步完成后,可以在左侧查看资料\", -1 /* HOISTED */)])))]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/contacts/ContactPanel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoriteList.vue?vue&type=template&id=0086db7c":
/*!************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoriteList.vue?vue&type=template&id=0086db7c ***!
\************************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"conversation-list favorite-list\"\n};\nconst _hoisted_2 = {\n class: \"list-header\"\n};\nconst _hoisted_3 = {\n class: \"sidebar-scroll\"\n};\nconst _hoisted_4 = [\"onClick\"];\nconst _hoisted_5 = {\n class: \"favorite-item-main\"\n};\nconst _hoisted_6 = {\n key: 0,\n class: \"empty-list\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"aside\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h2\", null, \"收藏\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.conversations.favoriteMessages.length) + \" 条消息\", 1 /* TEXT */)])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.conversations.favoriteMessages, item => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: item.key,\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"favorite-item\", {\n active: $setup.activeKey === item.key\n }]),\n onClick: $event => $setup.conversations.setActiveFavorite(item.key)\n }, [_cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"favorite-item-icon\"\n }, \"★\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.favoriteTitle(item)), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.favoritePreview(item)), 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"time\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatFavoriteTime(item.timestamp)), 1 /* TEXT */)], 10 /* CLASS, PROPS */, _hoisted_4);\n }), 128 /* KEYED_FRAGMENT */)), !$setup.conversations.favoriteMessages.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_6, \" 暂无收藏消息 \")) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)])]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoriteList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoritePanel.vue?vue&type=template&id=29e1a3e0":
/*!*************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoritePanel.vue?vue&type=template&id=29e1a3e0 ***!
\*************************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"favorite-panel\"\n};\nconst _hoisted_2 = {\n class: \"chat-header\"\n};\nconst _hoisted_3 = {\n class: \"favorite-detail\"\n};\nconst _hoisted_4 = {\n class: \"favorite-detail-body\"\n};\nconst _hoisted_5 = {\n key: 0,\n class: \"recall-mark\"\n};\nconst _hoisted_6 = [\"href\"];\nconst _hoisted_7 = [\"src\", \"alt\"];\nconst _hoisted_8 = [\"href\"];\nconst _hoisted_9 = {\n class: \"message-file-main\"\n};\nconst _hoisted_10 = {\n key: 3\n};\nconst _hoisted_11 = {\n class: \"favorite-detail-actions\"\n};\nconst _hoisted_12 = {\n key: 0,\n class: \"inline-save-status\"\n};\nconst _hoisted_13 = {\n key: 1,\n class: \"inline-save-status error\"\n};\nconst _hoisted_14 = {\n key: 1,\n class: \"empty-chat\"\n};\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"section\", _hoisted_1, [$setup.favorite ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 0\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[0] || (_cache[0] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h2\", null, \"收藏详情\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.favoriteTitle($setup.favorite)), 1 /* TEXT */)])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"favorite-detail-message\", {\n recalled: $setup.favorite.recalled\n }])\n }, [_cache[2] || (_cache[2] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"favorite-detail-star\"\n }, \"★\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [$setup.favorite.recalled ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_5, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.favorite.recallStatus || '已撤回'), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.isImageFavorite($setup.favorite) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"a\", {\n key: 1,\n class: \"favorite-detail-image\",\n href: $setup.favorite.attachment.url,\n target: \"_blank\",\n rel: \"noreferrer\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"img\", {\n src: $setup.imageDisplayUrl($setup.favorite.attachment.url),\n alt: $setup.favorite.attachment.name || '图片'\n }, null, 8 /* PROPS */, _hoisted_7)], 8 /* PROPS */, _hoisted_6)) : $setup.isFileFavorite($setup.favorite) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"a\", {\n key: 2,\n class: \"message-file favorite-detail-file\",\n href: $setup.favorite.attachment.url,\n target: \"_blank\",\n rel: \"noreferrer\",\n download: \"\"\n }, [_cache[1] || (_cache[1] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", {\n class: \"message-file-icon\"\n }, \"▤\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.favorite.attachment.name || '文件'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatFileSize($setup.favorite.attachment.size)), 1 /* TEXT */)])], 8 /* PROPS */, _hoisted_8)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.favoriteText($setup.favorite) ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.favoriteText($setup.favorite)), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"time\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatFavoriteTime($setup.favorite.timestamp)), 1 /* TEXT */)], 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_11, [$setup.notice ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.notice), 1 /* TEXT */)) : $setup.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_13, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.error), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n onClick: $setup.copyFavorite\n }, \"复制\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n onClick: $setup.openConversation\n }, \"打开原会话\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"danger-inline-action\",\n onClick: $setup.removeFavorite\n }, \"取消收藏\")])])], 64 /* STABLE_FRAGMENT */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_14, _cache[3] || (_cache[3] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"暂无收藏消息\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"右键消息气泡选择“收藏”后,会显示在这里\", -1 /* HOISTED */)])))]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoritePanel.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ContactList.vue?vue&type=template&id=7aaf5f2b":
/*!*********************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ContactList.vue?vue&type=template&id=7aaf5f2b ***!
\*********************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"conversation-list\"\n};\nconst _hoisted_2 = {\n class: \"list-header\"\n};\nconst _hoisted_3 = {\n class: \"header-actions\"\n};\nconst _hoisted_4 = {\n class: \"search-box\"\n};\nconst _hoisted_5 = {\n class: \"sidebar-scroll\"\n};\nconst _hoisted_6 = [\"onClick\"];\nconst _hoisted_7 = [\"src\"];\nconst _hoisted_8 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_9 = {\n class: \"conversation-copy\"\n};\nconst _hoisted_10 = {\n key: 0,\n class: \"empty-list\"\n};\nconst _hoisted_11 = {\n key: 0,\n class: \"form-error\"\n};\nconst _hoisted_12 = {\n key: 1,\n class: \"form-info\"\n};\nconst _hoisted_13 = {\n class: \"modal-actions\"\n};\nconst _hoisted_14 = [\"disabled\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"aside\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[3] || (_cache[3] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h2\", null, \"联系人\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.contacts.contacts.length) + \" 位好友\", 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"icon-button\",\n title: \"添加联系人\",\n onClick: $setup.openAddContact\n }, \"+\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"icon-button\",\n title: \"刷新\",\n onClick: _cache[0] || (_cache[0] = $event => $setup.contacts.refreshContacts({\n force: true\n }))\n }, \"↻\")])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[1] || (_cache[1] = $event => $setup.keyword = $event),\n placeholder: \"搜索联系人\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.keyword, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.filteredContacts, item => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: item.id,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"conversation-item\", {\n active: item.id === $setup.contacts.activeId\n }]),\n onClick: $event => $setup.contacts.setActiveContact(item.id)\n }, [item.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: item.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_7)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.avatarText), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.title), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.subtitle), 1 /* TEXT */)])], 10 /* CLASS, PROPS */, _hoisted_6);\n }), 128 /* KEYED_FRAGMENT */)), !$setup.filteredContacts.length ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.contacts.loading ? '正在加载' : '暂无联系人'), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.contacts.loading ? '请稍候' : '好友同步完成后会显示在这里'), 1 /* TEXT */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]), $setup.addingContact ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"modal-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.closeAddContact, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"form\", {\n class: \"modal-panel\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.submitAddContact, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [_cache[4] || (_cache[4] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"添加联系人\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeAddContact\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"用户ID / 手机号 / 用户名\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[2] || (_cache[2] = $event => $setup.addKeyword = $event),\n autocomplete: \"off\",\n placeholder: \"请输入要添加的联系人\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.addKeyword, void 0, {\n trim: true\n }]])]), $setup.contacts.actionError ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_11, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.contacts.actionError), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.contacts.actionInfo ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_12, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.contacts.actionInfo), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n onClick: $setup.closeAddContact\n }, \"取消\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"primary-inline-action\",\n disabled: $setup.contacts.loading || !$setup.addKeyword\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.contacts.loading ? '添加中...' : '添加'), 9 /* TEXT, PROPS */, _hoisted_14)])], 32 /* NEED_HYDRATION */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ContactList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ConversationList.vue?vue&type=template&id=7a656f78":
/*!**************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ConversationList.vue?vue&type=template&id=7a656f78 ***!
\**************************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"conversation-list\"\n};\nconst _hoisted_2 = {\n class: \"list-header\"\n};\nconst _hoisted_3 = {\n class: \"header-actions action-menu-anchor\"\n};\nconst _hoisted_4 = {\n class: \"search-box\"\n};\nconst _hoisted_5 = {\n class: \"sidebar-scroll\"\n};\nconst _hoisted_6 = [\"onClick\"];\nconst _hoisted_7 = [\"src\"];\nconst _hoisted_8 = {\n key: 1,\n class: \"conversation-avatar\"\n};\nconst _hoisted_9 = {\n class: \"conversation-copy\"\n};\nconst _hoisted_10 = [\"aria-label\"];\nconst _hoisted_11 = {\n key: 0,\n class: \"empty-list\"\n};\nconst _hoisted_12 = {\n key: 1,\n class: \"empty-list\"\n};\nconst _hoisted_13 = {\n key: 0\n};\nconst _hoisted_14 = {\n key: 2\n};\nconst _hoisted_15 = {\n key: 5,\n class: \"form-error\"\n};\nconst _hoisted_16 = {\n key: 6,\n class: \"form-info\"\n};\nconst _hoisted_17 = {\n class: \"modal-actions\"\n};\nconst _hoisted_18 = [\"disabled\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"aside\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", null, [_cache[18] || (_cache[18] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h2\", null, \"消息\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.conversations.totalUnread) + \" 条未读\", 1 /* TEXT */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_3, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"icon-button\",\n title: \"新建会话\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.toggleActionMenu, [\"stop\"])\n }, \"+\"), $setup.actionMenuOpen ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"quick-action-menu\",\n onClick: _cache[5] || (_cache[5] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, [\"stop\"]))\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[0] || (_cache[0] = $event => $setup.openAction('addContact'))\n }, \"添加联系人\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[1] || (_cache[1] = $event => $setup.openAction('createGroup'))\n }, \"新建群组\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[2] || (_cache[2] = $event => $setup.openAction('joinGroup'))\n }, \"加入群组\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[3] || (_cache[3] = $event => $setup.openAction('broadcast'))\n }, \"群发助手\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n onClick: _cache[4] || (_cache[4] = $event => $setup.openAction('createChannel'))\n }, \"创建频道/公告群\")])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[6] || (_cache[6] = $event => $setup.searchKeyword = $event),\n placeholder: \"搜索会话、联系人\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.searchKeyword, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.filteredConversationItems, item => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"button\", {\n key: item.resultKey,\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"conversation-item\", {\n active: $setup.isListItemActive(item)\n }]),\n onClick: $event => $setup.selectListItem(item)\n }, [item.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n class: \"conversation-avatar image-avatar\",\n src: item.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_7)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_8, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.avatarText), 1 /* TEXT */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.title), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"small\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.subtitle), 1 /* TEXT */)]), Number(item.unread || 0) > 0 ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", {\n key: 2,\n class: \"unread-badge\",\n \"aria-label\": `${item.unread} 条未读消息`\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.formatUnread(item.unread)), 9 /* TEXT, PROPS */, _hoisted_10)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 10 /* CLASS, PROPS */, _hoisted_6);\n }), 128 /* KEYED_FRAGMENT */)), !$setup.filteredConversationItems.length && $setup.searchKeyword ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_11, _cache[19] || (_cache[19] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"没有匹配结果\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"换个关键词再试试\", -1 /* HOISTED */)]))) : !$setup.conversations.conversations.length && !$setup.conversations.usingDemoData ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_12, _cache[20] || (_cache[20] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"暂无会话\", -1 /* HOISTED */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"收到或发起消息后会出现在这里\", -1 /* HOISTED */)]))) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]), $setup.activeAction ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"modal-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.closeActionModal, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"form\", {\n class: \"modal-panel conversation-action-panel\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.submitAction, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.actionTitle), 1 /* TEXT */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeActionModal\n }, \"×\")]), $setup.activeAction === 'addContact' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"label\", _hoisted_13, [_cache[21] || (_cache[21] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"用户ID / 手机号 / 用户名\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[7] || (_cache[7] = $event => $setup.addKeyword = $event),\n autocomplete: \"off\",\n placeholder: \"请输入要添加的联系人\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.addKeyword, void 0, {\n trim: true\n }]])])) : $setup.activeAction === 'createGroup' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 1\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"群组名称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[8] || (_cache[8] = $event => $setup.groupName = $event),\n maxlength: \"64\",\n autocomplete: \"off\",\n placeholder: \"请输入群组名称\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.groupName, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"群说明\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"textarea\", {\n \"onUpdate:modelValue\": _cache[9] || (_cache[9] = $event => $setup.groupAnnouncement = $event),\n maxlength: \"1000\",\n rows: \"3\",\n placeholder: \"可选\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.groupAnnouncement, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[24] || (_cache[24] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"欢迎词\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"textarea\", {\n \"onUpdate:modelValue\": _cache[10] || (_cache[10] = $event => $setup.groupWelcomeText = $event),\n maxlength: \"1000\",\n rows: \"3\",\n placeholder: \"群组创建后自动发送\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.groupWelcomeText, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"ContactPicker\"], {\n contacts: $setup.filteredContacts,\n \"selected-ids\": $setup.selectedContactIds,\n keyword: $setup.contactKeyword,\n \"empty-text\": \"暂无可选联系人\",\n \"onUpdate:keyword\": _cache[11] || (_cache[11] = $event => $setup.contactKeyword = $event),\n onToggle: $setup.toggleContact\n }, null, 8 /* PROPS */, [\"contacts\", \"selected-ids\", \"keyword\"])], 64 /* STABLE_FRAGMENT */)) : $setup.activeAction === 'joinGroup' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"label\", _hoisted_14, [_cache[25] || (_cache[25] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"群组ID / 群名称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[12] || (_cache[12] = $event => $setup.joinGroupKey = $event),\n autocomplete: \"off\",\n placeholder: \"请输入群组ID或群名称\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.joinGroupKey, void 0, {\n trim: true\n }]])])) : $setup.activeAction === 'broadcast' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 3\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[26] || (_cache[26] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"群发内容\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"textarea\", {\n \"onUpdate:modelValue\": _cache[13] || (_cache[13] = $event => $setup.broadcastText = $event),\n maxlength: \"2000\",\n rows: \"4\",\n placeholder: \"输入要群发的文字\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.broadcastText, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"ContactPicker\"], {\n contacts: $setup.filteredContacts,\n \"selected-ids\": $setup.selectedContactIds,\n keyword: $setup.contactKeyword,\n \"empty-text\": \"暂无可选联系人\",\n \"onUpdate:keyword\": _cache[14] || (_cache[14] = $event => $setup.contactKeyword = $event),\n onToggle: $setup.toggleContact\n }, null, 8 /* PROPS */, [\"contacts\", \"selected-ids\", \"keyword\"])], 64 /* STABLE_FRAGMENT */)) : $setup.activeAction === 'createChannel' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, {\n key: 4\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"频道/公告群名称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[15] || (_cache[15] = $event => $setup.channelName = $event),\n maxlength: \"64\",\n autocomplete: \"off\",\n placeholder: \"请输入名称\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.channelName, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[28] || (_cache[28] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"公告说明\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"textarea\", {\n \"onUpdate:modelValue\": _cache[16] || (_cache[16] = $event => $setup.channelAnnouncement = $event),\n maxlength: \"1000\",\n rows: \"3\",\n placeholder: \"可选\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.channelAnnouncement, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)($setup[\"ContactPicker\"], {\n contacts: $setup.filteredContacts,\n \"selected-ids\": $setup.selectedContactIds,\n keyword: $setup.contactKeyword,\n \"empty-text\": \"暂无可选联系人\",\n \"onUpdate:keyword\": _cache[17] || (_cache[17] = $event => $setup.contactKeyword = $event),\n onToggle: $setup.toggleContact\n }, null, 8 /* PROPS */, [\"contacts\", \"selected-ids\", \"keyword\"])], 64 /* STABLE_FRAGMENT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.modalError ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_15, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.modalError), 1 /* TEXT */)) : $setup.modalInfo ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"p\", _hoisted_16, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.modalInfo), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_17, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n onClick: $setup.closeActionModal\n }, \"取消\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"primary-inline-action\",\n disabled: $setup.actionBusy || $setup.submitDisabled\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.actionBusy ? '处理中...' : $setup.submitLabel), 9 /* TEXT, PROPS */, _hoisted_18)])], 32 /* NEED_HYDRATION */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)]);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ConversationList.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/NavigationRail.vue?vue&type=template&id=021016ee":
/*!************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/NavigationRail.vue?vue&type=template&id=021016ee ***!
\************************************************************************************************************************************************************************************************************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* binding */ render; }\n/* harmony export */ });\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n\nconst _hoisted_1 = {\n class: \"navigation-rail\"\n};\nconst _hoisted_2 = [\"src\"];\nconst _hoisted_3 = {\n key: 1\n};\nconst _hoisted_4 = {\n class: \"settings-panel\"\n};\nconst _hoisted_5 = {\n class: \"settings-layout\"\n};\nconst _hoisted_6 = {\n class: \"settings-menu\",\n \"aria-label\": \"设置菜单\"\n};\nconst _hoisted_7 = [\"onClick\"];\nconst _hoisted_8 = {\n key: 0\n};\nconst _hoisted_9 = {\n key: 0,\n class: \"inline-save-status\"\n};\nconst _hoisted_10 = {\n key: 1,\n class: \"inline-save-status error\"\n};\nconst _hoisted_11 = [\"disabled\"];\nconst _hoisted_12 = {\n key: 1,\n class: \"settings-placeholder\"\n};\nconst _hoisted_13 = {\n class: \"profile-avatar-field\"\n};\nconst _hoisted_14 = [\"src\"];\nconst _hoisted_15 = {\n key: 1\n};\nconst _hoisted_16 = [\"value\"];\nconst _hoisted_17 = {\n class: \"modal-actions\"\n};\nconst _hoisted_18 = {\n key: 0,\n class: \"inline-save-status\"\n};\nconst _hoisted_19 = {\n key: 1,\n class: \"inline-save-status error\"\n};\nconst _hoisted_20 = [\"disabled\"];\nconst _hoisted_21 = {\n class: \"avatar-preview-dialog\"\n};\nconst _hoisted_22 = {\n class: \"avatar-preview-actions\"\n};\nconst _hoisted_23 = [\"src\"];\nconst _hoisted_24 = {\n class: \"modal-panel avatar-cropper-panel\"\n};\nconst _hoisted_25 = {\n class: \"avatar-cropper-header-actions\"\n};\nconst _hoisted_26 = [\"disabled\"];\nconst _hoisted_27 = {\n class: \"avatar-cropper-layout\"\n};\nconst _hoisted_28 = {\n ref: \"cropperCanvas\"\n};\nconst _hoisted_29 = {\n key: 0,\n class: \"avatar-cropper-placeholder\"\n};\nconst _hoisted_30 = {\n class: \"avatar-cropper-controls\"\n};\nconst _hoisted_31 = {\n class: \"avatar-cropper-tools\"\n};\nconst _hoisted_32 = {\n class: \"avatar-cropper-preview\"\n};\nconst _hoisted_33 = {\n ref: \"cropperPreviewCanvas\"\n};\nconst _hoisted_34 = {\n key: 0,\n class: \"inline-save-status error\"\n};\nconst _hoisted_35 = [\"disabled\"];\nconst _hoisted_36 = [\"disabled\"];\nfunction render(_ctx, _cache, $props, $setup, $data, $options) {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"aside\", _hoisted_1, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"rail-avatar rail-avatar-button\",\n title: \"编辑个人资料\",\n onClick: $setup.openProfileEditor\n }, [$setup.session.portrait ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n src: $setup.session.portrait,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_2)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.initials), 1 /* TEXT */))]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"rail-button\", {\n active: $setup.navigation.section === 'messages'\n }]),\n title: \"消息\",\n onClick: _cache[0] || (_cache[0] = (...args) => $setup.navigation.showMessages && $setup.navigation.showMessages(...args))\n }, \"💬\", 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"rail-button\", {\n active: $setup.navigation.section === 'contacts'\n }]),\n title: \"联系人\",\n onClick: $setup.showContacts\n }, \"👥\", 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"rail-button\", {\n active: $setup.navigation.section === 'favorites'\n }]),\n title: \"收藏\",\n onClick: _cache[1] || (_cache[1] = (...args) => $setup.navigation.showFavorites && $setup.navigation.showFavorites(...args))\n }, \"☆\", 2 /* CLASS */), _cache[15] || (_cache[15] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"rail-spacer\"\n }, null, -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"rail-button\",\n title: \"设置\",\n \"aria-label\": \"设置\",\n onClick: $setup.openSettings\n }, _cache[13] || (_cache[13] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"svg\", {\n viewBox: \"0 0 24 24\",\n \"aria-hidden\": \"true\"\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"path\", {\n d: \"M12 8.2a3.8 3.8 0 1 1 0 7.6 3.8 3.8 0 0 1 0-7.6Z\"\n }), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"path\", {\n d: \"M19.4 13.6a7.8 7.8 0 0 0 .1-1.6l1.7-1.3-1.7-3-2 .8a8 8 0 0 0-1.4-.8L15.8 5h-3.5l-.3 2.1a8 8 0 0 0-1.5.8l-1.9-.8-1.8 3 1.7 1.3a7.8 7.8 0 0 0 0 1.6l-1.7 1.3 1.8 3 1.9-.8c.5.4 1 .7 1.5.8l.3 2.1h3.5l.3-2.1c.5-.2 1-.5 1.4-.8l2 .8 1.7-3-1.8-1.3Z\"\n })], -1 /* HOISTED */)])), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"rail-button rail-logout-button\",\n title: \"退出登录\",\n \"aria-label\": \"退出登录\",\n onClick: $setup.logout\n }, _cache[14] || (_cache[14] = [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createStaticVNode)(\"<svg viewBox=\\\"0 0 24 24\\\" aria-hidden=\\\"true\\\"><path d=\\\"M4.5 20.5V3.5h9.2a1.8 1.8 0 0 1 1.8 1.8v13.4a1.8 1.8 0 0 1-1.8 1.8H4.5Z\\\"></path><path d=\\\"M9 12h9.5\\\"></path><path d=\\\"m15.5 8.8 3.2 3.2-3.2 3.2\\\"></path><path d=\\\"M7.8 20.5V5.8l6.5-2.3\\\"></path></svg>\", 1)]))]), $setup.settingsOpen ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 0,\n class: \"modal-backdrop settings-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.closeSettings, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", _hoisted_4, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [_cache[16] || (_cache[16] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"设置\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeSettings\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_5, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"nav\", _hoisted_6, [((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($setup.settingsItems, item => {\n return (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n key: item.key,\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)({\n active: $setup.settingsSection === item.key\n }),\n onClick: $event => $setup.selectSettingsSection(item.key)\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(item.label), 1 /* TEXT */), item.key !== 'password' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"small\", _hoisted_8, \"稍后开放\")) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 10 /* CLASS, PROPS */, _hoisted_7);\n }), 64 /* STABLE_FRAGMENT */))]), $setup.settingsSection === 'password' ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"form\", {\n key: 0,\n class: \"settings-password-form\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.savePassword, [\"prevent\"])\n }, [_cache[20] || (_cache[20] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h3\", null, \"更改密码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[17] || (_cache[17] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"当前密码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[2] || (_cache[2] = $event => $setup.passwordDraft.oldPassword = $event),\n type: \"password\",\n autocomplete: \"current-password\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.passwordDraft.oldPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[18] || (_cache[18] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"新密码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[3] || (_cache[3] = $event => $setup.passwordDraft.newPassword = $event),\n type: \"password\",\n autocomplete: \"new-password\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.passwordDraft.newPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[19] || (_cache[19] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"确认新密码\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[4] || (_cache[4] = $event => $setup.passwordDraft.confirmPassword = $event),\n type: \"password\",\n autocomplete: \"new-password\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.passwordDraft.confirmPassword]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"footer\", null, [$setup.settingsNotice ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_9, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.settingsNotice), 1 /* TEXT */)) : $setup.settingsError ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_10, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.settingsError), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"submit\",\n class: \"primary-inline-action\",\n disabled: $setup.passwordSaving\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.passwordSaving ? '保存中...' : '保存密码'), 9 /* TEXT, PROPS */, _hoisted_11)])], 32 /* NEED_HYDRATION */)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"section\", _hoisted_12, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"h3\", null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.activeSettingsItem?.label || '设置'), 1 /* TEXT */), _cache[21] || (_cache[21] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"p\", null, \"该功能稍后开放。\", -1 /* HOISTED */))]))])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.profileOpen ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 1,\n class: \"modal-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.closeProfileEditor, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"form\", {\n class: \"modal-panel profile-edit-panel\",\n onSubmit: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.saveProfile, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [_cache[22] || (_cache[22] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"个人资料\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeProfileEditor\n }, \"×\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_13, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"profile-avatar-preview\", {\n clickable: $setup.currentAvatarUrl\n }]),\n title: \"预览头像\",\n onClick: $setup.openAvatarPreview\n }, [$setup.currentAvatarUrl ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"img\", {\n key: 0,\n src: $setup.currentAvatarUrl,\n alt: \"\"\n }, null, 8 /* PROPS */, _hoisted_14)) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_15, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.initials), 1 /* TEXT */))], 2 /* CLASS */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action profile-avatar-change-button\",\n onClick: $setup.choosePortraitFile\n }, \"更换头像\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n ref: \"portraitInput\",\n type: \"file\",\n accept: \"image/*\",\n onChange: $setup.selectPortrait\n }, null, 544 /* NEED_HYDRATION, NEED_PATCH */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[23] || (_cache[23] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"昵称\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.withDirectives)((0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n \"onUpdate:modelValue\": _cache[5] || (_cache[5] = $event => $setup.profileDraft.displayName = $event),\n maxlength: \"64\",\n autocomplete: \"off\"\n }, null, 512 /* NEED_PATCH */), [[vue__WEBPACK_IMPORTED_MODULE_0__.vModelText, $setup.profileDraft.displayName, void 0, {\n trim: true\n }]])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"label\", null, [_cache[24] || (_cache[24] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"span\", null, \"用户ID\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"input\", {\n value: $setup.session.userId,\n readonly: \"\"\n }, null, 8 /* PROPS */, _hoisted_16)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_17, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n onClick: $setup.closeProfileEditor\n }, \"取消\"), $setup.profileNotice ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_18, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.profileNotice), 1 /* TEXT */)) : $setup.profileError ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_19, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.profileError), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n class: \"primary-inline-action\",\n disabled: $setup.profileSaving || !$setup.profileDraft.displayName\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.profileSaving ? '保存中...' : '保存'), 9 /* TEXT, PROPS */, _hoisted_20)])], 32 /* NEED_HYDRATION */)])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.avatarPreviewViewer.open ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 2,\n class: \"modal-backdrop avatar-preview-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.closeAvatarPreview, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", _hoisted_21, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [_cache[25] || (_cache[25] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"头像预览\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_22, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"缩小\",\n onClick: _cache[6] || (_cache[6] = $event => $setup.zoomAvatarPreview(1 / 1.16))\n }, \"−\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"放大\",\n onClick: _cache[7] || (_cache[7] = $event => $setup.zoomAvatarPreview(1.16))\n }, \"+\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"还原\",\n onClick: $setup.resetAvatarPreview\n }, \"1:1\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeAvatarPreview\n }, \"×\")])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"avatar-preview-stage\", {\n dragging: $setup.avatarPreviewViewer.dragging\n }]),\n onWheel: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handleAvatarPreviewWheel, [\"prevent\"]),\n onPointerdown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.startAvatarPreviewDrag, [\"prevent\"]),\n onPointermove: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.moveAvatarPreviewDrag, [\"prevent\"]),\n onPointerup: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.stopAvatarPreviewDrag, [\"prevent\"]),\n onPointerleave: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.stopAvatarPreviewDrag, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"img\", {\n src: $setup.avatarPreviewViewer.url,\n alt: \"头像预览\",\n style: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeStyle)($setup.avatarPreviewStyle),\n draggable: \"false\"\n }, null, 12 /* STYLE, PROPS */, _hoisted_23)], 34 /* CLASS, NEED_HYDRATION */)])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), $setup.avatarCropper.open ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", {\n key: 3,\n class: \"modal-backdrop avatar-cropper-backdrop\",\n onClick: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.closeAvatarCropper, [\"self\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"section\", _hoisted_24, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"header\", null, [_cache[26] || (_cache[26] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"strong\", null, \"头像预裁切\", -1 /* HOISTED */)), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_25, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n disabled: $setup.avatarCropper.busy,\n onClick: $setup.choosePortraitFile\n }, \"上传\", 8 /* PROPS */, _hoisted_26), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"icon-button\",\n title: \"关闭\",\n onClick: $setup.closeAvatarCropper\n }, \"×\")])]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_27, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([\"avatar-cropper-stage\", {\n dragging: $setup.avatarCropper.dragging\n }]),\n onWheel: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.handleCropperWheel, [\"prevent\"]),\n onPointerdown: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.startCropperDrag, [\"prevent\"]),\n onPointermove: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.moveCropperDrag, [\"prevent\"]),\n onPointerup: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.stopCropperDrag, [\"prevent\"]),\n onPointerleave: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.stopCropperDrag, [\"prevent\"]),\n onDragover: _cache[8] || (_cache[8] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)(() => {}, [\"prevent\"])),\n onDrop: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withModifiers)($setup.dropPortrait, [\"prevent\"])\n }, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"canvas\", _hoisted_28, null, 512 /* NEED_PATCH */), _cache[27] || (_cache[27] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"avatar-cropper-mask\",\n \"aria-hidden\": \"true\"\n }, null, -1 /* HOISTED */)), _cache[28] || (_cache[28] = (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", {\n class: \"avatar-cropper-box\",\n \"aria-hidden\": \"true\"\n }, null, -1 /* HOISTED */)), !$setup.avatarCropper.loaded ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"div\", _hoisted_29, \"图片加载中\")) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 34 /* CLASS, NEED_HYDRATION */), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"aside\", _hoisted_30, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_31, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"左旋90度\",\n onClick: _cache[9] || (_cache[9] = $event => $setup.rotateCropper(-90))\n }, \"↶90°\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"右旋90度\",\n onClick: _cache[10] || (_cache[10] = $event => $setup.rotateCropper(90))\n }, \"↷90°\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"放大\",\n onClick: _cache[11] || (_cache[11] = $event => $setup.zoomCropper(1.12))\n }, \"+\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"缩小\",\n onClick: _cache[12] || (_cache[12] = $event => $setup.zoomCropper(1 / 1.12))\n }, \"−\"), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n title: \"重置\",\n onClick: $setup.resetCropperTransform\n }, \"重置\")]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"div\", _hoisted_32, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"canvas\", _hoisted_33, null, 512 /* NEED_PATCH */)]), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"footer\", null, [$setup.avatarCropper.error ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(\"span\", _hoisted_34, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.avatarCropper.error), 1 /* TEXT */)) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"ghost-inline-action\",\n disabled: $setup.avatarCropper.busy,\n onClick: $setup.closeAvatarCropper\n }, \"取消\", 8 /* PROPS */, _hoisted_35), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)(\"button\", {\n type: \"button\",\n class: \"primary-inline-action\",\n disabled: $setup.avatarCropper.busy || !$setup.avatarCropper.loaded,\n onClick: $setup.confirmAvatarCrop\n }, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($setup.avatarCropper.busy ? '处理中...' : '确认裁切'), 9 /* TEXT, PROPS */, _hoisted_36)])])])])])) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)(\"v-if\", true)], 64 /* STABLE_FRAGMENT */);\n}\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/NavigationRail.vue?./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use%5B0%5D!./node_modules/vue-loader/dist/templateLoader.js??ruleSet%5B1%5D.rules%5B3%5D!./node_modules/vue-loader/dist/index.js??ruleSet%5B0%5D.use%5B0%5D\n}");
/***/ }),
/***/ "./src/config.js":
/*!***********************!*\
!*** ./src/config.js ***!
\***********************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ appConfig: function() { return /* binding */ appConfig; }\n/* harmony export */ });\nconst currentHost = window.location.hostname || '127.0.0.1';\nconst runtimeConfig = window.JC_WEB_IM_CONFIG || {};\nconst appServerOrigin = `${window.location.protocol}//${currentHost}:8888`;\nconst qrAppServerOrigin = `${window.location.protocol}//${currentHost}:18888`;\nconst adminServerOrigin = `${window.location.protocol}//${currentHost}:8024`;\nconst appConfig = {\n appName: 'Web IM',\n adminServer: runtimeConfig.adminServer || undefined || adminServerOrigin,\n appServer: runtimeConfig.appServer || undefined || appServerOrigin,\n qrAppServer: runtimeConfig.qrAppServer || undefined || qrAppServerOrigin,\n platformConfigApi: runtimeConfig.platformConfigApi || undefined || ( true ? '/local-api/platform_config.php' : 0),\n registerConfigApi: runtimeConfig.registerConfigApi || undefined || `${adminServerOrigin}/api/register-config`,\n registerPhoneExistsApi: runtimeConfig.registerPhoneExistsApi || undefined || `${adminServerOrigin}/api/register-phone-exists`,\n contactsApi: runtimeConfig.contactsApi || undefined || ( true ? '/local-api/contacts.php' : 0),\n updateAliasApi: runtimeConfig.updateAliasApi || undefined || ( true ? '/local-api/update_alias.php' : 0),\n addContactApi: runtimeConfig.addContactApi || undefined || ( true ? '/local-api/add_contact.php' : 0),\n conversationActionsApi: runtimeConfig.conversationActionsApi || undefined || ( true ? '/local-api/conversation_actions.php' : 0),\n sendMessageApi: runtimeConfig.sendMessageApi || undefined || ( true ? '/local-api/send_message.php' : 0),\n messageActionApi: runtimeConfig.messageActionApi || undefined || ( true ? '/local-api/message_action.php' : 0),\n messageDetailApi: runtimeConfig.messageDetailApi || undefined || ( true ? '/local-api/message_detail.php' : 0),\n messagesApi: runtimeConfig.messagesApi || undefined || ( true ? '/local-api/messages.php' : 0),\n profileApi: runtimeConfig.profileApi || undefined || ( true ? '/local-api/profile.php' : 0),\n changePasswordApi: runtimeConfig.changePasswordApi || undefined || `${appServerOrigin}/auth/changePassword`,\n logoutApi: runtimeConfig.logoutApi || undefined || `${appServerOrigin}/auth/logout`,\n imServerHost: runtimeConfig.imServerHost || undefined || currentHost,\n imRoutePort: Number(runtimeConfig.imRoutePort || undefined || 18000),\n useWss: runtimeConfig.useWss ?? undefined === 'true',\n wsPath: runtimeConfig.wsPath || undefined || '/ws',\n wsUrl: runtimeConfig.wsUrl || undefined || '',\n sdkMode: runtimeConfig.sdkMode || undefined || 'http',\n syncIntervalMs: Number(runtimeConfig.syncIntervalMs || undefined || 300),\n sseEnabled: runtimeConfig.sseEnabled ?? undefined === 'true',\n sseTicketApi: runtimeConfig.sseTicketApi || undefined || '/api/sse_ticket.php',\n sseUrl: runtimeConfig.sseUrl || undefined || '/ws-events',\n platform: 5,\n clientIdStorageKey: 'qmt-web-im-client-id',\n authTokenStoragePrefix: 'qmt-web-im-auth-token-'\n};\n\n//# sourceURL=webpack://jc-web-im/./src/config.js?\n}");
/***/ }),
/***/ "./src/main.js":
/*!*********************!*\
!*** ./src/main.js ***!
\*********************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ \"./node_modules/vue/dist/vue.runtime.esm-bundler.js\");\n/* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! pinia */ \"./node_modules/pinia/dist/pinia.mjs\");\n/* harmony import */ var _App_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./App.vue */ \"./src/App.vue\");\n/* harmony import */ var _styles_base_css__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./styles/base.css */ \"./src/styles/base.css\");\n/* harmony import */ var _styles_base_css__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_styles_base_css__WEBPACK_IMPORTED_MODULE_3__);\n\n\n\n\n(0,vue__WEBPACK_IMPORTED_MODULE_0__.createApp)(_App_vue__WEBPACK_IMPORTED_MODULE_2__[\"default\"]).use((0,pinia__WEBPACK_IMPORTED_MODULE_1__.createPinia)()).mount('#app');\n\n//# sourceURL=webpack://jc-web-im/./src/main.js?\n}");
/***/ }),
/***/ "./src/services/appServerClient.js":
/*!*****************************************!*\
!*** ./src/services/appServerClient.js ***!
\*****************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ appServerGet: function() { return /* binding */ appServerGet; },\n/* harmony export */ appServerPost: function() { return /* binding */ appServerPost; },\n/* harmony export */ appServerRequest: function() { return /* binding */ appServerRequest; },\n/* harmony export */ clearStoredAppAuth: function() { return /* binding */ clearStoredAppAuth; },\n/* harmony export */ getStoredAppAuth: function() { return /* binding */ getStoredAppAuth; },\n/* harmony export */ persistAppAuth: function() { return /* binding */ persistAppAuth; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_typed_array_with_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.typed-array.with.js */ \"./node_modules/core-js/modules/es.typed-array.with.js\");\n/* harmony import */ var core_js_modules_es_typed_array_with_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_typed_array_with_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_uint8_array_set_from_base64_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.uint8-array.set-from-base64.js */ \"./node_modules/core-js/modules/es.uint8-array.set-from-base64.js\");\n/* harmony import */ var core_js_modules_es_uint8_array_set_from_base64_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_set_from_base64_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_uint8_array_set_from_hex_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.uint8-array.set-from-hex.js */ \"./node_modules/core-js/modules/es.uint8-array.set-from-hex.js\");\n/* harmony import */ var core_js_modules_es_uint8_array_set_from_hex_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_set_from_hex_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_uint8_array_to_base64_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.uint8-array.to-base64.js */ \"./node_modules/core-js/modules/es.uint8-array.to-base64.js\");\n/* harmony import */ var core_js_modules_es_uint8_array_to_base64_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_to_base64_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_es_uint8_array_to_hex_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/es.uint8-array.to-hex.js */ \"./node_modules/core-js/modules/es.uint8-array.to-hex.js\");\n/* harmony import */ var core_js_modules_es_uint8_array_to_hex_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_uint8_array_to_hex_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_web_dom_exception_stack_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/web.dom-exception.stack.js */ \"./node_modules/core-js/modules/web.dom-exception.stack.js\");\n/* harmony import */ var core_js_modules_web_dom_exception_stack_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_web_dom_exception_stack_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! axios */ \"./node_modules/axios/lib/axios.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n\n\n\n\n\n\n\n\n\n\nconst AES_KEY = 'xczx2026!@#secKe';\nconst ENCRYPTION_EXCLUDE_PATHS = ['/avatar/', '/f/', '/amr2mp3', '/appVersion/check'];\nconst AUTH_STORAGE_KEY = 'qmt-web-im-app-auth-v1';\nconst AUTH_ERROR_CODE = 13;\nconst REFRESH_ERROR_CODE = 20045;\nlet importedCryptoKeyPromise = null;\nlet refreshPromise = null;\nfunction storageScope() {\n return _config__WEBPACK_IMPORTED_MODULE_9__.appConfig.appServer || '';\n}\nfunction readAuthStore() {\n try {\n return JSON.parse(localStorage.getItem(AUTH_STORAGE_KEY) || '{}');\n } catch (error) {\n return {};\n }\n}\nfunction writeAuthStore(store) {\n localStorage.setItem(AUTH_STORAGE_KEY, JSON.stringify(store));\n}\nfunction normalizeAuthBundle(bundle = {}) {\n const accessToken = String(bundle.accessToken || '').trim();\n const refreshToken = String(bundle.refreshToken || '').trim();\n if (!accessToken || !refreshToken) {\n return null;\n }\n return {\n accessToken,\n refreshToken,\n tokenType: String(bundle.tokenType || 'Bearer').trim() || 'Bearer',\n accessTokenExpireIn: Number(bundle.accessTokenExpireIn || 0) || 0,\n accessTokenExpireAt: Number(bundle.accessTokenExpireAt || 0) || 0,\n refreshTokenExpireIn: Number(bundle.refreshTokenExpireIn || 0) || 0,\n refreshTokenExpireAt: Number(bundle.refreshTokenExpireAt || 0) || 0\n };\n}\nfunction getStoredAppAuth() {\n const store = readAuthStore();\n return normalizeAuthBundle(store[storageScope()]);\n}\nfunction persistAppAuth(bundle) {\n const normalized = normalizeAuthBundle(bundle);\n const store = readAuthStore();\n if (!normalized) {\n delete store[storageScope()];\n writeAuthStore(store);\n return null;\n }\n store[storageScope()] = normalized;\n writeAuthStore(store);\n return normalized;\n}\nfunction clearStoredAppAuth() {\n persistAppAuth(null);\n}\nfunction hasFormData(value) {\n return typeof FormData !== 'undefined' && value instanceof FormData;\n}\nfunction absoluteUrl(url) {\n return new URL(url, window.location.origin);\n}\nfunction shouldEncrypt(url) {\n const pathname = absoluteUrl(url).pathname;\n return !ENCRYPTION_EXCLUDE_PATHS.some(path => pathname === path || pathname.startsWith(path));\n}\nfunction shouldAttachAuth(config) {\n return !config.skipAuth;\n}\nfunction textEncoder() {\n return new TextEncoder();\n}\nfunction textDecoder() {\n return new TextDecoder();\n}\nfunction bytesToBase64(bytes) {\n let binary = '';\n bytes.forEach(byte => {\n binary += String.fromCharCode(byte);\n });\n return btoa(binary);\n}\nfunction base64ToBytes(base64) {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n}\nasync function getCryptoKey() {\n if (!importedCryptoKeyPromise) {\n importedCryptoKeyPromise = window.crypto.subtle.importKey('raw', textEncoder().encode(AES_KEY), {\n name: 'AES-CBC'\n }, false, ['encrypt', 'decrypt']);\n }\n return importedCryptoKeyPromise;\n}\nasync function encryptPayload(plainText) {\n const iv = window.crypto.getRandomValues(new Uint8Array(16));\n const key = await getCryptoKey();\n const encrypted = await window.crypto.subtle.encrypt({\n name: 'AES-CBC',\n iv\n }, key, textEncoder().encode(plainText));\n return `${bytesToBase64(iv)}:${bytesToBase64(new Uint8Array(encrypted))}`;\n}\nasync function decryptPayload(cipherText) {\n const [ivBase64, encryptedBase64] = String(cipherText || '').split(':', 2);\n if (!ivBase64 || !encryptedBase64) {\n throw new Error('Encrypted payload format is invalid');\n }\n const key = await getCryptoKey();\n const decrypted = await window.crypto.subtle.decrypt({\n name: 'AES-CBC',\n iv: base64ToBytes(ivBase64)\n }, key, base64ToBytes(encryptedBase64));\n return textDecoder().decode(decrypted);\n}\nfunction normalizeBusinessResponse(payload) {\n if (payload && typeof payload === 'object' && !Array.isArray(payload)) {\n return payload;\n }\n return {\n code: 0,\n message: 'success',\n data: payload\n };\n}\nasync function decodeResponsePayload(response) {\n const encrypted = String(response.headers?.['x-encrypted'] || '').toLowerCase() === 'true';\n if (encrypted && typeof response.data === 'string') {\n const plainText = await decryptPayload(response.data);\n response.data = normalizeBusinessResponse(JSON.parse(plainText));\n return response;\n }\n response.data = normalizeBusinessResponse(response.data);\n return response;\n}\nconst client = axios__WEBPACK_IMPORTED_MODULE_8__[\"default\"].create({\n withCredentials: false\n});\nclient.interceptors.request.use(async config => {\n const nextConfig = {\n ...config\n };\n const url = absoluteUrl(nextConfig.url || '').toString();\n if (shouldAttachAuth(nextConfig)) {\n const auth = getStoredAppAuth();\n if (auth?.accessToken) {\n nextConfig.headers = {\n ...(nextConfig.headers || {}),\n Authorization: `${auth.tokenType || 'Bearer'} ${auth.accessToken}`\n };\n }\n }\n if (!hasFormData(nextConfig.data) && nextConfig.method?.toLowerCase() !== 'get' && shouldEncrypt(url)) {\n const plainBody = JSON.stringify(nextConfig.data ?? {});\n nextConfig.data = await encryptPayload(plainBody);\n nextConfig.headers = {\n ...(nextConfig.headers || {}),\n 'Content-Type': 'text/plain;charset=UTF-8',\n 'X-Timestamp': `${Math.floor(Date.now() / 1000)}`\n };\n }\n return nextConfig;\n});\nclient.interceptors.response.use(async response => decodeResponsePayload(response));\nasync function refreshAccessToken() {\n if (refreshPromise) {\n return refreshPromise;\n }\n const auth = getStoredAppAuth();\n if (!auth?.refreshToken) {\n clearStoredAppAuth();\n throw new Error('登录状态已失效,请重新登录');\n }\n refreshPromise = client.post(`${_config__WEBPACK_IMPORTED_MODULE_9__.appConfig.appServer}/auth/refreshToken`, {\n refreshToken: auth.refreshToken\n }, {\n skipAuth: true\n }).then(response => {\n const payload = response.data || {};\n if (Number(payload.code) !== 0 || !payload.data) {\n if (Number(payload.code) === REFRESH_ERROR_CODE) {\n clearStoredAppAuth();\n }\n throw new Error(payload.message || '刷新登录状态失败');\n }\n persistAppAuth(payload.data);\n return payload.data;\n }).finally(() => {\n refreshPromise = null;\n });\n return refreshPromise;\n}\nasync function request(config) {\n const response = await client.request(config);\n const payload = response.data || {};\n if (Number(payload.code) === AUTH_ERROR_CODE && shouldAttachAuth(config) && !config._retriedAfterRefresh) {\n await refreshAccessToken();\n return request({\n ...config,\n _retriedAfterRefresh: true\n });\n }\n return response;\n}\nasync function appServerRequest(config) {\n return request(config);\n}\nasync function appServerGet(url, config = {}) {\n return request({\n ...config,\n method: 'get',\n url\n });\n}\nasync function appServerPost(url, data = {}, config = {}) {\n return request({\n ...config,\n method: 'post',\n url,\n data\n });\n}\n\n//# sourceURL=webpack://jc-web-im/./src/services/appServerClient.js?\n}");
/***/ }),
/***/ "./src/services/documentedHttpImClient.js":
/*!************************************************!*\
!*** ./src/services/documentedHttpImClient.js ***!
\************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DocumentedHttpImClient: function() { return /* binding */ DocumentedHttpImClient; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n/* harmony import */ var _httpImClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./httpImClient */ \"./src/services/httpImClient.js\");\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! axios */ \"./node_modules/axios/lib/axios.js\");\n/* harmony import */ var _appServerClient__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./appServerClient */ \"./src/services/appServerClient.js\");\n\n\n\n\n\nfunction inferAccountType(account) {\n return String(account || '').includes('@') ? 2 : 1;\n}\nfunction unwrapData(response) {\n return response.data?.data ?? response.data?.result ?? null;\n}\nfunction unwrapMessage(response, fallback) {\n return response.data?.message || response.data?.msg || fallback;\n}\nclass DocumentedHttpImClient extends _httpImClient__WEBPACK_IMPORTED_MODULE_2__.HttpImClient {\n unsupported(feature) {\n throw new Error(`当前对接文档未提供“${feature}”接口,已禁用旧本地代理链路`);\n }\n async loginWithPassword(account, password, type = inferAccountType(account)) {\n const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.appServerPost)(`${_config__WEBPACK_IMPORTED_MODULE_1__.appConfig.appServer}/auth/login_pwd`, {\n type,\n number: account,\n password,\n platform: _config__WEBPACK_IMPORTED_MODULE_1__.appConfig.platform,\n clientId: this.getClientId()\n }, {\n skipAuth: true\n });\n if (response.data?.code !== 0) {\n throw new Error(unwrapMessage(response, '登录失败'));\n }\n (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.persistAppAuth)(unwrapData(response));\n return unwrapData(response);\n }\n async requestAuthCode(email) {\n const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.appServerPost)(`${_config__WEBPACK_IMPORTED_MODULE_1__.appConfig.appServer}/auth/sendEmailCode`, {\n email\n }, {\n skipAuth: true\n });\n if (response.data?.code !== 0) {\n throw new Error(unwrapMessage(response, '验证码发送失败'));\n }\n return unwrapData(response);\n }\n async loginWithCode(account, code) {\n void account;\n void code;\n throw new Error('接口文档未提供验证码登录接口,请使用密码登录');\n }\n async register({\n type,\n number,\n code = '',\n password,\n invitationCode = ''\n }) {\n const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.appServerPost)(`${_config__WEBPACK_IMPORTED_MODULE_1__.appConfig.appServer}/auth/register`, {\n type,\n number,\n code,\n password,\n clientId: this.getClientId(),\n platform: _config__WEBPACK_IMPORTED_MODULE_1__.appConfig.platform,\n invitationCode\n }, {\n skipAuth: true\n });\n if (response.data?.code !== 0) {\n throw new Error(unwrapMessage(response, '注册失败'));\n }\n (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.persistAppAuth)(unwrapData(response));\n return unwrapData(response);\n }\n async createPcSession(userId = '') {\n const response = await axios__WEBPACK_IMPORTED_MODULE_3__[\"default\"].post(`${_config__WEBPACK_IMPORTED_MODULE_1__.appConfig.qrAppServer}/pc_session`, {\n flag: 1,\n device_name: 'Web IM',\n userId,\n clientId: this.getClientId(),\n platform: _config__WEBPACK_IMPORTED_MODULE_1__.appConfig.platform\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(unwrapMessage(response, '二维码登录会话创建失败'));\n }\n return unwrapData(response) || {};\n }\n async loginWithPcSession(token) {\n const url = `${_config__WEBPACK_IMPORTED_MODULE_1__.appConfig.qrAppServer}/session_login/${encodeURIComponent(token)}`;\n let response;\n try {\n response = await axios__WEBPACK_IMPORTED_MODULE_3__[\"default\"].post(url, null, {\n withCredentials: false\n });\n } catch (postError) {\n response = await axios__WEBPACK_IMPORTED_MODULE_3__[\"default\"].get(url, {\n withCredentials: false\n });\n }\n this.persistAppToken(url, response);\n const payload = response.data || {};\n const result = payload.result ?? payload.data ?? null;\n if (Number(payload.code) === 0 && result) {\n (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.persistAppAuth)(result);\n }\n if ([0, 8, 9, 10, 13, 18, 20042].includes(Number(payload.code))) {\n return {\n ...payload,\n data: result\n };\n }\n throw new Error(payload.message || '扫码登录失败');\n }\n async changePassword({\n oldPassword,\n newPassword\n }) {\n const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.appServerPost)(_config__WEBPACK_IMPORTED_MODULE_1__.appConfig.changePasswordApi, {\n oldPassword,\n newPassword\n });\n if (response.data?.code !== 0) {\n throw new Error(unwrapMessage(response, '密码修改失败'));\n }\n return true;\n }\n async resetPasswordWithCode({\n mobile,\n resetCode,\n newPassword\n }) {\n void mobile;\n void resetCode;\n void newPassword;\n throw new Error('接口文档未提供重置密码接口,请联系服务端确认流程');\n }\n async logout() {\n const auth = (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.getStoredAppAuth)();\n if (!auth?.refreshToken) {\n (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.clearStoredAppAuth)();\n return true;\n }\n try {\n const response = await (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.appServerPost)(_config__WEBPACK_IMPORTED_MODULE_1__.appConfig.logoutApi, {\n refreshToken: auth.refreshToken\n });\n if (response.data?.code !== 0) {\n throw new Error(unwrapMessage(response, '退出登录失败'));\n }\n } finally {\n (0,_appServerClient__WEBPACK_IMPORTED_MODULE_4__.clearStoredAppAuth)();\n }\n return true;\n }\n async fetchRemoteConversations() {\n return [];\n }\n async fetchRemoteMessages() {\n return [];\n }\n async getServerContactList() {\n return [];\n }\n async getProfile() {\n return null;\n }\n async sendTextMessage() {\n this.unsupported('发送消息');\n }\n async sendAttachmentMessage() {\n this.unsupported('发送附件消息');\n }\n async addContact() {\n this.unsupported('添加联系人');\n }\n async updateContactAlias() {\n this.unsupported('联系人备注');\n }\n async createGroup() {\n this.unsupported('创建群组');\n }\n async joinGroup() {\n this.unsupported('加入群组');\n }\n async broadcastMessage() {\n this.unsupported('群发消息');\n }\n async getGroupDetail() {\n this.unsupported('群详情');\n }\n async getGroupMembers() {\n this.unsupported('群成员');\n }\n async updateGroupAlias() {\n this.unsupported('群备注');\n }\n async leaveGroup() {\n this.unsupported('退出群组');\n }\n async dismissGroup() {\n this.unsupported('解散群组');\n }\n async transferGroup() {\n this.unsupported('转让群组');\n }\n async setGroupAdmins() {\n this.unsupported('设置群管理员');\n }\n async updateGroupProfile() {\n this.unsupported('更新群资料');\n }\n async kickGroupMembers() {\n this.unsupported('移除群成员');\n }\n async updateGroupMuteSetting() {\n this.unsupported('群禁言设置');\n }\n async updateProfile() {\n this.unsupported('更新个人资料');\n }\n async recallMessage() {\n this.unsupported('撤回消息');\n }\n async editMessage() {\n this.unsupported('编辑消息');\n }\n async getMessageDetail() {\n this.unsupported('消息详情');\n }\n}\n\n//# sourceURL=webpack://jc-web-im/./src/services/documentedHttpImClient.js?\n}");
/***/ }),
/***/ "./src/services/httpImClient.js":
/*!**************************************!*\
!*** ./src/services/httpImClient.js ***!
\**************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ HttpImClient: function() { return /* binding */ HttpImClient; },\n/* harmony export */ imClient: function() { return /* binding */ imClient; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/es.iterator.some.js */ \"./node_modules/core-js/modules/es.iterator.some.js\");\n/* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert.js */ \"./node_modules/core-js/modules/es.map.get-or-insert.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert-computed.js */ \"./node_modules/core-js/modules/es.map.get-or-insert-computed.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! core-js/modules/es.set.difference.v2.js */ \"./node_modules/core-js/modules/es.set.difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_10__);\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! core-js/modules/es.set.intersection.v2.js */ \"./node_modules/core-js/modules/es.set.intersection.v2.js\");\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! core-js/modules/es.set.is-disjoint-from.v2.js */ \"./node_modules/core-js/modules/es.set.is-disjoint-from.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_12__);\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! core-js/modules/es.set.is-subset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-subset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_13__);\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! core-js/modules/es.set.is-superset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-superset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_14__);\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! core-js/modules/es.set.symmetric-difference.v2.js */ \"./node_modules/core-js/modules/es.set.symmetric-difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_15__);\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! core-js/modules/es.set.union.v2.js */ \"./node_modules/core-js/modules/es.set.union.v2.js\");\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_16__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! axios */ \"./node_modules/axios/lib/axios.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n/* harmony import */ var _services_appServerClient__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @/services/appServerClient */ \"./src/services/appServerClient.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst LOCAL_MESSAGE_STORAGE_KEY = 'qmt-web-im-local-messages-v2';\nconst LOCAL_HIDDEN_MESSAGE_STORAGE_KEY = 'qmt-web-im-hidden-messages-v1';\nconst LOCAL_RECALLED_MESSAGE_STORAGE_KEY = 'qmt-web-im-recalled-messages-v1';\nfunction scopedStorageKey(baseKey, userId = '') {\n const scope = `${_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer || ''}:${userId || 'anonymous'}`;\n return `${baseKey}:${encodeURIComponent(scope)}`;\n}\nfunction randomId() {\n if (window.crypto && window.crypto.randomUUID) {\n return window.crypto.randomUUID().replaceAll('-', '');\n }\n return `${Date.now()}${Math.random().toString(16).slice(2)}`;\n}\nfunction readLocalMessages(userId) {\n try {\n return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_MESSAGE_STORAGE_KEY, userId)) || '{}');\n } catch (error) {\n return {};\n }\n}\nfunction readMessageSet(storageKey, userId) {\n try {\n return JSON.parse(localStorage.getItem(scopedStorageKey(storageKey, userId)) || '{}');\n } catch (error) {\n return {};\n }\n}\nfunction writeMessageSet(storageKey, messagesByConversation, userId) {\n localStorage.setItem(scopedStorageKey(storageKey, userId), JSON.stringify(messagesByConversation));\n}\nfunction messageKeys(message) {\n return [message?.id, message?.messageUid].filter(Boolean).map(value => String(value));\n}\nfunction hasStoredMessage(storageKey, conversationId, message, userId) {\n const stored = readMessageSet(storageKey, userId);\n const ids = new Set(stored[conversationId] || []);\n return messageKeys(message).some(id => ids.has(id));\n}\nfunction storeMessageKeys(storageKey, conversationId, messages, userId) {\n const stored = readMessageSet(storageKey, userId);\n const ids = new Set(stored[conversationId] || []);\n messages.forEach(message => {\n messageKeys(message).forEach(id => ids.add(id));\n });\n stored[conversationId] = Array.from(ids);\n writeMessageSet(storageKey, stored, userId);\n}\nfunction withRecalledState(message) {\n return {\n ...message,\n status: 'recalled',\n deliveryStatus: '',\n recalled: true,\n recallStatus: '已撤回'\n };\n}\nfunction applyLocalMessageState(conversationId, messages, userId) {\n return messages.filter(message => !hasStoredMessage(LOCAL_HIDDEN_MESSAGE_STORAGE_KEY, conversationId, message, userId)).map(message => {\n const isRecalled = Boolean(message.recalled) || message.status === 'recalled' || hasStoredMessage(LOCAL_RECALLED_MESSAGE_STORAGE_KEY, conversationId, message, userId);\n if (!isRecalled) {\n return message;\n }\n return withRecalledState(message);\n });\n}\nfunction writeLocalMessages(messagesByConversation, userId) {\n localStorage.setItem(scopedStorageKey(LOCAL_MESSAGE_STORAGE_KEY, userId), JSON.stringify(messagesByConversation));\n}\nfunction saveLocalMessage(message, userId) {\n const messagesByConversation = readLocalMessages(userId);\n messagesByConversation[message.conversationId] = messagesByConversation[message.conversationId] || [];\n const index = messagesByConversation[message.conversationId].findIndex(item => item.id === message.id);\n if (index >= 0) {\n messagesByConversation[message.conversationId].splice(index, 1, message);\n } else {\n messagesByConversation[message.conversationId].push(message);\n }\n writeLocalMessages(messagesByConversation, userId);\n}\nfunction mergeSyncedMessages(localMessages, remoteMessages, conversationId, userId) {\n const visibleLocalMessages = applyLocalMessageState(conversationId, localMessages, userId);\n const localByKey = new Map();\n visibleLocalMessages.forEach(message => {\n messageKeys(message).forEach(key => {\n if (!localByKey.has(key)) {\n localByKey.set(key, message);\n }\n });\n });\n const visibleRemoteMessages = applyLocalMessageState(conversationId, remoteMessages, userId).map(remoteMessage => {\n if (!remoteMessage.recalled || String(remoteMessage.text || '').trim()) {\n return remoteMessage;\n }\n const localMessage = messageKeys(remoteMessage).map(key => localByKey.get(key)).find(message => message?.text && message.text !== '你撤回了一条消息');\n return localMessage ? {\n ...remoteMessage,\n text: localMessage.text\n } : remoteMessage;\n });\n const remoteKeys = new Set();\n visibleRemoteMessages.forEach(message => {\n messageKeys(message).forEach(key => remoteKeys.add(key));\n });\n const now = Date.now();\n function hasRemoteMatch(localMessage) {\n if (localMessage.messageUid && remoteKeys.has(localMessage.messageUid)) {\n return true;\n }\n return visibleRemoteMessages.some(remoteMessage => {\n return remoteMessage.direction === localMessage.direction && remoteMessage.text === localMessage.text && Math.abs(Number(remoteMessage.timestamp || 0) - Number(localMessage.timestamp || 0)) < 15000;\n });\n }\n const pendingLocalMessages = visibleLocalMessages.filter(message => {\n if (message.status === 'recalled' || message.recalled) {\n return message.direction === 'out' && !hasRemoteMatch(message);\n }\n if (message.direction !== 'out') {\n return false;\n }\n if (message.status === 'sent' && message.messageUid) {\n return !hasRemoteMatch(message);\n }\n if (message.status === 'sent') {\n return !hasRemoteMatch(message) && now - Number(message.timestamp || 0) < 30000;\n }\n return message.status === 'sending' || message.status === 'failed';\n });\n return [...visibleRemoteMessages, ...pendingLocalMessages].sort((a, b) => {\n return Number(a.displayTimestamp || a.timestamp || 0) - Number(b.displayTimestamp || b.timestamp || 0);\n });\n}\nfunction getTitle(value, fallback) {\n return value || fallback || '';\n}\nfunction getUniqueEquipment(mobile, fallback) {\n const allowedDevices = {\n '18301902119': '67072d37062c4f31b1165073552933ba',\n '18301902116': '1777479418113eeea8e236edce',\n '18301902118': 'de89fb2f2a61480a8c381f6c16e28bd8',\n '18301902117': 'd117f480faa64145b6162107b1b49617'\n };\n return allowedDevices[mobile] || localStorage.getItem('uniqueEquipment') || fallback;\n}\nfunction canUseLocalLoginFallback(response) {\n const message = response.data?.message || '';\n return true && message.includes('允许此设备登录');\n}\nclass HttpImClient {\n constructor() {\n this.listeners = new Map();\n this.connected = false;\n this.currentUser = null;\n }\n getClientId() {\n let clientId = localStorage.getItem(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.clientIdStorageKey);\n if (!clientId) {\n clientId = randomId();\n localStorage.setItem(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.clientIdStorageKey, clientId);\n }\n return clientId;\n }\n restoreClientId(clientId) {\n if (clientId) {\n localStorage.setItem(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.clientIdStorageKey, clientId);\n }\n }\n getSdkVersion() {\n return 'HTTP';\n }\n async ensureSdk() {\n return true;\n }\n async loginWithPassword(mobile, password) {\n const url = `${_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer}/login_pwd`;\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(url, {\n mobile,\n password,\n platform: _config__WEBPACK_IMPORTED_MODULE_18__.appConfig.platform,\n clientId: this.getClientId()\n }, {\n withCredentials: false\n });\n this.persistAppToken(url, response);\n if (response.data?.code !== 0) {\n if (canUseLocalLoginFallback(response)) {\n return {\n userId: mobile,\n token: `local-device-pending-${Date.now()}`,\n displayName: mobile,\n localOnly: true\n };\n }\n throw new Error(response.data?.message || '登录失败');\n }\n return response.data.result;\n }\n async requestAuthCode(mobile) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(`${_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer}/send_code`, {\n mobile\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '验证码发送失败');\n }\n return response.data.result;\n }\n async loginWithCode(mobile, code) {\n const url = `${_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer}/login`;\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(url, {\n mobile,\n code,\n platform: _config__WEBPACK_IMPORTED_MODULE_18__.appConfig.platform,\n clientId: this.getClientId()\n }, {\n withCredentials: false\n });\n this.persistAppToken(url, response);\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '登录失败');\n }\n return response.data.result;\n }\n async createPcSession(userId = '') {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(`${_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer}/pc_session`, {\n flag: 1,\n device_name: 'Web IM',\n userId,\n clientId: this.getClientId(),\n platform: _config__WEBPACK_IMPORTED_MODULE_18__.appConfig.platform\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '二维码登录会话创建失败');\n }\n return response.data.result || {};\n }\n async loginWithPcSession(token) {\n const url = `${_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer}/session_login/${encodeURIComponent(token)}`;\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(url, null, {\n withCredentials: false\n });\n this.persistAppToken(url, response);\n const data = response.data || {};\n if ([0, 8, 9, 10, 18].includes(Number(data.code))) {\n return data;\n }\n throw new Error(data.message || '扫码登录失败');\n }\n async registerWithPhone(mobile, code) {\n const url = `${_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer}/register`;\n const deviceId = getUniqueEquipment(mobile, this.getClientId());\n try {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(url, {\n mobile,\n code,\n platform: _config__WEBPACK_IMPORTED_MODULE_18__.appConfig.platform,\n clientId: deviceId,\n uniqueEquipment: deviceId\n }, {\n withCredentials: false\n });\n this.persistAppToken(url, response);\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '注册失败');\n }\n return response.data.result;\n } catch (error) {\n const status = error.response?.status;\n if (status === 404 || status === 405) {\n return this.loginWithCode(mobile, code);\n }\n throw error;\n }\n }\n connect(userId, token) {\n this.currentUser = {\n userId,\n token\n };\n this.connected = true;\n this.emit('connectionStatusChanged', {\n connected: true,\n statusText: '已连接'\n });\n this.refreshConversationList();\n }\n disconnect() {\n this.connected = false;\n this.currentUser = null;\n this.emit('connectionStatusChanged', {\n connected: false,\n statusText: '未连接'\n });\n }\n getConversationList() {\n return [];\n }\n refreshConversationList() {\n const conversations = this.getConversationList();\n if (conversations.length) {\n this.emit('conversationsChanged', conversations);\n }\n if (this.currentUser?.userId) {\n this.fetchRemoteConversations().then(remoteConversations => {\n this.emit('conversationsChanged', remoteConversations);\n }).catch(() => {});\n }\n return conversations;\n }\n async fetchRemoteConversations(limit = 50) {\n if (!this.currentUser?.userId) {\n return [];\n }\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.messagesApi, {\n userId: this.currentUser.userId,\n limit\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '会话同步失败');\n }\n return (response.data?.result?.conversations || []).map(conversation => ({\n ...conversation,\n updatedAt: Number(conversation.updatedAt || Date.now()),\n avatarText: conversation.avatarText || String(conversation.title || conversation.target || '?').slice(0, 1).toUpperCase(),\n raw: conversation.raw || {\n type: 'single',\n target: conversation.target,\n line: 0\n }\n }));\n }\n getMessages(conversation) {\n if (!conversation?.id) {\n return [];\n }\n const userId = this.currentUser?.userId || '';\n return applyLocalMessageState(conversation.id, readLocalMessages(userId)[conversation.id] || [], userId);\n }\n async fetchRemoteMessages(conversation, limit = 50, options = {}) {\n if (!conversation?.id || !this.currentUser?.userId) {\n return [];\n }\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.messagesApi, {\n userId: this.currentUser.userId,\n target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''),\n limit,\n conversationType: conversation.type || conversation.raw?.type || 0,\n markRead: Boolean(options.markRead),\n includeConversations: Boolean(options.includeConversations)\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '消息同步失败');\n }\n const messages = (response.data?.result?.messages || []).map(message => ({\n ...message,\n displayTimestamp: message.displayTimestamp || message.timestamp,\n conversationId: conversation.id\n }));\n if (options.includeConversations && Array.isArray(response.data?.result?.conversations)) {\n const remoteConversations = response.data.result.conversations.map(remoteConversation => ({\n ...remoteConversation,\n updatedAt: Number(remoteConversation.updatedAt || Date.now()),\n avatarText: remoteConversation.avatarText || String(remoteConversation.title || remoteConversation.target || '?').slice(0, 1).toUpperCase(),\n raw: remoteConversation.raw || {\n type: 'single',\n target: remoteConversation.target,\n line: 0\n }\n }));\n this.emit('conversationsChanged', remoteConversations);\n }\n const userId = this.currentUser?.userId || '';\n const messagesByConversation = readLocalMessages(userId);\n messagesByConversation[conversation.id] = mergeSyncedMessages(messagesByConversation[conversation.id] || [], messages, conversation.id, userId);\n writeLocalMessages(messagesByConversation, userId);\n return messagesByConversation[conversation.id];\n }\n hideMessages(conversation, messages) {\n const items = Array.isArray(messages) ? messages : [messages];\n if (!conversation?.id || !items.length) {\n return;\n }\n const userId = this.currentUser?.userId || '';\n storeMessageKeys(LOCAL_HIDDEN_MESSAGE_STORAGE_KEY, conversation.id, items, userId);\n const messagesByConversation = readLocalMessages(userId);\n messagesByConversation[conversation.id] = applyLocalMessageState(conversation.id, messagesByConversation[conversation.id] || [], userId);\n writeLocalMessages(messagesByConversation, userId);\n }\n markMessagesRecalled(conversation, messages) {\n const items = Array.isArray(messages) ? messages : [messages];\n if (!conversation?.id || !items.length) {\n return;\n }\n const userId = this.currentUser?.userId || '';\n storeMessageKeys(LOCAL_RECALLED_MESSAGE_STORAGE_KEY, conversation.id, items, userId);\n const messagesByConversation = readLocalMessages(userId);\n messagesByConversation[conversation.id] = applyLocalMessageState(conversation.id, messagesByConversation[conversation.id] || [], userId);\n writeLocalMessages(messagesByConversation, userId);\n }\n async recallMessage(conversation, message) {\n const messageUid = String(message?.messageUid || message?.id || '').trim();\n if (!/^\\d+$/.test(messageUid)) {\n throw new Error('缺少可撤回的消息ID');\n }\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.messageActionApi, {\n action: 'recall',\n userId: this.currentUser?.userId || message.from || '',\n messageUid\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '撤回失败');\n }\n this.markMessagesRecalled(conversation, [message]);\n return response.data.result;\n }\n async editMessage(conversation, message, text) {\n const messageUid = String(message?.messageUid || message?.id || '').trim();\n if (!/^\\d+$/.test(messageUid)) {\n throw new Error('缺少可编辑的消息ID');\n }\n const nextText = String(text || '').trim();\n if (!nextText) {\n throw new Error('编辑内容不能为空');\n }\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.messageActionApi, {\n action: 'edit',\n userId: this.currentUser?.userId || message.from || '',\n messageUid,\n text: nextText\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '编辑失败');\n }\n const result = response.data?.result?.message || {};\n const editedMessage = {\n ...message,\n text: result.text || nextText,\n status: 'delivered',\n deliveryStatus: 'delivered',\n editedAt: Number(result.editedAt || Date.now()),\n activityTimestamp: Number(result.editedAt || Date.now())\n };\n saveLocalMessage(editedMessage, this.currentUser?.userId || '');\n this.emit('messageStatusChanged', editedMessage);\n return editedMessage;\n }\n async getMessageDetail(conversation, message) {\n const messageUid = String(message?.messageUid || message?.id || '').trim();\n if (!messageUid) {\n throw new Error('缺少消息ID');\n }\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.messageDetailApi, {\n userId: this.currentUser?.userId || '',\n target: conversation?.target || conversation?.raw?.target || conversation?.id?.replace(/^single-/, '') || '',\n conversationType: conversation?.type || conversation?.raw?.type || 'single',\n messageUid\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '消息详情加载失败');\n }\n return response.data?.result?.detail || null;\n }\n async sendTextMessage(conversation, text, initialMessage = null) {\n const senderRole = conversation?.role || conversation?.raw?.role || '';\n const message = initialMessage || {\n id: randomId(),\n conversationId: conversation.id,\n from: this.currentUser?.userId || 'me',\n senderRole,\n direction: 'out',\n type: 'text',\n text,\n status: 'sending',\n deliveryStatus: 'sending',\n timestamp: Date.now()\n };\n saveLocalMessage(message, this.currentUser?.userId || '');\n if (!initialMessage) {\n this.emit('messageSent', message);\n }\n try {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.sendMessageApi, {\n sender: this.currentUser?.userId || '',\n target: conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''),\n conversationType: conversation.type || conversation.raw?.type || 0,\n text\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '发送失败');\n }\n const sentMessage = {\n ...message,\n status: 'sent',\n deliveryStatus: 'sent',\n messageUid: response.data?.result?.messageUid ? String(response.data.result.messageUid) : '',\n senderRole: response.data?.result?.senderRole || message.senderRole || '',\n serverTimestamp: Number(response.data?.result?.timestamp || 0) || null,\n timestamp: message.timestamp,\n displayTimestamp: message.displayTimestamp || message.timestamp\n };\n saveLocalMessage(sentMessage, this.currentUser?.userId || '');\n this.emit('messageStatusChanged', sentMessage);\n return sentMessage;\n } catch (error) {\n const failedMessage = {\n ...message,\n status: 'failed',\n deliveryStatus: '',\n error: error.response?.data?.message || error.message || '发送失败'\n };\n saveLocalMessage(failedMessage, this.currentUser?.userId || '');\n this.emit('messageStatusChanged', failedMessage);\n return failedMessage;\n }\n }\n async sendAttachmentMessage(conversation, {\n type,\n file,\n text = ''\n }, initialMessage = null) {\n const senderRole = conversation?.role || conversation?.raw?.role || '';\n const message = initialMessage || {\n id: randomId(),\n conversationId: conversation.id,\n from: this.currentUser?.userId || 'me',\n senderRole,\n direction: 'out',\n type,\n text,\n attachment: {\n type,\n name: file?.name || (type === 'image' ? '图片' : '文件'),\n mime: file?.type || '',\n size: file?.size || 0,\n url: type === 'image' && file ? URL.createObjectURL(file) : ''\n },\n status: 'sending',\n deliveryStatus: 'sending',\n timestamp: Date.now()\n };\n saveLocalMessage(message, this.currentUser?.userId || '');\n if (!initialMessage) {\n this.emit('messageSent', message);\n }\n try {\n const formData = new FormData();\n formData.append('sender', this.currentUser?.userId || '');\n formData.append('target', conversation.target || conversation.raw?.target || conversation.id.replace(/^single-/, ''));\n formData.append('conversationType', conversation.type || conversation.raw?.type || 0);\n formData.append('messageType', type);\n formData.append('text', text || '');\n formData.append('attachment', file);\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.sendMessageApi, formData, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '发送失败');\n }\n const sentMessage = {\n ...message,\n status: 'sent',\n deliveryStatus: 'sent',\n messageUid: response.data?.result?.messageUid ? String(response.data.result.messageUid) : '',\n senderRole: response.data?.result?.senderRole || message.senderRole || '',\n attachment: response.data?.result?.attachment || message.attachment,\n serverTimestamp: Number(response.data?.result?.timestamp || 0) || null,\n timestamp: message.timestamp,\n displayTimestamp: message.displayTimestamp || message.timestamp\n };\n saveLocalMessage(sentMessage, this.currentUser?.userId || '');\n this.emit('messageStatusChanged', sentMessage);\n return sentMessage;\n } catch (error) {\n const failedMessage = {\n ...message,\n status: 'failed',\n deliveryStatus: '',\n error: error.response?.data?.message || error.message || '发送失败'\n };\n saveLocalMessage(failedMessage, this.currentUser?.userId || '');\n this.emit('messageStatusChanged', failedMessage);\n return failedMessage;\n }\n }\n getContactList() {\n return [];\n }\n async getServerContactList(userId) {\n if (!userId) {\n return [];\n }\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.contactsApi, {\n userId\n }, {\n withCredentials: false,\n headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.contactsApi)\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '联系人加载失败');\n }\n return (response.data?.result?.contacts || []).map(item => {\n return this.mapContact(item.uid, {\n alias: item.alias\n }, {\n uid: item.uid,\n displayName: item.displayName,\n name: item.name,\n mobile: item.mobile,\n portrait: item.portrait,\n address: item.address,\n friendAlias: item.alias\n });\n }).sort((a, b) => a.title.localeCompare(b.title, 'zh-CN'));\n }\n async addContact(userId, keyword, reason = '') {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.addContactApi, {\n userId,\n keyword,\n reason\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '添加联系人失败');\n }\n const item = response.data?.result?.contact;\n if (!item?.uid) {\n return null;\n }\n return this.mapContact(item.uid, {\n alias: item.alias\n }, {\n uid: item.uid,\n displayName: item.displayName,\n name: item.name,\n mobile: item.mobile,\n portrait: item.portrait,\n address: item.address,\n friendAlias: item.alias\n });\n }\n normalizeConversation(conversation) {\n const title = getTitle(conversation?.title, conversation?.target || '');\n return {\n ...conversation,\n id: conversation?.id || `${conversation?.type === 'single' ? 'single' : 'group'}-${conversation?.target}`,\n target: conversation?.target || conversation?.raw?.target || '',\n title,\n subtitle: conversation?.subtitle || '',\n unread: Number(conversation?.unread || 0),\n portrait: conversation?.portrait || '',\n avatarText: conversation?.avatarText || title.slice(0, 1).toUpperCase(),\n updatedAt: Number(conversation?.updatedAt || Date.now()),\n raw: conversation?.raw || {\n type: conversation?.type === 'single' ? 'single' : 'group',\n target: conversation?.target || '',\n line: 0\n }\n };\n }\n async createGroup(userId, {\n name,\n memberIds = [],\n announcement = '',\n welcomeText = '',\n channel = false\n }) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: channel ? 'create_channel' : 'create_group',\n userId,\n name,\n memberIds,\n announcement,\n welcomeText\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || (channel ? '创建公告群失败' : '创建群组失败'));\n }\n return this.normalizeConversation(response.data?.result?.conversation || {});\n }\n async joinGroup(userId, groupKey) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'join_group',\n userId,\n groupKey\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '加入群组失败');\n }\n return this.normalizeConversation(response.data?.result?.conversation || {});\n }\n async broadcastMessage(userId, targetIds, text) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'broadcast',\n userId,\n targetIds,\n text\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '群发失败');\n }\n return response.data?.result || {};\n }\n async getGroupDetail(userId, groupId) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'group_detail',\n userId,\n groupId\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '群资料加载失败');\n }\n return response.data?.result?.group || null;\n }\n async getGroupMembers(userId, groupId) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'group_members',\n userId,\n groupId\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '群员加载失败');\n }\n return response.data?.result?.members || [];\n }\n async updateGroupAlias(userId, groupId, alias) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'update_group_alias',\n userId,\n groupId,\n alias\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '本群昵称保存失败');\n }\n return response.data?.result?.alias || '';\n }\n async leaveGroup(userId, groupId) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'leave_group',\n userId,\n groupId\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '退出群组失败');\n }\n return response.data?.result || {};\n }\n async dismissGroup(userId, groupId) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'dismiss_group',\n userId,\n groupId\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '解散群组失败');\n }\n return response.data?.result || {};\n }\n async transferGroup(userId, groupId, targetUserId) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'transfer_group',\n userId,\n groupId,\n targetUserId\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '转让群组失败');\n }\n return response.data?.result || {};\n }\n async setGroupAdmins(userId, groupId, adminIds) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'set_group_admins',\n userId,\n groupId,\n adminIds\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '管理员设置失败');\n }\n return response.data?.result || {};\n }\n async updateGroupProfile(userId, groupId, {\n name,\n announcement,\n welcomeText\n }) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'update_group_profile',\n userId,\n groupId,\n name,\n announcement,\n welcomeText\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '群资料保存失败');\n }\n return response.data?.result || {};\n }\n async kickGroupMembers(userId, groupId, targetIds) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'kick_group_members',\n userId,\n groupId,\n targetIds\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '踢人失败');\n }\n return response.data?.result || {};\n }\n async updateGroupMuteSetting(userId, groupId, setting) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.conversationActionsApi, {\n action: 'update_mute_setting',\n userId,\n groupId,\n ...setting\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '禁言设置保存失败');\n }\n return response.data?.result?.muteSetting || null;\n }\n async updateContactAlias(userId, targetId, alias) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.updateAliasApi, {\n userId,\n targetId,\n alias\n }, {\n withCredentials: false,\n headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.updateAliasApi)\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '备注名修改失败');\n }\n return response.data?.result?.contact?.alias || '';\n }\n async getProfile(userId) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.profileApi, {\n action: 'get',\n userId\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '用户资料加载失败');\n }\n return response.data?.result?.profile || null;\n }\n async updateProfile(userId, {\n displayName,\n portraitFile\n }) {\n const formData = new FormData();\n formData.append('action', 'update');\n formData.append('userId', userId);\n formData.append('displayName', displayName);\n if (portraitFile) {\n formData.append('portraitFile', portraitFile);\n }\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.profileApi, formData, {\n withCredentials: false,\n headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.appServer)\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || '用户资料保存失败');\n }\n return response.data?.result?.profile || null;\n }\n async changePassword({\n oldPassword,\n newPassword\n }) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.changePasswordApi, {\n oldPassword,\n newPassword\n }, {\n withCredentials: false,\n headers: this.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.changePasswordApi)\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || response.data?.msg || '密码修改失败');\n }\n return true;\n }\n async resetPasswordWithCode({\n mobile,\n resetCode,\n newPassword\n }) {\n const response = await axios__WEBPACK_IMPORTED_MODULE_17__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.resetPasswordApi, {\n mobile,\n resetCode,\n newPassword\n }, {\n withCredentials: false\n });\n if (response.data?.code !== 0) {\n throw new Error(response.data?.message || response.data?.msg || '密码设置失败');\n }\n return true;\n }\n refreshContactList() {\n const contacts = this.getContactList();\n this.emit('contactsChanged', contacts);\n return contacts;\n }\n createSingleConversation(userId, userInfo = null) {\n const title = getTitle(userInfo?.title || userInfo?.displayName || userInfo?.name, userId);\n return {\n id: `single-${userId}`,\n type: 'single',\n target: userId,\n title,\n subtitle: '',\n unread: 0,\n portrait: userInfo?.portrait || '',\n avatarText: title.slice(0, 1).toUpperCase(),\n updatedAt: Date.now(),\n raw: {\n type: 'single',\n target: userId,\n line: 0\n }\n };\n }\n mapContact(userId, friend, userInfo) {\n const title = getTitle(userInfo?.friendAlias || friend?.alias || userInfo?.displayName || userInfo?.name, userId);\n return {\n id: userId,\n uid: userId,\n title,\n subtitle: userInfo?.mobile || userInfo?.name || userId,\n portrait: userInfo?.portrait || '',\n address: userInfo?.address || '',\n avatarText: title.slice(0, 1).toUpperCase(),\n alias: friend?.alias || userInfo?.friendAlias || '',\n rawFriend: friend,\n rawUser: userInfo\n };\n }\n on(eventName, handler) {\n if (!this.listeners.has(eventName)) {\n this.listeners.set(eventName, new Set());\n }\n this.listeners.get(eventName).add(handler);\n return () => this.off(eventName, handler);\n }\n off(eventName, handler) {\n this.listeners.get(eventName)?.delete(handler);\n }\n emit(eventName, payload) {\n this.listeners.get(eventName)?.forEach(handler => handler(payload));\n }\n persistAppToken(url, response) {\n const appToken = response.headers?.authtoken || response.headers?.authToken;\n if (appToken) {\n localStorage.setItem(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.authTokenStoragePrefix + this.getUrlHost(url), appToken);\n }\n }\n getAppAuthHeaders(url) {\n const host = this.getUrlHost(url);\n if (!host) {\n return {};\n }\n const token = localStorage.getItem(_config__WEBPACK_IMPORTED_MODULE_18__.appConfig.authTokenStoragePrefix + host);\n return token ? {\n authToken: token\n } : {};\n }\n getUrlHost(url) {\n try {\n return new URL(url, window.location.origin).host;\n } catch (error) {\n return '';\n }\n }\n}\nconst imClient = new HttpImClient();\n\n//# sourceURL=webpack://jc-web-im/./src/services/httpImClient.js?\n}");
/***/ }),
/***/ "./src/services/imClient.js":
/*!**********************************!*\
!*** ./src/services/imClient.js ***!
\**********************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ DocumentedHttpImClient: function() { return /* reexport safe */ _documentedHttpImClient__WEBPACK_IMPORTED_MODULE_3__.DocumentedHttpImClient; },\n/* harmony export */ HttpImClient: function() { return /* reexport safe */ _httpImClient__WEBPACK_IMPORTED_MODULE_1__.HttpImClient; },\n/* harmony export */ LongConnectionImClient: function() { return /* reexport safe */ _longConnectionImClient__WEBPACK_IMPORTED_MODULE_2__.LongConnectionImClient; },\n/* harmony export */ WildfireImClient: function() { return /* binding */ UnsupportedWildfireImClient; },\n/* harmony export */ imClient: function() { return /* binding */ imClient; }\n/* harmony export */ });\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n/* harmony import */ var _httpImClient__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./httpImClient */ \"./src/services/httpImClient.js\");\n/* harmony import */ var _longConnectionImClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./longConnectionImClient */ \"./src/services/longConnectionImClient.js\");\n/* harmony import */ var _documentedHttpImClient__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./documentedHttpImClient */ \"./src/services/documentedHttpImClient.js\");\n\n\n\n\nclass UnsupportedWildfireImClient {\n constructor() {\n throw new Error('当前本地社区版 Web 客户端未启用 WildFire Web SDK');\n }\n}\nconst imClient = _config__WEBPACK_IMPORTED_MODULE_0__.appConfig.sdkMode === 'wildfire' ? new UnsupportedWildfireImClient() : _config__WEBPACK_IMPORTED_MODULE_0__.appConfig.sdkMode === 'custom-ws' || _config__WEBPACK_IMPORTED_MODULE_0__.appConfig.sdkMode === 'long' ? new _longConnectionImClient__WEBPACK_IMPORTED_MODULE_2__.LongConnectionImClient() : _config__WEBPACK_IMPORTED_MODULE_0__.appConfig.sdkMode === 'legacy-http' ? new _httpImClient__WEBPACK_IMPORTED_MODULE_1__.HttpImClient() : new _documentedHttpImClient__WEBPACK_IMPORTED_MODULE_3__.DocumentedHttpImClient();\n\n\n//# sourceURL=webpack://jc-web-im/./src/services/imClient.js?\n}");
/***/ }),
/***/ "./src/services/longConnectionImClient.js":
/*!************************************************!*\
!*** ./src/services/longConnectionImClient.js ***!
\************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LongConnectionImClient: function() { return /* binding */ LongConnectionImClient; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n/* harmony import */ var _httpImClient__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./httpImClient */ \"./src/services/httpImClient.js\");\n\n\n\n\n\n\nconst HEARTBEAT_INTERVAL_MS = 25000;\nconst RECONNECT_MIN_MS = 1000;\nconst RECONNECT_MAX_MS = 15000;\nfunction buildWsUrl() {\n if (_config__WEBPACK_IMPORTED_MODULE_4__.appConfig.wsUrl) {\n return _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.wsUrl;\n }\n const protocol = _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.useWss ? 'wss' : 'ws';\n const host = _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.imServerHost || window.location.hostname;\n const port = _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.imRoutePort ? `:${_config__WEBPACK_IMPORTED_MODULE_4__.appConfig.imRoutePort}` : '';\n const path = _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.wsPath?.startsWith('/') ? _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.wsPath : `/${_config__WEBPACK_IMPORTED_MODULE_4__.appConfig.wsPath || 'ws'}`;\n return `${protocol}://${host}${port}${path}`;\n}\nfunction normalizeConversationId(payload) {\n const target = payload.target || payload.to || payload.receiver || payload.conversationTarget || payload.from || payload.sender;\n return payload.conversationId || (target ? `single-${target}` : '');\n}\nfunction normalizeIncomingMessage(payload, currentUserId) {\n const item = payload.message || payload;\n const from = item.from || item.sender || item.fromUser || '';\n const target = item.target || item.to || item.receiver || '';\n const direction = from && String(from) === String(currentUserId) ? 'out' : 'in';\n const conversationId = item.conversationId || normalizeConversationId({\n ...item,\n target: direction === 'out' ? target : from\n });\n if (!conversationId) {\n return null;\n }\n const status = item.status || item.deliveryStatus || 'sent';\n return {\n id: item.id || item.messageId || item.messageUid || `${Date.now()}${Math.random().toString(16).slice(2)}`,\n messageUid: item.messageUid || item.uid || item.messageId || '',\n conversationId,\n from,\n target,\n direction,\n type: item.type || 'text',\n text: item.text || item.content || item.searchableContent || '',\n status,\n deliveryStatus: item.deliveryStatus || (direction === 'out' ? status : ''),\n timestamp: Number(item.timestamp || item.serverTimestamp || Date.now()),\n displayTimestamp: Number(item.displayTimestamp || item.timestamp || item.serverTimestamp || Date.now()),\n raw: item\n };\n}\nclass LongConnectionImClient extends _httpImClient__WEBPACK_IMPORTED_MODULE_5__.HttpImClient {\n constructor() {\n super();\n this.socket = null;\n this.wsUrl = buildWsUrl();\n this.heartbeatTimer = null;\n this.reconnectTimer = null;\n this.reconnectAttempts = 0;\n this.manualClose = false;\n }\n getSdkVersion() {\n return 'JC-LC/0.1';\n }\n shouldUseMessagePolling() {\n return !this.connected;\n }\n async ensureSdk() {\n if (typeof WebSocket === 'undefined') {\n throw new Error('当前浏览器不支持 WebSocket 长连接');\n }\n return true;\n }\n connect(userId, token) {\n this.currentUser = {\n userId,\n token\n };\n this.manualClose = false;\n this.openSocket();\n }\n disconnect() {\n this.manualClose = true;\n this.clearReconnectTimer();\n this.clearHeartbeatTimer();\n if (this.socket) {\n this.socket.close();\n this.socket = null;\n }\n super.disconnect();\n }\n openSocket() {\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.sendAuthFrame();\n return;\n }\n if (this.socket?.readyState === WebSocket.CONNECTING) {\n return;\n }\n this.emit('connectionStatusChanged', {\n connected: false,\n statusText: '长连接连接中'\n });\n try {\n this.socket = new WebSocket(this.wsUrl);\n this.socket.binaryType = 'arraybuffer';\n } catch (error) {\n this.emit('connectionStatusChanged', {\n connected: false,\n statusText: '长连接创建失败,使用HTTP补偿'\n });\n this.scheduleReconnect();\n return;\n }\n this.socket.onopen = () => {\n this.connected = true;\n this.reconnectAttempts = 0;\n this.emit('connectionStatusChanged', {\n connected: true,\n statusText: '长连接已连接'\n });\n this.sendAuthFrame();\n this.startHeartbeat();\n this.refreshConversationList();\n };\n this.socket.onmessage = event => {\n this.handleFrame(event.data);\n };\n this.socket.onerror = () => {\n this.emit('connectionStatusChanged', {\n connected: false,\n statusText: '长连接异常,使用HTTP补偿'\n });\n };\n this.socket.onclose = () => {\n this.connected = false;\n this.clearHeartbeatTimer();\n this.socket = null;\n if (this.manualClose) {\n return;\n }\n this.emit('connectionStatusChanged', {\n connected: false,\n statusText: '长连接重连中'\n });\n this.scheduleReconnect();\n };\n }\n sendAuthFrame() {\n this.sendFrame({\n type: 'auth',\n userId: this.currentUser?.userId || '',\n token: this.currentUser?.token || '',\n clientId: this.getClientId(),\n platform: _config__WEBPACK_IMPORTED_MODULE_4__.appConfig.platform,\n timestamp: Date.now()\n });\n }\n sendFrame(frame) {\n if (this.socket?.readyState !== WebSocket.OPEN) {\n return false;\n }\n this.socket.send(JSON.stringify(frame));\n return true;\n }\n handleFrame(rawData) {\n if (rawData instanceof ArrayBuffer) {\n this.emit('rawFrameReceived', rawData);\n return;\n }\n let payload;\n try {\n payload = typeof rawData === 'string' ? JSON.parse(rawData) : rawData;\n } catch (error) {\n return;\n }\n const type = payload.type || payload.event || payload.cmd || '';\n if (type === 'pong' || type === 'auth_ok' || type === 'connected') {\n return;\n }\n if (type === 'contactsChanged') {\n this.emit('contactsChanged', payload.contacts || []);\n return;\n }\n if (type === 'conversationsChanged') {\n this.emit('conversationsChanged', payload.conversations || []);\n return;\n }\n if (type === 'messages' && Array.isArray(payload.messages)) {\n payload.messages.map(message => normalizeIncomingMessage(message, this.currentUser?.userId)).filter(Boolean).forEach(message => this.emit('messageReceived', message));\n return;\n }\n const message = normalizeIncomingMessage(payload, this.currentUser?.userId);\n if (message) {\n this.emit(message.direction === 'out' ? 'messageStatusChanged' : 'messageReceived', message);\n }\n }\n startHeartbeat() {\n this.clearHeartbeatTimer();\n this.heartbeatTimer = window.setInterval(() => {\n this.sendFrame({\n type: 'ping',\n timestamp: Date.now()\n });\n }, HEARTBEAT_INTERVAL_MS);\n }\n clearHeartbeatTimer() {\n if (this.heartbeatTimer) {\n window.clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n scheduleReconnect() {\n this.clearReconnectTimer();\n const delay = Math.min(RECONNECT_MAX_MS, RECONNECT_MIN_MS * 2 ** this.reconnectAttempts);\n this.reconnectAttempts += 1;\n this.reconnectTimer = window.setTimeout(() => {\n this.openSocket();\n }, delay);\n }\n clearReconnectTimer() {\n if (this.reconnectTimer) {\n window.clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n}\n\n//# sourceURL=webpack://jc-web-im/./src/services/longConnectionImClient.js?\n}");
/***/ }),
/***/ "./src/services/mediaProxy.js":
/*!************************************!*\
!*** ./src/services/mediaProxy.js ***!
\************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ imageDisplayUrl: function() { return /* binding */ imageDisplayUrl; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.set.difference.v2.js */ \"./node_modules/core-js/modules/es.set.difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.set.intersection.v2.js */ \"./node_modules/core-js/modules/es.set.intersection.v2.js\");\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.set.is-disjoint-from.v2.js */ \"./node_modules/core-js/modules/es.set.is-disjoint-from.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/es.set.is-subset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-subset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/es.set.is-superset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-superset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! core-js/modules/es.set.symmetric-difference.v2.js */ \"./node_modules/core-js/modules/es.set.symmetric-difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! core-js/modules/es.set.union.v2.js */ \"./node_modules/core-js/modules/es.set.union.v2.js\");\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_9__);\n\n\n\n\n\n\n\n\n\n\nfunction configuredProxyHosts() {\n const configured = window.JC_WEB_IM_CONFIG?.mediaProxyHosts;\n const values = Array.isArray(configured) ? configured : String(configured || '').split(/[\\s,]+/);\n return new Set(values.map(value => String(value || '').trim().toLowerCase().replace(/\\.$/, '')).filter(Boolean));\n}\nfunction imageDisplayUrl(value) {\n const source = String(value || '').trim();\n if (!source || source.startsWith('blob:') || source.startsWith('data:')) {\n return source;\n }\n try {\n const url = new URL(source, window.location.origin);\n if (url.protocol !== 'https:' || !configuredProxyHosts().has(url.hostname.toLowerCase())) {\n return source;\n }\n const proxyUrl = new URL('/api/media_proxy.php', window.location.origin);\n proxyUrl.searchParams.set('url', url.toString());\n return proxyUrl.toString();\n } catch (error) {\n return source;\n }\n}\n\n//# sourceURL=webpack://jc-web-im/./src/services/mediaProxy.js?\n}");
/***/ }),
/***/ "./src/services/realtimeNotifications.js":
/*!***********************************************!*\
!*** ./src/services/realtimeNotifications.js ***!
\***********************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ realtimeNotifications: function() { return /* binding */ realtimeNotifications; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! axios */ \"./node_modules/axios/lib/axios.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n/* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/services/imClient */ \"./src/services/imClient.js\");\n\n\n\n\nclass RealtimeNotificationClient {\n constructor() {\n this.source = null;\n this.userId = '';\n this.handler = null;\n this.reconnectTimer = null;\n this.reconnectAttempt = 0;\n this.generation = 0;\n }\n isConnected() {\n return this.source?.readyState === WebSocket.OPEN;\n }\n start(userId, handler) {\n this.stop();\n if (!_config__WEBPACK_IMPORTED_MODULE_2__.appConfig.sseEnabled || !userId || typeof window.WebSocket !== 'function') return;\n this.userId = userId;\n this.handler = handler;\n this.generation += 1;\n this.open(this.generation);\n }\n stop() {\n this.generation += 1;\n window.clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n if (this.source) this.source.close();\n this.source = null;\n this.userId = '';\n this.handler = null;\n this.reconnectAttempt = 0;\n }\n async open(generation) {\n try {\n const response = await axios__WEBPACK_IMPORTED_MODULE_1__[\"default\"].post(_config__WEBPACK_IMPORTED_MODULE_2__.appConfig.sseTicketApi, {\n userId: this.userId\n }, {\n withCredentials: false,\n headers: _services_imClient__WEBPACK_IMPORTED_MODULE_3__.imClient.getAppAuthHeaders(_config__WEBPACK_IMPORTED_MODULE_2__.appConfig.appServer)\n });\n if (generation !== this.generation) return;\n if (response.data?.code !== 0) throw new Error(response.data?.message || '实时通知凭证申请失败');\n const ticket = response.data?.result?.ticket || '';\n if (!ticket) throw new Error('实时通知凭证为空');\n const separator = _config__WEBPACK_IMPORTED_MODULE_2__.appConfig.sseUrl.includes('?') ? '&' : '?';\n const endpoint = `${_config__WEBPACK_IMPORTED_MODULE_2__.appConfig.sseUrl}${separator}ticket=${encodeURIComponent(ticket)}`;\n const socketUrl = endpoint.startsWith('ws://') || endpoint.startsWith('wss://') ? endpoint : `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}${endpoint.startsWith('/') ? '' : '/'}${endpoint}`;\n const source = new WebSocket(socketUrl);\n this.source = source;\n source.onopen = () => {\n this.reconnectAttempt = 0;\n };\n source.onmessage = event => {\n if (generation !== this.generation) return;\n let payload = {};\n try {\n payload = JSON.parse(event.data || '{}');\n } catch (error) {\n payload = {};\n }\n if (payload.type !== 'message-notification') return;\n this.handler?.(payload);\n };\n source.onerror = () => {\n if (generation !== this.generation) return;\n source.close();\n if (this.source === source) this.source = null;\n this.scheduleReconnect(generation);\n };\n source.onclose = () => {\n if (generation !== this.generation || this.source !== source) return;\n this.source = null;\n this.scheduleReconnect(generation);\n };\n } catch (error) {\n if (generation === this.generation) this.scheduleReconnect(generation);\n }\n }\n scheduleReconnect(generation) {\n window.clearTimeout(this.reconnectTimer);\n const delay = Math.min(30000, 1000 * 2 ** Math.min(this.reconnectAttempt, 5));\n this.reconnectAttempt += 1;\n this.reconnectTimer = window.setTimeout(() => this.open(generation), delay);\n }\n}\nconst realtimeNotifications = new RealtimeNotificationClient();\n\n//# sourceURL=webpack://jc-web-im/./src/services/realtimeNotifications.js?\n}");
/***/ }),
/***/ "./src/stores/contacts.js":
/*!********************************!*\
!*** ./src/stores/contacts.js ***!
\********************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useContactStore: function() { return /* binding */ useContactStore; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert.js */ \"./node_modules/core-js/modules/es.map.get-or-insert.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert-computed.js */ \"./node_modules/core-js/modules/es.map.get-or-insert-computed.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! pinia */ \"./node_modules/pinia/dist/pinia.mjs\");\n/* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @/services/imClient */ \"./src/services/imClient.js\");\n/* harmony import */ var _stores_conversations__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @/stores/conversations */ \"./src/stores/conversations.js\");\n/* harmony import */ var _stores_navigation__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @/stores/navigation */ \"./src/stores/navigation.js\");\n/* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @/stores/session */ \"./src/stores/session.js\");\n\n\n\n\n\n\n\n\n\n\n\nconst CONTACT_CACHE_MS = 15000;\nfunction normalizeContacts(contacts) {\n const unique = new Map();\n contacts.forEach(contact => {\n const uid = String(contact.uid || contact.id || '').trim();\n if (!uid) {\n return;\n }\n const normalized = {\n ...contact,\n id: String(contact.id || uid),\n uid\n };\n unique.set(uid, {\n ...(unique.get(uid) || {}),\n ...normalized\n });\n });\n return Array.from(unique.values()).sort((a, b) => a.title.localeCompare(b.title, 'zh-CN'));\n}\nconst useContactStore = (0,pinia__WEBPACK_IMPORTED_MODULE_6__.defineStore)('contacts', {\n state: () => ({\n contacts: [],\n activeId: '',\n loading: false,\n eventsBound: false,\n refreshSerial: 0,\n refreshPromise: null,\n loadedForUserId: '',\n loadedAt: 0,\n actionError: '',\n actionInfo: ''\n }),\n getters: {\n activeContact(state) {\n return state.contacts.find(item => item.id === state.activeId) || state.contacts[0] || null;\n }\n },\n actions: {\n bindImEvents() {\n if (this.eventsBound) {\n return;\n }\n this.eventsBound = true;\n _services_imClient__WEBPACK_IMPORTED_MODULE_7__.imClient.on('contactsChanged', contacts => {\n if (!contacts.length && this.contacts.length) {\n return;\n }\n this.contacts = normalizeContacts(contacts);\n if (!this.contacts.find(item => item.id === this.activeId)) {\n this.activeId = this.contacts[0]?.id || '';\n }\n });\n },\n async refreshContacts(options = {}) {\n this.bindImEvents();\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__.useSessionStore)();\n const requestUserId = session.userId;\n const force = Boolean(options.force);\n if (!requestUserId) {\n this.clearContacts();\n return [];\n }\n if (!force && this.contacts.length && this.loadedForUserId === requestUserId && Date.now() - this.loadedAt < CONTACT_CACHE_MS) {\n return this.contacts;\n }\n if (this.refreshPromise && !force) {\n return this.refreshPromise;\n }\n const serial = this.refreshSerial + 1;\n this.refreshSerial = serial;\n this.loading = true;\n this.refreshPromise = (async () => {\n this.contacts = normalizeContacts(_services_imClient__WEBPACK_IMPORTED_MODULE_7__.imClient.refreshContactList());\n if (!this.contacts.find(item => item.id === this.activeId)) {\n this.activeId = this.contacts[0]?.id || '';\n }\n if (!this.contacts.length || force) {\n const serverContacts = await _services_imClient__WEBPACK_IMPORTED_MODULE_7__.imClient.getServerContactList(requestUserId);\n if (serial !== this.refreshSerial || (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__.useSessionStore)().userId !== requestUserId) {\n return this.contacts;\n }\n this.contacts = normalizeContacts(serverContacts);\n this.loadedForUserId = requestUserId;\n this.loadedAt = Date.now();\n if (!this.contacts.find(item => item.id === this.activeId)) {\n this.activeId = this.contacts[0]?.id || '';\n }\n }\n window.setTimeout(() => {\n if (serial !== this.refreshSerial || (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__.useSessionStore)().userId !== requestUserId) {\n return;\n }\n const latest = _services_imClient__WEBPACK_IMPORTED_MODULE_7__.imClient.getContactList(false);\n if (latest.length || !this.contacts.length) {\n this.contacts = normalizeContacts(latest);\n this.loadedForUserId = requestUserId;\n this.loadedAt = Date.now();\n if (!this.contacts.find(item => item.id === this.activeId)) {\n this.activeId = this.contacts[0]?.id || '';\n }\n }\n }, 1200);\n return this.contacts;\n })();\n try {\n return await this.refreshPromise;\n } finally {\n if (serial === this.refreshSerial) {\n this.loading = false;\n this.refreshPromise = null;\n }\n }\n },\n async addContact(keyword) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__.useSessionStore)();\n const value = String(keyword || '').trim();\n this.actionError = '';\n this.actionInfo = '';\n if (!session.userId) {\n this.actionError = '请先登录';\n return false;\n }\n if (!value) {\n this.actionError = '请输入用户ID、手机号或用户名';\n return false;\n }\n this.loading = true;\n try {\n const contact = await _services_imClient__WEBPACK_IMPORTED_MODULE_7__.imClient.addContact(session.userId, value, '添加联系人');\n if (contact) {\n this.contacts = normalizeContacts([...this.contacts, contact]);\n this.activeId = contact.id;\n }\n this.actionInfo = '联系人已添加';\n await this.refreshContacts({\n force: true\n });\n return true;\n } catch (error) {\n this.actionError = error.message || '添加联系人失败';\n return false;\n } finally {\n this.loading = false;\n }\n },\n async updateContactAlias(contactId, alias) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_10__.useSessionStore)();\n const targetId = String(contactId || '').trim();\n const nextAlias = String(alias || '').trim();\n this.actionError = '';\n this.actionInfo = '';\n if (!session.userId) {\n this.actionError = '请先登录';\n return false;\n }\n if (!targetId) {\n this.actionError = '缺少联系人ID';\n return false;\n }\n try {\n const savedAlias = await _services_imClient__WEBPACK_IMPORTED_MODULE_7__.imClient.updateContactAlias(session.userId, targetId, nextAlias);\n this.contacts = normalizeContacts(this.contacts.map(item => {\n if (item.uid !== targetId && item.id !== targetId) {\n return item;\n }\n const rawUser = {\n ...(item.rawUser || {}),\n friendAlias: savedAlias\n };\n const rawFriend = {\n ...(item.rawFriend || {}),\n alias: savedAlias\n };\n const title = savedAlias || rawUser.displayName || rawUser.name || item.uid;\n return {\n ...item,\n title,\n avatarText: title.slice(0, 1).toUpperCase(),\n alias: savedAlias,\n rawFriend,\n rawUser\n };\n }));\n this.loadedAt = Date.now();\n this.actionInfo = '备注名已修改';\n return true;\n } catch (error) {\n this.actionError = error.message || '备注名修改失败';\n return false;\n }\n },\n clearContacts() {\n this.refreshSerial += 1;\n this.contacts = [];\n this.activeId = '';\n this.loading = false;\n this.refreshPromise = null;\n this.loadedForUserId = '';\n this.loadedAt = 0;\n this.actionError = '';\n this.actionInfo = '';\n },\n setActiveContact(id) {\n this.activeId = id;\n },\n openChat(contact) {\n if (!contact) {\n return;\n }\n const conversations = (0,_stores_conversations__WEBPACK_IMPORTED_MODULE_8__.useConversationStore)();\n const navigation = (0,_stores_navigation__WEBPACK_IMPORTED_MODULE_9__.useNavigationStore)();\n const conversation = _services_imClient__WEBPACK_IMPORTED_MODULE_7__.imClient.createSingleConversation(contact.uid, contact);\n conversations.upsertConversation(conversation);\n conversations.setActiveConversation(conversation.id);\n navigation.showMessages();\n }\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/stores/contacts.js?\n}");
/***/ }),
/***/ "./src/stores/conversations.js":
/*!*************************************!*\
!*** ./src/stores/conversations.js ***!
\*************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useConversationStore: function() { return /* binding */ useConversationStore; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! core-js/modules/es.array.push.js */ \"./node_modules/core-js/modules/es.array.push.js\");\n/* harmony import */ var core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_push_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! core-js/modules/es.iterator.constructor.js */ \"./node_modules/core-js/modules/es.iterator.constructor.js\");\n/* harmony import */ var core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_constructor_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! core-js/modules/es.iterator.filter.js */ \"./node_modules/core-js/modules/es.iterator.filter.js\");\n/* harmony import */ var core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_filter_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! core-js/modules/es.iterator.find.js */ \"./node_modules/core-js/modules/es.iterator.find.js\");\n/* harmony import */ var core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_find_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! core-js/modules/es.iterator.flat-map.js */ \"./node_modules/core-js/modules/es.iterator.flat-map.js\");\n/* harmony import */ var core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_flat_map_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! core-js/modules/es.iterator.for-each.js */ \"./node_modules/core-js/modules/es.iterator.for-each.js\");\n/* harmony import */ var core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_for_each_js__WEBPACK_IMPORTED_MODULE_6__);\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! core-js/modules/es.iterator.map.js */ \"./node_modules/core-js/modules/es.iterator.map.js\");\n/* harmony import */ var core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_map_js__WEBPACK_IMPORTED_MODULE_7__);\n/* harmony import */ var core_js_modules_es_iterator_reduce_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! core-js/modules/es.iterator.reduce.js */ \"./node_modules/core-js/modules/es.iterator.reduce.js\");\n/* harmony import */ var core_js_modules_es_iterator_reduce_js__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_reduce_js__WEBPACK_IMPORTED_MODULE_8__);\n/* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! core-js/modules/es.iterator.some.js */ \"./node_modules/core-js/modules/es.iterator.some.js\");\n/* harmony import */ var core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_iterator_some_js__WEBPACK_IMPORTED_MODULE_9__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert.js */ \"./node_modules/core-js/modules/es.map.get-or-insert.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_js__WEBPACK_IMPORTED_MODULE_10__);\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! core-js/modules/es.map.get-or-insert-computed.js */ \"./node_modules/core-js/modules/es.map.get-or-insert-computed.js\");\n/* harmony import */ var core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_map_get_or_insert_computed_js__WEBPACK_IMPORTED_MODULE_11__);\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! core-js/modules/es.set.difference.v2.js */ \"./node_modules/core-js/modules/es.set.difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_difference_v2_js__WEBPACK_IMPORTED_MODULE_12__);\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! core-js/modules/es.set.intersection.v2.js */ \"./node_modules/core-js/modules/es.set.intersection.v2.js\");\n/* harmony import */ var core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_intersection_v2_js__WEBPACK_IMPORTED_MODULE_13__);\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! core-js/modules/es.set.is-disjoint-from.v2.js */ \"./node_modules/core-js/modules/es.set.is-disjoint-from.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_disjoint_from_v2_js__WEBPACK_IMPORTED_MODULE_14__);\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! core-js/modules/es.set.is-subset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-subset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_subset_of_v2_js__WEBPACK_IMPORTED_MODULE_15__);\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! core-js/modules/es.set.is-superset-of.v2.js */ \"./node_modules/core-js/modules/es.set.is-superset-of.v2.js\");\n/* harmony import */ var core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_is_superset_of_v2_js__WEBPACK_IMPORTED_MODULE_16__);\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! core-js/modules/es.set.symmetric-difference.v2.js */ \"./node_modules/core-js/modules/es.set.symmetric-difference.v2.js\");\n/* harmony import */ var core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_symmetric_difference_v2_js__WEBPACK_IMPORTED_MODULE_17__);\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! core-js/modules/es.set.union.v2.js */ \"./node_modules/core-js/modules/es.set.union.v2.js\");\n/* harmony import */ var core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_18___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_set_union_v2_js__WEBPACK_IMPORTED_MODULE_18__);\n/* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! pinia */ \"./node_modules/pinia/dist/pinia.mjs\");\n/* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! @/services/imClient */ \"./src/services/imClient.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n/* harmony import */ var _stores_session__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! @/stores/session */ \"./src/stores/session.js\");\n/* harmony import */ var _services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! @/services/realtimeNotifications */ \"./src/services/realtimeNotifications.js\");\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst LOCAL_CONVERSATION_STORAGE_KEY = 'qmt-web-im-local-conversations-v2';\nconst LOCAL_FAVORITE_MESSAGES_KEY = 'qmt-web-im-favorite-messages-v1';\nfunction scopedStorageKey(baseKey) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__.useSessionStore)();\n const scope = `${_config__WEBPACK_IMPORTED_MODULE_21__.appConfig.appServer || ''}:${session.userId || 'anonymous'}`;\n return `${baseKey}:${encodeURIComponent(scope)}`;\n}\nfunction readFavoriteMessages() {\n try {\n return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_FAVORITE_MESSAGES_KEY)) || '[]');\n } catch (error) {\n return [];\n }\n}\nfunction writeFavoriteMessages(messages) {\n localStorage.setItem(scopedStorageKey(LOCAL_FAVORITE_MESSAGES_KEY), JSON.stringify(messages));\n}\nfunction readLocalConversations() {\n try {\n return JSON.parse(localStorage.getItem(scopedStorageKey(LOCAL_CONVERSATION_STORAGE_KEY)) || '[]');\n } catch (error) {\n return [];\n }\n}\nfunction writeLocalConversations(conversations) {\n localStorage.setItem(scopedStorageKey(LOCAL_CONVERSATION_STORAGE_KEY), JSON.stringify(conversations));\n}\nfunction randomId() {\n if (window.crypto && window.crypto.randomUUID) {\n return window.crypto.randomUUID().replaceAll('-', '');\n }\n return `${Date.now()}${Math.random().toString(16).slice(2)}`;\n}\nfunction messageKey(message) {\n return message.id || message.messageUid;\n}\nfunction messageStableKey(message) {\n return String(message?.messageUid || message?.id || '');\n}\nfunction messageActivityTimestamp(message) {\n return Number(message?.activityTimestamp || message?.editedAt || message?.displayTimestamp || message?.timestamp || 0);\n}\nfunction isRecalledMessage(message) {\n return Boolean(message?.recalled) || message?.status === 'recalled';\n}\nfunction attachmentLabel(message) {\n const attachment = message?.attachment;\n if (!attachment) {\n return '';\n }\n if (attachment.type === 'image') {\n return '[图片]';\n }\n return `[文件] ${attachment.name || '文件'}`;\n}\nfunction messagePreviewText(message) {\n if (isRecalledMessage(message)) {\n return `[${message?.recallStatus || '已撤回'}]`;\n }\n const text = String(message?.text || '').replace(/\\s+/g, ' ').trim();\n return text || attachmentLabel(message);\n}\nfunction quotePrefix(message) {\n const text = messagePreviewText(message);\n return text.length > 48 ? `${text.slice(0, 48)}...` : text;\n}\nasync function writeClipboard(text) {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return;\n }\n const element = document.createElement('textarea');\n element.value = text;\n element.setAttribute('readonly', 'readonly');\n element.style.position = 'fixed';\n element.style.left = '-9999px';\n document.body.appendChild(element);\n element.select();\n document.execCommand('copy');\n document.body.removeChild(element);\n}\nfunction isSameMessage(left, right) {\n if (left.messageUid && right.messageUid && left.messageUid === right.messageUid) {\n return true;\n }\n if (left.id && right.id && left.id === right.id) {\n return true;\n }\n return left.direction === right.direction && left.text === right.text && (left.type || 'text') === (right.type || 'text') && Math.abs(Number(left.displayTimestamp || left.timestamp || 0) - Number(right.displayTimestamp || right.timestamp || 0)) < 15000;\n}\nfunction hasExactMessage(messages, message) {\n return messages.some(item => {\n if (item.id && message.id && item.id === message.id) {\n return true;\n }\n return item.messageUid && message.messageUid && item.messageUid === message.messageUid;\n });\n}\nfunction shouldUseMessagePolling() {\n return _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.shouldUseMessagePolling ? _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.shouldUseMessagePolling() : true;\n}\nfunction canMarkReadNow(options = {}) {\n if (typeof document === 'undefined') {\n return false;\n }\n if (document.visibilityState !== 'visible') {\n return false;\n }\n if (options.userAction) {\n return true;\n }\n return true;\n}\nfunction normalizeMessageForDisplay(message) {\n if (!message || message.attachment || String(message.text || '').trim()) {\n return message;\n }\n const contentType = Number(message.contentType || 0);\n const labels = {\n 3: '[图片加载失败]',\n 90: '[红包]',\n 105: '[领取了红包]'\n };\n if (!labels[contentType]) {\n return message;\n }\n return {\n ...message,\n type: 'text',\n text: labels[contentType]\n };\n}\nfunction mergeVisibleMessages(currentMessages, syncedMessages) {\n const merged = [...syncedMessages].map(normalizeMessageForDisplay);\n currentMessages.forEach(currentMessage => {\n currentMessage = normalizeMessageForDisplay(currentMessage);\n const exists = merged.some(message => isSameMessage(message, currentMessage));\n const shouldKeepLocal = currentMessage.status === 'sending' || currentMessage.status === 'failed' || currentMessage.direction === 'out' && currentMessage.status === 'sent' && Date.now() - Number(currentMessage.timestamp || 0) < 30000;\n if (!exists && shouldKeepLocal) {\n merged.push(currentMessage);\n }\n });\n return merged.filter((message, index, messages) => {\n const key = messageKey(message);\n return messages.findIndex(item => messageKey(item) === key) === index;\n }).sort((a, b) => Number(a.displayTimestamp || a.timestamp || 0) - Number(b.displayTimestamp || b.timestamp || 0));\n}\nfunction incomingEditedMessages(previousMessages, nextMessages) {\n const previousByKey = new Map();\n (previousMessages || []).forEach(message => {\n const key = messageStableKey(message);\n if (key) {\n previousByKey.set(key, message);\n }\n });\n return (nextMessages || []).filter(message => {\n if (message.direction !== 'in') {\n return false;\n }\n const editedAt = Number(message.editedAt || 0);\n if (editedAt <= 0) {\n return false;\n }\n const previous = previousByKey.get(messageStableKey(message));\n return previous && editedAt > Number(previous.editedAt || 0);\n });\n}\nlet notificationAudioContext = null;\nfunction playNotificationSound() {\n if (typeof window === 'undefined') {\n return;\n }\n try {\n const AudioContext = window.AudioContext || window.webkitAudioContext;\n if (!AudioContext) {\n return;\n }\n notificationAudioContext = notificationAudioContext || new AudioContext();\n if (notificationAudioContext.state === 'suspended') {\n notificationAudioContext.resume().catch(() => {});\n }\n const oscillator = notificationAudioContext.createOscillator();\n const gain = notificationAudioContext.createGain();\n const startAt = notificationAudioContext.currentTime;\n oscillator.type = 'sine';\n oscillator.frequency.setValueAtTime(880, startAt);\n oscillator.frequency.setValueAtTime(660, startAt + 0.1);\n gain.gain.setValueAtTime(0.0001, startAt);\n gain.gain.exponentialRampToValueAtTime(0.12, startAt + 0.02);\n gain.gain.exponentialRampToValueAtTime(0.0001, startAt + 0.22);\n oscillator.connect(gain);\n gain.connect(notificationAudioContext.destination);\n oscillator.start(startAt);\n oscillator.stop(startAt + 0.24);\n } catch (error) {\n // Notification sound is best-effort; browsers may block audio until user interaction.\n }\n}\nconst useConversationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_19__.defineStore)('conversations', {\n state: () => ({\n activeId: '',\n conversations: [],\n messagesByConversation: {},\n visibleMessagesByConversation: {},\n eventsBound: false,\n usingDemoData: false,\n loading: false,\n syncTimer: null,\n conversationSyncTimer: null,\n readPresenceEventsBound: false,\n syncInFlight: false,\n pendingReadReceiptConversationId: '',\n conversationSyncInFlight: false,\n syncAfterSendTimer: null,\n optimisticMessagesByConversation: {},\n quotedMessage: null,\n forwardingMessages: [],\n editingMessage: null,\n editingText: '',\n editingMode: '',\n messageDetailOpen: false,\n messageDetailLoading: false,\n messageDetailError: '',\n messageDetail: null,\n attentionMessageId: '',\n attentionMessageTimer: null,\n selectionMode: false,\n selectedMessageIds: [],\n favoriteMessages: [],\n activeFavoriteKey: '',\n actionNotice: '',\n actionError: '',\n realtimeSyncTimer: null\n }),\n getters: {\n activeConversation(state) {\n return state.conversations.find(item => item.id === state.activeId) || state.conversations[0] || null;\n },\n activeMessages(state) {\n return state.visibleMessagesByConversation[state.activeId] || [];\n },\n totalUnread(state) {\n return state.conversations.reduce((sum, item) => sum + Number(item.unread || 0), 0);\n },\n canSendActiveConversation(state) {\n const conversation = state.conversations.find(item => item.id === state.activeId) || state.conversations[0] || null;\n if (!conversation) {\n return false;\n }\n if (conversation.type !== 'channel') {\n return true;\n }\n return ['owner', 'admin'].includes(conversation.role || conversation.raw?.role || '');\n },\n favoriteMessageIds(state) {\n return state.favoriteMessages.map(message => message.key);\n },\n activeFavorite(state) {\n return state.favoriteMessages.find(message => message.key === state.activeFavoriteKey) || state.favoriteMessages[0] || null;\n },\n selectedMessages(state) {\n const selectedIds = new Set(state.selectedMessageIds);\n return (state.visibleMessagesByConversation[state.activeId] || []).filter(message => selectedIds.has(messageStableKey(message)));\n }\n },\n actions: {\n bootstrapDemoData() {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__.useSessionStore)();\n this.bindImEvents();\n this.usingDemoData = false;\n if (!session.userId) {\n this.clearUserState();\n return;\n }\n this.loadScopedLocalState();\n this.startMessageSync();\n _services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__.realtimeNotifications.start(session.userId, payload => this.handleRealtimeNotification(payload));\n },\n loadScopedLocalState() {\n this.conversations = [];\n this.favoriteMessages = readFavoriteMessages();\n this.activeFavoriteKey = this.favoriteMessages[0]?.key || '';\n this.activeId = '';\n this.messagesByConversation = {};\n this.visibleMessagesByConversation = {};\n this.optimisticMessagesByConversation = {};\n this.quotedMessage = null;\n this.forwardingMessages = [];\n this.editingMessage = null;\n this.editingText = '';\n this.editingMode = '';\n this.messageDetailOpen = false;\n this.messageDetailLoading = false;\n this.messageDetailError = '';\n this.messageDetail = null;\n this.selectionMode = false;\n this.selectedMessageIds = [];\n },\n clearUserState() {\n window.clearInterval(this.syncTimer);\n window.clearInterval(this.conversationSyncTimer);\n window.clearTimeout(this.syncAfterSendTimer);\n window.clearTimeout(this.attentionMessageTimer);\n window.clearTimeout(this.realtimeSyncTimer);\n _services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__.realtimeNotifications.stop();\n this.syncTimer = null;\n this.conversationSyncTimer = null;\n this.syncAfterSendTimer = null;\n this.attentionMessageTimer = null;\n this.realtimeSyncTimer = null;\n this.syncInFlight = false;\n this.conversationSyncInFlight = false;\n this.pendingReadReceiptConversationId = '';\n this.activeId = '';\n this.conversations = [];\n this.messagesByConversation = {};\n this.visibleMessagesByConversation = {};\n this.optimisticMessagesByConversation = {};\n this.quotedMessage = null;\n this.forwardingMessages = [];\n this.editingMessage = null;\n this.editingText = '';\n this.editingMode = '';\n this.messageDetailOpen = false;\n this.messageDetailLoading = false;\n this.messageDetailError = '';\n this.messageDetail = null;\n this.attentionMessageId = '';\n this.selectionMode = false;\n this.selectedMessageIds = [];\n this.favoriteMessages = [];\n this.activeFavoriteKey = '';\n this.actionNotice = '';\n this.actionError = '';\n },\n bindImEvents() {\n if (this.eventsBound) {\n return;\n }\n this.eventsBound = true;\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.on('messageSent', message => {\n this.appendMessage(message.conversationId, message);\n });\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.on('messageReceived', message => {\n this.appendMessage(message.conversationId, message);\n if (message.conversationId === this.activeId) {\n this.scheduleActiveMessagesSync({\n allowReadReceipt: true\n }, 500);\n }\n });\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.on('messageStatusChanged', message => {\n this.replaceMessage(message.conversationId, message);\n });\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.on('conversationsChanged', remoteConversations => {\n this.usingDemoData = false;\n this.applyRemoteConversations(remoteConversations);\n });\n },\n setActiveConversation(id) {\n this.activeId = id;\n const conversation = this.conversations.find(item => item.id === id);\n if (conversation) {\n conversation.unread = 0;\n }\n this.loadActiveMessages({\n allowReadReceipt: true,\n userAction: true\n });\n },\n sendText(text) {\n const conversation = this.activeConversation;\n if (!conversation || !text.trim()) {\n return;\n }\n let value = text.trim();\n if (this.quotedMessage) {\n value = `引用:${quotePrefix(this.quotedMessage)}\\n${value}`;\n this.quotedMessage = null;\n }\n const message = {\n id: randomId(),\n conversationId: conversation.id,\n from: 'me',\n direction: 'out',\n type: 'text',\n text: value,\n status: 'sending',\n deliveryStatus: 'sending',\n timestamp: Date.now(),\n displayTimestamp: Date.now()\n };\n this.appendVisibleMessage(conversation.id, message);\n this.appendMessage(conversation.id, message);\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.sendTextMessage(conversation, value, message);\n conversation.subtitle = value;\n conversation.updatedAt = Date.now();\n writeLocalConversations(this.conversations);\n window.clearTimeout(this.syncAfterSendTimer);\n this.syncAfterSendTimer = window.setTimeout(() => this.syncActiveMessages(), 250);\n },\n sendAttachment({\n type,\n file,\n text = ''\n }) {\n const conversation = this.activeConversation;\n if (!conversation || !file || !['image', 'file'].includes(type)) {\n return;\n }\n let value = text.trim();\n if (this.quotedMessage) {\n value = `引用:${quotePrefix(this.quotedMessage)}\\n${value}`.trim();\n this.quotedMessage = null;\n }\n const now = Date.now();\n const message = {\n id: randomId(),\n conversationId: conversation.id,\n from: 'me',\n senderRole: conversation.role || conversation.raw?.role || '',\n direction: 'out',\n type,\n text: value,\n attachment: {\n type,\n name: file.name || (type === 'image' ? '图片' : '文件'),\n mime: file.type || '',\n size: file.size || 0,\n url: type === 'image' ? URL.createObjectURL(file) : ''\n },\n status: 'sending',\n deliveryStatus: 'sending',\n timestamp: now,\n displayTimestamp: now\n };\n this.appendVisibleMessage(conversation.id, message);\n this.appendMessage(conversation.id, message);\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.sendAttachmentMessage(conversation, {\n type,\n file,\n text: value\n }, message);\n conversation.subtitle = messagePreviewText(message);\n conversation.updatedAt = now;\n writeLocalConversations(this.conversations);\n window.clearTimeout(this.syncAfterSendTimer);\n this.syncAfterSendTimer = window.setTimeout(() => this.syncActiveMessages(), 350);\n },\n async sendTextToConversation(conversation, text) {\n if (!conversation || !text.trim()) {\n return null;\n }\n const value = text.trim();\n const message = {\n id: randomId(),\n conversationId: conversation.id,\n from: 'me',\n direction: 'out',\n type: 'text',\n text: value,\n status: 'sending',\n deliveryStatus: 'sending',\n timestamp: Date.now(),\n displayTimestamp: Date.now()\n };\n this.appendMessage(conversation.id, message);\n const sentMessage = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.sendTextMessage(conversation, value, message);\n this.replaceMessage(conversation.id, sentMessage);\n return sentMessage;\n },\n upsertConversation(conversation) {\n const index = this.conversations.findIndex(item => item.id === conversation.id);\n if (index >= 0) {\n this.conversations.splice(index, 1, {\n ...this.conversations[index],\n ...conversation\n });\n } else {\n this.conversations.unshift(conversation);\n }\n this.usingDemoData = false;\n writeLocalConversations(this.conversations);\n },\n removeConversation(conversationId) {\n this.conversations = this.conversations.filter(conversation => conversation.id !== conversationId);\n const {\n [conversationId]: removedMessages,\n ...messagesByConversation\n } = this.messagesByConversation;\n const {\n [conversationId]: removedVisibleMessages,\n ...visibleMessagesByConversation\n } = this.visibleMessagesByConversation;\n const {\n [conversationId]: removedOptimisticMessages,\n ...optimisticMessagesByConversation\n } = this.optimisticMessagesByConversation;\n void removedMessages;\n void removedVisibleMessages;\n void removedOptimisticMessages;\n this.messagesByConversation = messagesByConversation;\n this.visibleMessagesByConversation = visibleMessagesByConversation;\n this.optimisticMessagesByConversation = optimisticMessagesByConversation;\n if (this.activeId === conversationId) {\n this.activeId = this.conversations[0]?.id || '';\n }\n writeLocalConversations(this.conversations);\n if (this.activeId) {\n this.loadActiveMessages();\n }\n },\n applyRemoteConversations(remoteConversations) {\n const remote = Array.isArray(remoteConversations) ? remoteConversations : [];\n if (!remote.length && this.conversations.length) {\n return;\n }\n const merged = new Map();\n this.conversations.forEach(conversation => {\n merged.set(conversation.id, conversation);\n });\n remote.forEach(conversation => {\n const unread = conversation.id === this.activeId && canMarkReadNow() ? 0 : Number(conversation.unread || 0);\n merged.set(conversation.id, {\n ...(merged.get(conversation.id) || {}),\n ...conversation,\n unread\n });\n });\n this.conversations = Array.from(merged.values()).sort((a, b) => Number(b.updatedAt || 0) - Number(a.updatedAt || 0)).slice(0, 100);\n if (!this.conversations.length) {\n this.activeId = '';\n this.messagesByConversation = {};\n this.visibleMessagesByConversation = {};\n this.optimisticMessagesByConversation = {};\n writeLocalConversations(this.conversations);\n return;\n }\n if (!this.conversations.find(item => item.id === this.activeId)) {\n this.activeId = this.conversations[0].id;\n }\n writeLocalConversations(this.conversations);\n this.loadActiveMessages();\n },\n appendMessage(conversationId, message) {\n if (!this.messagesByConversation[conversationId]) {\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversationId]: []\n };\n }\n if (message.direction === 'out' && (message.status === 'sending' || message.status === 'sent')) {\n this.keepOptimisticMessage(conversationId, message);\n }\n if (!hasExactMessage(this.messagesByConversation[conversationId], message)) {\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversationId]: [...this.messagesByConversation[conversationId], message]\n };\n }\n this.updateConversationFromMessage(conversationId, message);\n this.syncVisibleMessages(conversationId);\n writeLocalConversations(this.conversations);\n },\n removeMessages(conversationId, messages) {\n const ids = new Set(messages.flatMap(message => [message.id, message.messageUid].filter(Boolean).map(String)));\n const filterMessages = list => (list || []).filter(message => {\n return ![message.id, message.messageUid].filter(Boolean).some(id => ids.has(String(id)));\n });\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversationId]: filterMessages(this.messagesByConversation[conversationId])\n };\n this.visibleMessagesByConversation = {\n ...this.visibleMessagesByConversation,\n [conversationId]: filterMessages(this.visibleMessagesByConversation[conversationId])\n };\n this.optimisticMessagesByConversation = {\n ...this.optimisticMessagesByConversation,\n [conversationId]: filterMessages(this.optimisticMessagesByConversation[conversationId])\n };\n this.selectedMessageIds = this.selectedMessageIds.filter(id => !ids.has(String(id)));\n },\n replaceLocalMessage(conversationId, targetMessage, nextMessage) {\n const keys = new Set([targetMessage.id, targetMessage.messageUid].filter(Boolean).map(String));\n const replaceInList = list => (list || []).map(message => {\n const matched = [message.id, message.messageUid].filter(Boolean).some(id => keys.has(String(id)));\n return matched ? {\n ...message,\n ...nextMessage\n } : message;\n });\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversationId]: replaceInList(this.messagesByConversation[conversationId])\n };\n this.visibleMessagesByConversation = {\n ...this.visibleMessagesByConversation,\n [conversationId]: replaceInList(this.visibleMessagesByConversation[conversationId])\n };\n },\n updateConversationFromMessage(conversationId, message) {\n const conversation = this.conversations.find(item => item.id === conversationId);\n if (!conversation) {\n return;\n }\n conversation.subtitle = message.text || conversation.subtitle || '';\n conversation.updatedAt = messageActivityTimestamp(message) || Date.now();\n if (message.direction === 'in') {\n conversation.unread = conversationId === this.activeId ? 0 : Number(conversation.unread || 0) + 1;\n }\n this.conversations = [...this.conversations].sort((a, b) => Number(b.updatedAt || 0) - Number(a.updatedAt || 0));\n },\n appendVisibleMessage(conversationId, message) {\n const messages = this.visibleMessagesByConversation[conversationId] || [];\n this.visibleMessagesByConversation = {\n ...this.visibleMessagesByConversation,\n [conversationId]: [...messages.filter(item => item.id !== message.id), message].sort((a, b) => Number(a.displayTimestamp || a.timestamp || 0) - Number(b.displayTimestamp || b.timestamp || 0))\n };\n },\n replaceMessage(conversationId, message) {\n if (!this.messagesByConversation[conversationId]) {\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversationId]: []\n };\n }\n if (message.direction === 'out' && (message.status === 'sending' || message.status === 'sent' || message.status === 'failed')) {\n this.keepOptimisticMessage(conversationId, message);\n }\n const index = this.messagesByConversation[conversationId].findIndex(item => item.id === message.id);\n if (index >= 0) {\n const messages = [...this.messagesByConversation[conversationId]];\n messages.splice(index, 1, message);\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversationId]: messages\n };\n } else {\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversationId]: [...this.messagesByConversation[conversationId], message]\n };\n }\n this.syncVisibleMessages(conversationId);\n },\n syncVisibleMessages(conversationId) {\n this.visibleMessagesByConversation = {\n ...this.visibleMessagesByConversation,\n [conversationId]: mergeVisibleMessages(this.optimisticMessagesByConversation[conversationId] || [], this.messagesByConversation[conversationId] || [])\n };\n },\n keepOptimisticMessage(conversationId, message) {\n if (!this.optimisticMessagesByConversation[conversationId]) {\n this.optimisticMessagesByConversation = {\n ...this.optimisticMessagesByConversation,\n [conversationId]: []\n };\n }\n const messages = this.optimisticMessagesByConversation[conversationId];\n const index = messages.findIndex(item => item.id === message.id);\n let nextMessages;\n if (index >= 0) {\n nextMessages = [...messages];\n nextMessages.splice(index, 1, message);\n } else {\n nextMessages = [...messages, message];\n }\n this.optimisticMessagesByConversation = {\n ...this.optimisticMessagesByConversation,\n [conversationId]: nextMessages\n };\n },\n pruneOptimisticMessages(conversationId, syncedMessages) {\n const messages = this.optimisticMessagesByConversation[conversationId] || [];\n if (!messages.length) {\n return;\n }\n this.optimisticMessagesByConversation = {\n ...this.optimisticMessagesByConversation,\n [conversationId]: messages.filter(message => {\n const remoteMatched = syncedMessages.some(syncedMessage => {\n return syncedMessage.id !== message.id && isSameMessage(syncedMessage, message);\n });\n if (remoteMatched && message.status !== 'failed') {\n return false;\n }\n return Date.now() - Number(message.displayTimestamp || message.timestamp || 0) < 30000 || message.status === 'failed';\n })\n };\n },\n loadActiveMessages(options = {}) {\n const syncOptions = typeof options === 'boolean' ? {\n allowReadReceipt: options\n } : options;\n const conversation = this.activeConversation;\n if (!conversation) {\n return;\n }\n this.loading = true;\n const messages = _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.getMessages(conversation, 30);\n this.pruneOptimisticMessages(conversation.id, messages);\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [conversation.id]: mergeVisibleMessages(this.messagesByConversation[conversation.id] || [], messages)\n };\n this.syncVisibleMessages(conversation.id);\n this.loading = false;\n this.syncActiveMessages(syncOptions);\n },\n async syncActiveMessages(options = {}) {\n const conversation = this.activeConversation;\n if (!conversation) {\n return;\n }\n const wantsReadReceipt = Boolean(options.allowReadReceipt);\n const explicitReadReceipt = wantsReadReceipt && canMarkReadNow({\n userAction: Boolean(options.userAction)\n });\n const pollingReadReceipt = canMarkReadNow();\n const markRead = explicitReadReceipt || pollingReadReceipt;\n if (this.syncInFlight) {\n if (wantsReadReceipt) {\n this.pendingReadReceiptConversationId = conversation.id;\n }\n return;\n }\n this.syncInFlight = true;\n const syncedConversationId = conversation.id;\n const previousMessages = this.messagesByConversation[syncedConversationId] || [];\n try {\n const messages = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.fetchRemoteMessages(conversation, 50, {\n markRead,\n includeConversations: Boolean(options.includeConversations)\n });\n const editedIncomingMessages = incomingEditedMessages(previousMessages, messages);\n this.pruneOptimisticMessages(syncedConversationId, messages);\n this.messagesByConversation = {\n ...this.messagesByConversation,\n [syncedConversationId]: mergeVisibleMessages(this.messagesByConversation[syncedConversationId] || [], messages)\n };\n this.syncVisibleMessages(syncedConversationId);\n if (editedIncomingMessages.length && syncedConversationId === this.activeId) {\n this.focusMessage(editedIncomingMessages.sort((a, b) => messageActivityTimestamp(b) - messageActivityTimestamp(a))[0]);\n playNotificationSound();\n }\n const latest = messages.reduce((latestMessage, message) => {\n if (!latestMessage || messageActivityTimestamp(message) > messageActivityTimestamp(latestMessage)) {\n return message;\n }\n return latestMessage;\n }, null);\n if (latest) {\n conversation.subtitle = messagePreviewText(latest);\n conversation.updatedAt = messageActivityTimestamp(latest);\n writeLocalConversations(this.conversations);\n }\n } catch (error) {\n // Keep the local view usable if a polling request misses.\n } finally {\n this.syncInFlight = false;\n if (this.pendingReadReceiptConversationId === this.activeId && canMarkReadNow()) {\n this.pendingReadReceiptConversationId = '';\n window.setTimeout(() => this.syncActiveMessages({\n allowReadReceipt: true\n }), 0);\n }\n }\n },\n scheduleActiveMessagesSync(options = {}, delay = 500) {\n if (!this.activeId || typeof document !== 'undefined' && document.visibilityState !== 'visible') {\n return;\n }\n window.clearTimeout(this.syncAfterSendTimer);\n this.syncAfterSendTimer = window.setTimeout(() => {\n this.syncAfterSendTimer = null;\n this.syncActiveMessages(options);\n }, Math.max(0, Number(delay) || 0));\n },\n startMessageSync() {\n this.bindReadPresenceEvents();\n if (!this.syncTimer) {\n this.syncTimer = window.setInterval(() => {\n if (document.visibilityState === 'visible' && !_services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__.realtimeNotifications.isConnected()) {\n this.syncActiveMessages();\n }\n }, Math.max(250, _config__WEBPACK_IMPORTED_MODULE_21__.appConfig.syncIntervalMs));\n }\n if (!this.conversationSyncTimer) {\n this.conversationSyncTimer = window.setInterval(() => {\n if (document.visibilityState === 'visible' && !_services_realtimeNotifications__WEBPACK_IMPORTED_MODULE_23__.realtimeNotifications.isConnected()) {\n this.refreshRemoteConversations();\n }\n }, Math.max(5000, _config__WEBPACK_IMPORTED_MODULE_21__.appConfig.syncIntervalMs * 2));\n this.refreshRemoteConversations();\n }\n },\n handleRealtimeNotification() {\n window.clearTimeout(this.realtimeSyncTimer);\n this.realtimeSyncTimer = window.setTimeout(() => {\n this.refreshRemoteConversations();\n this.scheduleActiveMessagesSync({\n allowReadReceipt: canMarkReadNow(),\n includeConversations: true\n }, 300);\n }, 300);\n },\n bindReadPresenceEvents() {\n if (this.readPresenceEventsBound || typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n this.readPresenceEventsBound = true;\n const syncWhenReadable = () => {\n if (canMarkReadNow()) {\n this.refreshRemoteConversations();\n this.scheduleActiveMessagesSync({\n allowReadReceipt: true\n }, 200);\n }\n };\n window.addEventListener('focus', syncWhenReadable);\n document.addEventListener('visibilitychange', syncWhenReadable);\n },\n async refreshRemoteConversations() {\n this.bindImEvents();\n this.usingDemoData = false;\n if (this.conversationSyncInFlight) {\n return;\n }\n this.conversationSyncInFlight = true;\n try {\n const remoteConversations = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.fetchRemoteConversations(50);\n this.applyRemoteConversations(remoteConversations);\n } catch (error) {\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.refreshConversationList();\n } finally {\n this.conversationSyncInFlight = false;\n }\n },\n setActionNotice(message) {\n this.actionNotice = message;\n this.actionError = '';\n },\n setActionError(message) {\n this.actionError = message;\n this.actionNotice = '';\n },\n focusMessage(message) {\n const key = messageStableKey(message);\n if (!key) {\n return;\n }\n this.attentionMessageId = key;\n window.clearTimeout(this.attentionMessageTimer);\n this.attentionMessageTimer = window.setTimeout(() => {\n if (this.attentionMessageId === key) {\n this.attentionMessageId = '';\n }\n }, 2800);\n },\n async handleMessageAction({\n action,\n message\n }) {\n if (!message) {\n return;\n }\n if (action === 'copy') {\n await this.copyMessages([message]);\n } else if (action === 'edit') {\n this.startEditMessage(message);\n } else if (action === 'delete') {\n this.deleteMessages([message]);\n } else if (action === 'forward') {\n this.startForward([message]);\n } else if (action === 'favorite') {\n this.toggleFavorite(message);\n } else if (action === 'detail') {\n await this.openMessageDetail(message);\n } else if (action === 'quote') {\n this.quoteMessage(message);\n } else if (action === 'select') {\n this.enterSelectionMode(message);\n } else if (action === 'recall') {\n await this.recallMessage(message);\n }\n },\n async openMessageDetail(message) {\n const conversation = this.activeConversation;\n if (!conversation || !message) {\n return;\n }\n const key = messageStableKey(message);\n this.messageDetailOpen = true;\n this.messageDetailLoading = true;\n this.messageDetailError = '';\n this.messageDetail = {\n messageUid: key,\n conversationType: conversation.type || conversation.raw?.type || 'single',\n sentAt: Number(message.displayTimestamp || message.timestamp || 0),\n editedAt: Number(message.editedAt || 0),\n recalled: isRecalledMessage(message),\n localOnly: true,\n sender: {\n uid: message.from || '',\n name: message.senderName || message.from || ''\n }\n };\n try {\n if (!/^\\d+$/.test(key)) {\n this.messageDetailError = '本地临时消息暂无送达/已读详情';\n return;\n }\n const detail = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.getMessageDetail(conversation, message);\n this.messageDetail = detail || this.messageDetail;\n } catch (error) {\n this.messageDetailError = error.message || '消息详情加载失败';\n } finally {\n this.messageDetailLoading = false;\n }\n },\n closeMessageDetail() {\n this.messageDetailOpen = false;\n this.messageDetailLoading = false;\n this.messageDetailError = '';\n this.messageDetail = null;\n },\n async copyMessages(messages) {\n const text = messages.map(message => message.text || '').join('\\n');\n if (!text.trim()) {\n return;\n }\n try {\n await writeClipboard(text);\n this.setActionNotice(messages.length > 1 ? '已复制所选消息' : '已复制');\n } catch (error) {\n this.setActionError('复制失败');\n }\n },\n deleteMessages(messages) {\n const conversation = this.activeConversation;\n if (!conversation || !messages.length) {\n return;\n }\n _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.hideMessages(conversation, messages);\n this.removeMessages(conversation.id, messages);\n if (!this.selectedMessageIds.length) {\n this.selectionMode = false;\n }\n this.setActionNotice(messages.length > 1 ? '已删除所选消息' : '已删除');\n },\n toggleFavorite(message) {\n const key = messageStableKey(message);\n if (!key) {\n return;\n }\n const index = this.favoriteMessages.findIndex(item => item.key === key);\n if (index >= 0) {\n this.favoriteMessages.splice(index, 1);\n if (this.activeFavoriteKey === key) {\n this.activeFavoriteKey = this.favoriteMessages[0]?.key || '';\n }\n this.setActionNotice('已取消收藏');\n } else {\n const conversation = this.conversations.find(item => item.id === message.conversationId) || {};\n this.favoriteMessages.unshift({\n key,\n id: message.id,\n messageUid: message.messageUid,\n conversationId: message.conversationId,\n conversationTitle: conversation.title || message.conversationTitle || '',\n type: message.type || 'text',\n text: message.text || '',\n preview: messagePreviewText(message),\n senderName: message.senderName || message.from || '',\n timestamp: Number(message.displayTimestamp || message.timestamp || Date.now()),\n editedAt: Number(message.editedAt || 0),\n recalled: isRecalledMessage(message),\n recallStatus: message.recallStatus || (isRecalledMessage(message) ? '已撤回' : ''),\n attachment: message.attachment ? {\n ...message.attachment\n } : null\n });\n this.activeFavoriteKey = key;\n this.setActionNotice('已收藏');\n }\n this.favoriteMessages = this.favoriteMessages.slice(0, 200);\n writeFavoriteMessages(this.favoriteMessages);\n },\n setActiveFavorite(key) {\n this.activeFavoriteKey = String(key || '');\n },\n removeFavorite(key) {\n const value = String(key || '');\n if (!value) {\n return;\n }\n this.favoriteMessages = this.favoriteMessages.filter(message => message.key !== value);\n if (this.activeFavoriteKey === value) {\n this.activeFavoriteKey = this.favoriteMessages[0]?.key || '';\n }\n writeFavoriteMessages(this.favoriteMessages);\n },\n quoteMessage(message) {\n this.quotedMessage = {\n ...message,\n quoteText: quotePrefix(message)\n };\n this.setActionNotice('已引用,输入后发送');\n },\n cancelQuote() {\n this.quotedMessage = null;\n },\n enterSelectionMode(message = null) {\n this.selectionMode = true;\n if (message) {\n const key = messageStableKey(message);\n this.selectedMessageIds = key ? [key] : [];\n }\n },\n toggleSelectedMessage(message) {\n const key = messageStableKey(message);\n if (!key) {\n return;\n }\n const selected = new Set(this.selectedMessageIds);\n if (selected.has(key)) {\n selected.delete(key);\n } else {\n selected.add(key);\n }\n this.selectedMessageIds = Array.from(selected);\n this.selectionMode = this.selectedMessageIds.length > 0;\n },\n clearSelection() {\n this.selectionMode = false;\n this.selectedMessageIds = [];\n },\n copySelectedMessages() {\n return this.copyMessages(this.selectedMessages);\n },\n deleteSelectedMessages() {\n this.deleteMessages(this.selectedMessages);\n },\n startForward(messages) {\n this.forwardingMessages = messages.filter(message => message?.text);\n if (!this.forwardingMessages.length) {\n this.setActionError('没有可转发的消息');\n }\n },\n startForwardSelectedMessages() {\n this.startForward(this.selectedMessages);\n },\n cancelForward() {\n this.forwardingMessages = [];\n },\n startEditMessage(message) {\n const isResend = isRecalledMessage(message);\n if (!isResend && !message?.text) {\n this.setActionError('没有可编辑的文字内容');\n return;\n }\n this.editingMessage = message;\n this.editingText = message.text || '';\n this.editingMode = isResend ? 'resend' : 'edit';\n },\n cancelEditMessage() {\n this.editingMessage = null;\n this.editingText = '';\n this.editingMode = '';\n },\n async completeEditMessage() {\n const conversation = this.activeConversation;\n const message = this.editingMessage;\n const text = this.editingText.trim();\n const isResend = this.editingMode === 'resend' || isRecalledMessage(message);\n if (!conversation || !message) {\n this.cancelEditMessage();\n return;\n }\n if (!text) {\n this.setActionError('编辑内容不能为空');\n return;\n }\n if (!isResend && text === String(message.text || '').trim()) {\n this.cancelEditMessage();\n return;\n }\n try {\n if (isResend) {\n await this.sendTextToConversation(conversation, text);\n this.cancelEditMessage();\n this.setActionNotice('已重新发送');\n return;\n }\n const editedMessage = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.editMessage(conversation, message, text);\n this.replaceLocalMessage(conversation.id, message, editedMessage);\n if (messageActivityTimestamp(editedMessage) >= Number(conversation.updatedAt || 0)) {\n conversation.subtitle = editedMessage.text;\n conversation.updatedAt = messageActivityTimestamp(editedMessage);\n writeLocalConversations(this.conversations);\n }\n this.cancelEditMessage();\n this.setActionNotice('已编辑');\n } catch (error) {\n this.setActionError(error.message || '编辑失败');\n }\n },\n async completeForward(targetConversationId) {\n const target = this.conversations.find(conversation => conversation.id === targetConversationId);\n if (!target || !this.forwardingMessages.length) {\n return;\n }\n const text = this.forwardingMessages.map(message => `转发:${message.text || ''}`).join('\\n\\n');\n try {\n await this.sendTextToConversation(target, text);\n this.forwardingMessages = [];\n this.clearSelection();\n this.setActionNotice('已转发');\n } catch (error) {\n this.setActionError(error.message || '转发失败');\n }\n },\n async recallMessage(message) {\n const conversation = this.activeConversation;\n if (!conversation) {\n return;\n }\n try {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.recallMessage(conversation, message);\n if (message.direction !== 'out') {\n this.removeMessages(conversation.id, [message]);\n this.setActionNotice('已撤回');\n this.syncActiveMessages();\n return;\n }\n this.replaceLocalMessage(conversation.id, message, {\n status: 'recalled',\n deliveryStatus: '',\n recalled: true,\n recallStatus: '已撤回'\n });\n this.setActionNotice('已撤回');\n } catch (error) {\n this.setActionError(error.message || '撤回失败');\n }\n },\n async createGroup(options = {}) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__.useSessionStore)();\n if (!session.userId) {\n this.setActionError('请先登录');\n return false;\n }\n try {\n const conversation = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.createGroup(session.userId, options);\n this.upsertConversation(conversation);\n this.setActiveConversation(conversation.id);\n this.setActionNotice(options.channel ? '公告群已创建' : '群组已创建');\n this.refreshRemoteConversations();\n return true;\n } catch (error) {\n this.setActionError(error.message || (options.channel ? '创建公告群失败' : '创建群组失败'));\n return false;\n }\n },\n async joinGroup(groupKey) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__.useSessionStore)();\n if (!session.userId) {\n this.setActionError('请先登录');\n return false;\n }\n try {\n const conversation = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.joinGroup(session.userId, groupKey);\n this.upsertConversation(conversation);\n this.setActiveConversation(conversation.id);\n this.setActionNotice('已加入群组');\n this.refreshRemoteConversations();\n return true;\n } catch (error) {\n this.setActionError(error.message || '加入群组失败');\n return false;\n }\n },\n async broadcastMessage(targetIds, text) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__.useSessionStore)();\n if (!session.userId) {\n this.setActionError('请先登录');\n return false;\n }\n try {\n const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.broadcastMessage(session.userId, targetIds, text);\n const successCount = Number(result.successCount || 0);\n const failedCount = Number(result.failedCount || 0);\n this.setActionNotice(failedCount > 0 ? `已群发 ${successCount} 条,失败 ${failedCount} 条` : `已群发 ${successCount} 条`);\n this.refreshRemoteConversations();\n return true;\n } catch (error) {\n this.setActionError(error.message || '群发失败');\n return false;\n }\n },\n async leaveGroup(conversation) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__.useSessionStore)();\n if (!session.userId || !conversation?.target) {\n this.setActionError('缺少群组信息');\n return false;\n }\n try {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.leaveGroup(session.userId, conversation.target);\n this.removeConversation(conversation.id);\n this.setActionNotice('已退出群组');\n this.refreshRemoteConversations();\n return true;\n } catch (error) {\n this.setActionError(error.message || '退出群组失败');\n return false;\n }\n },\n async dismissGroup(conversation) {\n const session = (0,_stores_session__WEBPACK_IMPORTED_MODULE_22__.useSessionStore)();\n if (!session.userId || !conversation?.target) {\n this.setActionError('缺少群组信息');\n return false;\n }\n try {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_20__.imClient.dismissGroup(session.userId, conversation.target);\n this.removeConversation(conversation.id);\n this.setActionNotice('群组已解散');\n this.refreshRemoteConversations();\n return true;\n } catch (error) {\n this.setActionError(error.message || '解散群组失败');\n return false;\n }\n }\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/stores/conversations.js?\n}");
/***/ }),
/***/ "./src/stores/navigation.js":
/*!**********************************!*\
!*** ./src/stores/navigation.js ***!
\**********************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useNavigationStore: function() { return /* binding */ useNavigationStore; }\n/* harmony export */ });\n/* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! pinia */ \"./node_modules/pinia/dist/pinia.mjs\");\n\nconst useNavigationStore = (0,pinia__WEBPACK_IMPORTED_MODULE_0__.defineStore)('navigation', {\n state: () => ({\n section: 'messages'\n }),\n actions: {\n showMessages() {\n this.section = 'messages';\n },\n showContacts() {\n this.section = 'contacts';\n },\n showFavorites() {\n this.section = 'favorites';\n }\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/stores/navigation.js?\n}");
/***/ }),
/***/ "./src/stores/session.js":
/*!*******************************!*\
!*** ./src/stores/session.js ***!
\*******************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ useSessionStore: function() { return /* binding */ useSessionStore; }\n/* harmony export */ });\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! core-js/modules/es.array.includes.js */ \"./node_modules/core-js/modules/es.array.includes.js\");\n/* harmony import */ var core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(core_js_modules_es_array_includes_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var pinia__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! pinia */ \"./node_modules/pinia/dist/pinia.mjs\");\n/* harmony import */ var _services_imClient__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @/services/imClient */ \"./src/services/imClient.js\");\n/* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/config */ \"./src/config.js\");\n\n\n\n\nconst STORAGE_KEY = 'qmt-web-im-session';\nfunction normalizeStoredPortrait(portrait) {\n return portrait || '';\n}\nfunction nextProfilePortrait(profilePortrait, currentPortrait) {\n return normalizeStoredPortrait(profilePortrait) || normalizeStoredPortrait(currentPortrait);\n}\nfunction inferAccountType(account) {\n return String(account || '').includes('@') ? 2 : 1;\n}\nconst useSessionStore = (0,pinia__WEBPACK_IMPORTED_MODULE_1__.defineStore)('session', {\n state: () => ({\n isAuthenticated: false,\n connecting: false,\n connected: false,\n connectionStatusText: '未连接',\n userId: '',\n token: '',\n displayName: '',\n portrait: '',\n error: '',\n sdkVersion: '',\n eventsBound: false\n }),\n actions: {\n restore() {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) {\n return;\n }\n try {\n const session = JSON.parse(raw);\n if (session.appServer !== _config__WEBPACK_IMPORTED_MODULE_3__.appConfig.appServer) {\n localStorage.removeItem(STORAGE_KEY);\n return;\n }\n if (session.userId && session.token) {\n if (!session.clientId) {\n localStorage.removeItem(STORAGE_KEY);\n return;\n }\n this.userId = session.userId;\n this.token = session.token;\n this.displayName = session.displayName || session.userId;\n this.portrait = normalizeStoredPortrait(session.portrait);\n this.isAuthenticated = true;\n _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.restoreClientId(session.clientId);\n this.connect();\n this.refreshProfile();\n }\n } catch (error) {\n localStorage.removeItem(STORAGE_KEY);\n }\n },\n async loginWithPassword(account, password, type = inferAccountType(account)) {\n this.error = '';\n this.connecting = true;\n try {\n const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.loginWithPassword(account, password, type);\n this.applyLoginResult(result);\n await this.connect();\n } catch (error) {\n this.error = error.message || '登录失败';\n } finally {\n this.connecting = false;\n }\n },\n async loginWithCode(account, code) {\n this.error = '';\n this.connecting = true;\n try {\n const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.loginWithCode(account, code);\n this.applyLoginResult(result);\n await this.connect();\n } catch (error) {\n this.error = error.message || '登录失败';\n } finally {\n this.connecting = false;\n }\n },\n async completePcSessionLogin(result) {\n this.error = '';\n this.connecting = true;\n try {\n this.applyLoginResult(result);\n await this.connect();\n } catch (error) {\n this.error = error.message || '扫码登录失败';\n } finally {\n this.connecting = false;\n }\n },\n async register(payload) {\n this.error = '';\n this.connecting = true;\n try {\n const result = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.register(payload);\n this.applyLoginResult(result);\n await this.connect();\n return result;\n } catch (error) {\n this.error = error.message || '注册失败';\n return null;\n } finally {\n this.connecting = false;\n }\n },\n applyLoginResult(result) {\n this.userId = result.userId || result.uid || result.id || '';\n this.token = result.token || result.imToken || '';\n this.displayName = result.displayName || result.userName || result.name || this.userId;\n this.portrait = normalizeStoredPortrait(result.portrait);\n this.isAuthenticated = Boolean(this.userId && this.token);\n this.persistSession();\n },\n persistSession() {\n localStorage.setItem(STORAGE_KEY, JSON.stringify({\n userId: this.userId,\n token: this.token,\n displayName: this.displayName,\n portrait: this.portrait,\n clientId: _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.getClientId(),\n appServer: _config__WEBPACK_IMPORTED_MODULE_3__.appConfig.appServer\n }));\n },\n applyProfile(profile) {\n if (!profile) {\n return;\n }\n this.userId = profile.userId || profile.uid || this.userId;\n this.displayName = profile.displayName || profile.name || this.displayName || this.userId;\n this.portrait = nextProfilePortrait(profile.portrait, this.portrait);\n this.persistSession();\n },\n async refreshProfile() {\n if (!this.userId) {\n return null;\n }\n try {\n const profile = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.getProfile(this.userId);\n this.applyProfile(profile);\n return profile;\n } catch (error) {\n return null;\n }\n },\n async saveProfile({\n displayName,\n portraitFile\n }) {\n if (!this.userId) {\n throw new Error('请先登录');\n }\n const profile = await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.updateProfile(this.userId, {\n displayName,\n portraitFile\n });\n this.applyProfile(profile);\n return profile;\n },\n async changePassword({\n oldPassword,\n newPassword\n }) {\n if (!this.userId) {\n throw new Error('请先登录');\n }\n await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.changePassword({\n oldPassword,\n newPassword\n });\n await this.logout();\n return true;\n },\n async resetPasswordWithCode({\n mobile,\n resetCode,\n newPassword\n }) {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.resetPasswordWithCode({\n mobile,\n resetCode,\n newPassword\n });\n return true;\n },\n async connect() {\n if (!this.userId || !this.token) {\n return;\n }\n await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.ensureSdk();\n this.sdkVersion = _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.getSdkVersion();\n this.bindImEvents();\n await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.connect(this.userId, this.token);\n },\n bindImEvents() {\n if (this.eventsBound) {\n return;\n }\n this.eventsBound = true;\n _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.on('connectionStatusChanged', status => {\n this.connected = status.connected;\n this.connectionStatusText = status.statusText || (status.connected ? '已连接' : '未连接');\n });\n },\n async logout() {\n try {\n await _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.logout?.();\n } catch (error) {\n this.error = error.message || '退出登录失败';\n } finally {\n _services_imClient__WEBPACK_IMPORTED_MODULE_2__.imClient.disconnect();\n localStorage.removeItem(STORAGE_KEY);\n this.$reset();\n }\n }\n }\n});\n\n//# sourceURL=webpack://jc-web-im/./src/stores/session.js?\n}");
/***/ }),
/***/ "./node_modules/css-loader/dist/cjs.js??clonedRuleSet-14.use[1]!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-14.use[2]!./src/styles/base.css":
/*!***************************************************************************************************************************************************************!*\
!*** ./node_modules/css-loader/dist/cjs.js??clonedRuleSet-14.use[1]!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-14.use[2]!./src/styles/base.css ***!
\***************************************************************************************************************************************************************/
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \":root {\\r\\n color-scheme: light;\\r\\n --bg: #f4f6f8;\\r\\n --panel: #ffffff;\\r\\n --panel-soft: #f8fafc;\\r\\n --line: #d9e0e7;\\r\\n --text: #18212f;\\r\\n --muted: #6a7584;\\r\\n --primary: #177d72;\\r\\n --primary-strong: #0f625a;\\r\\n --accent: #d84e3f;\\r\\n --bubble-in: #ffffff;\\r\\n --bubble-out: #dff4ef;\\r\\n --rail: #202a33;\\r\\n}\\r\\n\\r\\n* {\\r\\n box-sizing: border-box;\\r\\n}\\r\\n\\r\\nhtml,\\r\\nbody,\\r\\n#app {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\nbody {\\r\\n margin: 0;\\r\\n min-width: 320px;\\r\\n background: var(--bg);\\r\\n color: var(--text);\\r\\n font-family: -apple-system, BlinkMacSystemFont, \\\"Segoe UI\\\", sans-serif;\\r\\n}\\r\\n\\r\\nbutton,\\r\\ninput,\\r\\ntextarea {\\r\\n font: inherit;\\r\\n}\\r\\n\\r\\nbutton {\\r\\n cursor: pointer;\\r\\n}\\r\\n\\r\\n.login-page {\\r\\n min-height: 100vh;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n padding: 24px;\\r\\n background: linear-gradient(135deg, #eef6f3 0%, #f7f3ee 55%, #eef2f7 100%);\\r\\n}\\r\\n\\r\\n.login-panel {\\r\\n width: min(420px, 100%);\\r\\n padding: 32px;\\r\\n background: var(--panel);\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n box-shadow: 0 18px 48px rgba(30, 40, 50, 0.12);\\r\\n}\\r\\n\\r\\n.brand-lockup {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n gap: 14px;\\r\\n margin-bottom: 28px;\\r\\n}\\r\\n\\r\\n.brand-mark,\\r\\n.rail-avatar,\\r\\n.conversation-avatar {\\r\\n display: grid;\\r\\n place-items: center;\\r\\n flex: 0 0 auto;\\r\\n}\\r\\n\\r\\n.image-avatar {\\r\\n -o-object-fit: cover;\\r\\n object-fit: cover;\\r\\n}\\r\\n\\r\\n.brand-mark {\\r\\n width: 48px;\\r\\n height: 48px;\\r\\n border-radius: 8px;\\r\\n -o-object-fit: contain;\\r\\n object-fit: contain;\\r\\n background: #fff;\\r\\n}\\r\\n\\r\\n.brand-lockup h1,\\r\\n.list-header h2,\\r\\n.chat-header h2 {\\r\\n margin: 0;\\r\\n font-size: 20px;\\r\\n}\\r\\n\\r\\n.brand-lockup p,\\r\\n.list-header p,\\r\\n.chat-header p {\\r\\n margin: 4px 0 0;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.login-form {\\r\\n display: grid;\\r\\n gap: 16px;\\r\\n}\\r\\n\\r\\n.login-tabs,\\r\\n.code-row,\\r\\n.phone-row,\\r\\n.captcha-row {\\r\\n display: grid;\\r\\n grid-template-columns: 1fr 1fr;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.login-tabs button,\\r\\n.code-action {\\r\\n height: 38px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.login-tabs button.active {\\r\\n border-color: var(--primary);\\r\\n background: #e8f4f2;\\r\\n color: var(--primary-strong);\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.login-tabs {\\r\\n grid-template-columns: repeat(3, minmax(0, 1fr));\\r\\n}\\r\\n\\r\\n.login-tabs button {\\r\\n min-width: 0;\\r\\n padding: 0 6px;\\r\\n overflow-wrap: anywhere;\\r\\n}\\r\\n\\r\\n.code-row {\\r\\n grid-template-columns: minmax(0, 1fr) 112px;\\r\\n}\\r\\n\\r\\n.captcha-row {\\r\\n grid-template-columns: minmax(0, 1fr) 112px;\\r\\n}\\r\\n\\r\\n.phone-row {\\r\\n grid-template-columns: 86px minmax(0, 1fr);\\r\\n}\\r\\n\\r\\n.country-code-field {\\r\\n height: 42px;\\r\\n display: grid;\\r\\n grid-template-columns: 24px minmax(0, 1fr);\\r\\n align-items: center;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.country-code-field:focus-within {\\r\\n border-color: var(--primary);\\r\\n box-shadow: 0 0 0 3px rgba(23, 125, 114, 0.12);\\r\\n}\\r\\n\\r\\n.country-code-field span {\\r\\n display: grid;\\r\\n place-items: center;\\r\\n color: var(--muted);\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.code-action:disabled {\\r\\n cursor: not-allowed;\\r\\n opacity: 0.55;\\r\\n}\\r\\n\\r\\n.login-form label {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.label-row {\\r\\n min-height: 18px;\\r\\n display: grid;\\r\\n grid-template-columns: 86px minmax(0, 1fr);\\r\\n align-items: center;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.field-error-badge {\\r\\n min-height: 28px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n padding: 4px 10px;\\r\\n border-radius: 2px;\\r\\n background: var(--accent);\\r\\n color: #fff;\\r\\n font-weight: 700;\\r\\n line-height: 1.2;\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.login-form input,\\r\\n.login-form select,\\r\\n.modal-panel input,\\r\\n.modal-panel textarea,\\r\\n.search-box input,\\r\\n.message-composer textarea {\\r\\n width: 100%;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n outline: none;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.login-form input,\\r\\n.login-form select,\\r\\n.modal-panel input,\\r\\n.search-box input {\\r\\n height: 42px;\\r\\n padding: 0 12px;\\r\\n}\\r\\n\\r\\n.modal-panel textarea {\\r\\n min-height: 92px;\\r\\n resize: vertical;\\r\\n padding: 10px 12px;\\r\\n line-height: 1.5;\\r\\n}\\r\\n\\r\\n.login-form .country-code-field input {\\r\\n height: 40px;\\r\\n padding: 0 10px 0 0;\\r\\n border: 0;\\r\\n border-radius: 0;\\r\\n}\\r\\n\\r\\n.login-form .country-code-field input:focus {\\r\\n border-color: transparent;\\r\\n box-shadow: none;\\r\\n}\\r\\n\\r\\n.login-form input:focus,\\r\\n.login-form select:focus,\\r\\n.modal-panel input:focus,\\r\\n.modal-panel textarea:focus,\\r\\n.search-box input:focus,\\r\\n.message-composer textarea:focus {\\r\\n border-color: var(--primary);\\r\\n box-shadow: 0 0 0 3px rgba(23, 125, 114, 0.12);\\r\\n}\\r\\n\\r\\n.login-form input.captcha-input-valid {\\r\\n border-color: var(--primary);\\r\\n background: var(--primary);\\r\\n color: #fff;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.login-form input.captcha-input-valid::-moz-placeholder {\\r\\n color: rgba(255, 255, 255, 0.75);\\r\\n}\\r\\n\\r\\n.login-form input.captcha-input-valid::placeholder {\\r\\n color: rgba(255, 255, 255, 0.75);\\r\\n}\\r\\n\\r\\n.login-form input.captcha-input-invalid {\\r\\n border-color: var(--accent);\\r\\n color: var(--accent);\\r\\n box-shadow: 0 0 0 3px rgba(216, 78, 63, 0.12);\\r\\n}\\r\\n\\r\\n.login-form input.field-input-error {\\r\\n border-color: var(--accent);\\r\\n color: var(--accent);\\r\\n box-shadow: 0 0 0 3px rgba(216, 78, 63, 0.12);\\r\\n}\\r\\n\\r\\n.login-form input.field-input-error::-moz-placeholder {\\r\\n color: rgba(216, 78, 63, 0.78);\\r\\n}\\r\\n\\r\\n.login-form input.field-input-error::placeholder {\\r\\n color: rgba(216, 78, 63, 0.78);\\r\\n}\\r\\n\\r\\n.captcha-button {\\r\\n width: 112px;\\r\\n height: 42px;\\r\\n padding: 0;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #f7fbfa;\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.captcha-button img {\\r\\n display: block;\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n -o-object-fit: contain;\\r\\n object-fit: contain;\\r\\n}\\r\\n\\r\\n.qr-login-card {\\r\\n position: relative;\\r\\n width: min(248px, 100%);\\r\\n aspect-ratio: 1;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n justify-self: center;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: #fff;\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.qr-code-button {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n padding: 18px;\\r\\n border: 0;\\r\\n background: #fff;\\r\\n color: var(--muted);\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.qr-code-button:disabled {\\r\\n cursor: default;\\r\\n}\\r\\n\\r\\n.qr-code-button img {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n -o-object-fit: contain;\\r\\n object-fit: contain;\\r\\n image-rendering: pixelated;\\r\\n}\\r\\n\\r\\n.qr-login-card.scanned .qr-code-button,\\r\\n.qr-login-card.expired .qr-code-button,\\r\\n.qr-login-card.error .qr-code-button {\\r\\n opacity: 0.22;\\r\\n}\\r\\n\\r\\n.qr-scan-user {\\r\\n position: absolute;\\r\\n inset: 0;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n background: rgba(255, 255, 255, 0.76);\\r\\n}\\r\\n\\r\\n.qr-scan-user img,\\r\\n.qr-scan-user span {\\r\\n width: 70px;\\r\\n height: 70px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border-radius: 8px;\\r\\n background: var(--primary);\\r\\n color: #fff;\\r\\n font-size: 28px;\\r\\n font-weight: 800;\\r\\n -o-object-fit: cover;\\r\\n object-fit: cover;\\r\\n}\\r\\n\\r\\n.qr-login-status {\\r\\n min-height: 48px;\\r\\n display: grid;\\r\\n gap: 4px;\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.qr-login-status strong {\\r\\n color: var(--text);\\r\\n font-size: 15px;\\r\\n}\\r\\n\\r\\n.qr-login-status span {\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.primary-action,\\r\\n.primary-inline-action,\\r\\n.send-button {\\r\\n border: 0;\\r\\n border-radius: 6px;\\r\\n background: var(--primary);\\r\\n color: #fff;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.primary-action {\\r\\n height: 44px;\\r\\n}\\r\\n\\r\\n.primary-action:hover,\\r\\n.primary-inline-action:hover,\\r\\n.send-button:hover {\\r\\n background: var(--primary-strong);\\r\\n}\\r\\n\\r\\n.primary-action:disabled,\\r\\n.primary-inline-action:disabled,\\r\\n.send-button:disabled {\\r\\n cursor: not-allowed;\\r\\n opacity: 0.55;\\r\\n}\\r\\n\\r\\n.ghost-action {\\r\\n width: 100%;\\r\\n height: 40px;\\r\\n margin-top: 12px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.ghost-inline-action,\\r\\n.primary-inline-action,\\r\\n.danger-inline-action {\\r\\n height: 38px;\\r\\n display: inline-flex;\\r\\n align-items: center;\\r\\n justify-content: center;\\r\\n padding: 0 16px;\\r\\n border-radius: 6px;\\r\\n font-weight: 700;\\r\\n line-height: 1;\\r\\n}\\r\\n\\r\\n.ghost-inline-action {\\r\\n border: 1px solid var(--line);\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.ghost-inline-action:hover {\\r\\n background: #edf2f5;\\r\\n}\\r\\n\\r\\n.danger-inline-action {\\r\\n border: 1px solid #ef4444;\\r\\n background: #fff;\\r\\n color: #b91c1c;\\r\\n}\\r\\n\\r\\n.danger-inline-action:hover {\\r\\n background: #fee2e2;\\r\\n}\\r\\n\\r\\n.form-error {\\r\\n margin: 0;\\r\\n color: var(--accent);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.form-info {\\r\\n margin: 0;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.app-shell {\\n height: 100dvh;\\n min-height: 0;\\n display: grid;\\n grid-template-columns: 64px minmax(260px, 340px) minmax(0, 1fr);\\n overflow: hidden;\\n background: var(--panel);\\n}\\n\\n.documented-shell {\\n min-height: 100dvh;\\n display: grid;\\n grid-template-columns: 260px minmax(0, 1fr);\\n background:\\n radial-gradient(circle at top left, rgba(23, 125, 114, 0.08), transparent 28%),\\n linear-gradient(180deg, #f4f8f7 0%, #eef3f7 100%);\\n}\\n\\n.documented-rail {\\n min-height: 0;\\n display: grid;\\n align-content: start;\\n gap: 14px;\\n padding: 24px 20px;\\n border-right: 1px solid var(--line);\\n background: rgba(255, 255, 255, 0.82);\\n backdrop-filter: blur(12px);\\n}\\n\\n.documented-avatar {\\n width: 64px;\\n height: 64px;\\n display: grid;\\n place-items: center;\\n overflow: hidden;\\n border-radius: 16px;\\n background: #dff4ef;\\n color: var(--primary-strong);\\n font-size: 28px;\\n font-weight: 800;\\n}\\n\\n.documented-avatar img {\\n width: 100%;\\n height: 100%;\\n -o-object-fit: cover;\\n object-fit: cover;\\n}\\n\\n.documented-rail-copy {\\n display: grid;\\n gap: 4px;\\n}\\n\\n.documented-rail-copy strong {\\n font-size: 16px;\\n}\\n\\n.documented-rail-copy small {\\n color: var(--muted);\\n overflow-wrap: anywhere;\\n}\\n\\n.documented-rail-button {\\n min-height: 40px;\\n padding: 0 14px;\\n border: 0;\\n border-radius: 10px;\\n background: var(--primary);\\n color: #fff;\\n font-weight: 700;\\n text-align: left;\\n}\\n\\n.documented-rail-button.ghost {\\n border: 1px solid var(--line);\\n background: #fff;\\n color: var(--text);\\n}\\n\\n.documented-main {\\n min-width: 0;\\n min-height: 0;\\n overflow: auto;\\n padding: 28px;\\n display: grid;\\n align-content: start;\\n gap: 18px;\\n}\\n\\n.documented-header {\\n display: flex;\\n align-items: end;\\n justify-content: space-between;\\n gap: 18px;\\n}\\n\\n.documented-header h1 {\\n margin: 0;\\n font-size: 28px;\\n}\\n\\n.documented-header p {\\n margin: 6px 0 0;\\n color: var(--muted);\\n}\\n\\n.documented-status {\\n min-width: 180px;\\n display: grid;\\n gap: 4px;\\n padding: 14px 16px;\\n border: 1px solid var(--line);\\n border-radius: 14px;\\n background: rgba(255, 255, 255, 0.88);\\n}\\n\\n.documented-status span {\\n color: var(--muted);\\n font-size: 12px;\\n}\\n\\n.documented-status strong {\\n font-size: 15px;\\n}\\n\\n.documented-card {\\n display: grid;\\n gap: 12px;\\n padding: 20px;\\n border: 1px solid var(--line);\\n border-radius: 16px;\\n background: rgba(255, 255, 255, 0.88);\\n box-shadow: 0 16px 36px rgba(24, 33, 47, 0.06);\\n}\\n\\n.documented-card h2 {\\n margin: 0;\\n font-size: 18px;\\n}\\n\\n.documented-text {\\n margin: 0;\\n color: var(--muted);\\n line-height: 1.6;\\n}\\n\\n.documented-list {\\n margin: 0;\\n padding-left: 18px;\\n display: grid;\\n gap: 8px;\\n line-height: 1.55;\\n}\\n\\n.documented-list.muted {\\n color: var(--muted);\\n}\\n\\n.documented-meta {\\n margin: 0;\\n display: grid;\\n gap: 10px;\\n}\\n\\n.documented-meta div {\\n display: grid;\\n grid-template-columns: 110px minmax(0, 1fr);\\n gap: 12px;\\n padding-top: 10px;\\n border-top: 1px solid var(--line);\\n}\\n\\n.documented-meta dt {\\n color: var(--muted);\\n}\\n\\n.documented-meta dd {\\n margin: 0;\\n overflow-wrap: anywhere;\\n}\\n\\n.documented-password-panel {\\n width: min(100%, 360px);\\n}\\n\\r\\n.navigation-rail {\\r\\n min-height: 0;\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n align-items: center;\\r\\n gap: 14px;\\r\\n padding: 16px 10px;\\r\\n background: var(--rail);\\r\\n}\\r\\n\\r\\n.rail-avatar {\\r\\n width: 40px;\\r\\n height: 40px;\\r\\n border-radius: 8px;\\r\\n background: #e9f7f4;\\r\\n color: var(--primary-strong);\\r\\n font-weight: 800;\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.rail-avatar-button {\\r\\n position: relative;\\r\\n border: 0;\\r\\n padding: 0;\\r\\n cursor: pointer;\\r\\n}\\r\\n\\r\\n.rail-avatar-button::after {\\r\\n content: \\\"+\\\";\\r\\n position: absolute;\\r\\n right: -2px;\\r\\n bottom: -2px;\\r\\n width: 15px;\\r\\n height: 15px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border: 1px solid var(--rail);\\r\\n border-radius: 50%;\\r\\n background: var(--primary);\\r\\n color: #fff;\\r\\n font-size: 11px;\\r\\n font-weight: 800;\\r\\n line-height: 1;\\r\\n}\\r\\n\\r\\n.rail-avatar-button:hover,\\r\\n.rail-avatar-button:focus-visible {\\r\\n box-shadow: 0 0 0 3px rgba(47, 196, 178, 0.28);\\r\\n}\\r\\n\\r\\n.rail-avatar img {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n -o-object-fit: cover;\\r\\n object-fit: cover;\\r\\n}\\r\\n\\r\\n.rail-button,\\r\\n.icon-button {\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border: 0;\\r\\n border-radius: 6px;\\r\\n background: transparent;\\r\\n}\\r\\n\\r\\n.rail-button {\\r\\n width: 40px;\\r\\n height: 40px;\\r\\n color: #dbe5ea;\\r\\n font-size: 18px;\\r\\n}\\r\\n\\r\\n.rail-button svg {\\r\\n width: 22px;\\r\\n height: 22px;\\r\\n fill: none;\\r\\n stroke: currentColor;\\r\\n stroke-width: 1.8;\\r\\n stroke-linecap: round;\\r\\n stroke-linejoin: round;\\r\\n}\\r\\n\\r\\n.rail-button.active,\\r\\n.rail-button:hover {\\r\\n background: rgba(255, 255, 255, 0.12);\\r\\n}\\r\\n\\r\\n.rail-logout-button:hover {\\r\\n background: rgba(239, 68, 68, 0.2);\\r\\n color: #fecaca;\\r\\n}\\r\\n\\r\\n.rail-spacer {\\r\\n flex: 1;\\r\\n}\\r\\n\\r\\n.conversation-list {\\r\\n position: relative;\\r\\n min-height: 0;\\r\\n display: grid;\\r\\n grid-template-rows: 72px auto minmax(0, 1fr);\\r\\n border-right: 1px solid var(--line);\\r\\n background: var(--panel-soft);\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.modal-backdrop {\\r\\n position: absolute;\\r\\n inset: 0;\\r\\n z-index: 5;\\r\\n display: grid;\\r\\n place-items: start center;\\r\\n padding: 88px 16px 16px;\\r\\n background: rgba(24, 33, 47, 0.28);\\r\\n}\\r\\n\\r\\n.modal-panel {\\r\\n width: min(100%, 308px);\\r\\n display: grid;\\r\\n gap: 14px;\\r\\n padding: 16px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 18px 40px rgba(24, 33, 47, 0.18);\\r\\n}\\r\\n\\r\\n.modal-panel header,\\r\\n.modal-actions {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.modal-panel header strong {\\r\\n font-size: 16px;\\r\\n}\\r\\n\\r\\n.modal-panel label {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.settings-backdrop {\\r\\n z-index: 24;\\r\\n place-items: center;\\r\\n padding: 24px 16px;\\r\\n}\\r\\n\\r\\n.settings-panel {\\r\\n width: min(620px, calc(100vw - 32px));\\r\\n max-height: calc(100dvh - 48px);\\r\\n display: grid;\\r\\n gap: 14px;\\r\\n overflow: auto;\\r\\n padding: 16px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 18px 40px rgba(24, 33, 47, 0.18);\\r\\n}\\r\\n\\r\\n.settings-panel header,\\r\\n.settings-password-form footer {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n gap: 12px;\\r\\n}\\r\\n\\r\\n.settings-panel header strong {\\r\\n font-size: 16px;\\r\\n}\\r\\n\\r\\n.settings-layout {\\r\\n display: grid;\\r\\n grid-template-columns: 170px minmax(0, 1fr);\\r\\n gap: 14px;\\r\\n}\\r\\n\\r\\n.settings-menu {\\r\\n display: grid;\\r\\n align-content: start;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.settings-menu button {\\r\\n min-height: 46px;\\r\\n display: grid;\\r\\n gap: 2px;\\r\\n justify-items: start;\\r\\n padding: 8px 10px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.settings-menu button.active,\\r\\n.settings-menu button:hover {\\r\\n border-color: var(--primary);\\r\\n background: #e8f4f2;\\r\\n color: var(--primary-strong);\\r\\n}\\r\\n\\r\\n.settings-menu button span {\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.settings-menu button small {\\r\\n color: var(--muted);\\r\\n font-size: 11px;\\r\\n}\\r\\n\\r\\n.settings-password-form,\\r\\n.settings-placeholder {\\r\\n min-height: 250px;\\r\\n display: grid;\\r\\n align-content: start;\\r\\n gap: 12px;\\r\\n}\\r\\n\\r\\n.settings-password-form h3,\\r\\n.settings-placeholder h3 {\\r\\n margin: 0;\\r\\n font-size: 16px;\\r\\n}\\r\\n\\r\\n.settings-password-form label {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.settings-password-form input {\\r\\n width: 100%;\\r\\n height: 42px;\\r\\n padding: 0 12px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n outline: none;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.settings-password-form input:focus {\\r\\n border-color: var(--primary);\\r\\n box-shadow: 0 0 0 3px rgba(23, 125, 114, 0.12);\\r\\n}\\r\\n\\r\\n.settings-password-form footer {\\r\\n margin-top: 4px;\\r\\n justify-content: flex-end;\\r\\n flex-wrap: wrap;\\r\\n}\\r\\n\\r\\n.settings-password-form footer .inline-save-status {\\r\\n margin-right: auto;\\r\\n}\\r\\n\\r\\n.settings-placeholder {\\r\\n place-items: center;\\r\\n border: 1px dashed var(--line);\\r\\n border-radius: 8px;\\r\\n color: var(--muted);\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.settings-placeholder p {\\r\\n margin: 0;\\r\\n}\\r\\n\\r\\n.profile-edit-panel {\\r\\n width: min(100%, 360px);\\r\\n}\\r\\n\\r\\n.profile-avatar-field {\\r\\n display: grid;\\r\\n justify-items: center;\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.profile-avatar-field input[type=\\\"file\\\"] {\\r\\n position: absolute;\\r\\n inline-size: 1px;\\r\\n block-size: 1px;\\r\\n opacity: 0;\\r\\n pointer-events: none;\\r\\n}\\r\\n\\r\\n.profile-avatar-preview {\\r\\n width: 88px;\\r\\n height: 88px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n overflow: hidden;\\r\\n padding: 0;\\r\\n border: 0;\\r\\n border-radius: 8px;\\r\\n background: #dce8f2;\\r\\n color: #24435c;\\r\\n cursor: default;\\r\\n font-size: 30px;\\r\\n font-weight: 800;\\r\\n}\\r\\n\\r\\n.profile-avatar-preview.clickable {\\r\\n cursor: zoom-in;\\r\\n}\\r\\n\\r\\n.profile-avatar-preview.clickable:hover {\\r\\n box-shadow: 0 0 0 3px rgba(23, 125, 114, 0.16);\\r\\n}\\r\\n\\r\\n.profile-avatar-preview img {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n -o-object-fit: cover;\\r\\n object-fit: cover;\\r\\n}\\r\\n\\r\\n.profile-avatar-change-button {\\r\\n min-width: 96px;\\r\\n}\\r\\n\\r\\n.avatar-preview-backdrop {\\r\\n z-index: 32;\\r\\n place-items: center;\\r\\n padding: 24px 16px;\\r\\n}\\r\\n\\r\\n.avatar-preview-dialog {\\r\\n width: min(520px, calc(100vw - 32px));\\r\\n max-height: calc(100dvh - 48px);\\r\\n display: grid;\\r\\n gap: 12px;\\r\\n padding: 14px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 18px 40px rgba(24, 33, 47, 0.18);\\r\\n}\\r\\n\\r\\n.avatar-preview-dialog header {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n gap: 12px;\\r\\n}\\r\\n\\r\\n.avatar-preview-actions {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n gap: 6px;\\r\\n}\\r\\n\\r\\n.avatar-preview-actions button {\\r\\n min-width: 34px;\\r\\n height: 34px;\\r\\n display: inline-flex;\\r\\n align-items: center;\\r\\n justify-content: center;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.avatar-preview-actions .icon-button {\\r\\n border: 0;\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.avatar-preview-stage {\\r\\n height: min(430px, calc(100dvh - 160px));\\r\\n min-height: 260px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n overflow: hidden;\\r\\n border-radius: 8px;\\r\\n background: #101820;\\r\\n cursor: zoom-in;\\r\\n touch-action: none;\\r\\n}\\r\\n\\r\\n.avatar-preview-stage.dragging {\\r\\n cursor: grabbing;\\r\\n}\\r\\n\\r\\n.avatar-preview-stage img {\\r\\n max-width: min(100%, 430px);\\r\\n max-height: 100%;\\r\\n border-radius: 8px;\\r\\n -o-object-fit: contain;\\r\\n object-fit: contain;\\r\\n transform-origin: center center;\\r\\n transition: transform 0.08s ease-out;\\r\\n -webkit-user-select: none;\\r\\n -moz-user-select: none;\\r\\n user-select: none;\\r\\n pointer-events: none;\\r\\n}\\r\\n\\r\\n.avatar-preview-stage.dragging img {\\r\\n transition: none;\\r\\n}\\r\\n\\r\\n.avatar-cropper-backdrop {\\r\\n z-index: 30;\\r\\n place-items: center;\\r\\n padding: 24px 16px;\\r\\n}\\r\\n\\r\\n.avatar-cropper-panel {\\r\\n width: min(720px, calc(100vw - 32px));\\r\\n max-height: calc(100dvh - 48px);\\r\\n overflow: auto;\\r\\n}\\r\\n\\r\\n.avatar-cropper-header-actions {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.avatar-cropper-layout {\\r\\n display: grid;\\r\\n grid-template-columns: minmax(0, 1fr) 190px;\\r\\n gap: 14px;\\r\\n}\\r\\n\\r\\n.avatar-cropper-stage {\\r\\n position: relative;\\r\\n height: 360px;\\r\\n min-height: 360px;\\r\\n overflow: hidden;\\r\\n border: 1px dashed #b8ccd7;\\r\\n border-radius: 8px;\\r\\n background: #0f1b24;\\r\\n touch-action: none;\\r\\n cursor: grab;\\r\\n}\\r\\n\\r\\n.avatar-cropper-stage.dragging {\\r\\n cursor: grabbing;\\r\\n}\\r\\n\\r\\n.avatar-cropper-stage canvas {\\r\\n position: absolute;\\r\\n inset: 0;\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n display: block;\\r\\n}\\r\\n\\r\\n.avatar-cropper-box {\\r\\n position: absolute;\\r\\n left: 50%;\\r\\n top: 50%;\\r\\n width: 74%;\\r\\n aspect-ratio: 1;\\r\\n max-width: calc(100% - 44px);\\r\\n max-height: calc(100% - 44px);\\r\\n transform: translate(-50%, -50%);\\r\\n border: 2px dashed var(--primary);\\r\\n border-radius: 8px;\\r\\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.72);\\r\\n pointer-events: none;\\r\\n}\\r\\n\\r\\n.avatar-cropper-mask {\\r\\n position: absolute;\\r\\n inset: 0;\\r\\n pointer-events: none;\\r\\n}\\r\\n\\r\\n.avatar-cropper-placeholder {\\r\\n position: absolute;\\r\\n inset: 0;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n color: #d9e8ee;\\r\\n font-size: 13px;\\r\\n pointer-events: none;\\r\\n}\\r\\n\\r\\n.avatar-cropper-controls {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n align-content: start;\\r\\n gap: 12px;\\r\\n}\\r\\n\\r\\n.avatar-cropper-tools {\\r\\n display: grid;\\r\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.avatar-cropper-tools button {\\r\\n min-height: 34px;\\r\\n padding: 0 10px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.avatar-cropper-tools button:hover {\\r\\n border-color: var(--primary);\\r\\n color: var(--primary-strong);\\r\\n}\\r\\n\\r\\n.avatar-cropper-preview {\\r\\n width: 108px;\\r\\n height: 108px;\\r\\n justify-self: center;\\r\\n overflow: hidden;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: #eef4f7;\\r\\n}\\r\\n\\r\\n.avatar-cropper-preview canvas {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n display: block;\\r\\n}\\r\\n\\r\\n.avatar-cropper-controls footer {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: flex-end;\\r\\n flex-wrap: wrap;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.avatar-cropper-controls footer .inline-save-status {\\r\\n flex: 1 1 100%;\\r\\n}\\r\\n\\r\\n.modal-actions {\\r\\n justify-content: flex-end;\\r\\n}\\r\\n\\r\\n.list-header,\\r\\n.chat-header {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n min-height: 72px;\\r\\n padding: 16px 18px;\\r\\n border-bottom: 1px solid var(--line);\\r\\n}\\r\\n\\r\\n.icon-button {\\r\\n width: 34px;\\r\\n height: 34px;\\r\\n color: var(--muted);\\r\\n font-size: 20px;\\r\\n}\\r\\n\\r\\n.icon-button:hover {\\r\\n background: #edf2f5;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.search-box {\\r\\n padding: 12px 14px;\\r\\n}\\r\\n\\r\\n.sidebar-scroll {\\r\\n min-height: 0;\\r\\n overflow: auto;\\r\\n overscroll-behavior: contain;\\r\\n}\\r\\n\\r\\n.conversation-item {\\r\\n width: 100%;\\r\\n display: grid;\\r\\n grid-template-columns: 42px minmax(0, 1fr) auto;\\r\\n align-items: center;\\r\\n gap: 10px;\\r\\n padding: 12px 14px;\\r\\n border: 0;\\r\\n border-top: 1px solid rgba(217, 224, 231, 0.7);\\r\\n background: transparent;\\r\\n color: inherit;\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.conversation-item.active,\\r\\n.conversation-item:hover {\\r\\n background: #eaf3f1;\\r\\n}\\r\\n\\r\\n.favorite-item {\\r\\n width: 100%;\\r\\n display: grid;\\r\\n grid-template-columns: 32px minmax(0, 1fr) auto;\\r\\n align-items: center;\\r\\n gap: 10px;\\r\\n padding: 12px 14px;\\r\\n border: 0;\\r\\n border-top: 1px solid rgba(217, 224, 231, 0.7);\\r\\n background: transparent;\\r\\n color: inherit;\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.favorite-item.active,\\r\\n.favorite-item:hover {\\r\\n background: #eaf3f1;\\r\\n}\\r\\n\\r\\n.favorite-item-icon {\\r\\n width: 32px;\\r\\n height: 32px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border-radius: 6px;\\r\\n background: #fff7df;\\r\\n color: #c79520;\\r\\n font-size: 16px;\\r\\n}\\r\\n\\r\\n.favorite-item-main {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n gap: 4px;\\r\\n}\\r\\n\\r\\n.favorite-item-main strong,\\r\\n.favorite-item-main small {\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.favorite-item-main strong {\\r\\n font-size: 14px;\\r\\n}\\r\\n\\r\\n.favorite-item-main small,\\r\\n.favorite-item time {\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.favorite-panel {\\r\\n min-width: 0;\\r\\n min-height: 0;\\r\\n display: grid;\\r\\n grid-template-rows: auto minmax(0, 1fr);\\r\\n background: #eef3f6;\\r\\n}\\r\\n\\r\\n.favorite-detail {\\r\\n min-height: 0;\\r\\n display: grid;\\r\\n align-content: start;\\r\\n gap: 16px;\\r\\n padding: 28px;\\r\\n overflow: auto;\\r\\n}\\r\\n\\r\\n.favorite-detail-message {\\r\\n width: min(680px, 100%);\\r\\n display: grid;\\r\\n grid-template-columns: auto minmax(0, 1fr);\\r\\n gap: 10px 12px;\\r\\n padding: 18px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 8px 24px rgba(24, 33, 47, 0.08);\\r\\n}\\r\\n\\r\\n.favorite-detail-message.recalled {\\r\\n border-color: #f1c7c1;\\r\\n background: #fff7f6;\\r\\n}\\r\\n\\r\\n.favorite-detail-star {\\r\\n color: #c79520;\\r\\n font-size: 18px;\\r\\n line-height: 1.4;\\r\\n}\\r\\n\\r\\n.favorite-detail-body {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.favorite-detail-message p {\\r\\n margin: 0;\\r\\n white-space: pre-wrap;\\r\\n overflow-wrap: anywhere;\\r\\n line-height: 1.55;\\r\\n}\\r\\n\\r\\n.favorite-detail-message time {\\r\\n grid-column: 2;\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.favorite-detail-image {\\r\\n width: min(420px, 100%);\\r\\n display: block;\\r\\n overflow: hidden;\\r\\n border: 1px solid #b9ded8;\\r\\n border-radius: 8px;\\r\\n background: #fff;\\r\\n}\\r\\n\\r\\n.favorite-detail-image img {\\r\\n display: block;\\r\\n width: 100%;\\r\\n max-height: 360px;\\r\\n -o-object-fit: contain;\\r\\n object-fit: contain;\\r\\n background: #f8fbfc;\\r\\n}\\r\\n\\r\\n.favorite-detail-file {\\r\\n width: min(360px, 100%);\\r\\n}\\r\\n\\r\\n.favorite-detail-actions {\\r\\n width: min(680px, 100%);\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: flex-end;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.favorite-detail-actions .inline-save-status {\\r\\n margin-right: auto;\\r\\n}\\r\\n\\r\\n.empty-list,\\r\\n.empty-chat {\\r\\n display: grid;\\r\\n place-items: center;\\r\\n align-content: center;\\r\\n gap: 8px;\\r\\n color: var(--muted);\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.empty-list {\\r\\n min-height: 180px;\\r\\n padding: 24px;\\r\\n}\\r\\n\\r\\n.empty-chat {\\r\\n min-height: 0;\\r\\n padding: 24px;\\r\\n}\\r\\n\\r\\n.empty-list strong,\\r\\n.empty-chat strong {\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.conversation-avatar {\\r\\n width: 42px;\\r\\n height: 42px;\\r\\n border-radius: 8px;\\r\\n background: #dce8f2;\\r\\n color: #24435c;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.conversation-copy {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n gap: 4px;\\r\\n}\\r\\n\\r\\n.conversation-copy strong,\\r\\n.conversation-copy small {\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.conversation-copy small {\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.unread-badge {\\r\\n justify-self: end;\\r\\n min-width: 20px;\\r\\n height: 20px;\\r\\n padding: 0 6px;\\r\\n border-radius: 999px;\\r\\n background: #ef4444;\\r\\n color: #fff;\\r\\n font-size: 12px;\\r\\n font-weight: 800;\\r\\n line-height: 20px;\\r\\n text-align: center;\\r\\n box-shadow: 0 0 0 2px #f7fafc;\\r\\n}\\r\\n\\r\\n.chat-panel {\\r\\n position: relative;\\r\\n min-width: 0;\\r\\n min-height: 0;\\r\\n height: 100%;\\r\\n display: grid;\\r\\n grid-template-rows: 72px minmax(0, 1fr) auto auto;\\r\\n overflow: hidden;\\r\\n background: #eef2f5;\\r\\n}\\r\\n\\r\\n.contact-panel {\\r\\n min-width: 0;\\r\\n min-height: 0;\\r\\n height: 100%;\\r\\n display: grid;\\r\\n grid-template-rows: 72px minmax(0, 1fr);\\r\\n overflow: auto;\\r\\n background: #eef2f5;\\r\\n}\\r\\n\\r\\n.contact-profile {\\r\\n align-self: start;\\r\\n width: min(520px, calc(100% - 48px));\\r\\n margin: 48px auto;\\r\\n display: grid;\\r\\n justify-items: center;\\r\\n gap: 18px;\\r\\n padding: 32px;\\r\\n background: var(--panel);\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n}\\r\\n\\r\\n.profile-avatar {\\r\\n width: 76px;\\r\\n height: 76px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border-radius: 8px;\\r\\n background: #dce8f2;\\r\\n color: #24435c;\\r\\n font-size: 28px;\\r\\n font-weight: 800;\\r\\n}\\r\\n\\r\\n.profile-main {\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.remark-row {\\r\\n min-width: 0;\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: center;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.profile-main h3 {\\r\\n margin: 0;\\r\\n font-size: 22px;\\r\\n overflow-wrap: anywhere;\\r\\n}\\r\\n\\r\\n.remark-edit-button {\\r\\n width: 32px;\\r\\n height: 32px;\\r\\n flex: 0 0 auto;\\r\\n font-size: 16px;\\r\\n}\\r\\n\\r\\n.profile-main p {\\r\\n margin: 6px 0 0;\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.profile-fields {\\r\\n width: 100%;\\r\\n display: grid;\\r\\n gap: 12px;\\r\\n margin: 0;\\r\\n}\\r\\n\\r\\n.profile-fields div {\\r\\n display: grid;\\r\\n grid-template-columns: 80px minmax(0, 1fr);\\r\\n gap: 12px;\\r\\n padding: 10px 0;\\r\\n border-top: 1px solid var(--line);\\r\\n}\\r\\n\\r\\n.profile-fields dt {\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.profile-fields dd {\\r\\n margin: 0;\\r\\n overflow-wrap: anywhere;\\r\\n}\\r\\n\\r\\n.profile-action {\\r\\n width: 160px;\\r\\n}\\r\\n\\r\\n.contact-panel .contact-modal-backdrop {\\r\\n position: fixed;\\r\\n}\\r\\n\\r\\n.header-actions {\\r\\n display: flex;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.chat-header-actions {\\r\\n position: relative;\\r\\n}\\r\\n\\r\\n.chat-title-button {\\r\\n display: grid;\\r\\n grid-template-columns: 38px minmax(0, 1fr);\\r\\n align-items: center;\\r\\n gap: 10px;\\r\\n max-width: min(460px, 52vw);\\r\\n padding: 0;\\r\\n border: 0;\\r\\n background: transparent;\\r\\n color: var(--text);\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.chat-title-avatar {\\r\\n width: 38px;\\r\\n height: 38px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border-radius: 8px;\\r\\n background: #dce8f2;\\r\\n color: #24435c;\\r\\n font-size: 16px;\\r\\n font-weight: 800;\\r\\n}\\r\\n\\r\\n.chat-title-copy {\\r\\n min-width: 0;\\r\\n}\\r\\n\\r\\n.chat-title-button h2 {\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.chat-title-button:hover h2 {\\r\\n color: var(--primary-strong);\\r\\n}\\r\\n\\r\\n.chat-more-menu {\\r\\n top: 38px;\\r\\n width: 150px;\\r\\n}\\r\\n\\r\\n.action-menu-anchor {\\r\\n position: relative;\\r\\n}\\r\\n\\r\\n.quick-action-menu {\\r\\n position: absolute;\\r\\n top: 40px;\\r\\n right: 0;\\r\\n z-index: 7;\\r\\n width: 168px;\\r\\n display: grid;\\r\\n padding: 6px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 14px 34px rgba(24, 33, 47, 0.16);\\r\\n}\\r\\n\\r\\n.quick-action-menu button {\\r\\n height: 34px;\\r\\n padding: 0 10px;\\r\\n border: 0;\\r\\n border-radius: 6px;\\r\\n background: transparent;\\r\\n color: var(--text);\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.quick-action-menu button:hover {\\r\\n background: #edf2f5;\\r\\n}\\r\\n\\r\\n.quick-action-menu.chat-more-menu {\\r\\n top: 38px;\\r\\n width: 150px;\\r\\n}\\r\\n\\r\\n.conversation-action-panel {\\r\\n width: min(100%, 340px);\\r\\n max-height: calc(100dvh - 116px);\\r\\n overflow: auto;\\r\\n}\\r\\n\\r\\n.contact-picker {\\r\\n display: grid;\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.contact-picker > input {\\r\\n width: 100%;\\r\\n height: 38px;\\r\\n padding: 0 10px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n outline: none;\\r\\n}\\r\\n\\r\\n.contact-picker-list {\\r\\n max-height: 220px;\\r\\n overflow: auto;\\r\\n display: grid;\\r\\n gap: 6px;\\r\\n padding-right: 2px;\\r\\n}\\r\\n\\r\\n.contact-picker-row {\\r\\n width: 100%;\\r\\n min-height: 48px;\\r\\n display: grid;\\r\\n grid-template-columns: 22px 36px minmax(0, 1fr);\\r\\n align-items: center;\\r\\n gap: 8px;\\r\\n padding: 6px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.contact-picker-row:hover,\\r\\n.contact-picker-row.selected {\\r\\n border-color: #9fd4cc;\\r\\n background: #edf8f5;\\r\\n}\\r\\n\\r\\n.contact-picker-row .conversation-avatar {\\r\\n width: 36px;\\r\\n height: 36px;\\r\\n border-radius: 6px;\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.contact-check {\\r\\n width: 20px;\\r\\n height: 20px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 4px;\\r\\n color: var(--primary-strong);\\r\\n font-size: 13px;\\r\\n font-weight: 800;\\r\\n}\\r\\n\\r\\n.contact-picker-copy {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n gap: 2px;\\r\\n}\\r\\n\\r\\n.contact-picker-copy strong,\\r\\n.contact-picker-copy small {\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.contact-picker-copy small {\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.contact-picker-empty {\\r\\n min-height: 64px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n color: var(--muted);\\r\\n border: 1px dashed var(--line);\\r\\n border-radius: 6px;\\r\\n}\\r\\n\\r\\n.group-dialog {\\r\\n width: min(420px, calc(100% - 32px));\\r\\n max-height: calc(100dvh - 116px);\\r\\n display: grid;\\r\\n gap: 16px;\\r\\n padding: 18px;\\r\\n overflow: auto;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 18px 40px rgba(24, 33, 47, 0.18);\\r\\n}\\r\\n\\r\\n.group-dialog header,\\r\\n.group-dialog footer {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n gap: 12px;\\r\\n}\\r\\n\\r\\n.group-dialog h3 {\\r\\n margin: 0;\\r\\n font-size: 18px;\\r\\n}\\r\\n\\r\\n.single-profile-dialog {\\r\\n width: min(420px, calc(100% - 32px));\\r\\n}\\r\\n\\r\\n.single-profile-summary {\\r\\n display: grid;\\r\\n justify-items: center;\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.single-profile-summary strong {\\r\\n max-width: 100%;\\r\\n overflow-wrap: anywhere;\\r\\n font-size: 18px;\\r\\n}\\r\\n\\r\\n.single-profile-footer {\\r\\n align-items: center;\\r\\n justify-content: flex-end;\\r\\n}\\r\\n\\r\\n.single-profile-footer .inline-save-status {\\r\\n margin-right: auto;\\r\\n}\\r\\n\\r\\n.message-detail-dialog {\\r\\n width: min(560px, calc(100% - 32px));\\r\\n}\\r\\n\\r\\n.message-detail-meta div {\\r\\n grid-template-columns: 88px minmax(0, 1fr);\\r\\n}\\r\\n\\r\\n.message-detail-muted {\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.message-detail-summary {\\r\\n display: flex;\\r\\n flex-wrap: wrap;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.message-detail-summary span {\\r\\n min-height: 30px;\\r\\n display: inline-flex;\\r\\n align-items: center;\\r\\n gap: 4px;\\r\\n padding: 0 10px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #f8fbfb;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.message-detail-summary strong {\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.message-detail-groups {\\r\\n display: grid;\\r\\n gap: 14px;\\r\\n}\\r\\n\\r\\n.message-detail-section {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.message-detail-section header {\\r\\n min-height: 28px;\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n gap: 12px;\\r\\n border-bottom: 1px solid var(--line);\\r\\n}\\r\\n\\r\\n.message-detail-section header strong {\\r\\n font-size: 14px;\\r\\n}\\r\\n\\r\\n.message-detail-section header span {\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.message-detail-member-list {\\r\\n display: grid;\\r\\n overflow: hidden;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n}\\r\\n\\r\\n.message-detail-member-row {\\r\\n display: grid;\\r\\n grid-template-columns: 34px minmax(0, 1fr) auto auto;\\r\\n align-items: center;\\r\\n gap: 8px;\\r\\n min-height: 48px;\\r\\n padding: 7px 8px;\\r\\n border-top: 1px solid var(--line);\\r\\n}\\r\\n\\r\\n.message-detail-member-row:first-child {\\r\\n border-top: 0;\\r\\n}\\r\\n\\r\\n.message-detail-member-row .conversation-avatar {\\r\\n width: 34px;\\r\\n height: 34px;\\r\\n border-radius: 6px;\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.message-detail-member-main {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n gap: 2px;\\r\\n}\\r\\n\\r\\n.message-detail-member-main strong,\\r\\n.message-detail-member-main small {\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.message-detail-member-main strong {\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.message-detail-member-main small,\\r\\n.message-detail-member-time {\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.message-detail-member-time {\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.message-detail-role {\\r\\n min-height: 22px;\\r\\n display: inline-flex;\\r\\n align-items: center;\\r\\n padding: 0 7px;\\r\\n border: 1px solid #c7d9e5;\\r\\n border-radius: 6px;\\r\\n color: #416272;\\r\\n font-size: 12px;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.group-dialog label {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.group-dialog input {\\r\\n width: 100%;\\r\\n height: 42px;\\r\\n padding: 0 12px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n outline: none;\\r\\n}\\r\\n\\r\\n.group-dialog textarea,\\r\\n.group-dialog select {\\r\\n width: 100%;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n outline: none;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.group-dialog textarea {\\r\\n min-height: 86px;\\r\\n resize: vertical;\\r\\n padding: 10px 12px;\\r\\n line-height: 1.5;\\r\\n}\\r\\n\\r\\n.group-dialog select {\\r\\n height: 42px;\\r\\n padding: 0 10px;\\r\\n}\\r\\n\\r\\n.group-dialog input:focus {\\r\\n border-color: var(--primary);\\r\\n box-shadow: 0 0 0 3px rgba(23, 125, 114, 0.12);\\r\\n}\\r\\n\\r\\n.group-dialog textarea:focus,\\r\\n.group-dialog select:focus {\\r\\n border-color: var(--primary);\\r\\n box-shadow: 0 0 0 3px rgba(23, 125, 114, 0.12);\\r\\n}\\r\\n\\r\\n.group-profile {\\r\\n display: grid;\\r\\n gap: 10px;\\r\\n margin: 0;\\r\\n}\\r\\n\\r\\n.group-profile div {\\r\\n display: grid;\\r\\n grid-template-columns: 78px minmax(0, 1fr);\\r\\n gap: 12px;\\r\\n padding: 10px 0;\\r\\n border-top: 1px solid var(--line);\\r\\n}\\r\\n\\r\\n.group-profile dt {\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.group-profile dd {\\r\\n margin: 0;\\r\\n overflow-wrap: anywhere;\\r\\n}\\r\\n\\r\\n.group-loading {\\r\\n min-height: 96px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.group-member-list {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.group-member-row {\\r\\n display: grid;\\r\\n grid-template-columns: 42px minmax(0, 1fr);\\r\\n align-items: center;\\r\\n gap: 10px;\\r\\n min-height: 54px;\\r\\n padding: 8px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n}\\r\\n\\r\\n.group-member-row.selectable {\\r\\n cursor: pointer;\\r\\n}\\r\\n\\r\\n.group-member-row.with-check {\\r\\n grid-template-columns: 24px 42px minmax(0, 1fr);\\r\\n}\\r\\n\\r\\n.group-member-row.selectable:hover,\\r\\n.group-member-row.selectable.selected {\\r\\n border-color: #9fd4cc;\\r\\n background: #edf8f5;\\r\\n}\\r\\n\\r\\n.group-member-row input[type=\\\"checkbox\\\"] {\\r\\n justify-self: center;\\r\\n width: 16px;\\r\\n height: 16px;\\r\\n}\\r\\n\\r\\n.group-member-row span:last-child {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n gap: 3px;\\r\\n}\\r\\n\\r\\n.group-member-row strong,\\r\\n.group-member-row small {\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.group-member-row small {\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.group-management-dialog {\\r\\n width: min(520px, calc(100% - 32px));\\r\\n}\\r\\n\\r\\n.group-management-tabs {\\r\\n display: flex;\\r\\n flex-wrap: wrap;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.group-management-tabs button {\\r\\n height: 34px;\\r\\n padding: 0 10px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.group-management-tabs button.active,\\r\\n.group-management-tabs button:hover {\\r\\n border-color: var(--primary);\\r\\n background: #e8f4f2;\\r\\n color: var(--primary-strong);\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.group-manage-section {\\r\\n display: grid;\\r\\n gap: 14px;\\r\\n}\\r\\n\\r\\n.group-manage-section footer {\\r\\n justify-content: flex-end;\\r\\n}\\r\\n\\r\\n.mute-save-footer {\\r\\n align-items: center;\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.inline-save-status {\\r\\n color: var(--primary-strong);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.inline-save-status.error {\\r\\n color: var(--accent);\\r\\n}\\r\\n\\r\\n.mute-time-grid {\\r\\n display: grid;\\r\\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.message-list {\\r\\n min-height: 0;\\r\\n overflow: auto;\\r\\n overscroll-behavior: contain;\\r\\n padding: 24px;\\r\\n}\\r\\n\\r\\n.message-row {\\r\\n display: flex;\\r\\n align-items: flex-end;\\r\\n gap: 8px;\\r\\n margin-bottom: 14px;\\r\\n}\\r\\n\\r\\n.message-row.out {\\r\\n justify-content: flex-end;\\r\\n}\\r\\n\\r\\n.message-sender-avatar {\\r\\n width: 34px;\\r\\n height: 34px;\\r\\n flex: 0 0 auto;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n overflow: hidden;\\r\\n padding: 0;\\r\\n border: 0;\\r\\n border-radius: 8px;\\r\\n background: #dce8f2;\\r\\n color: #24435c;\\r\\n font-size: 14px;\\r\\n font-weight: 800;\\r\\n}\\r\\n\\r\\n.message-sender-avatar img {\\r\\n width: 100%;\\r\\n height: 100%;\\r\\n -o-object-fit: cover;\\r\\n object-fit: cover;\\r\\n}\\r\\n\\r\\n.message-stack {\\r\\n max-width: min(68%, 720px);\\r\\n display: grid;\\r\\n justify-items: start;\\r\\n gap: 4px;\\r\\n}\\r\\n\\r\\n.message-row.out .message-stack {\\r\\n justify-items: end;\\r\\n}\\r\\n\\r\\n.message-sender-name {\\r\\n min-height: 18px;\\r\\n max-width: 100%;\\r\\n padding: 0;\\r\\n border: 0;\\r\\n background: transparent;\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n font-weight: 700;\\r\\n text-align: left;\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.message-sender-name:hover {\\r\\n color: var(--primary-strong);\\r\\n}\\r\\n\\r\\n.message-sender-role {\\r\\n margin-left: 4px;\\r\\n color: var(--primary-strong);\\r\\n font-size: 11px;\\r\\n}\\r\\n\\r\\n.message-row.selected .message-bubble {\\r\\n box-shadow: 0 0 0 2px rgba(24, 138, 121, 0.26);\\r\\n}\\r\\n\\r\\n.message-row.attention .message-bubble {\\r\\n animation: message-attention 1.4s ease-in-out 2;\\r\\n box-shadow: 0 0 0 3px rgba(24, 138, 121, 0.3);\\r\\n}\\r\\n\\r\\n@keyframes message-attention {\\r\\n 0%,\\r\\n 100% {\\r\\n box-shadow: 0 0 0 2px rgba(24, 138, 121, 0.16);\\r\\n }\\r\\n\\r\\n 45% {\\r\\n box-shadow: 0 0 0 5px rgba(24, 138, 121, 0.36);\\r\\n }\\r\\n}\\r\\n\\r\\n.message-select {\\r\\n width: 24px;\\r\\n height: 24px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n}\\r\\n\\r\\n.message-select input {\\r\\n width: 16px;\\r\\n height: 16px;\\r\\n}\\r\\n\\r\\n.message-bubble {\\r\\n position: relative;\\r\\n max-width: min(68%, 720px);\\r\\n padding: 10px 12px 8px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--bubble-in);\\r\\n box-shadow: 0 2px 8px rgba(30, 40, 50, 0.05);\\r\\n}\\r\\n\\r\\n.message-stack .message-bubble {\\r\\n max-width: 100%;\\r\\n}\\r\\n\\r\\n.message-row.out .message-bubble {\\r\\n background: var(--bubble-out);\\r\\n border-color: #bfe4dc;\\r\\n}\\r\\n\\r\\n.message-bubble:hover {\\r\\n border-color: #9fd4cc;\\r\\n}\\r\\n\\r\\n.message-bubble.role-bubble-owner,\\r\\n.message-bubble.role-bubble-admin {\\r\\n overflow: hidden;\\r\\n}\\r\\n\\r\\n.message-bubble.role-bubble-owner::after,\\r\\n.message-bubble.role-bubble-admin::after {\\r\\n content: \\\"\\\";\\r\\n position: absolute;\\r\\n top: 0;\\r\\n right: 0;\\r\\n width: 0;\\r\\n height: 0;\\r\\n border-top: 16px solid #d79d22;\\r\\n border-left: 16px solid transparent;\\r\\n}\\r\\n\\r\\n.message-bubble.role-bubble-admin::after {\\r\\n border-top-color: #178a79;\\r\\n}\\r\\n\\r\\n.message-bubble p {\\r\\n margin: 0;\\r\\n line-height: 1.5;\\r\\n white-space: pre-wrap;\\r\\n overflow-wrap: anywhere;\\r\\n}\\r\\n\\r\\n.message-image {\\r\\n padding: 0;\\r\\n border: 0;\\r\\n display: block;\\r\\n max-width: min(280px, 62vw);\\r\\n overflow: hidden;\\r\\n border-radius: 6px;\\r\\n background: #edf2f5;\\r\\n cursor: zoom-in;\\r\\n}\\r\\n\\r\\n.message-image + p,\\r\\n.message-file + p {\\r\\n margin-top: 8px;\\r\\n}\\r\\n\\r\\n.message-image img {\\r\\n display: block;\\r\\n max-width: 100%;\\r\\n max-height: 320px;\\r\\n -o-object-fit: contain;\\r\\n object-fit: contain;\\r\\n}\\r\\n\\r\\n.image-viewer-backdrop {\\r\\n position: fixed;\\r\\n inset: 0;\\r\\n z-index: 80;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n padding: 24px;\\r\\n background: rgba(12, 18, 26, 0.58);\\r\\n}\\r\\n\\r\\n.image-viewer-dialog {\\r\\n width: min(880px, calc(100vw - 48px));\\r\\n height: min(640px, calc(100vh - 48px));\\r\\n min-width: 360px;\\r\\n min-height: 280px;\\r\\n max-width: calc(100vw - 48px);\\r\\n max-height: calc(100vh - 48px);\\r\\n display: grid;\\r\\n grid-template-rows: 52px minmax(0, 1fr);\\r\\n overflow: hidden;\\r\\n resize: both;\\r\\n border: 1px solid rgba(255, 255, 255, 0.18);\\r\\n border-radius: 8px;\\r\\n background: #101820;\\r\\n box-shadow: 0 24px 70px rgba(0, 0, 0, 0.36);\\r\\n}\\r\\n\\r\\n.image-viewer-toolbar {\\r\\n min-width: 0;\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: flex-end;\\r\\n gap: 8px;\\r\\n padding: 8px 10px;\\r\\n border-bottom: 1px solid rgba(255, 255, 255, 0.12);\\r\\n background: rgba(24, 33, 47, 0.94);\\r\\n}\\r\\n\\r\\n.image-viewer-title {\\r\\n min-width: 0;\\r\\n flex: 1;\\r\\n overflow: hidden;\\r\\n color: #f8fafc;\\r\\n font-size: 13px;\\r\\n font-weight: 700;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.image-viewer-toolbar button {\\r\\n width: 36px;\\r\\n height: 36px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border: 0;\\r\\n border-radius: 6px;\\r\\n background: transparent;\\r\\n color: #f8fafc;\\r\\n font-size: 17px;\\r\\n font-weight: 700;\\r\\n line-height: 1;\\r\\n}\\r\\n\\r\\n.image-viewer-toolbar button:hover {\\r\\n background: rgba(255, 255, 255, 0.14);\\r\\n}\\r\\n\\r\\n.image-viewer-stage {\\r\\n min-width: 0;\\r\\n min-height: 0;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n overflow: hidden;\\r\\n background: #0c121a;\\r\\n cursor: default;\\r\\n touch-action: none;\\r\\n}\\r\\n\\r\\n.image-viewer-stage.zoomed {\\r\\n cursor: grab;\\r\\n}\\r\\n\\r\\n.image-viewer-stage.dragging {\\r\\n cursor: grabbing;\\r\\n}\\r\\n\\r\\n.image-viewer-img {\\r\\n max-width: calc(100% - 32px);\\r\\n max-height: calc(100% - 32px);\\r\\n -o-object-fit: contain;\\r\\n object-fit: contain;\\r\\n transform-origin: center center;\\r\\n transition: transform 0.08s ease-out;\\r\\n -webkit-user-select: none;\\r\\n -moz-user-select: none;\\r\\n user-select: none;\\r\\n pointer-events: none;\\r\\n}\\r\\n\\r\\n.image-viewer-stage.dragging .image-viewer-img {\\r\\n transition: none;\\r\\n}\\r\\n\\r\\n.sender-profile-backdrop {\\r\\n position: fixed;\\r\\n inset: 0;\\r\\n z-index: 84;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n padding: 24px;\\r\\n background: rgba(24, 33, 47, 0.32);\\r\\n}\\r\\n\\r\\n.sender-profile-dialog {\\r\\n width: min(380px, calc(100vw - 32px));\\r\\n display: grid;\\r\\n gap: 16px;\\r\\n padding: 18px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 18px 40px rgba(24, 33, 47, 0.18);\\r\\n}\\r\\n\\r\\n.sender-profile-dialog header {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n gap: 12px;\\r\\n}\\r\\n\\r\\n.sender-profile-main {\\r\\n display: grid;\\r\\n justify-items: center;\\r\\n gap: 8px;\\r\\n text-align: center;\\r\\n}\\r\\n\\r\\n.sender-profile-main strong {\\r\\n max-width: 100%;\\r\\n overflow-wrap: anywhere;\\r\\n font-size: 18px;\\r\\n}\\r\\n\\r\\n.sender-profile-main span {\\r\\n color: var(--primary-strong);\\r\\n font-size: 12px;\\r\\n font-weight: 700;\\r\\n}\\r\\n\\r\\n.sender-profile-fields {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n margin: 0;\\r\\n}\\r\\n\\r\\n.sender-profile-fields div {\\r\\n display: grid;\\r\\n grid-template-columns: 72px minmax(0, 1fr);\\r\\n gap: 10px;\\r\\n padding-top: 8px;\\r\\n border-top: 1px solid var(--line);\\r\\n}\\r\\n\\r\\n.sender-profile-fields dt {\\r\\n color: var(--muted);\\r\\n}\\r\\n\\r\\n.sender-profile-fields dd {\\r\\n margin: 0;\\r\\n overflow-wrap: anywhere;\\r\\n}\\r\\n\\r\\n.sender-profile-alias {\\r\\n display: grid;\\r\\n gap: 8px;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.sender-profile-alias input {\\r\\n width: 100%;\\r\\n height: 40px;\\r\\n padding: 0 12px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 6px;\\r\\n outline: none;\\r\\n background: #fff;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.sender-profile-alias input:focus {\\r\\n border-color: var(--primary);\\r\\n box-shadow: 0 0 0 3px rgba(23, 125, 114, 0.12);\\r\\n}\\r\\n\\r\\n.sender-profile-actions {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: flex-end;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.sender-profile-actions .inline-save-status {\\r\\n margin-right: auto;\\r\\n}\\r\\n\\r\\n@media (max-width: 480px) {\\r\\n .image-viewer-backdrop {\\r\\n padding: 12px;\\r\\n }\\r\\n\\r\\n .image-viewer-dialog {\\r\\n width: calc(100vw - 24px);\\r\\n height: min(560px, calc(100vh - 24px));\\r\\n min-width: 280px;\\r\\n min-height: 240px;\\r\\n max-width: calc(100vw - 24px);\\r\\n max-height: calc(100vh - 24px);\\r\\n }\\r\\n\\r\\n .image-viewer-toolbar {\\r\\n gap: 4px;\\r\\n padding: 6px;\\r\\n }\\r\\n\\r\\n .image-viewer-toolbar button {\\r\\n width: 32px;\\r\\n height: 32px;\\r\\n font-size: 15px;\\r\\n }\\r\\n\\r\\n .message-detail-member-row {\\r\\n grid-template-columns: 34px minmax(0, 1fr);\\r\\n }\\r\\n\\r\\n .message-detail-member-time,\\r\\n .message-detail-role {\\r\\n grid-column: 2;\\r\\n justify-self: start;\\r\\n }\\r\\n\\r\\n .avatar-cropper-panel {\\r\\n width: calc(100vw - 24px);\\r\\n max-height: calc(100dvh - 24px);\\r\\n }\\r\\n\\r\\n .avatar-cropper-layout {\\r\\n grid-template-columns: minmax(0, 1fr);\\r\\n }\\r\\n\\r\\n .avatar-cropper-stage {\\r\\n height: 300px;\\r\\n min-height: 300px;\\r\\n }\\r\\n\\r\\n .avatar-cropper-controls {\\r\\n grid-template-columns: minmax(0, 1fr) auto;\\r\\n align-items: center;\\r\\n }\\r\\n\\r\\n .avatar-cropper-tools {\\r\\n grid-template-columns: repeat(3, minmax(0, 1fr));\\r\\n }\\r\\n\\r\\n .avatar-cropper-preview {\\r\\n width: 82px;\\r\\n height: 82px;\\r\\n }\\r\\n\\r\\n .avatar-cropper-controls footer {\\r\\n grid-column: 1 / -1;\\r\\n }\\r\\n\\r\\n .settings-panel {\\r\\n width: calc(100vw - 24px);\\r\\n max-height: calc(100dvh - 24px);\\r\\n }\\r\\n\\r\\n .settings-layout {\\r\\n grid-template-columns: minmax(0, 1fr);\\r\\n }\\r\\n\\r\\n .settings-menu {\\r\\n grid-auto-flow: column;\\r\\n grid-auto-columns: minmax(120px, 1fr);\\r\\n overflow-x: auto;\\r\\n padding-bottom: 2px;\\r\\n }\\r\\n\\r\\n .settings-password-form footer .inline-save-status {\\r\\n flex: 1 1 100%;\\r\\n }\\r\\n}\\r\\n\\r\\n.message-file {\\r\\n width: min(280px, 62vw);\\r\\n display: grid;\\r\\n grid-template-columns: 38px minmax(0, 1fr);\\r\\n align-items: center;\\r\\n gap: 10px;\\r\\n padding: 10px;\\r\\n border: 1px solid #d6e2e7;\\r\\n border-radius: 6px;\\r\\n background: #f8fbfc;\\r\\n color: var(--text);\\r\\n text-decoration: none;\\r\\n}\\r\\n\\r\\n.message-file:hover {\\r\\n border-color: #9fd4cc;\\r\\n background: #edf8f5;\\r\\n}\\r\\n\\r\\n.message-file-icon {\\r\\n width: 38px;\\r\\n height: 38px;\\r\\n display: grid;\\r\\n place-items: center;\\r\\n border-radius: 6px;\\r\\n background: #e3eff2;\\r\\n color: var(--primary-strong);\\r\\n font-size: 18px;\\r\\n font-weight: 800;\\r\\n}\\r\\n\\r\\n.message-file-main {\\r\\n min-width: 0;\\r\\n display: grid;\\r\\n gap: 3px;\\r\\n}\\r\\n\\r\\n.message-file-main strong,\\r\\n.message-file-main small {\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n}\\r\\n\\r\\n.message-file-main strong {\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.message-file-main small {\\r\\n color: var(--muted);\\r\\n font-size: 11px;\\r\\n}\\r\\n\\r\\n.message-bubble time {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: flex-end;\\r\\n flex-wrap: wrap;\\r\\n gap: 4px;\\r\\n margin-top: 4px;\\r\\n color: var(--muted);\\r\\n font-size: 11px;\\r\\n text-align: right;\\r\\n}\\r\\n\\r\\n.recall-mark {\\r\\n margin-right: auto;\\r\\n color: #d93025;\\r\\n font-size: 11px;\\r\\n font-weight: 700;\\r\\n line-height: 1;\\r\\n}\\r\\n\\r\\n.edit-mark {\\r\\n color: #7a8792;\\r\\n font-size: 11px;\\r\\n font-weight: 600;\\r\\n line-height: 1;\\r\\n}\\r\\n\\r\\n.delivery-mark {\\r\\n display: inline-flex;\\r\\n align-items: center;\\r\\n justify-content: flex-end;\\r\\n min-width: 14px;\\r\\n color: #8f9aa3;\\r\\n font-size: 14px;\\r\\n font-weight: 800;\\r\\n letter-spacing: 0;\\r\\n line-height: 1;\\r\\n}\\r\\n\\r\\n.delivery-mark-delivered,\\r\\n.delivery-mark-read {\\r\\n min-width: 19px;\\r\\n}\\r\\n\\r\\n.delivery-mark-read {\\r\\n color: #1aa66a;\\r\\n}\\r\\n\\r\\n.favorite-mark {\\r\\n color: #c79520;\\r\\n font-size: 12px;\\r\\n line-height: 1;\\r\\n}\\r\\n\\r\\n.delivery-check {\\r\\n display: inline-block;\\r\\n}\\r\\n\\r\\n.delivery-check-second {\\r\\n margin-left: -5px;\\r\\n}\\r\\n\\r\\n.delivery-error {\\r\\n color: #c0392b;\\r\\n}\\r\\n\\r\\n.message-context-menu {\\r\\n position: fixed;\\r\\n z-index: 30;\\r\\n width: 136px;\\r\\n padding: 6px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 16px 40px rgba(24, 33, 47, 0.18);\\r\\n}\\r\\n\\r\\n.message-context-menu button {\\r\\n width: 100%;\\r\\n min-height: 32px;\\r\\n padding: 0 10px;\\r\\n border: 0;\\r\\n border-radius: 6px;\\r\\n background: transparent;\\r\\n color: var(--text);\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.message-context-menu button:hover {\\r\\n background: #eaf3f1;\\r\\n}\\r\\n\\r\\n.selection-toolbar {\\r\\n min-height: 42px;\\r\\n display: flex;\\r\\n align-items: center;\\r\\n gap: 8px;\\r\\n padding: 8px 16px;\\r\\n border-top: 1px solid var(--line);\\r\\n background: #f7fafc;\\r\\n}\\r\\n\\r\\n.selection-toolbar span {\\r\\n flex: 1;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.selection-toolbar button {\\r\\n min-height: 30px;\\r\\n padding: 0 10px;\\r\\n border-radius: 6px;\\r\\n}\\r\\n\\r\\n.forward-dialog,\\r\\n.edit-dialog {\\r\\n width: min(100%, 340px);\\r\\n max-height: min(520px, calc(100vh - 130px));\\r\\n display: grid;\\r\\n gap: 4px;\\r\\n padding: 14px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 18px 40px rgba(24, 33, 47, 0.18);\\r\\n overflow: auto;\\r\\n}\\r\\n\\r\\n.forward-dialog header,\\r\\n.edit-dialog header,\\r\\n.forward-target {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n gap: 10px;\\r\\n}\\r\\n\\r\\n.forward-dialog header,\\r\\n.edit-dialog header {\\r\\n justify-content: space-between;\\r\\n margin-bottom: 6px;\\r\\n}\\r\\n\\r\\n.forward-dialog h3,\\r\\n.edit-dialog h3 {\\r\\n margin: 0;\\r\\n font-size: 16px;\\r\\n}\\r\\n\\r\\n.edit-dialog {\\r\\n width: min(100%, 420px);\\r\\n gap: 12px;\\r\\n}\\r\\n\\r\\n.edit-dialog textarea {\\r\\n width: 100%;\\r\\n min-height: 132px;\\r\\n resize: vertical;\\r\\n border-radius: 8px;\\r\\n border: 1px solid var(--line);\\r\\n padding: 10px;\\r\\n background: #f9fbfc;\\r\\n color: var(--text);\\r\\n line-height: 1.5;\\r\\n}\\r\\n\\r\\n.edit-dialog textarea:focus {\\r\\n border-color: var(--accent);\\r\\n outline: 0;\\r\\n box-shadow: 0 0 0 3px rgba(24, 138, 121, 0.14);\\r\\n}\\r\\n\\r\\n.edit-dialog footer {\\r\\n display: flex;\\r\\n justify-content: flex-end;\\r\\n gap: 8px;\\r\\n}\\r\\n\\r\\n.edit-dialog footer button {\\r\\n min-height: 34px;\\r\\n padding: 0 14px;\\r\\n border-radius: 8px;\\r\\n}\\r\\n\\r\\n.forward-target {\\r\\n min-height: 52px;\\r\\n padding: 6px;\\r\\n border: 0;\\r\\n border-radius: 8px;\\r\\n background: transparent;\\r\\n color: var(--text);\\r\\n text-align: left;\\r\\n}\\r\\n\\r\\n.forward-target:hover {\\r\\n background: #eaf3f1;\\r\\n}\\r\\n\\r\\n.chat-toast {\\r\\n position: absolute;\\r\\n left: 50%;\\r\\n bottom: 132px;\\r\\n z-index: 20;\\r\\n transform: translateX(-50%);\\r\\n padding: 8px 12px;\\r\\n border-radius: 8px;\\r\\n background: rgba(35, 45, 58, 0.92);\\r\\n color: #fff;\\r\\n font-size: 13px;\\r\\n pointer-events: none;\\r\\n}\\r\\n\\r\\n.chat-toast.error {\\r\\n background: rgba(192, 57, 43, 0.94);\\r\\n}\\r\\n\\r\\n.message-composer {\\r\\n position: relative;\\r\\n min-height: 0;\\r\\n border-top: 1px solid var(--line);\\r\\n background: var(--panel);\\r\\n}\\r\\n\\r\\n.message-composer::after {\\r\\n content: \\\"\\\";\\r\\n position: absolute;\\r\\n inset: 6px;\\r\\n z-index: 4;\\r\\n border: 2px dashed transparent;\\r\\n border-radius: 8px;\\r\\n pointer-events: none;\\r\\n transition: border-color 0.12s ease, background-color 0.12s ease;\\r\\n}\\r\\n\\r\\n.message-composer.drop-active::after {\\r\\n border-color: var(--primary);\\r\\n background: rgba(23, 125, 114, 0.08);\\r\\n}\\r\\n\\r\\n.quote-preview {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n gap: 8px;\\r\\n padding: 8px 16px 0;\\r\\n color: var(--muted);\\r\\n font-size: 13px;\\r\\n}\\r\\n\\r\\n.quote-preview span {\\r\\n min-width: 0;\\r\\n flex: 1;\\r\\n overflow: hidden;\\r\\n text-overflow: ellipsis;\\r\\n white-space: nowrap;\\r\\n border-left: 3px solid var(--accent);\\r\\n padding-left: 8px;\\r\\n}\\r\\n\\r\\n.quote-preview strong {\\r\\n margin-right: 6px;\\r\\n color: var(--text);\\r\\n}\\r\\n\\r\\n.quote-preview button {\\r\\n width: 26px;\\r\\n height: 26px;\\r\\n border: 0;\\r\\n border-radius: 6px;\\r\\n background: transparent;\\r\\n color: var(--muted);\\r\\n font-size: 18px;\\r\\n}\\r\\n\\r\\n.quote-preview button:hover {\\r\\n background: #edf2f5;\\r\\n}\\r\\n\\r\\n.composer-tools {\\r\\n position: relative;\\r\\n display: flex;\\r\\n gap: 4px;\\r\\n padding: 8px 16px 0;\\r\\n}\\r\\n\\r\\n.composer-tools input[type=\\\"file\\\"] {\\r\\n display: none;\\r\\n}\\r\\n\\r\\n.composer-tools button {\\r\\n width: 32px;\\r\\n height: 32px;\\r\\n border: 0;\\r\\n border-radius: 6px;\\r\\n background: transparent;\\r\\n color: var(--muted);\\r\\n font-size: 18px;\\r\\n}\\r\\n\\r\\n.composer-tools button:hover {\\r\\n background: #edf2f5;\\r\\n}\\r\\n\\r\\n.emoji-picker {\\r\\n position: absolute;\\r\\n left: 16px;\\r\\n bottom: 38px;\\r\\n z-index: 12;\\r\\n width: 256px;\\r\\n display: grid;\\r\\n grid-template-columns: repeat(8, 1fr);\\r\\n gap: 2px;\\r\\n padding: 8px;\\r\\n border: 1px solid var(--line);\\r\\n border-radius: 8px;\\r\\n background: var(--panel);\\r\\n box-shadow: 0 14px 34px rgba(24, 33, 47, 0.16);\\r\\n}\\r\\n\\r\\n.emoji-picker button {\\r\\n width: 28px;\\r\\n height: 28px;\\r\\n border-radius: 6px;\\r\\n font-size: 17px;\\r\\n}\\r\\n\\r\\n.message-composer textarea {\\r\\n display: block;\\r\\n min-height: 86px;\\r\\n max-height: 180px;\\r\\n padding: 12px 16px;\\r\\n border: 0;\\r\\n border-radius: 0;\\r\\n resize: none;\\r\\n box-shadow: none;\\r\\n}\\r\\n\\r\\n.composer-footer {\\r\\n display: flex;\\r\\n align-items: center;\\r\\n justify-content: space-between;\\r\\n gap: 12px;\\r\\n padding: 0 16px 14px;\\r\\n color: var(--muted);\\r\\n font-size: 12px;\\r\\n}\\r\\n\\r\\n.send-button {\\r\\n min-width: 72px;\\r\\n height: 34px;\\r\\n}\\r\\n\\r\\n@media (max-width: 760px) {\\r\\n .app-shell {\\r\\n grid-template-columns: 56px minmax(0, 1fr);\\r\\n }\\r\\n\\r\\n .conversation-list {\\r\\n display: none;\\r\\n }\\r\\n\\r\\n .message-bubble {\\r\\n max-width: 86%;\\r\\n }\\r\\n}\\r\\n\", \"\"]);\n// Exports\n/* harmony default export */ __webpack_exports__[\"default\"] = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://jc-web-im/./src/styles/base.css?./node_modules/css-loader/dist/cjs.js??clonedRuleSet-14.use%5B1%5D!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-14.use%5B2%5D\n}");
/***/ }),
/***/ "./src/App.vue":
/*!*********************!*\
!*** ./src/App.vue ***!
\*********************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _App_vue_vue_type_template_id_7ba5bd90__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./App.vue?vue&type=template&id=7ba5bd90 */ \"./src/App.vue?vue&type=template&id=7ba5bd90\");\n/* harmony import */ var _App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./App.vue?vue&type=script&setup=true&lang=js */ \"./src/App.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_App_vue_vue_type_template_id_7ba5bd90__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/App.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/App.vue?\n}");
/***/ }),
/***/ "./src/components/ChatShell.vue":
/*!**************************************!*\
!*** ./src/components/ChatShell.vue ***!
\**************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ChatShell_vue_vue_type_template_id_2fe58db8__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ChatShell.vue?vue&type=template&id=2fe58db8 */ \"./src/components/ChatShell.vue?vue&type=template&id=2fe58db8\");\n/* harmony import */ var _ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ChatShell.vue?vue&type=script&setup=true&lang=js */ \"./src/components/ChatShell.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_ChatShell_vue_vue_type_template_id_2fe58db8__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/ChatShell.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/ChatShell.vue?\n}");
/***/ }),
/***/ "./src/components/LoginView.vue":
/*!**************************************!*\
!*** ./src/components/LoginView.vue ***!
\**************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _LoginView_vue_vue_type_template_id_37959aa4__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./LoginView.vue?vue&type=template&id=37959aa4 */ \"./src/components/LoginView.vue?vue&type=template&id=37959aa4\");\n/* harmony import */ var _LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LoginView.vue?vue&type=script&setup=true&lang=js */ \"./src/components/LoginView.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_LoginView_vue_vue_type_template_id_37959aa4__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/LoginView.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/LoginView.vue?\n}");
/***/ }),
/***/ "./src/components/chat/ChatPanel.vue":
/*!*******************************************!*\
!*** ./src/components/chat/ChatPanel.vue ***!
\*******************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ChatPanel_vue_vue_type_template_id_358a1705__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ChatPanel.vue?vue&type=template&id=358a1705 */ \"./src/components/chat/ChatPanel.vue?vue&type=template&id=358a1705\");\n/* harmony import */ var _ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ChatPanel.vue?vue&type=script&setup=true&lang=js */ \"./src/components/chat/ChatPanel.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_ChatPanel_vue_vue_type_template_id_358a1705__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/chat/ChatPanel.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/ChatPanel.vue?\n}");
/***/ }),
/***/ "./src/components/chat/MessageComposer.vue":
/*!*************************************************!*\
!*** ./src/components/chat/MessageComposer.vue ***!
\*************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _MessageComposer_vue_vue_type_template_id_08eca580__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./MessageComposer.vue?vue&type=template&id=08eca580 */ \"./src/components/chat/MessageComposer.vue?vue&type=template&id=08eca580\");\n/* harmony import */ var _MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MessageComposer.vue?vue&type=script&setup=true&lang=js */ \"./src/components/chat/MessageComposer.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_MessageComposer_vue_vue_type_template_id_08eca580__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/chat/MessageComposer.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageComposer.vue?\n}");
/***/ }),
/***/ "./src/components/chat/MessageList.vue":
/*!*********************************************!*\
!*** ./src/components/chat/MessageList.vue ***!
\*********************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _MessageList_vue_vue_type_template_id_a39e6c04__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./MessageList.vue?vue&type=template&id=a39e6c04 */ \"./src/components/chat/MessageList.vue?vue&type=template&id=a39e6c04\");\n/* harmony import */ var _MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MessageList.vue?vue&type=script&setup=true&lang=js */ \"./src/components/chat/MessageList.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_MessageList_vue_vue_type_template_id_a39e6c04__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/chat/MessageList.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageList.vue?\n}");
/***/ }),
/***/ "./src/components/contacts/ContactPanel.vue":
/*!**************************************************!*\
!*** ./src/components/contacts/ContactPanel.vue ***!
\**************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ContactPanel_vue_vue_type_template_id_63d88b80__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ContactPanel.vue?vue&type=template&id=63d88b80 */ \"./src/components/contacts/ContactPanel.vue?vue&type=template&id=63d88b80\");\n/* harmony import */ var _ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ContactPanel.vue?vue&type=script&setup=true&lang=js */ \"./src/components/contacts/ContactPanel.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_ContactPanel_vue_vue_type_template_id_63d88b80__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/contacts/ContactPanel.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/contacts/ContactPanel.vue?\n}");
/***/ }),
/***/ "./src/components/favorites/FavoriteList.vue":
/*!***************************************************!*\
!*** ./src/components/favorites/FavoriteList.vue ***!
\***************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _FavoriteList_vue_vue_type_template_id_0086db7c__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FavoriteList.vue?vue&type=template&id=0086db7c */ \"./src/components/favorites/FavoriteList.vue?vue&type=template&id=0086db7c\");\n/* harmony import */ var _FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./FavoriteList.vue?vue&type=script&setup=true&lang=js */ \"./src/components/favorites/FavoriteList.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_FavoriteList_vue_vue_type_template_id_0086db7c__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/favorites/FavoriteList.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoriteList.vue?\n}");
/***/ }),
/***/ "./src/components/favorites/FavoritePanel.vue":
/*!****************************************************!*\
!*** ./src/components/favorites/FavoritePanel.vue ***!
\****************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _FavoritePanel_vue_vue_type_template_id_29e1a3e0__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FavoritePanel.vue?vue&type=template&id=29e1a3e0 */ \"./src/components/favorites/FavoritePanel.vue?vue&type=template&id=29e1a3e0\");\n/* harmony import */ var _FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./FavoritePanel.vue?vue&type=script&setup=true&lang=js */ \"./src/components/favorites/FavoritePanel.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_FavoritePanel_vue_vue_type_template_id_29e1a3e0__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/favorites/FavoritePanel.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoritePanel.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/ContactList.vue":
/*!************************************************!*\
!*** ./src/components/sidebar/ContactList.vue ***!
\************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ContactList_vue_vue_type_template_id_7aaf5f2b__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ContactList.vue?vue&type=template&id=7aaf5f2b */ \"./src/components/sidebar/ContactList.vue?vue&type=template&id=7aaf5f2b\");\n/* harmony import */ var _ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ContactList.vue?vue&type=script&setup=true&lang=js */ \"./src/components/sidebar/ContactList.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_ContactList_vue_vue_type_template_id_7aaf5f2b__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/sidebar/ContactList.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ContactList.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/ConversationList.vue":
/*!*****************************************************!*\
!*** ./src/components/sidebar/ConversationList.vue ***!
\*****************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _ConversationList_vue_vue_type_template_id_7a656f78__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./ConversationList.vue?vue&type=template&id=7a656f78 */ \"./src/components/sidebar/ConversationList.vue?vue&type=template&id=7a656f78\");\n/* harmony import */ var _ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./ConversationList.vue?vue&type=script&setup=true&lang=js */ \"./src/components/sidebar/ConversationList.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_ConversationList_vue_vue_type_template_id_7a656f78__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/sidebar/ConversationList.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ConversationList.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/NavigationRail.vue":
/*!***************************************************!*\
!*** ./src/components/sidebar/NavigationRail.vue ***!
\***************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _NavigationRail_vue_vue_type_template_id_021016ee__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./NavigationRail.vue?vue&type=template&id=021016ee */ \"./src/components/sidebar/NavigationRail.vue?vue&type=template&id=021016ee\");\n/* harmony import */ var _NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./NavigationRail.vue?vue&type=script&setup=true&lang=js */ \"./src/components/sidebar/NavigationRail.vue?vue&type=script&setup=true&lang=js\");\n/* harmony import */ var _node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/dist/exportHelper.js */ \"./node_modules/vue-loader/dist/exportHelper.js\");\n\n\n\n\n;\nconst __exports__ = /*#__PURE__*/(0,_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(_NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"], [['render',_NavigationRail_vue_vue_type_template_id_021016ee__WEBPACK_IMPORTED_MODULE_0__.render],['__file',\"src/components/sidebar/NavigationRail.vue\"]])\n/* hot reload */\nif (false) // removed by dead control flow\n{}\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (__exports__);\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/NavigationRail.vue?\n}");
/***/ }),
/***/ "./src/App.vue?vue&type=script&setup=true&lang=js":
/*!********************************************************!*\
!*** ./src/App.vue?vue&type=script&setup=true&lang=js ***!
\********************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_App_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./App.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/App.vue?\n}");
/***/ }),
/***/ "./src/components/ChatShell.vue?vue&type=script&setup=true&lang=js":
/*!*************************************************************************!*\
!*** ./src/components/ChatShell.vue?vue&type=script&setup=true&lang=js ***!
\*************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatShell_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ChatShell.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ChatShell.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/ChatShell.vue?\n}");
/***/ }),
/***/ "./src/components/LoginView.vue?vue&type=script&setup=true&lang=js":
/*!*************************************************************************!*\
!*** ./src/components/LoginView.vue?vue&type=script&setup=true&lang=js ***!
\*************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_LoginView_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./LoginView.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/LoginView.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/LoginView.vue?\n}");
/***/ }),
/***/ "./src/components/chat/ChatPanel.vue?vue&type=script&setup=true&lang=js":
/*!******************************************************************************!*\
!*** ./src/components/chat/ChatPanel.vue?vue&type=script&setup=true&lang=js ***!
\******************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ChatPanel.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/ChatPanel.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/ChatPanel.vue?\n}");
/***/ }),
/***/ "./src/components/chat/MessageComposer.vue?vue&type=script&setup=true&lang=js":
/*!************************************************************************************!*\
!*** ./src/components/chat/MessageComposer.vue?vue&type=script&setup=true&lang=js ***!
\************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageComposer_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./MessageComposer.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageComposer.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageComposer.vue?\n}");
/***/ }),
/***/ "./src/components/chat/MessageList.vue?vue&type=script&setup=true&lang=js":
/*!********************************************************************************!*\
!*** ./src/components/chat/MessageList.vue?vue&type=script&setup=true&lang=js ***!
\********************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./MessageList.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageList.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageList.vue?\n}");
/***/ }),
/***/ "./src/components/contacts/ContactPanel.vue?vue&type=script&setup=true&lang=js":
/*!*************************************************************************************!*\
!*** ./src/components/contacts/ContactPanel.vue?vue&type=script&setup=true&lang=js ***!
\*************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactPanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ContactPanel.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/contacts/ContactPanel.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/contacts/ContactPanel.vue?\n}");
/***/ }),
/***/ "./src/components/favorites/FavoriteList.vue?vue&type=script&setup=true&lang=js":
/*!**************************************************************************************!*\
!*** ./src/components/favorites/FavoriteList.vue?vue&type=script&setup=true&lang=js ***!
\**************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoriteList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./FavoriteList.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoriteList.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoriteList.vue?\n}");
/***/ }),
/***/ "./src/components/favorites/FavoritePanel.vue?vue&type=script&setup=true&lang=js":
/*!***************************************************************************************!*\
!*** ./src/components/favorites/FavoritePanel.vue?vue&type=script&setup=true&lang=js ***!
\***************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoritePanel_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./FavoritePanel.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoritePanel.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoritePanel.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/ContactList.vue?vue&type=script&setup=true&lang=js":
/*!***********************************************************************************!*\
!*** ./src/components/sidebar/ContactList.vue?vue&type=script&setup=true&lang=js ***!
\***********************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ContactList.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ContactList.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ContactList.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/ConversationList.vue?vue&type=script&setup=true&lang=js":
/*!****************************************************************************************!*\
!*** ./src/components/sidebar/ConversationList.vue?vue&type=script&setup=true&lang=js ***!
\****************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ConversationList_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ConversationList.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ConversationList.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ConversationList.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/NavigationRail.vue?vue&type=script&setup=true&lang=js":
/*!**************************************************************************************!*\
!*** ./src/components/sidebar/NavigationRail.vue?vue&type=script&setup=true&lang=js ***!
\**************************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_NavigationRail_vue_vue_type_script_setup_true_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./NavigationRail.vue?vue&type=script&setup=true&lang=js */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/NavigationRail.vue?vue&type=script&setup=true&lang=js\");\n \n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/NavigationRail.vue?\n}");
/***/ }),
/***/ "./src/App.vue?vue&type=template&id=7ba5bd90":
/*!***************************************************!*\
!*** ./src/App.vue?vue&type=template&id=7ba5bd90 ***!
\***************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_App_vue_vue_type_template_id_7ba5bd90__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_App_vue_vue_type_template_id_7ba5bd90__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./App.vue?vue&type=template&id=7ba5bd90 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/App.vue?vue&type=template&id=7ba5bd90\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/App.vue?\n}");
/***/ }),
/***/ "./src/components/ChatShell.vue?vue&type=template&id=2fe58db8":
/*!********************************************************************!*\
!*** ./src/components/ChatShell.vue?vue&type=template&id=2fe58db8 ***!
\********************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatShell_vue_vue_type_template_id_2fe58db8__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatShell_vue_vue_type_template_id_2fe58db8__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ChatShell.vue?vue&type=template&id=2fe58db8 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/ChatShell.vue?vue&type=template&id=2fe58db8\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/ChatShell.vue?\n}");
/***/ }),
/***/ "./src/components/LoginView.vue?vue&type=template&id=37959aa4":
/*!********************************************************************!*\
!*** ./src/components/LoginView.vue?vue&type=template&id=37959aa4 ***!
\********************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_LoginView_vue_vue_type_template_id_37959aa4__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_LoginView_vue_vue_type_template_id_37959aa4__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./LoginView.vue?vue&type=template&id=37959aa4 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/LoginView.vue?vue&type=template&id=37959aa4\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/LoginView.vue?\n}");
/***/ }),
/***/ "./src/components/chat/ChatPanel.vue?vue&type=template&id=358a1705":
/*!*************************************************************************!*\
!*** ./src/components/chat/ChatPanel.vue?vue&type=template&id=358a1705 ***!
\*************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatPanel_vue_vue_type_template_id_358a1705__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ChatPanel_vue_vue_type_template_id_358a1705__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ChatPanel.vue?vue&type=template&id=358a1705 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/ChatPanel.vue?vue&type=template&id=358a1705\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/ChatPanel.vue?\n}");
/***/ }),
/***/ "./src/components/chat/MessageComposer.vue?vue&type=template&id=08eca580":
/*!*******************************************************************************!*\
!*** ./src/components/chat/MessageComposer.vue?vue&type=template&id=08eca580 ***!
\*******************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageComposer_vue_vue_type_template_id_08eca580__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageComposer_vue_vue_type_template_id_08eca580__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./MessageComposer.vue?vue&type=template&id=08eca580 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageComposer.vue?vue&type=template&id=08eca580\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageComposer.vue?\n}");
/***/ }),
/***/ "./src/components/chat/MessageList.vue?vue&type=template&id=a39e6c04":
/*!***************************************************************************!*\
!*** ./src/components/chat/MessageList.vue?vue&type=template&id=a39e6c04 ***!
\***************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageList_vue_vue_type_template_id_a39e6c04__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_MessageList_vue_vue_type_template_id_a39e6c04__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./MessageList.vue?vue&type=template&id=a39e6c04 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/chat/MessageList.vue?vue&type=template&id=a39e6c04\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/chat/MessageList.vue?\n}");
/***/ }),
/***/ "./src/components/contacts/ContactPanel.vue?vue&type=template&id=63d88b80":
/*!********************************************************************************!*\
!*** ./src/components/contacts/ContactPanel.vue?vue&type=template&id=63d88b80 ***!
\********************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactPanel_vue_vue_type_template_id_63d88b80__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactPanel_vue_vue_type_template_id_63d88b80__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ContactPanel.vue?vue&type=template&id=63d88b80 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/contacts/ContactPanel.vue?vue&type=template&id=63d88b80\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/contacts/ContactPanel.vue?\n}");
/***/ }),
/***/ "./src/components/favorites/FavoriteList.vue?vue&type=template&id=0086db7c":
/*!*********************************************************************************!*\
!*** ./src/components/favorites/FavoriteList.vue?vue&type=template&id=0086db7c ***!
\*********************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoriteList_vue_vue_type_template_id_0086db7c__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoriteList_vue_vue_type_template_id_0086db7c__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./FavoriteList.vue?vue&type=template&id=0086db7c */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoriteList.vue?vue&type=template&id=0086db7c\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoriteList.vue?\n}");
/***/ }),
/***/ "./src/components/favorites/FavoritePanel.vue?vue&type=template&id=29e1a3e0":
/*!**********************************************************************************!*\
!*** ./src/components/favorites/FavoritePanel.vue?vue&type=template&id=29e1a3e0 ***!
\**********************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoritePanel_vue_vue_type_template_id_29e1a3e0__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_FavoritePanel_vue_vue_type_template_id_29e1a3e0__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./FavoritePanel.vue?vue&type=template&id=29e1a3e0 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/favorites/FavoritePanel.vue?vue&type=template&id=29e1a3e0\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/favorites/FavoritePanel.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/ContactList.vue?vue&type=template&id=7aaf5f2b":
/*!******************************************************************************!*\
!*** ./src/components/sidebar/ContactList.vue?vue&type=template&id=7aaf5f2b ***!
\******************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactList_vue_vue_type_template_id_7aaf5f2b__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ContactList_vue_vue_type_template_id_7aaf5f2b__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ContactList.vue?vue&type=template&id=7aaf5f2b */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ContactList.vue?vue&type=template&id=7aaf5f2b\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ContactList.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/ConversationList.vue?vue&type=template&id=7a656f78":
/*!***********************************************************************************!*\
!*** ./src/components/sidebar/ConversationList.vue?vue&type=template&id=7a656f78 ***!
\***********************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ConversationList_vue_vue_type_template_id_7a656f78__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_ConversationList_vue_vue_type_template_id_7a656f78__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./ConversationList.vue?vue&type=template&id=7a656f78 */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/ConversationList.vue?vue&type=template&id=7a656f78\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/ConversationList.vue?\n}");
/***/ }),
/***/ "./src/components/sidebar/NavigationRail.vue?vue&type=template&id=021016ee":
/*!*********************************************************************************!*\
!*** ./src/components/sidebar/NavigationRail.vue?vue&type=template&id=021016ee ***!
\*********************************************************************************/
/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ render: function() { return /* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_NavigationRail_vue_vue_type_template_id_021016ee__WEBPACK_IMPORTED_MODULE_0__.render; }\n/* harmony export */ });\n/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_40_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_3_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_NavigationRail_vue_vue_type_template_id_021016ee__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./NavigationRail.vue?vue&type=template&id=021016ee */ \"./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./src/components/sidebar/NavigationRail.vue?vue&type=template&id=021016ee\");\n\n\n//# sourceURL=webpack://jc-web-im/./src/components/sidebar/NavigationRail.vue?\n}");
/***/ }),
/***/ "./src/styles/base.css":
/*!*****************************!*\
!*** ./src/styles/base.css ***!
\*****************************/
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
eval("{// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = __webpack_require__(/*! !!../../node_modules/css-loader/dist/cjs.js??clonedRuleSet-14.use[1]!../../node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-14.use[2]!./base.css */ \"./node_modules/css-loader/dist/cjs.js??clonedRuleSet-14.use[1]!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-14.use[2]!./src/styles/base.css\");\nif(content.__esModule) content = content.default;\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar add = (__webpack_require__(/*! !../../node_modules/vue-style-loader/lib/addStylesClient.js */ \"./node_modules/vue-style-loader/lib/addStylesClient.js\")[\"default\"])\nvar update = add(\"1a9917ba\", content, false, {\"sourceMap\":false,\"shadowMode\":false});\n// Hot Module Replacement\nif(false) // removed by dead control flow\n{}\n\n//# sourceURL=webpack://jc-web-im/./src/styles/base.css?\n}");
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ if (!(moduleId in __webpack_modules__)) {
/******/ delete __webpack_module_cache__[moduleId];
/******/ var e = new Error("Cannot find module '" + moduleId + "'");
/******/ e.code = 'MODULE_NOT_FOUND';
/******/ throw e;
/******/ }
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/chunk loaded */
/******/ !function() {
/******/ var deferred = [];
/******/ __webpack_require__.O = function(result, chunkIds, fn, priority) {
/******/ if(chunkIds) {
/******/ priority = priority || 0;
/******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
/******/ deferred[i] = [chunkIds, fn, priority];
/******/ return;
/******/ }
/******/ var notFulfilled = Infinity;
/******/ for (var i = 0; i < deferred.length; i++) {
/******/ var chunkIds = deferred[i][0];
/******/ var fn = deferred[i][1];
/******/ var priority = deferred[i][2];
/******/ var fulfilled = true;
/******/ for (var j = 0; j < chunkIds.length; j++) {
/******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {
/******/ chunkIds.splice(j--, 1);
/******/ } else {
/******/ fulfilled = false;
/******/ if(priority < notFulfilled) notFulfilled = priority;
/******/ }
/******/ }
/******/ if(fulfilled) {
/******/ deferred.splice(i--, 1)
/******/ var r = fn();
/******/ if (r !== undefined) result = r;
/******/ }
/******/ }
/******/ return result;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/compat get default export */
/******/ !function() {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function() { return module['default']; } :
/******/ function() { return module; };
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter/value functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ if(Array.isArray(definition)) {
/******/ var i = 0;
/******/ while(i < definition.length) {
/******/ var key = definition[i++];
/******/ var binding = definition[i++];
/******/ if(!__webpack_require__.o(exports, key)) {
/******/ if(binding === 0) {
/******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] });
/******/ } else {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: binding });
/******/ }
/******/ } else if(binding === 0) { i++; }
/******/ }
/******/ } else {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/global */
/******/ !function() {
/******/ __webpack_require__.g = (function() {
/******/ if (typeof globalThis === 'object') return globalThis;
/******/ try {
/******/ return this || new Function('return this')();
/******/ } catch (e) {
/******/ if (typeof window === 'object') return window;
/******/ }
/******/ })();
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ !function() {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/set anonymous default export name */
/******/ !function() {
/******/ // set .name for anonymous default exports per ES spec
/******/ __webpack_require__.dn = function(x) {
/******/ (Object.getOwnPropertyDescriptor(x, "name") || {}).writable || Object.defineProperty(x, "name", { value: "default", configurable: true });
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ !function() {
/******/ // no baseURI
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ "app": 0
/******/ };
/******/
/******/ // no chunk on demand loading
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ __webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = function(parentChunkLoadingFunction, data) {
/******/ var chunkIds = data[0];
/******/ var moreModules = data[1];
/******/ var runtime = data[2];
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ if(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) var result = runtime(__webpack_require__);
/******/ }
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ return __webpack_require__.O(result);
/******/ }
/******/
/******/ var chunkLoadingGlobal = self["webpackChunkjc_web_im"] = self["webpackChunkjc_web_im"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ }();
/******/
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module depends on other loaded chunks and execution need to be delayed
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["chunk-vendors"], function() { return __webpack_require__("./src/main.js"); })
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
/******/
/******/ })()
;