diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..55712c1
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "typescript.tsdk": "node_modules/typescript/lib"
+}
\ No newline at end of file
diff --git a/bin/register.ts b/bin/register.ts
index bdd9ea7..6f7d2ea 100644
--- a/bin/register.ts
+++ b/bin/register.ts
@@ -4,9 +4,8 @@
*/
import bcrypt from 'bcryptjs';
-import { promisify } from 'util';
-import User from '../server/models/user';
+import User, { UserDocument } from '../server/models/user';
import Group from '../server/models/group';
import options from '../utils/commandOptions';
@@ -37,10 +36,11 @@ connectDB()
const defaultGroup = await Group.findOne({ isDefault: true });
if (!defaultGroup) {
exitWithError('默认群组不存在');
+ return;
}
- const salt = await promisify(bcrypt.genSalt)(saltRounds);
- const hash = await promisify(bcrypt.hash)(password, salt);
+ const salt = await bcrypt.genSalt(saltRounds);
+ const hash = await bcrypt.hash(password, salt);
let newUser = null;
try {
@@ -52,21 +52,24 @@ connectDB()
});
} catch (createError) {
if (createError.name === 'ValidationError') {
- return exitWithError('用户名包含不支持的字符或者长度超过限制');
+ exitWithError('用户名包含不支持的字符或者长度超过限制');
+ return;
}
console.error(createError);
exitWithError('创建新用户失败');
}
if (!defaultGroup.creator) {
- defaultGroup.creator = newUser;
+ defaultGroup.creator = newUser as UserDocument;
+ }
+ if (newUser) {
+ defaultGroup.members.push(newUser._id);
}
- defaultGroup.members.push(newUser);
await defaultGroup.save();
console.log('注册成功');
- return process.exit(0);
+ process.exit(0);
})
.catch((err) => {
console.error('connect database error!');
diff --git a/build/build.ts b/build/build.ts
index 549010a..4ac9d8d 100644
--- a/build/build.ts
+++ b/build/build.ts
@@ -14,9 +14,9 @@ process.env.NODE_ENV = 'production';
const spinner = ora('building for production...');
spinner.start();
-rm(path.join(config.build.assetsRoot), (err) => {
+rm(path.join(config.build.assetsRoot), (err: any) => {
if (err) throw err;
- webpack(webpackConfig, (wErr, stats) => {
+ webpack(webpackConfig, (wErr: any, stats: any) => {
spinner.stop();
if (wErr) throw wErr;
process.stdout.write(`${stats.toString({
diff --git a/build/check-versions.ts b/build/check-versions.ts
index d2e20b3..5250f93 100644
--- a/build/check-versions.ts
+++ b/build/check-versions.ts
@@ -6,14 +6,14 @@ import cp from 'child_process';
import packageJson from '../package.json';
-function exec(cmd) {
+function exec(cmd: any) {
return cp.execSync(cmd).toString().trim();
}
const versionRequirements = [
{
name: 'node',
- currentVersion: semver.clean(process.version),
+ currentVersion: semver.clean(process.version) as string,
versionRequirement: packageJson.engines.node,
},
{
diff --git a/build/dev-client.ts b/build/dev-client.ts
index eb1b7e5..0c2f988 100644
--- a/build/dev-client.ts
+++ b/build/dev-client.ts
@@ -5,7 +5,7 @@ import 'eventsource-polyfill';
// @ts-ignore
import hotClient from 'webpack-hot-middleware/client?noInfo=true&reload=true'; // eslint-disable-line import/no-unresolved
-hotClient.subscribe((event) => {
+hotClient.subscribe((event: any) => {
if (event.action === 'reload') {
window.location.reload();
}
diff --git a/build/dev-server.ts b/build/dev-server.ts
index ad93335..698aced 100644
--- a/build/dev-server.ts
+++ b/build/dev-server.ts
@@ -5,7 +5,6 @@ import opn from 'opn';
import path from 'path';
import express from 'express';
import webpack from 'webpack';
-import proxyMiddleware from 'http-proxy-middleware';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import connectionHistoryApiFallback from 'connect-history-api-fallback';
@@ -20,7 +19,6 @@ if (!process.env.NODE_ENV) {
const host = process.env.HOST || config.dev.host;
const port = process.env.PORT || config.dev.port;
const autoOpenBrowser = !!config.dev.autoOpenBrowser;
-const { proxyTable } = config.dev;
const app = express();
const compiler = webpack(webpackConfig);
@@ -36,22 +34,14 @@ const hotMiddleware = webpackHotMiddleware(compiler, {
});
-compiler.plugin('compilation', (compilation) => {
- compilation.plugin('html-webpack-plugin-after-emit', (data, cb) => {
+compiler.plugin('compilation', (compilation: any) => {
+ compilation.plugin('html-webpack-plugin-after-emit', (data: any, cb: any) => {
if (cb) {
cb();
}
});
});
-Object.keys(proxyTable).forEach((context) => {
- let options = proxyTable[context];
- if (typeof options === 'string') {
- options = { target: options };
- }
- app.use(proxyMiddleware(options.filter || context, options));
-});
-
app.use(connectionHistoryApiFallback());
app.use(devMiddleware);
diff --git a/build/utils.ts b/build/utils.ts
index 876bf96..3322ac3 100644
--- a/build/utils.ts
+++ b/build/utils.ts
@@ -5,7 +5,7 @@ import LessPluginAutoPrefix from 'less-plugin-autoprefix';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import config from '../config/webpack';
-export function assetsPath(_path) {
+export function assetsPath(_path: any) {
return path.posix.join('', _path);
}
diff --git a/build/webpack.base.conf.ts b/build/webpack.base.conf.ts
index ceb0da8..b5c181a 100644
--- a/build/webpack.base.conf.ts
+++ b/build/webpack.base.conf.ts
@@ -3,12 +3,12 @@ import * as utils from './utils';
import config from '../config/webpack';
import pages from '../config/pages';
-const entry = {};
+const entry: { [key: string]: string } = {};
pages.forEach((page) => {
entry[page.entry.key] = page.entry.file;
});
-function resolve(dir) {
+function resolve(dir: any) {
return path.join(__dirname, '..', dir);
}
@@ -36,10 +36,7 @@ export default {
{
test: /\.tsx?$/,
exclude: /node_modules/,
- use: [
- 'babel-loader',
- 'ts-loader',
- ],
+ use: ['babel-loader', 'ts-loader'],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
diff --git a/build/webpack.dev.conf.ts b/build/webpack.dev.conf.ts
index e42bd91..d8e3963 100644
--- a/build/webpack.dev.conf.ts
+++ b/build/webpack.dev.conf.ts
@@ -14,6 +14,7 @@ import pages from '../config/pages';
const htmlPlugins = pages.map((page) => new HtmlWebpackPlugin(page));
Object.keys(baseWebpackConfig.entry).forEach((name) => {
+ // @ts-ignore
baseWebpackConfig.entry[name] = ['react-hot-loader/patch', './build/dev-client'].concat(baseWebpackConfig.entry[name]);
});
diff --git a/build/webpack.prod.conf.ts b/build/webpack.prod.conf.ts
index a28f850..817d3e5 100644
--- a/build/webpack.prod.conf.ts
+++ b/build/webpack.prod.conf.ts
@@ -35,18 +35,6 @@ const webpackConfig = merge(baseWebpackConfig, {
rules: utils.getStyleLoaders(),
},
devtool: config.build.productionSourceMap ? '#source-map' : false,
- // optimization: {
- // splitChunks: {
- // cacheGroups: {
- // vendor: {
- // test: module => /node_modules/.test(module.context),
- // chunks: 'initial',
- // name: 'vendor',
- // enforce: true,
- // },
- // },
- // },
- // },
plugins: [
// @ts-ignore
new webpack.DefinePlugin({
diff --git a/client/App.tsx b/client/App.tsx
index 66f7d19..17b6095 100644
--- a/client/App.tsx
+++ b/client/App.tsx
@@ -66,6 +66,7 @@ function App() {
setHeight(getHeightPercent());
};
+ // @ts-ignore
inobounce($app.current);
}, []);
@@ -121,11 +122,11 @@ function App() {
const [groupInfo, setGroupInfo] = useState(null);
const contextValue = useMemo(() => ({
- showUserInfo(user) {
+ showUserInfo(user: any) {
setUserInfo(user);
toggleUserInfoDialog(true);
},
- showGroupInfo(group) {
+ showGroupInfo(group: any) {
setGroupInfo(group);
toggleGroupInfoDialog(true);
},
@@ -135,7 +136,7 @@ function App() {
-
+
@@ -145,11 +146,13 @@ function App() {
toggleUserInfoDialog(false)}
+ // @ts-ignore
user={userInfo}
/>
toggleGroupInfoDialog(false)}
+ // @ts-ignore
group={groupInfo}
/>
diff --git a/client/components/Input.tsx b/client/components/Input.tsx
index 9c1be9f..811837c 100644
--- a/client/components/Input.tsx
+++ b/client/components/Input.tsx
@@ -24,7 +24,7 @@ function Input(props: InputProps) {
onFocus = () => {},
} = props;
- function handleInput(e) {
+ function handleInput(e: any) {
onChange(e.target.value);
}
@@ -35,18 +35,19 @@ function Input(props: InputProps) {
function handleIMEEnd() {
setLockEnter(false);
}
- function handleKeyDown(e) {
+ function handleKeyDown(e: any) {
if (lockEnter) {
return;
}
if (e.key === 'Enter') {
- onEnter(value);
+ onEnter(value as string);
}
}
const $input = useRef(null);
function handleClickClear() {
onChange('');
+ // @ts-ignore
$input.current.focus();
}
diff --git a/client/components/Message.tsx b/client/components/Message.tsx
index 52bea7e..2b02536 100644
--- a/client/components/Message.tsx
+++ b/client/components/Message.tsx
@@ -5,7 +5,7 @@ import 'rc-notification/dist/rc-notification.min.css';
import Style from './Message.less';
function showMessage(text: string, duration = 1500, type = 'success') {
- Notification.newInstance({}, (notification) => {
+ Notification.newInstance({}, (notification: any) => {
notification.notice({
content: (
diff --git a/client/hooks/useAction.ts b/client/hooks/useAction.ts
index 0ca09be..85c0ab8 100644
--- a/client/hooks/useAction.ts
+++ b/client/hooks/useAction.ts
@@ -47,7 +47,7 @@ export default function useAction() {
});
},
- removeLinkman(linkmanId) {
+ removeLinkman(linkmanId: string) {
dispatch({
type: ActionTypes.RemoveLinkman,
payload: linkmanId,
@@ -120,7 +120,7 @@ export default function useAction() {
window.localStorage.setItem(key, value);
},
- toggleLoginRegisterDialog(visible) {
+ toggleLoginRegisterDialog(visible: boolean) {
dispatch({
type: ActionTypes.SetStatus,
payload: {
diff --git a/client/localStorage.ts b/client/localStorage.ts
index 49554d5..cab97e5 100644
--- a/client/localStorage.ts
+++ b/client/localStorage.ts
@@ -47,7 +47,9 @@ export default function getData() {
backgroundImage: '',
aero: false,
};
+ // @ts-ignore
if (theme && config.theme[theme]) {
+ // @ts-ignore
themeConfig = config.theme[theme];
} else {
themeConfig = {
diff --git a/client/modules/Chat/Chat.tsx b/client/modules/Chat/Chat.tsx
index f05ddf1..a314554 100644
--- a/client/modules/Chat/Chat.tsx
+++ b/client/modules/Chat/Chat.tsx
@@ -72,6 +72,7 @@ function Chat() {
action.setLinkmanProperty(focus, 'onlineMembers', onlineMembers);
toggleGroupManagePanel(true);
} else {
+ // @ts-ignore
context.showUserInfo(linkman);
}
}
diff --git a/client/modules/Chat/ChatInput.tsx b/client/modules/Chat/ChatInput.tsx
index 1f48719..a3a7dc9 100644
--- a/client/modules/Chat/ChatInput.tsx
+++ b/client/modules/Chat/ChatInput.tsx
@@ -29,10 +29,10 @@ function ChatInput() {
const action = useAction();
const isLogin = useIsLogin();
const connect = useSelector((state: State) => state.connect);
- const selfId = useSelector((state: State) => state.user._id);
- const username = useSelector((state: State) => state.user.username);
- const avatar = useSelector((state: State) => state.user.avatar);
- const tag = useSelector((state: State) => state.user.tag);
+ const selfId = useSelector((state: State) => state.user?._id);
+ const username = useSelector((state: State) => state.user?.username);
+ const avatar = useSelector((state: State) => state.user?.avatar);
+ const tag = useSelector((state: State) => state.user?.tag);
const focus = useSelector((state: State) => state.focus);
const linkman = useSelector((state: State) => state.linkmans[focus]);
const selfVoiceSwitch = useSelector((state: State) => state.status.selfVoiceSwitch);
@@ -52,6 +52,7 @@ function ChatInput() {
return;
}
e.preventDefault();
+ // @ts-ignore
$input.current.focus(e);
}
useEffect(() => {
@@ -63,13 +64,17 @@ function ChatInput() {
(async () => {
if (expressionDialog && !Expression) {
// @ts-ignore
- const ExpressionModule = await import(/* webpackChunkName: "expression" */ './Expression');
+ const ExpressionModule = await import(
+ /* webpackChunkName: "expression" */ './Expression',
+ );
Expression = ExpressionModule.default;
setTimestamp(Date.now());
}
if (codeEditorDialog && !CodeEditor) {
// @ts-ignore
- const CodeEditorModule = await import(/* webpackChunkName: "code-editor" */ './CodeEditor');
+ const CodeEditorModule = await import(
+ /* webpackChunkName: "code-editor" */ './CodeEditor',
+ );
CodeEditor = CodeEditorModule.default;
setTimestamp(Date.now());
}
@@ -99,14 +104,14 @@ function ChatInput() {
* @param value 要插入的文本
*/
function insertAtCursor(value: string) {
- const input = $input.current;
+ const input = ($input.current as unknown) as HTMLInputElement;
if (input.selectionStart || input.selectionStart === 0) {
const startPos = input.selectionStart;
const endPos = input.selectionEnd;
const restoreTop = input.scrollTop;
input.value = input.value.substring(0, startPos)
+ value
- + input.value.substring(endPos, input.value.length);
+ + input.value.substring(endPos as number, input.value.length);
if (restoreTop > 0) {
input.scrollTop = restoreTop;
}
@@ -124,7 +129,7 @@ function ChatInput() {
insertAtCursor(`#(${expression})`);
}
- function addSelfMessage(type, content) {
+ function addSelfMessage(type: string, content: string) {
const _id = focus + Date.now();
const message = {
_id,
@@ -152,7 +157,7 @@ function ChatInput() {
.replace(/#/g, '');
if (text.length > 0 && text.length <= 100) {
- voice.push(text, Math.random());
+ voice.push(text, Math.random().toString());
}
}
@@ -160,7 +165,12 @@ function ChatInput() {
}
// eslint-disable-next-line react/destructuring-assignment
- async function handleSendMessage(localId, type, content, linkmanId = focus) {
+ async function handleSendMessage(
+ localId: string,
+ type: string,
+ content: string,
+ linkmanId = focus,
+ ) {
const [error, message] = await sendMessage(linkmanId, type, content);
if (error) {
action.deleteMessage(focus, localId);
@@ -185,6 +195,7 @@ function ChatInput() {
return;
}
+ // @ts-ignore
const ext = image.type
.split('/')
.pop()
@@ -234,7 +245,7 @@ function ChatInput() {
handleSendMessage(id, 'image', huaji);
}
- function handleFeatureMenuClick({ key, domEvent }) {
+ function handleFeatureMenuClick({ key, domEvent }: {key: string, domEvent: any}) {
// Quickly hitting the Enter key causes the button to repeatedly trigger the problem
if (domEvent.keyCode === 13) {
return;
@@ -261,7 +272,7 @@ function ChatInput() {
}
}
- async function handlePaste(e) {
+ async function handlePaste(e: any) {
// eslint-disable-next-line react/destructuring-assignment
if (!connect) {
e.preventDefault();
@@ -281,11 +292,12 @@ function ChatInput() {
const image = new Image();
image.onload = async () => {
const imageBlob = await compressImage(image, file.type, 0.8);
+ // @ts-ignore
sendImageMessage({
filename: file.name,
- ext: imageBlob.type.split('/').pop(),
- length: imageBlob.size,
- type: imageBlob.type,
+ ext: imageBlob?.type.split('/').pop(),
+ length: imageBlob?.size,
+ type: imageBlob?.type,
result: imageBlob,
});
};
@@ -305,6 +317,7 @@ function ChatInput() {
return Message.error('发送消息失败, 您当前处于离线状态');
}
+ // @ts-ignore
const message = $input.current.value.trim();
if (message.length === 0) {
return null;
@@ -325,11 +338,12 @@ function ChatInput() {
const id = addSelfMessage('text', xss(message));
handleSendMessage(id, 'text', message);
}
+ // @ts-ignore
$input.current.value = '';
return null;
}
- async function handleInputKeyDown(e) {
+ async function handleInputKeyDown(e: any) {
if (e.key === 'Tab') {
e.preventDefault();
} else if (e.key === 'Enter' && !inputIME) {
@@ -342,6 +356,7 @@ function ChatInput() {
e.preventDefault();
} else if (e.key === '@') {
// 如果按下@建, 则进入@计算模式
+ // @ts-ignore
if (!/@/.test($input.current.value)) {
setAt({
enable: true,
@@ -357,6 +372,7 @@ function ChatInput() {
// 延时, 以便拿到新的value和ime状态
setTimeout(() => {
// 如果@已经被删掉了, 退出@计算模式
+ // @ts-ignore
if (!/@/.test($input.current.value)) {
setAt({ enable: false, content: '' });
return;
@@ -375,6 +391,7 @@ function ChatInput() {
if (inputIME) {
return;
}
+ // @ts-ignore
const regexResult = /@([^ ]*)/.exec($input.current.value);
if (regexResult) {
setAt({ enable: true, content: regexResult[1] });
@@ -396,7 +413,8 @@ function ChatInput() {
});
}
- function replaceAt(targetUsername) {
+ function replaceAt(targetUsername: string) {
+ // @ts-ignore
$input.current.value = $input.current.value.replace(
`@${at.content}`,
`@${targetUsername} `,
@@ -405,6 +423,7 @@ function ChatInput() {
enable: false,
content: '',
});
+ // @ts-ignore
$input.current.focus();
}
@@ -475,8 +494,11 @@ function ChatInput() {
iconSize={32}
/>
-
);
- function handleClickExpression(e) {
+ function handleClickExpression(e: any) {
const $target = e.target;
const url = addParam($target.src, {
width: $target.naturalWidth,
diff --git a/client/modules/Chat/GroupManagePanel.tsx b/client/modules/Chat/GroupManagePanel.tsx
index 1454ed0..bb114cf 100644
--- a/client/modules/Chat/GroupManagePanel.tsx
+++ b/client/modules/Chat/GroupManagePanel.tsx
@@ -31,7 +31,7 @@ function GroupManagePanel(props: GroupManagePanelProps) {
const action = useAction();
const isLogin = useIsLogin();
- const selfId = useSelector((state: State) => state.user._id);
+ const selfId = useSelector((state: State) => state.user?._id);
const [deleteConfirmDialog, setDialogStatus] = useState(false);
const [groupName, setGroupName] = useState('');
const context = useContext(ShowUserOrGroupInfoContext);
@@ -100,6 +100,7 @@ function GroupManagePanel(props: GroupManagePanelProps) {
if (userInfo._id === selfId) {
return;
}
+ // @ts-ignore
context.showUserInfo(userInfo);
onClose();
}
diff --git a/client/modules/Chat/HeaderBar.tsx b/client/modules/Chat/HeaderBar.tsx
index e89c696..70b0f7b 100644
--- a/client/modules/Chat/HeaderBar.tsx
+++ b/client/modules/Chat/HeaderBar.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import { useSelector } from 'react-redux';
-import { CopyToClipboard } from 'react-copy-to-clipboard';
+import CopyToClipboard from 'react-copy-to-clipboard';
import { isMobile } from '../../../utils/ua';
import { State } from '../../state/reducer';
diff --git a/client/modules/Chat/Message/CodeDialog.tsx b/client/modules/Chat/Message/CodeDialog.tsx
index 4f4d605..e745e18 100644
--- a/client/modules/Chat/Message/CodeDialog.tsx
+++ b/client/modules/Chat/Message/CodeDialog.tsx
@@ -16,6 +16,7 @@ function CodeDialog(props: CodeDialogProps) {
const { visible, onClose, language, code } = props;
const html = language === 'text'
? xss(code)
+ // @ts-ignore
: Prism.highlight(code, Prism.languages[language]);
setTimeout(Prism.highlightAll.bind(Prism), 0); // TODO: https://github.com/PrismJS/prism/issues/1487
diff --git a/client/modules/Chat/Message/CodeMessage.tsx b/client/modules/Chat/Message/CodeMessage.tsx
index 215c2a9..fb30871 100644
--- a/client/modules/Chat/Message/CodeMessage.tsx
+++ b/client/modules/Chat/Message/CodeMessage.tsx
@@ -4,7 +4,11 @@ import Style from './CodeMessage.less';
let CodeDialog: any = null;
-const languagesMap = {
+type LanguageMap = {
+ [language: string]: string;
+}
+
+const languagesMap: LanguageMap = {
javascript: 'javascript',
typescript: 'typescript',
java: 'java',
diff --git a/client/modules/Chat/Message/Message.tsx b/client/modules/Chat/Message/Message.tsx
index 58cb3d7..2c059f9 100644
--- a/client/modules/Chat/Message/Message.tsx
+++ b/client/modules/Chat/Message/Message.tsx
@@ -55,7 +55,7 @@ interface MessageState {
class Message extends Component
{
$container = createRef();
- constructor(props) {
+ constructor(props: MessageProps) {
super(props);
this.state = {
showButtonList: false,
@@ -65,6 +65,7 @@ class Message extends Component {
componentDidMount() {
const { shouldScroll } = this.props;
if (shouldScroll) {
+ // @ts-ignore
this.$container.current.scrollIntoView();
}
}
@@ -169,6 +170,7 @@ class Message extends Component {
className={Style.avatar}
src={avatar}
size={44}
+ // @ts-ignore
onClick={() => this.handleClickAvatar(context.showUserInfo)}
/>
)}
diff --git a/client/modules/Chat/MessageList.tsx b/client/modules/Chat/MessageList.tsx
index 4fe960d..eb2ffbc 100644
--- a/client/modules/Chat/MessageList.tsx
+++ b/client/modules/Chat/MessageList.tsx
@@ -11,7 +11,7 @@ import Style from './MessageList.less';
function MessageList() {
const action = useAction();
- const selfId = useSelector((state: State) => state.user._id);
+ const selfId = useSelector((state: State) => state.user?._id);
const focus = useSelector((state: State) => state.focus);
const isGroup = useSelector((state: State) => state.linkmans[focus].type === 'group');
const creator = useSelector((state: State) => state.linkmans[focus].creator);
@@ -22,7 +22,7 @@ function MessageList() {
const $list = useRef(null);
let isFetching = false;
- async function handleScroll(e) {
+ async function handleScroll(e: any) {
// Don't know why the code-view dialog will also trigger when scrolling
if ($list.current && e.target !== $list.current) {
return;
@@ -56,6 +56,7 @@ function MessageList() {
const isSelf = message.from._id === selfId;
let shouldScroll = true;
if ($list.current) {
+ // @ts-ignore
const { scrollHeight, clientHeight, scrollTop } = $list.current;
shouldScroll = isSelf
|| scrollHeight === clientHeight
diff --git a/client/modules/FunctionBarAndLinkmanList/FunctionBar.tsx b/client/modules/FunctionBarAndLinkmanList/FunctionBar.tsx
index fe07dbf..a6407c6 100644
--- a/client/modules/FunctionBarAndLinkmanList/FunctionBar.tsx
+++ b/client/modules/FunctionBarAndLinkmanList/FunctionBar.tsx
@@ -10,13 +10,18 @@ import { search } from '../../service';
import Style from './FunctionBar.less';
import Input from '../../components/Input';
+type SearchResult = {
+ users: any[];
+ groups: any[];
+}
+
function FunctionBar() {
const [keywords, setKeywords] = useState('');
const [addButtonVisible, toggleAddButtonVisible] = useState(true);
const [searchResultVisible, toggleSearchResultVisible] = useState(false);
const [searchResultActiveKey, setSearchResultActiveKey] = useState('all');
const [createGroupDialogVisible, toggleCreateGroupDialogVisible] = useState(false);
- const [searchResult, setSearchResult] = useState({ users: [], groups: [] });
+ const [searchResult, setSearchResult] = useState({ users: [], groups: [] });
const context = useContext(ShowUserOrGroupInfoContext);
const placeholder = '搜索群组/用户';
@@ -29,7 +34,7 @@ function FunctionBar() {
setKeywords('');
}
- function handleBodyClick(e) {
+ function handleBodyClick(e: any) {
if (e.target.getAttribute('placeholder') === placeholder || !searchResultVisible) {
return;
}
@@ -70,7 +75,8 @@ function FunctionBar() {
const { users } = searchResult;
count = Math.min(count, users.length);
- function handleClick(targetUser) {
+ function handleClick(targetUser: any) {
+ // @ts-ignore
context.showUserInfo(targetUser);
resetSearch();
}
@@ -95,7 +101,8 @@ function FunctionBar() {
const { groups } = searchResult;
count = Math.min(count, groups.length);
- function handleClick(targetGroup) {
+ function handleClick(targetGroup: any) {
+ // @ts-ignore
context.showGroupInfo(targetGroup);
resetSearch();
}
diff --git a/client/modules/FunctionBarAndLinkmanList/FunctionBarAndLinkmanList.tsx b/client/modules/FunctionBarAndLinkmanList/FunctionBarAndLinkmanList.tsx
index 18b7f86..9f25507 100644
--- a/client/modules/FunctionBarAndLinkmanList/FunctionBarAndLinkmanList.tsx
+++ b/client/modules/FunctionBarAndLinkmanList/FunctionBarAndLinkmanList.tsx
@@ -22,7 +22,7 @@ function FunctionBarAndLinkmanList() {
return null;
}
- function handleClick(e) {
+ function handleClick(e: any) {
if (e.target === e.currentTarget) {
action.setStatus('functionBarAndLinkmanListVisible', false);
}
diff --git a/client/modules/GroupInfo.tsx b/client/modules/GroupInfo.tsx
index bc31968..1d4dbca 100644
--- a/client/modules/GroupInfo.tsx
+++ b/client/modules/GroupInfo.tsx
@@ -25,7 +25,8 @@ function GroupInfo(props: GroupInfoProps) {
const { visible, onClose, group } = props;
const action = useAction();
- const hasLinkman = useSelector((state: State) => !!state.linkmans[group && group._id]);
+ // @ts-ignore
+ const hasLinkman = useSelector((state: State) => !!state.linkmans[group?._id]);
const [largerAvatar, toggleLargetAvatar] = useState(false);
if (!group) {
@@ -34,6 +35,10 @@ function GroupInfo(props: GroupInfoProps) {
async function handleJoinGroup() {
onClose();
+
+ if (!group) {
+ return;
+ }
const groupRes = await joinGroup(group._id);
if (groupRes) {
groupRes.type = 'group';
@@ -48,6 +53,10 @@ function GroupInfo(props: GroupInfoProps) {
function handleFocusGroup() {
onClose();
+
+ if (!group) {
+ return;
+ }
action.setFocus(group._id);
}
diff --git a/client/modules/LoginAndRegister/Login.tsx b/client/modules/LoginAndRegister/Login.tsx
index 7bd801f..ae12b73 100644
--- a/client/modules/LoginAndRegister/Login.tsx
+++ b/client/modules/LoginAndRegister/Login.tsx
@@ -23,7 +23,7 @@ function Login() {
const user = await login(
username,
password,
- platform.os.family,
+ platform.os?.family,
platform.name,
platform.description,
);
@@ -33,11 +33,12 @@ function Login() {
window.localStorage.setItem('token', user.token);
const linkmanIds = [
- ...user.groups.map((group) => group._id),
- ...user.friends.map((friend) => getFriendId(friend.from, friend.to._id)),
+ ...user.groups.map((group: any) => group._id),
+ ...user.friends.map((friend: any) => getFriendId(friend.from, friend.to._id)),
];
const linkmanMessages = await getLinkmansLastMessages(linkmanIds);
Object.values(linkmanMessages).forEach(
+ // @ts-ignore
(messages: Message[]) => messages.forEach(convertMessage),
);
dispatch({
diff --git a/client/modules/LoginAndRegister/Register.tsx b/client/modules/LoginAndRegister/Register.tsx
index 0c7a9b5..b884808 100644
--- a/client/modules/LoginAndRegister/Register.tsx
+++ b/client/modules/LoginAndRegister/Register.tsx
@@ -22,7 +22,7 @@ function Register() {
const user = await register(
username,
password,
- platform.os.family,
+ platform.os?.family,
platform.name,
platform.description,
);
@@ -32,11 +32,12 @@ function Register() {
window.localStorage.setItem('token', user.token);
const linkmanIds = [
- ...user.groups.map((group) => group._id),
- ...user.friends.map((friend) => getFriendId(friend.from, friend.to._id)),
+ ...user.groups.map((group: any) => group._id),
+ ...user.friends.map((friend: any) => getFriendId(friend.from, friend.to._id)),
];
const linkmanMessages = await getLinkmansLastMessages(linkmanIds);
Object.values(linkmanMessages).forEach(
+ // @ts-ignore
(messages: Message[]) => messages.forEach(convertMessage),
);
dispatch({
diff --git a/client/modules/Sidebar/SelfInfo.tsx b/client/modules/Sidebar/SelfInfo.tsx
index 0898153..9a9063e 100644
--- a/client/modules/Sidebar/SelfInfo.tsx
+++ b/client/modules/Sidebar/SelfInfo.tsx
@@ -28,8 +28,8 @@ function SelfInfo(props: SelfInfoProps) {
const { visible, onClose } = props;
const action = useAction();
- const userId = useSelector((state: State) => state.user._id);
- const avatar = useSelector((state: State) => state.user.avatar);
+ const userId = useSelector((state: State) => state.user?._id);
+ const avatar = useSelector((state: State) => state.user?.avatar);
const primaryColor = useSelector((state: State) => state.status.primaryColor);
const [loading, toggleLoading] = useState(false);
const [cropper, setCropper] = useState({
@@ -90,7 +90,8 @@ function SelfInfo(props: SelfInfoProps) {
}
function handleChangeAvatar() {
- $cropper.current.getCroppedCanvas().toBlob(async (blob) => {
+ // @ts-ignore
+ $cropper.current.getCroppedCanvas().toBlob(async (blob: any) => {
uploadAvatar(blob, cropper.ext);
});
}
@@ -127,7 +128,7 @@ function SelfInfo(props: SelfInfoProps) {
}
}
- function handleCloseDialog(event) {
+ function handleCloseDialog(event: any) {
/**
* 点击关闭按钮, 或者在非图片裁剪时点击蒙层, 才能关闭弹窗
*/
@@ -137,7 +138,12 @@ function SelfInfo(props: SelfInfoProps) {
}
return (
-