From b2c42f5f23e6bf3af0e6eef175cb1a8edcedc75b Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sun, 19 Sep 2021 22:13:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=9A=E8=AF=9D=E9=9D=A2=E6=9D=BF?= =?UTF-8?q?=E6=8A=AC=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/i18n/langs/en-US/translation.json | 3 + shared/i18n/langs/zh-CN/translation.json | 3 + shared/index.tsx | 1 + shared/utils/__tests__/array-helper.spec.ts | 14 +++++ shared/utils/array-helper.ts | 17 ++++++ .../Panel/personal/ConversePanel.tsx | 60 +++++++++++++++++++ .../Main/Content/Personal/Converse/index.tsx | 12 ++-- .../routes/Main/Content/Personal/index.tsx | 4 +- 8 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 shared/utils/__tests__/array-helper.spec.ts create mode 100644 shared/utils/array-helper.ts create mode 100644 web/src/components/Panel/personal/ConversePanel.tsx diff --git a/shared/i18n/langs/en-US/translation.json b/shared/i18n/langs/en-US/translation.json index 2f5c0ff0..31164e89 100644 --- a/shared/i18n/langs/en-US/translation.json +++ b/shared/i18n/langs/en-US/translation.json @@ -22,6 +22,7 @@ "k35abe359": "Lobby", "k35f486ba": "Nickname", "k35f990b0": "View Detail", + "k36722a78": "Conversation with <1>", "k3b4b656d": "About", "k3bbf3bbd": "Register Account", "k3c502edb": "E-mail can not be empty", @@ -64,6 +65,7 @@ "k7fc7e508": "Dark Mode", "k821ff85a": "Common", "k8582af3f": "Refuse", + "k8849b674": "Multiplayer conversations with <1> and <4>", "k89df1d1e": "The network is abnormal", "k8abdba5c": "Has been sent", "k8acbe00": "Current service available", @@ -120,6 +122,7 @@ "kdd6c18f8": "Service exception", "ke17b2c87": "Do not upload pictures that violate local laws and regulations", "ke187440d": "Panel type cannot be empty", + "kea50b8e9": "Multi-person conversation with <1>{{membersEl}} and others", "kecbd7449": "Delete", "ked2baf28": "Loading...", "ked5385d5": "Create Panel", diff --git a/shared/i18n/langs/zh-CN/translation.json b/shared/i18n/langs/zh-CN/translation.json index f3b9a3c4..27d68ea9 100644 --- a/shared/i18n/langs/zh-CN/translation.json +++ b/shared/i18n/langs/zh-CN/translation.json @@ -22,6 +22,7 @@ "k35abe359": "大厅", "k35f486ba": "用户昵称", "k35f990b0": "查看详情", + "k36722a78": "与 <1> 的会话", "k3b4b656d": "关于", "k3bbf3bbd": "注册账号", "k3c502edb": "邮箱不能为空", @@ -64,6 +65,7 @@ "k7fc7e508": "暗黑模式", "k821ff85a": "通用", "k8582af3f": "拒绝", + "k8849b674": "与 <1> 和 <4> 的多人会话", "k89df1d1e": "网络出现异常", "k8abdba5c": "已发送", "k8acbe00": "当前服务可用", @@ -120,6 +122,7 @@ "kdd6c18f8": "服务异常", "ke17b2c87": "请勿上传违反当地法律法规的图片", "ke187440d": "面板类型不能为空", + "kea50b8e9": "与 <1>{{membersEl}} 等人的多人会话", "kecbd7449": "删除", "ked2baf28": "加载中...", "ked5385d5": "创建面板", diff --git a/shared/index.tsx b/shared/index.tsx index 4f581d9f..1fc1f3e1 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -122,6 +122,7 @@ export { createStore } from './redux/store'; export type { AppStore, AppState, AppDispatch } from './redux/store'; // utils +export { joinArray } from './utils/array-helper'; export { shouldShowMessageTime, getMessageTimeDiff, diff --git a/shared/utils/__tests__/array-helper.spec.ts b/shared/utils/__tests__/array-helper.spec.ts new file mode 100644 index 00000000..fc4495c8 --- /dev/null +++ b/shared/utils/__tests__/array-helper.spec.ts @@ -0,0 +1,14 @@ +import { joinArray } from '../array-helper'; + +describe('array-helper', () => { + test('joinArray', () => { + expect(joinArray([1, 2, 3], '5')).toMatchObject([1, '5', 2, '5', 3]); + expect(joinArray([{ a: 1 }, { a: 2 }, { a: 3 }], '5')).toMatchObject([ + { a: 1 }, + '5', + { a: 2 }, + '5', + { a: 3 }, + ]); + }); +}); diff --git a/shared/utils/array-helper.ts b/shared/utils/array-helper.ts new file mode 100644 index 00000000..3c784b2a --- /dev/null +++ b/shared/utils/array-helper.ts @@ -0,0 +1,17 @@ +import _flatten from 'lodash/flatten'; + +/** + * 类似于join,但是返回一个数组 + * join会将元素强制转化为字符串 + */ +export function joinArray(arr: T[], separator: K): (T | K)[] { + return _flatten( + arr.map((item, i) => { + if (i === 0) { + return [item]; + } else { + return [separator, item]; + } + }) + ); +} diff --git a/web/src/components/Panel/personal/ConversePanel.tsx b/web/src/components/Panel/personal/ConversePanel.tsx new file mode 100644 index 00000000..a4543d34 --- /dev/null +++ b/web/src/components/Panel/personal/ConversePanel.tsx @@ -0,0 +1,60 @@ +import { ChatBox } from '@/components/ChatBox'; +import React from 'react'; +import { joinArray, Trans, useAppSelector, useUserId } from 'tailchat-shared'; +import { PanelCommonHeader } from '../common/Header'; +import _without from 'lodash/without'; +import _take from 'lodash/take'; +import { UserName } from '@/components/UserName'; + +function useConverseTitle(converseId: string): React.ReactNode { + const members = useAppSelector( + (state) => state.chat.converses[converseId]?.members ?? [] + ); + const userId = useUserId(); + const otherMembers = _without(members, userId ?? ''); + const len = otherMembers.length; + + if (len === 1) { + return ( + + 与 的会话 + + ); + } else if (len === 2) { + return ( + + 与 和{' '} + 的多人会话 + + ); + } else { + const membersEl = joinArray( + _take(otherMembers, 2).map((uid) => ), + + ); + return ( + + 与 {{ membersEl }} 等人的多人会话 + + ); + } +} + +interface ConversePanelProps { + converseId: string; +} +export const ConversePanel: React.FC = React.memo( + ({ converseId }) => { + const title = useConverseTitle(converseId); + + return ( +
+ {title} +
+ +
+
+ ); + } +); +ConversePanel.displayName = 'ConversePanel'; diff --git a/web/src/routes/Main/Content/Personal/Converse/index.tsx b/web/src/routes/Main/Content/Personal/Converse/index.tsx index 77ca2c4d..93da617c 100644 --- a/web/src/routes/Main/Content/Personal/Converse/index.tsx +++ b/web/src/routes/Main/Content/Personal/Converse/index.tsx @@ -1,4 +1,4 @@ -import { ChatBox } from '@/components/ChatBox'; +import { ConversePanel } from '@/components/Panel/personal/ConversePanel'; import React from 'react'; import { useParams } from 'react-router'; @@ -6,13 +6,9 @@ interface UserConversePanelParams { converseId: string; } -export const ConversePanel: React.FC = React.memo(() => { +export const PersonalConverse: React.FC = React.memo(() => { const params = useParams(); - return ( -
- -
- ); + return ; }); -ConversePanel.displayName = 'ConversePanel'; +PersonalConverse.displayName = 'PersonalConverse'; diff --git a/web/src/routes/Main/Content/Personal/index.tsx b/web/src/routes/Main/Content/Personal/index.tsx index 6bbb8cc0..7f90b26b 100644 --- a/web/src/routes/Main/Content/Personal/index.tsx +++ b/web/src/routes/Main/Content/Personal/index.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Redirect, Route, Switch } from 'react-router-dom'; import { PageContent } from '../PageContent'; -import { ConversePanel } from './Converse'; +import { PersonalConverse } from './Converse'; import { FriendPanel } from './Friends'; import { PluginsPanel } from './Plugins'; import { PersonalSidebar } from './Sidebar'; @@ -16,7 +16,7 @@ export const Personal: React.FC = React.memo(() => {