feat: batch delete messages

This commit is contained in:
zerosoul
2022-04-28 10:54:23 +08:00
parent d83a090bc5
commit a4617765b6
6 changed files with 94 additions and 56 deletions
+3 -3
View File
@@ -49,7 +49,7 @@ export default function ForwardModal({ mids, closeModal }) {
users: selectedMembers,
channels: selectedChannels,
});
if (appendText) {
if (appendText.trim()) {
await sendMessages({
content: appendText,
users: selectedMembers,
@@ -144,7 +144,7 @@ export default function ForwardModal({ mids, closeModal }) {
key={cid}
id={cid}
interactive={false}
avatarSize={40}
// avatarSize={40}
/>
<CloseIcon
className="remove"
@@ -160,7 +160,7 @@ export default function ForwardModal({ mids, closeModal }) {
key={uid}
uid={uid}
interactive={false}
avatarSize={40}
// avatarSize={40}
/>
<CloseIcon
className="remove"
@@ -1,44 +0,0 @@
// import React from "react";
import { useEffect } from "react";
// import { useDispatch } from "react-redux";
// import BASE_URL from "../../app/config";
import { useLazyDeleteMessageQuery } from "../../../app/services/message";
import StyledModal from "../styled/Modal";
import Button from "../styled/Button";
import Modal from "../Modal";
import PreviewMessage from "./PreviewMessage";
export default function DeleteMessageConfirmModal({ closeModal, mid = 0 }) {
// const dispatch = useDispatch();
const [deleteMessage, { isLoading, isSuccess }] = useLazyDeleteMessageQuery();
const handleDelete = (evt) => {
const { mid } = evt.target.dataset;
if (!mid) return;
deleteMessage(mid);
};
useEffect(() => {
if (isSuccess) {
closeModal();
}
}, [isSuccess]);
if (!mid) return null;
return (
<Modal>
<StyledModal
// className="animate__animated animate__fadeInDown animate__faster"
buttons={
<>
<Button onClick={closeModal}>Cancel</Button>
<Button data-mid={mid} onClick={handleDelete} className="danger">
{isLoading ? "Deleting" : `Delete`}
</Button>
</>
}
title="Delete Message"
description="Are you sure want to delete this message?"
>
<PreviewMessage mid={mid} />
</StyledModal>
</Modal>
);
}
@@ -15,23 +15,23 @@ const StyledPinModal = styled(StyledModal)`
overflow-x: hidden;
}
`;
// import { useDispatch } from "react-redux";
// import BASE_URL from "../../app/config";
import { usePinMessageMutation } from "../../../app/services/message";
import usePinMessage from "../../hook/usePinMessage";
import StyledModal from "../styled/Modal";
import Button from "../styled/Button";
import Modal from "../Modal";
import PreviewMessage from "./PreviewMessage";
import toast from "react-hot-toast";
export default function PinMessageModal({ closeModal, mid = 0, gid = 0 }) {
// const dispatch = useDispatch();
const [pinMessage, { isLoading, isSuccess }] = usePinMessageMutation();
const { pinMessage, isPining, isSuccess } = usePinMessage(gid);
const handlePin = () => {
pinMessage({ mid, gid });
pinMessage(mid);
};
useEffect(() => {
if (isSuccess) {
closeModal();
toast.success("Pin Message Successfully");
}
}, [isSuccess]);
@@ -45,8 +45,8 @@ export default function PinMessageModal({ closeModal, mid = 0, gid = 0 }) {
<Button onClick={closeModal} className="cancel">
Cancel
</Button>
<Button disabled={isLoading} onClick={handlePin} className="main">
{isLoading ? "Pining" : `Pin It`}
<Button disabled={isPining} onClick={handlePin} className="main">
{isPining ? "Pining" : `Pin It`}
</Button>
</>
}
+45
View File
@@ -0,0 +1,45 @@
import { useState } from "react";
import { useSelector } from "react-redux";
import { useLazyDeleteMessageQuery } from "../../app/services/message";
export default function useDeleteMessage() {
const [deleting, setDeleting] = useState(false);
const { loginUser, messageData } = useSelector((store) => {
return {
messageData: store.message,
loginUser: store.contacts.byId[store.authData.uid],
};
});
const [
remove,
// { isError, isLoading, isSuccess },
] = useLazyDeleteMessageQuery();
const deleteMessage = async (mids) => {
if (!mids) return;
const _arr = Array.isArray(mids) ? mids : [mids];
setDeleting(true);
for await (const mid of _arr) {
await remove(mid);
}
setDeleting(false);
};
const canDelete = (mids = []) => {
if (!mids || mids.length == 0) return false;
// 管理员
if (loginUser.is_admin) return true;
// 检查是否是自己的消息
return mids.every((mid) => {
return messageData[mid]?.from_uid == loginUser.uid;
});
};
// useEffect(() => {
// if (channel) {
// setPins(channel.pinned_messages);
// }
// }, [channel]);
return {
canDelete,
isDeleting: deleting,
deleteMessage,
};
}
+7
View File
@@ -14,6 +14,7 @@ import {
addChannel,
removeChannel,
updateChannel,
updatePinMessage,
} from "../../../app/slices/channels";
import {
updateUsersVersion,
@@ -257,6 +258,12 @@ export default function useStreaming() {
console.log("kicked from group", data.gid);
dispatch(removeChannel(data.gid));
break;
case "pinned_message_updated":
{
// const {gid,mid,msg}=data;
dispatch(updatePinMessage(data));
}
break;
case "chat":
{
chatMessageHandler(data, dispatch, {
+32 -2
View File
@@ -2,12 +2,16 @@ import { useState } from "react";
import styled from "styled-components";
import { useDispatch, useSelector } from "react-redux";
import { useKey } from "rooks";
import useDeleteMessage from "../../../common/hook/useDeleteMessage";
import { updateSelectMessages } from "../../../app/slices/ui";
import { useFavoriteMessageMutation } from "../../../app/services/message";
import IconForward from "../../../assets/icons/forward.svg";
import IconBookmark from "../../../assets/icons/bookmark.svg";
import IconDelete from "../../../assets/icons/delete.svg";
import IconClose from "../../../assets/icons/close.circle.svg";
import ForwardModal from "../../../common/component/ForwardModal";
import toast from "react-hot-toast";
import DeleteMessageConfirmModal from "../../../common/component/DeleteMessageConfirm";
const Styled = styled.div`
position: relative;
padding: 16px;
@@ -21,6 +25,9 @@ const Styled = styled.div`
padding: 8px;
background: #f2f4f7;
border-radius: var(--br);
&:disabled svg path {
fill: #ccc;
}
}
.close {
cursor: pointer;
@@ -31,6 +38,9 @@ const Styled = styled.div`
}
`;
export default function Operations({ context, id }) {
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const { canDelete } = useDeleteMessage();
const [favoriteMsg] = useFavoriteMessageMutation();
const mids = useSelector(
(store) => store.ui.selectMessages[`${context}_${id}`]
);
@@ -39,6 +49,18 @@ export default function Operations({ context, id }) {
const handleClose = () => {
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
};
const handleFav = async () => {
await favoriteMsg(mids);
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
toast.success("Messages Saved!");
};
const toggleDeleteModal = (isSuccess = false) => {
setDeleteModalVisible((prev) => !prev);
if (isSuccess) {
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
toast.success("Messages Deleted!");
}
};
const toggleForwardModal = () => {
setForwardModalVisible((prev) => !prev);
};
@@ -46,16 +68,21 @@ export default function Operations({ context, id }) {
console.log("Escape keypress", evt);
dispatch(updateSelectMessages({ context, id, operation: "reset" }));
});
const canDel = canDelete(mids);
return (
<>
<Styled>
<button className="opt" onClick={toggleForwardModal}>
<IconForward />
</button>
<button className="opt">
<button className="opt" onClick={handleFav}>
<IconBookmark />
</button>
<button className="opt">
<button
className="opt"
disabled={!canDel}
onClick={toggleDeleteModal.bind(null, false)}
>
<IconDelete />
</button>
<IconClose className="close" onClick={handleClose} />
@@ -63,6 +90,9 @@ export default function Operations({ context, id }) {
{forwardModalVisible && (
<ForwardModal mids={mids} closeModal={toggleForwardModal} />
)}
{deleteModalVisible && (
<DeleteMessageConfirmModal mids={mids} closeModal={toggleDeleteModal} />
)}
</>
);
}