第八轮最小粒度测试:修复CSS选择器/JSX结构不匹配的一整类bug,清理Tinode品牌残留
第八轮改用"读CSS选择器+核对JSX结构"的方式复测全部11章,命中了7轮纯接口测试从未发现的一类 问题——选择器写对了但目标元素的实际DOM结构/className对不上,样式静默失效: - 语音通话最小化胶囊按钮尺寸被同特异度规则覆盖;移动端悬浮通话窗口left/right/width三值同时 生效导致过度约束;来电全屏页认证徽章/姓名标题缺少专属样式覆盖 - 我的收藏-语音卡片三列grid对应实际只有1个子元素,播放器被压缩到卡片左侧一角;链接/记录头部 完全没有基础样式,退化成浏览器默认外观 - 多选模式下"收到的"消息气泡被flex auto-margin一起拖到最右侧;.avatar-box/#send-message-panel 两处逗号断句错误导致后半句选择器丢失祖先限定 - 按住说话悬浮反馈渲染成内联胶囊,而参考图要求的居中悬浮卡片样式其实已经存在(挂在了另一个非 生产demo组件上);批量转发确认框沿用了80%视口高度;audio-player.jsx的playback类点在canvas 上而非包裹层,波形和计时器可能纵向堆叠 - "消息已撤回"占位符误拼了日期分隔条的class而非专属的deleted 品牌清理:浏览器标签页标题、未读数标题更新均硬编码"Tinode";LINK_CONTACT_US等三个链接常量 指向开源Tinode项目自己的域名(联系我们改为跟用户条款/隐私协议一致的toast,不再发起外部mailto)。 以及:空会话丢失.chat-box样式类、青少年模式PIN定位、若干收藏/文件类型展示细节。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
5e173c55e8
commit
d759f67b11
+100
-88
@@ -2400,9 +2400,9 @@ const FORWARDED_PREVIEW_LENGTH = 84;
|
||||
const EDIT_PREVIEW_LENGTH = 48;
|
||||
const MIN_DURATION = 2_000;
|
||||
const MAX_DURATION = 600_000;
|
||||
const LINK_CONTACT_US = 'mailto:support@tinode.co';
|
||||
const LINK_PRIVACY_POLICY = 'https://tinode.co/privacy.html';
|
||||
const LINK_TERMS_OF_SERVICE = 'https://tinode.co/terms.html';
|
||||
const LINK_CONTACT_US = null;
|
||||
const LINK_PRIVACY_POLICY = null;
|
||||
const LINK_TERMS_OF_SERVICE = null;
|
||||
const IMMEDIATE_P2P_SUBSCRIPTION = false;
|
||||
const CLICKABLE_URL_SCHEMES = ['http', 'https', 'ftp', 'ftps'];
|
||||
const QRCODE_SIZE = 128;
|
||||
@@ -3722,7 +3722,8 @@ const UPLOAD_CTRL_TEXT_CN = {
|
||||
'too large': '文件大小超出限制',
|
||||
'malformed': '请求内容有误,请稍后重试',
|
||||
'permission denied': '没有权限执行此操作',
|
||||
'gone': '内容不存在或已被删除'
|
||||
'gone': '内容不存在或已被删除',
|
||||
'not found': '内容不存在或已被删除'
|
||||
};
|
||||
function uploadLargeFile(tinode, file, onProgress) {
|
||||
const authToken = tinode && tinode.getAuthToken && tinode.getAuthToken();
|
||||
@@ -4886,7 +4887,7 @@ function updateFavicon(count) {
|
||||
head.removeChild(oldIcon);
|
||||
}
|
||||
head.appendChild(newIcon);
|
||||
document.title = (count > 0 ? '(' + count + ') ' : '') + 'Tinode';
|
||||
document.title = (count > 0 ? '(' + count + ') ' : '') + _config_js__WEBPACK_IMPORTED_MODULE_1__.BASE_APP_NAME;
|
||||
}
|
||||
function theCard(fn, imageUrl, imageMimeType, note) {
|
||||
let card = null;
|
||||
@@ -5470,96 +5471,93 @@ __webpack_require__.r(__webpack_exports__);
|
||||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
||||
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-intl */ "react-intl");
|
||||
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_intl__WEBPACK_IMPORTED_MODULE_1__);
|
||||
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tinode-sdk */ "tinode-sdk");
|
||||
/* harmony import */ var tinode_sdk__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(tinode_sdk__WEBPACK_IMPORTED_MODULE_2__);
|
||||
/* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../config.js */ "./src/config.js");
|
||||
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react/jsx-dev-runtime */ "./node_modules/react/jsx-dev-runtime.js");
|
||||
|
||||
/* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../config.js */ "./src/config.js");
|
||||
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react/jsx-dev-runtime */ "./node_modules/react/jsx-dev-runtime.js");
|
||||
|
||||
|
||||
|
||||
|
||||
function FlatLink({
|
||||
href,
|
||||
icon,
|
||||
children
|
||||
}) {
|
||||
return href ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("a", {
|
||||
href: href,
|
||||
className: "flat-button",
|
||||
target: "_blank",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("i", {
|
||||
className: "material-icons",
|
||||
children: icon
|
||||
}, void 0, false), " \xA0", children]
|
||||
}, void 0, true) : (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("span", {
|
||||
className: "flat-button",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("i", {
|
||||
className: "material-icons",
|
||||
children: icon
|
||||
}, void 0, false), " \xA0", children]
|
||||
}, void 0, true);
|
||||
}
|
||||
class AccSupportView extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) {
|
||||
render() {
|
||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("div", {
|
||||
className: "scrollable-panel",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("div", {
|
||||
className: "panel-form-column",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("a", {
|
||||
href: _config_js__WEBPACK_IMPORTED_MODULE_3__.LINK_CONTACT_US,
|
||||
className: "flat-button",
|
||||
target: "_blank",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("i", {
|
||||
className: "material-icons",
|
||||
children: "email"
|
||||
}, void 0, false), " \xA0", (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(FlatLink, {
|
||||
href: _config_js__WEBPACK_IMPORTED_MODULE_2__.LINK_CONTACT_US,
|
||||
icon: "email",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
id: "link_contact_us",
|
||||
defaultMessage: "Contact Us",
|
||||
description: "Ancor text for contacting us by email"
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("a", {
|
||||
href: _config_js__WEBPACK_IMPORTED_MODULE_3__.LINK_TERMS_OF_SERVICE,
|
||||
className: "flat-button",
|
||||
target: "_blank",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("i", {
|
||||
className: "material-icons",
|
||||
children: "description"
|
||||
}, void 0, false), " \xA0", (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
}, void 0, false)
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(FlatLink, {
|
||||
href: _config_js__WEBPACK_IMPORTED_MODULE_2__.LINK_TERMS_OF_SERVICE,
|
||||
icon: "description",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
id: "link_terms_of_service",
|
||||
defaultMessage: "Terms of Service",
|
||||
description: "Ancor text for terms of service link"
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("a", {
|
||||
href: _config_js__WEBPACK_IMPORTED_MODULE_3__.LINK_PRIVACY_POLICY,
|
||||
className: "flat-button",
|
||||
target: "_blank",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("i", {
|
||||
className: "material-icons",
|
||||
children: "policy"
|
||||
}, void 0, false), " \xA0", (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
}, void 0, false)
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(FlatLink, {
|
||||
href: _config_js__WEBPACK_IMPORTED_MODULE_2__.LINK_PRIVACY_POLICY,
|
||||
icon: "policy",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
id: "link_privacy_policy",
|
||||
defaultMessage: "Privacy Policy",
|
||||
description: "Ancor text for privacy policy link"
|
||||
}, void 0, false)]
|
||||
}, void 0, true)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
}, void 0, false)
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("div", {
|
||||
className: "hr"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("div", {
|
||||
className: "panel-form-column",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("div", {
|
||||
className: "panel-form-row",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("label", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("label", {
|
||||
className: "small",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
id: "label_client",
|
||||
defaultMessage: "Client:",
|
||||
description: "Label for a client version"
|
||||
}, void 0, false)
|
||||
}, void 0, false), _config_js__WEBPACK_IMPORTED_MODULE_3__.APP_NAME]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
}, void 0, false), _config_js__WEBPACK_IMPORTED_MODULE_2__.APP_NAME]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("div", {
|
||||
className: "panel-form-row",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("label", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("label", {
|
||||
className: "small",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
id: "label_sdk",
|
||||
defaultMessage: "SDK:"
|
||||
}, void 0, false)
|
||||
}, void 0, false), tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.Tinode.getLibrary()]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
className: "panel-form-row",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("label", {
|
||||
className: "small",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
id: "label_server",
|
||||
defaultMessage: "Server:",
|
||||
description: "Label for a server version"
|
||||
}, void 0, false)
|
||||
}, void 0, false), this.props.serverVersion]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("div", {
|
||||
className: "panel-form-row",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("label", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("label", {
|
||||
className: "small",
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
||||
id: "label_server_address",
|
||||
defaultMessage: "Server address:"
|
||||
}, void 0, false)
|
||||
@@ -5965,13 +5963,14 @@ function EnterpriseRegister() {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("ol", {
|
||||
className: "auth-steps",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("li", {
|
||||
className: submitted ? '' : 'active',
|
||||
className: "active",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("span", {
|
||||
children: "1"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("b", {
|
||||
children: "填写企业信息"
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("li", {
|
||||
className: submitted ? 'active' : '',
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("span", {
|
||||
children: "2"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("b", {
|
||||
@@ -6356,7 +6355,9 @@ function Register({
|
||||
invite: e.target.value.replace(/[^A-Za-z]/g, '').slice(0, 5)
|
||||
}),
|
||||
placeholder: "请输入邀请码(非必填)",
|
||||
error: errors.invite
|
||||
error: errors.invite,
|
||||
autoCapitalize: "off",
|
||||
autoCorrect: "off"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_3__.jsxDEV)("button", {
|
||||
className: "auth-primary",
|
||||
type: "submit",
|
||||
@@ -7664,7 +7665,7 @@ function AddressBook({
|
||||
}).catch(() => {}).finally(() => setLoading(false));
|
||||
(0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_4__.fetchAllPages)(cursor => (0,_lib_im_api_js__WEBPACK_IMPORTED_MODULE_4__.getFriendRequests)('inbound', 'pending', cursor)).then(list => setPendingCount(list.length)).catch(() => {});
|
||||
}, []);
|
||||
const visible = friends.filter(item => `${item.display_name}${item.remark || ''}`.includes(query));
|
||||
const visible = friends.filter(item => `${item.display_name}${item.remark || ''}`.toLowerCase().includes(query.toLowerCase()));
|
||||
const groups = visible.reduce((result, item) => {
|
||||
const key = alphaInitial(item.remark || item.display_name);
|
||||
return {
|
||||
@@ -8486,7 +8487,7 @@ function Settings({
|
||||
className: "people-remark-edit",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("input", {
|
||||
value: remarkDraft,
|
||||
maxLength: "20",
|
||||
maxLength: "64",
|
||||
onChange: e => setRemarkDraft(e.target.value),
|
||||
autoFocus: true
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||
@@ -9040,10 +9041,18 @@ const FILE_TYPE_META = {
|
||||
document: ['description', '#e05d44'],
|
||||
file: ['insert_drive_file', '#8a8f98']
|
||||
};
|
||||
const DOCUMENT_EXT = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'];
|
||||
function extFromName(name) {
|
||||
const m = /\.([a-zA-Z0-9]+)$/.exec(name || '');
|
||||
return m ? m[1].toUpperCase() : '';
|
||||
}
|
||||
function fileTypeFromMime(mime, name) {
|
||||
const prefix = (mime || '').split('/')[0];
|
||||
if (prefix === 'image' || prefix === 'video' || prefix === 'audio') return prefix;
|
||||
const ext = extFromName(name).toLowerCase();
|
||||
if (mime === 'application/pdf' || DOCUMENT_EXT.includes(ext)) return 'document';
|
||||
return 'file';
|
||||
}
|
||||
function FileCard({
|
||||
name,
|
||||
size,
|
||||
@@ -9053,11 +9062,15 @@ function FileCard({
|
||||
onOpen
|
||||
}) {
|
||||
const ext = extFromName(name);
|
||||
const [, color] = FILE_TYPE_META[fileTypeFromMime(mime, name)];
|
||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
className: 'library-file-card' + (removed ? ' removed' : ''),
|
||||
onClick: removed ? undefined : onOpen,
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)("span", {
|
||||
style: {
|
||||
backgroundColor: color
|
||||
},
|
||||
children: ext || (mime || '').split('/')[0].toUpperCase() || '?'
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)("div", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)("strong", {
|
||||
@@ -9206,6 +9219,7 @@ function FavoriteItem({
|
||||
}, void 0, false) : null, item.type === 'image' || item.type === 'video' ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)(MediaThumb, {
|
||||
url: item._thumbUrl,
|
||||
video: item.type === 'video',
|
||||
duration: att && att.duration,
|
||||
onOpen: onOpen,
|
||||
removed: item.availability === 'removed'
|
||||
}, void 0, false) : null, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_8__.jsxDEV)("footer", {
|
||||
@@ -11688,9 +11702,10 @@ function GroupProfile({
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Icon, {
|
||||
children: "chevron_right"
|
||||
}, void 0, false)]
|
||||
}, void 0, true), canEdit ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('group-nickname', topic),
|
||||
disabled: !canEdit,
|
||||
onClick: () => canEdit && navigate('group-nickname', topic),
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("span", {
|
||||
children: "群名称"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("small", {
|
||||
@@ -11698,15 +11713,10 @@ function GroupProfile({
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Icon, {
|
||||
children: "chevron_right"
|
||||
}, void 0, false)]
|
||||
}, void 0, true) : (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("span", {
|
||||
children: "群名称"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("small", {
|
||||
children: group.name
|
||||
}, void 0, false)]
|
||||
}, void 0, true), canEdit ? (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
onClick: () => navigate('group-description', topic),
|
||||
disabled: !canEdit,
|
||||
onClick: () => canEdit && navigate('group-description', topic),
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("span", {
|
||||
children: "群简介"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("small", {
|
||||
@@ -11714,12 +11724,6 @@ function GroupProfile({
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Icon, {
|
||||
children: "chevron_right"
|
||||
}, void 0, false)]
|
||||
}, void 0, true) : (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("span", {
|
||||
children: "群简介"
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("small", {
|
||||
children: group.description || '群主很懒,还没有群简介'
|
||||
}, void 0, false)]
|
||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
className: "group-profile-qr",
|
||||
@@ -11895,6 +11899,7 @@ function GroupQr({
|
||||
const GOVERNANCE_FIELDS = [['join_approval', '进群验证', '开启后,他人申请加入群聊需群主或管理员同意'], ['mute_all', '全体禁言', '开启后,仅群主和管理员可以发言'], ['member_upload_files', '群成员文件上传', '关闭后,普通成员将无法上传群文件'], ['member_invite', '群成员邀请', '关闭后,仅群主和管理员可以邀请新成员进群'], ['member_private_chat', '群成员私信权限', '关闭后,不允许发送名片消息,且普通成员在群聊界面、群组信息内点击头像无反应。']];
|
||||
function Governance({
|
||||
topic,
|
||||
myRole,
|
||||
tinode,
|
||||
onToast
|
||||
}) {
|
||||
@@ -11922,6 +11927,7 @@ function Governance({
|
||||
}).catch(err => onToast(err.message || '设置失败'));
|
||||
};
|
||||
const dissolve = () => {
|
||||
if (myRole !== 'owner') return;
|
||||
if (!window.confirm('解散后群聊将无法恢复,确定要解散该群聊吗?')) return;
|
||||
const t = tinode ? tinode.getTopic(topic) : null;
|
||||
if (!t) return;
|
||||
@@ -12014,7 +12020,7 @@ function Governance({
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("button", {
|
||||
type: "button",
|
||||
className: "group-danger",
|
||||
disabled: dissolving,
|
||||
disabled: dissolving || myRole !== 'owner',
|
||||
onClick: dissolve,
|
||||
children: "解散群组"
|
||||
}, void 0, false)]
|
||||
@@ -12147,7 +12153,7 @@ function GroupMembers({
|
||||
setLoadError(true);
|
||||
});
|
||||
}, [topic]);
|
||||
const visible = (members || []).filter(m => (m.group_nickname || m.display_name || '').includes(query));
|
||||
const visible = (members || []).filter(m => (m.group_nickname || m.display_name || '').toLowerCase().includes(query.toLowerCase()));
|
||||
const groups = groupBy(visible, m => alphaInitial(m.group_nickname || m.display_name));
|
||||
const roleLabel = role => role === 'owner' ? '群主' : role === 'admin' ? '管理员' : '';
|
||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)("div", {
|
||||
@@ -12214,7 +12220,7 @@ function MemberPicker({
|
||||
setLoadError(true);
|
||||
});
|
||||
}, [topic, mute]);
|
||||
const visible = (members || []).filter(m => (m.group_nickname || m.display_name || '').includes(query));
|
||||
const visible = (members || []).filter(m => (m.group_nickname || m.display_name || '').toLowerCase().includes(query.toLowerCase()));
|
||||
const groups = groupBy(visible, m => alphaInitial(m.group_nickname || m.display_name));
|
||||
const toggle = id => setSelected(v => v.includes(id) ? v.filter(x => x != id) : v.concat(id));
|
||||
const done = () => {
|
||||
@@ -12380,7 +12386,7 @@ function OwnerSelect({
|
||||
setLoadError(true);
|
||||
});
|
||||
}, [topic]);
|
||||
const visible = (members || []).filter(m => (m.group_nickname || m.display_name || '').includes(query));
|
||||
const visible = (members || []).filter(m => (m.group_nickname || m.display_name || '').toLowerCase().includes(query.toLowerCase()));
|
||||
const admins = visible.filter(m => m.role === 'admin');
|
||||
const others = visible.filter(m => m.role !== 'admin');
|
||||
const reset = () => {
|
||||
@@ -12896,6 +12902,7 @@ function GroupManagementView({
|
||||
onToast: setToast
|
||||
}, void 0, false);else if (view === 'group-governance') content = (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(Governance, {
|
||||
topic: topic,
|
||||
myRole: myRole,
|
||||
tinode: tinode,
|
||||
onToast: setToast
|
||||
}, void 0, false);else if (['group-admins', 'group-admin-success', 'group-admin-partial', 'group-admin-removed'].includes(view)) content = (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxDEV)(AdminList, {
|
||||
@@ -13643,6 +13650,8 @@ function MessageActions() {
|
||||
}, void 0, true);
|
||||
}
|
||||
const NOTIFICATION_TEXT = {
|
||||
'group.created': '你创建了一个新群聊',
|
||||
'group.join_request.created': '有人申请加入你管理的群聊',
|
||||
'group.member.joined': '有成员加入了群聊',
|
||||
'group.member.left': '有成员退出了群聊',
|
||||
'group.member.updated': '群成员资料有更新',
|
||||
@@ -15835,9 +15844,7 @@ function AppVersion({
|
||||
onClick: () => onToast('隐私协议')
|
||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)(MenuRow, {
|
||||
title: "联系我们",
|
||||
onClick: () => {
|
||||
window.location.href = _config_js__WEBPACK_IMPORTED_MODULE_4__.LINK_CONTACT_US;
|
||||
}
|
||||
onClick: () => onToast('联系我们')
|
||||
}, void 0, false)]
|
||||
}, void 0, true)]
|
||||
}, void 0, true)]
|
||||
@@ -22698,6 +22705,10 @@ class AudioPlayer extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
|
||||
playing: false
|
||||
});
|
||||
} else if (this.audioPlayer.readyState >= 2) {
|
||||
if (activeAudioPlayer && activeAudioPlayer !== this) {
|
||||
activeAudioPlayer.pauseForOtherPlayer();
|
||||
}
|
||||
activeAudioPlayer = this;
|
||||
this.audioPlayer.play();
|
||||
this.setState({
|
||||
playing: true
|
||||
@@ -22745,6 +22756,7 @@ class AudioPlayer extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComp
|
||||
}, void 0, false), play]
|
||||
}, void 0, true) : (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.Fragment, {
|
||||
children: [play, (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
||||
className: "playback-row",
|
||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("canvas", {
|
||||
className: "playback",
|
||||
ref: this.canvasRef,
|
||||
|
||||
Reference in New Issue
Block a user