修复用户实测反馈的4处问题:品牌名泄露、修改密码页注释泄露、安全提醒页未居中、群相关行间距
- 品牌名:BASE_APP_NAME 从 "TinodeWeb" 改为 "MeetingIM"(关于页/青少年模式文案不再暴露 Tinode 字样);
logo-view.jsx(未选中会话时的空状态)去掉开源模板遗留的 Tinode 主页/GitHub 链接/原始版本号,
换成品牌图标+"选择一个会话开始聊天"
- personal-settings-view.jsx:删除 ChangePassword 页面里被误当正文渲染的开发注释(提及 Tinode 协议),
改回真正的代码注释
- base.css:.risk-info-page(安全提醒整页)补 margin:0 auto——原来复用模态弹窗的 .risk-dialog 样式,
宽屏下整块内容贴左显示,没有居中
- base.css:.group-member-picker/.group-settings-header/.group-member-section-title 的 strong/small
漏加入既有的 line-height:1.3 覆盖名单,继承通用 button{line-height:2.2rem},导致群成员列表/群聊设置
头部的姓名与角色/简介文字行间距异常大、贴底部分割线过近
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
bede45fd7f
commit
f2218a822e
+42
-12
@@ -3955,12 +3955,29 @@ img.channel {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: var(--clr-cyan-50);
|
background-color: var(--clr-cyan-50);
|
||||||
}
|
|
||||||
#dummy-view a {
|
|
||||||
text-decoration: none;
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
#dummy-view-icon {
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
width: 6.5rem;
|
||||||
|
height: 6.5rem;
|
||||||
|
margin: 0 auto 0.8rem;
|
||||||
|
border-radius: 1.2rem;
|
||||||
|
color: #fff;
|
||||||
|
background: #2878d6;
|
||||||
|
}
|
||||||
|
#dummy-view-icon .material-icons {
|
||||||
|
font-size: 4.2rem;
|
||||||
|
}
|
||||||
|
#dummy-view h2 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
#dummy-view p {
|
||||||
|
margin: 0.25rem 0 0;
|
||||||
|
color: #777f89;
|
||||||
|
}
|
||||||
|
|
||||||
#image-preview {
|
#image-preview {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -9164,7 +9181,8 @@ div.toast.show {
|
|||||||
.group-list strong,
|
.group-list strong,
|
||||||
.group-request-list strong,
|
.group-request-list strong,
|
||||||
.group-admin-page strong,
|
.group-admin-page strong,
|
||||||
.group-muted-list strong {
|
.group-muted-list strong,
|
||||||
|
.group-member-picker strong {
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9176,7 +9194,8 @@ div.toast.show {
|
|||||||
.group-list small,
|
.group-list small,
|
||||||
.group-request-list small,
|
.group-request-list small,
|
||||||
.group-admin-page small,
|
.group-admin-page small,
|
||||||
.group-muted-list small {
|
.group-muted-list small,
|
||||||
|
.group-member-picker small {
|
||||||
margin-top: 0.2rem;
|
margin-top: 0.2rem;
|
||||||
color: #9299a2;
|
color: #9299a2;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
@@ -9882,7 +9901,11 @@ div.toast.show {
|
|||||||
自己的 place-items:center 就只剩交叉轴(水平)生效,主轴(垂直)退回 flex-start,
|
自己的 place-items:center 就只剩交叉轴(水平)生效,主轴(垂直)退回 flex-start,
|
||||||
里面的图标会贴着方块顶部而不是居中。 */
|
里面的图标会贴着方块顶部而不是居中。 */
|
||||||
.group-settings-header > span:not(.group-avatar) { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
|
.group-settings-header > span:not(.group-avatar) { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
|
||||||
.group-settings-header small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #9299a2; }
|
/* Same generic `button { line-height: 2.2rem }` leak as .group-member-picker's rows (see its
|
||||||
|
comment) -- name and description each sat in a ~29px box instead of hugging their own text,
|
||||||
|
reading as far more gap between the two lines than the .15rem `gap` above actually specifies. */
|
||||||
|
.group-settings-header strong { line-height: 1.3; }
|
||||||
|
.group-settings-header small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #9299a2; line-height: 1.3; }
|
||||||
|
|
||||||
.group-list > button {
|
.group-list > button {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -10223,11 +10246,13 @@ div.toast.show {
|
|||||||
.group-member-section-title > strong {
|
.group-member-section-title > strong {
|
||||||
color: #30353c;
|
color: #30353c;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-member-section-title > small {
|
.group-member-section-title > small {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
color: #949ba4;
|
color: #949ba4;
|
||||||
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-settings section > .group-member-grid {
|
.group-settings section > .group-member-grid {
|
||||||
@@ -10540,11 +10565,6 @@ div.toast.show {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-member-picker small {
|
|
||||||
margin-top: 0.2rem;
|
|
||||||
color: #9299a2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-check {
|
.group-check {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
@@ -13808,6 +13828,16 @@ div.toast.show {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* .risk-dialog was designed as a modal card, centered by .risk-overlay's place-items:center wrapper
|
||||||
|
(RiskConfirmDialog). FraudAwareness reuses the same class directly as .support-page's <main> (no
|
||||||
|
overlay wrapper, no explicit height on the page unlike a modal) to pick up its ul/li/aside/button
|
||||||
|
styling -- but .support-page is a plain flex column with no centering of its own, so the capped
|
||||||
|
width left the whole page pinned to the left edge on anything wider than ~25rem instead of centered
|
||||||
|
like every other support-page/group-page/people-page in the app. */
|
||||||
|
.risk-info-page {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
.risk-symbol {
|
.risk-symbol {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+3
-2
@@ -1,7 +1,8 @@
|
|||||||
import { PACKAGE_VERSION } from './version.js';
|
import { PACKAGE_VERSION } from './version.js';
|
||||||
|
|
||||||
// Version-independent name of this application, used for Firebase app name.
|
// Version-independent name of this application, used for Firebase app name and shown to users
|
||||||
export const BASE_APP_NAME = 'TinodeWeb';
|
// (about page, youth-mode copy).
|
||||||
|
export const BASE_APP_NAME = 'MeetingIM';
|
||||||
// Name of this application, used in the User-Agent.
|
// Name of this application, used in the User-Agent.
|
||||||
export const APP_NAME = BASE_APP_NAME + '/' + (PACKAGE_VERSION || '0.25');
|
export const APP_NAME = BASE_APP_NAME + '/' + (PACKAGE_VERSION || '0.25');
|
||||||
|
|
||||||
|
|||||||
+6
-13
@@ -1,25 +1,18 @@
|
|||||||
/* This is just a static page to display when no conversation is selected. */
|
/* Static placeholder shown in the message pane when no conversation is selected. */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
import { Tinode } from 'tinode-sdk';
|
import { BASE_APP_NAME } from '../config.js';
|
||||||
|
|
||||||
import { APP_NAME } from '../config.js';
|
function Icon({children}) { return <i className="material-icons" aria-hidden="true">{children}</i>; }
|
||||||
|
|
||||||
export default class LogoView extends React.PureComponent {
|
export default class LogoView extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const version = APP_NAME + ' (' + Tinode.getLibrary() + ')';
|
|
||||||
return (
|
return (
|
||||||
<div id="dummy-view">
|
<div id="dummy-view">
|
||||||
<div>
|
<div>
|
||||||
<a href="https://github.com/tinode/chat/">
|
<span id="dummy-view-icon"><Icon>forum</Icon></span>
|
||||||
<img id="logo" alt="logo" src="img/logo.svg" />
|
<h2>{BASE_APP_NAME}</h2>
|
||||||
<h2>Tinode Web</h2>
|
<p>选择一个会话开始聊天</p>
|
||||||
</a>
|
|
||||||
<p><FormattedMessage id="label_client" defaultMessage="Client:"
|
|
||||||
description="Label for a client version" /> {version}</p>
|
|
||||||
<p><FormattedMessage id="label_server" defaultMessage="Server:"
|
|
||||||
description="Label for a server version" /> {this.props.serverVersion} ({this.props.serverAddress})</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2127,9 +2127,7 @@ class MessagesView extends React.Component {
|
|||||||
|
|
||||||
let component;
|
let component;
|
||||||
if (!this.state.topic) {
|
if (!this.state.topic) {
|
||||||
component = <LogoView
|
component = <LogoView />;
|
||||||
serverVersion={this.props.serverVersion}
|
|
||||||
serverAddress={this.props.serverAddress} />;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
let component2;
|
let component2;
|
||||||
|
|||||||
@@ -395,6 +395,8 @@ function ClearHistoryConfirm({tinode, chatList, onToast}) {
|
|||||||
// (Tinode.updateAccountBasic), already wired end-to-end via tinode-web.jsx's
|
// (Tinode.updateAccountBasic), already wired end-to-end via tinode-web.jsx's
|
||||||
// handleUpdatePasswordRequest/onUpdatePassword prop (used today by the old acc-security-view.jsx).
|
// handleUpdatePasswordRequest/onUpdatePassword prop (used today by the old acc-security-view.jsx).
|
||||||
// Reusing that verified callback here instead of reimplementing the WS call.
|
// Reusing that verified callback here instead of reimplementing the WS call.
|
||||||
|
// The server-side account-update call never checks the caller's current password -- "原密码" below
|
||||||
|
// is a frontend-only speed bump against fat-fingering this field, not a real credential check.
|
||||||
function ChangePassword({onUpdatePassword, onToast}) {
|
function ChangePassword({onUpdatePassword, onToast}) {
|
||||||
const [oldPwd, setOldPwd] = React.useState('');
|
const [oldPwd, setOldPwd] = React.useState('');
|
||||||
const [newPwd, setNewPwd] = React.useState('');
|
const [newPwd, setNewPwd] = React.useState('');
|
||||||
@@ -421,7 +423,6 @@ function ChangePassword({onUpdatePassword, onToast}) {
|
|||||||
<label><span>原密码</span><input type="password" value={oldPwd} onChange={e => setOldPwd(e.target.value)} placeholder="请输入当前密码" /></label>
|
<label><span>原密码</span><input type="password" value={oldPwd} onChange={e => setOldPwd(e.target.value)} placeholder="请输入当前密码" /></label>
|
||||||
<label><span>新密码</span><input type="password" value={newPwd} onChange={e => setNewPwd(e.target.value)} placeholder="至少6位" /></label>
|
<label><span>新密码</span><input type="password" value={newPwd} onChange={e => setNewPwd(e.target.value)} placeholder="至少6位" /></label>
|
||||||
<label><span>确认新密码</span><input type="password" value={confirmPwd} onChange={e => setConfirmPwd(e.target.value)} placeholder="再次输入新密码" /></label>
|
<label><span>确认新密码</span><input type="password" value={confirmPwd} onChange={e => setConfirmPwd(e.target.value)} placeholder="再次输入新密码" /></label>
|
||||||
<p>Tinode 协议本身不会在服务端校验"原密码",这里的原密码输入是前端自己加的一道二次确认,防止误触。</p>
|
|
||||||
</main></div>;
|
</main></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -2358,7 +2358,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
/* harmony import */ var _version_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./version.js */ "./src/version.js");
|
/* harmony import */ var _version_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./version.js */ "./src/version.js");
|
||||||
|
|
||||||
const BASE_APP_NAME = 'TinodeWeb';
|
const BASE_APP_NAME = 'MeetingIM';
|
||||||
const APP_NAME = BASE_APP_NAME + '/' + (_version_js__WEBPACK_IMPORTED_MODULE_0__.PACKAGE_VERSION || '0.25');
|
const APP_NAME = BASE_APP_NAME + '/' + (_version_js__WEBPACK_IMPORTED_MODULE_0__.PACKAGE_VERSION || '0.25');
|
||||||
const API_KEY = "AQAAAAABAAAoeOI7tA3HsYvdzDhYhZJy" || 0;
|
const API_KEY = "AQAAAAABAAAoeOI7tA3HsYvdzDhYhZJy" || 0;
|
||||||
const KNOWN_HOSTS = {
|
const KNOWN_HOSTS = {
|
||||||
@@ -15741,9 +15741,7 @@ function ChangePassword({
|
|||||||
onChange: e => setConfirmPwd(e.target.value),
|
onChange: e => setConfirmPwd(e.target.value),
|
||||||
placeholder: "再次输入新密码"
|
placeholder: "再次输入新密码"
|
||||||
}, void 0, false)]
|
}, void 0, false)]
|
||||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_7__.jsxDEV)("p", {
|
}, void 0, true)]
|
||||||
children: "Tinode 协议本身不会在服务端校验\"原密码\",这里的原密码输入是前端自己加的一道二次确认,防止误触。"
|
|
||||||
}, void 0, false)]
|
|
||||||
}, void 0, true)]
|
}, void 0, true)]
|
||||||
}, void 0, true);
|
}, void 0, true);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -13,45 +13,35 @@ __webpack_require__.r(__webpack_exports__);
|
|||||||
/* harmony export */ });
|
/* harmony export */ });
|
||||||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "react");
|
||||||
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
/* 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 _config_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../config.js */ "./src/config.js");
|
||||||
/* harmony import */ var react_intl__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_intl__WEBPACK_IMPORTED_MODULE_1__);
|
/* harmony import */ var react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react/jsx-dev-runtime */ "./node_modules/react/jsx-dev-runtime.js");
|
||||||
/* 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");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Icon({
|
||||||
|
children
|
||||||
|
}) {
|
||||||
|
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxDEV)("i", {
|
||||||
|
className: "material-icons",
|
||||||
|
"aria-hidden": "true",
|
||||||
|
children: children
|
||||||
|
}, void 0, false);
|
||||||
|
}
|
||||||
class LogoView extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) {
|
class LogoView extends (react__WEBPACK_IMPORTED_MODULE_0___default().PureComponent) {
|
||||||
render() {
|
render() {
|
||||||
const version = _config_js__WEBPACK_IMPORTED_MODULE_3__.APP_NAME + ' (' + tinode_sdk__WEBPACK_IMPORTED_MODULE_2__.Tinode.getLibrary() + ')';
|
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxDEV)("div", {
|
||||||
return (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
|
||||||
id: "dummy-view",
|
id: "dummy-view",
|
||||||
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("div", {
|
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxDEV)("div", {
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("a", {
|
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxDEV)("span", {
|
||||||
href: "https://github.com/tinode/chat/",
|
id: "dummy-view-icon",
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("img", {
|
children: (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxDEV)(Icon, {
|
||||||
id: "logo",
|
children: "forum"
|
||||||
alt: "logo",
|
}, void 0, false)
|
||||||
src: "img/logo.svg"
|
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxDEV)("h2", {
|
||||||
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("h2", {
|
children: _config_js__WEBPACK_IMPORTED_MODULE_1__.BASE_APP_NAME
|
||||||
children: "Tinode Web"
|
}, void 0, false), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxDEV)("p", {
|
||||||
|
children: "选择一个会话开始聊天"
|
||||||
}, void 0, false)]
|
}, void 0, false)]
|
||||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("p", {
|
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
|
||||||
id: "label_client",
|
|
||||||
defaultMessage: "Client:",
|
|
||||||
description: "Label for a client version"
|
|
||||||
}, void 0, false), " ", version]
|
|
||||||
}, void 0, true), (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)("p", {
|
|
||||||
children: [(0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxDEV)(react_intl__WEBPACK_IMPORTED_MODULE_1__.FormattedMessage, {
|
|
||||||
id: "label_server",
|
|
||||||
defaultMessage: "Server:",
|
|
||||||
description: "Label for a server version"
|
|
||||||
}, void 0, false), " ", this.props.serverVersion, " (", this.props.serverAddress, ")"]
|
|
||||||
}, void 0, true)]
|
|
||||||
}, void 0, true)
|
}, void 0, true)
|
||||||
}, void 0, false);
|
}, void 0, false);
|
||||||
}
|
}
|
||||||
@@ -1841,10 +1831,7 @@ class MessagesView extends (react__WEBPACK_IMPORTED_MODULE_0___default().Compone
|
|||||||
}, void 0, false);
|
}, void 0, false);
|
||||||
let component;
|
let component;
|
||||||
if (!this.state.topic) {
|
if (!this.state.topic) {
|
||||||
component = (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_22__.jsxDEV)(_logo_view_jsx__WEBPACK_IMPORTED_MODULE_10__["default"], {
|
component = (0,react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_22__.jsxDEV)(_logo_view_jsx__WEBPACK_IMPORTED_MODULE_10__["default"], {}, void 0, false);
|
||||||
serverVersion: this.props.serverVersion,
|
|
||||||
serverAddress: this.props.serverAddress
|
|
||||||
}, void 0, false);
|
|
||||||
} else {
|
} else {
|
||||||
let component2;
|
let component2;
|
||||||
if (this.state.imagePreview) {
|
if (this.state.imagePreview) {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user