feat: forward message UX

This commit is contained in:
zerosoul
2022-04-13 21:48:37 +08:00
parent 9552efc75e
commit 506fc8e59a
8 changed files with 281 additions and 12 deletions
+18 -1
View File
@@ -12,7 +12,9 @@ import EmojiPicker from "./EmojiPicker";
import replyIcon from "../../../assets/icons/reply.svg?url";
import reactIcon from "../../../assets/icons/reaction.svg?url";
import editIcon from "../../../assets/icons/edit.svg?url";
import bookmarkIcon from "../../../assets/icons/bookmark.svg?url";
import moreIcon from "../../../assets/icons/more.svg?url";
import ForwardModal from "../ForwardModal";
const StyledCmds = styled.ul`
z-index: 9999;
position: absolute;
@@ -60,6 +62,7 @@ export default function Commands({
}) {
const dispatch = useDispatch();
const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const [forwardModalVisible, setForwardModalVisible] = useState(false);
const [tippyVisible, setTippyVisible] = useState(false);
const currUid = useSelector((store) => store.authData.uid);
const cmdsRef = useRef(null);
@@ -71,7 +74,10 @@ export default function Commands({
hideAll();
}
};
const toggleForwardModal = () => {
hideAll();
setForwardModalVisible((prev) => !prev);
};
const toggleDeleteModal = () => {
hideAll();
setDeleteModalVisible((prev) => !prev);
@@ -111,6 +117,11 @@ export default function Commands({
</Tooltip>
</li>
)}
<li className="cmd">
<Tooltip placement="top" tip="Add to Favorites">
<img src={bookmarkIcon} className="toggler" alt="icon bookmark" />
</Tooltip>
</li>
<Tippy
onShow={handleTippyVisible.bind(null, true)}
onHide={handleTippyVisible.bind(null, false)}
@@ -121,6 +132,9 @@ export default function Commands({
<StyledMenu className="menu">
{/* <li className="item">Edit Message</li> */}
<li className="item underline">Pin Message</li>
<li className="item" onClick={toggleForwardModal}>
Forward
</li>
<li className="item" onClick={handleReply.bind(null, true)}>
Reply
</li>
@@ -142,6 +156,9 @@ export default function Commands({
{deleteModalVisible && (
<DeleteMessageConfirm closeModal={toggleDeleteModal} mid={mid} />
)}
{forwardModalVisible && (
<ForwardModal mid={mid} closeModal={toggleForwardModal} />
)}
</StyledCmds>
);
}
+6 -3
View File
@@ -4,23 +4,26 @@ import Tippy from "@tippyjs/react";
import Profile from "../Profile";
import styled from "styled-components";
const Styled = styled.span`
cursor: pointer;
padding: 0 2px;
color: #1fe1f9;
&.clickable {
cursor: pointer;
}
`;
export default function Mention({ uid }) {
export default function Mention({ uid, popover = true }) {
const contactsData = useSelector((store) => store.contacts.byId);
const user = contactsData[uid];
if (!user) return null;
return (
<Tippy
disabled={!popover}
duration={0}
interactive
placement="top"
trigger="click"
content={<Profile uid={uid} type="card" />}
>
<Styled>{`@${user.name}`}</Styled>
<Styled className={popover ? "clickable" : ""}>{`@${user.name}`}</Styled>
</Tippy>
);
}
+25 -5
View File
@@ -1,13 +1,14 @@
// import React from "react";
import styled from "styled-components";
import { useSelector } from "react-redux";
import reactStringReplace from "react-string-replace";
import MrakdownRender from "../MrakdownRender";
import Mention from "./Mention";
import { ContentTypes } from "../../../app/config";
import { getFileIcon, isImage } from "../../utils";
import Avatar from "../Avatar";
const Styled = styled.div`
cursor: pointer;
display: flex;
align-items: flex-start;
padding: 8px;
@@ -15,6 +16,9 @@ const Styled = styled.div`
border-radius: var(--br);
gap: 8px;
margin-bottom: 4px;
&.clickable {
cursor: pointer;
}
.user {
display: flex;
align-items: center;
@@ -89,7 +93,19 @@ const renderContent = (data) => {
let res = null;
switch (content_type) {
case ContentTypes.text:
res = <span className="txt"> {content}</span>;
res = (
<span className="txt">
{reactStringReplace(
content,
/(\s{1}\@[0-9]+\s{1})/g,
(match, idx) => {
console.log("match", match);
const uid = match.trim().slice(1);
return <Mention key={idx} uid={uid} popover={false} />;
}
)}
</span>
);
break;
case ContentTypes.markdown:
res = (
@@ -120,7 +136,7 @@ const renderContent = (data) => {
}
return res;
};
export default function Reply({ mid }) {
export default function Reply({ mid, interactive = true }) {
const { data, users } = useSelector((store) => {
return { data: store.message[mid], users: store.contacts.byId };
});
@@ -140,7 +156,11 @@ export default function Reply({ mid }) {
const currUser = users[data.from_uid];
if (!currUser) return null;
return (
<Styled data-mid={mid} className="reply" onClick={handleClick}>
<Styled
data-mid={mid}
className={`reply ${interactive ? "clickable" : ""}`}
onClick={interactive ? handleClick : null}
>
<div className="user">
<Avatar className="avatar" url={currUser.avatar} name={currUser.name} />
<span className="name">{currUser.name}</span>