Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to show deleted message #442

Merged
merged 1 commit into from
Sep 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintrc
Expand Up @@ -47,7 +47,6 @@
"jsx-a11y/interactive-supports-focus": 0,
"jsx-a11y/no-noninteractive-element-interactions": 0,
"jsx-a11y/no-noninteractive-element-to-interactive-role": 0,
"no-console": 0,
"no-param-reassign": 0,
"no-plusplus": 0,
"no-script-url": 0,
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/pages/Chat/Message.tsx
Expand Up @@ -49,7 +49,8 @@ function Message({
const self = useSelfId();
const focus = useFocus();

const couldDelete = isAdmin || message.from._id === self;
const couldDelete =
message.type !== 'system' && (isAdmin || message.from._id === self);

useEffect(() => {
if (shouldScroll) {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/socket.ts
Expand Up @@ -38,7 +38,7 @@ const options = {
transports: ['websocket'],
};

const host = 'https://fiora.suisuijiang.com';
const host = 'http://10.132.67.127:9200';
const socket = IO(host, options);

function fetch<T = any>(
Expand Down
9 changes: 5 additions & 4 deletions packages/app/src/state/reducer.ts
Expand Up @@ -117,7 +117,7 @@ const reducer = produce((state: State = initialState, action: ActionTypes) => {
...linkman,
...(action.linkmans[linkman._id]
? {
messages: action.linkmans[linkman._id].messages,
messages: action.linkmans[linkman._id].messages.map(convertMessage),
unread: action.linkmans[linkman._id].unread,
}
: {}),
Expand Down Expand Up @@ -259,11 +259,12 @@ const reducer = produce((state: State = initialState, action: ActionTypes) => {
(linkman) => linkman._id === action.linkmanId,
);
if (targetLinkman) {
const targetMessageIndex = targetLinkman.messages.findIndex(
const targetMessage = targetLinkman.messages.find(
(message) => message._id === action.messageId,
);
if (targetMessageIndex !== -1) {
targetLinkman.messages.splice(targetMessageIndex, 1);
if (targetMessage) {
targetMessage.deleted = true;
convertMessage(targetMessage);
}
}
return state;
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/types/redux.ts
Expand Up @@ -17,7 +17,7 @@ export type SetLinkmanMessagesAction = {
linkmans: Record<
string,
{
messages: { [linkmanId: string]: Message[] };
messages: Message[];
unread: number;
}
>;
Expand Down Expand Up @@ -154,6 +154,7 @@ export type Message = {
originUsername?: string;
};
to: string;
deleted?: boolean;
};

export type Group = {
Expand Down
9 changes: 9 additions & 0 deletions packages/app/src/utils/convertMessage.ts
Expand Up @@ -46,7 +46,16 @@ function convertSystemMessage(message: Message) {
message.content = '不支持的指令';
}
}
} else if (message.deleted) {
message.type = 'system';
message.from._id = 'system';
message.from.originUsername = message.from.username;
message.from.username = '乌贼娘殿下';
message.from.avatar = WuZeiNiangImage;
message.from.tag = 'system';
message.content = `撤回了消息`;
}

return message;
}

Expand Down
12 changes: 12 additions & 0 deletions packages/database/mongoose/models/message.ts
Expand Up @@ -22,6 +22,10 @@ const MessageSchema = new Schema({
type: String,
default: '',
},
deleted: {
type: Boolean,
default: false,
},
});

export interface MessageDocument extends Document {
Expand All @@ -35,6 +39,8 @@ export interface MessageDocument extends Document {
content: string;
/** 创建时间 */
createTime: Date;
/** Has it been deleted */
deleted: boolean;
}

/**
Expand All @@ -45,6 +51,12 @@ const Message = model<MessageDocument>('Message', MessageSchema);

export default Message;

interface SendMessageData {
to: string;
type: string;
content: string;
}

export async function handleInviteV2Message(message: SendMessageData) {
if (message.type === 'inviteV2') {
const inviteInfo = JSON.parse(message.content);
Expand Down
21 changes: 10 additions & 11 deletions packages/server/src/routes/message.ts
Expand Up @@ -64,7 +64,7 @@ async function pushNotification(
}
});
} catch (error) {
logger.error('[Notification]', error.message);
logger.error('[Notification]', (error as Error).message);
}
}
}
Expand Down Expand Up @@ -237,6 +237,7 @@ export async function getLinkmansLastMessages(
content: 1,
from: 1,
createTime: 1,
deleted: 1,
},
{ sort: { createTime: -1 }, limit: FirstTimeMessagesCount },
).populate('from', { username: 1, avatar: 1, tag: 1 });
Expand Down Expand Up @@ -282,6 +283,7 @@ export async function getLinkmansLastMessagesV2(
content: 1,
from: 1,
createTime: 1,
deleted: 1,
},
{
sort: { createTime: -1 },
Expand Down Expand Up @@ -340,6 +342,7 @@ export async function getLinkmanHistoryMessages(
content: 1,
from: 1,
createTime: 1,
deleted: 1,
},
{
sort: { createTime: -1 },
Expand Down Expand Up @@ -371,6 +374,7 @@ export async function getDefaultGroupHistoryMessages(
content: 1,
from: 1,
createTime: 1,
deleted: 1,
},
{
sort: { createTime: -1 },
Expand All @@ -382,22 +386,17 @@ export async function getDefaultGroupHistoryMessages(
return result;
}

interface DeleteMessageData {
/** 消息id */
messageId: string;
}

/**
* 删除消息, 需要管理员权限
*/
export async function deleteMessage(ctx: Context<{ messageId: string }>) {
const { messageId } = ctx.data;
assert(messageId, 'messageId不能为空');

assert(
!client.disableDeleteMessage || ctx.socket.isAdmin,
'已禁止撤回消息',
);

const { messageId } = ctx.data;
assert(messageId, 'messageId不能为空');

const message = await Message.findOne({ _id: messageId });
if (!message) {
Expand All @@ -409,8 +408,8 @@ export async function deleteMessage(ctx: Context<{ messageId: string }>) {
'只能撤回本人的消息',
);

await Message.deleteOne({ _id: message._id });
await History.deleteMany({ message: message._id });
message.deleted = true;
await message.save();

/**
* 广播删除消息通知, 区分群消息和私聊消息
Expand Down
3 changes: 2 additions & 1 deletion packages/server/src/routes/user.ts
Expand Up @@ -117,7 +117,7 @@ export async function register(
avatar: getRandomAvatar(),
} as UserDocument);
} catch (err) {
if (err.name === 'ValidationError') {
if ((err as Error).name === 'ValidationError') {
return '用户名包含不支持的字符或者长度超过限制';
}
throw err;
Expand Down Expand Up @@ -357,6 +357,7 @@ export async function guest(ctx: Context<Environment>) {
content: 1,
from: 1,
createTime: 1,
deleted: 1,
},
{ sort: { createTime: -1 }, limit: 15 },
).populate('from', { username: 1, avatar: 1 });
Expand Down
9 changes: 9 additions & 0 deletions packages/utils/convertMessage.ts
Expand Up @@ -37,9 +37,18 @@ function convertSystemMessage(message: any) {
message.content = '不支持的指令';
}
}
} else if (message.deleted) {
message.type = 'system';
message.from._id = 'system';
message.from.originUsername = message.from.username;
message.from.username = '乌贼娘殿下';
message.from.avatar = WuZeiNiangImage;
message.from.tag = 'system';
message.content = `撤回了消息`;
}
}

export default function convertMessage(message: any) {
convertSystemMessage(message);
return message;
}
6 changes: 5 additions & 1 deletion packages/web/src/modules/Chat/Message/Message.tsx
Expand Up @@ -73,7 +73,10 @@ class Message extends Component<MessageProps, MessageState> {
}

handleMouseEnter = () => {
const { isAdmin, isSelf } = this.props;
const { isAdmin, isSelf, type } = this.props;
if (type === 'system') {
return;
}
if (isAdmin || (!client.disableDeleteMessage && isSelf)) {
this.setState({ showButtonList: true });
}
Expand Down Expand Up @@ -111,6 +114,7 @@ class Message extends Component<MessageProps, MessageState> {
messageId: id,
} as DeleteMessagePayload,
});
this.setState({ showButtonList: false });
}
};

Expand Down
38 changes: 18 additions & 20 deletions packages/web/src/state/reducer.ts
@@ -1,5 +1,6 @@
import { isMobile } from '@fiora/utils/ua';
import getFriendId from '@fiora/utils/getFriendId';
import convertMessage from '@fiora/utils/convertMessage';
import getData from '../localStorage';
import {
Action,
Expand Down Expand Up @@ -31,6 +32,7 @@ export interface Message {
loading: boolean;
percent: number;
createTime: string;
deleted?: boolean;
}

export interface MessagesMap {
Expand Down Expand Up @@ -225,7 +227,7 @@ function transformFriend(friend: Linkman): Linkman {
// @ts-ignore
createTime: friend.createTime,
};
initLinkmanFields((transformedFriend as unknown) as Linkman, 'friend');
initLinkmanFields(transformedFriend as unknown as Linkman, 'friend');
return transformedFriend as Linkman;
}

Expand Down Expand Up @@ -304,15 +306,8 @@ function reducer(state: State = initialState, action: Action): State {
}

case ActionTypes.SetUser: {
const {
_id,
username,
avatar,
tag,
groups,
friends,
isAdmin,
} = action.payload as SetUserPayload;
const { _id, username, avatar, tag, groups, friends, isAdmin } =
action.payload as SetUserPayload;
// @ts-ignore
const linkmans: Linkman[] = [
// @ts-ignore
Expand Down Expand Up @@ -466,7 +461,8 @@ function reducer(state: State = initialState, action: Action): State {
}

case ActionTypes.SetLinkmansLastMessages: {
const linkmansMessages = action.payload as SetLinkmansLastMessagesPayload;
const linkmansMessages =
action.payload as SetLinkmansLastMessagesPayload;
const { linkmans } = state;
const newState = { ...state, linkmans: {} };
Object.keys(linkmans).forEach((linkmanId) => {
Expand Down Expand Up @@ -527,10 +523,8 @@ function reducer(state: State = initialState, action: Action): State {
}

case ActionTypes.DeleteMessage: {
const {
linkmanId,
messageId,
} = action.payload as DeleteMessagePayload;
const { linkmanId, messageId } =
action.payload as DeleteMessagePayload;
if (!state.linkmans[linkmanId]) {
/* istanbul ignore next */
if (!__TEST__) {
Expand All @@ -541,17 +535,21 @@ function reducer(state: State = initialState, action: Action): State {
return state;
}

const messages = deleteObjectKey(
state.linkmans[linkmanId].messages,
messageId,
);
return {
...state,
linkmans: {
...state.linkmans,
[linkmanId]: {
...state.linkmans[linkmanId],
messages,
messages: {
...state.linkmans[linkmanId].messages,
[messageId]: convertMessage({
...state.linkmans[linkmanId].messages[
messageId
],
deleted: true,
}),
},
},
},
};
Expand Down