feat: batch delete messages
This commit is contained in:
@@ -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>
|
||||
</>
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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, {
|
||||
|
||||
@@ -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} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user