refactor: add typescript definition
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { FC } from "react";
|
||||
import styled from "styled-components";
|
||||
import Avatar from "./Avatar";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
@@ -46,14 +47,21 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Channel({ interactive = true, id = "", compact = false, avatarSize = 32 }) {
|
||||
interface Props {
|
||||
interactive?: boolean;
|
||||
id: number;
|
||||
compact?: boolean;
|
||||
avatarSize?: number;
|
||||
}
|
||||
|
||||
const Channel: FC<Props> = ({ interactive = true, id, compact = false, avatarSize = 32 }) => {
|
||||
const { channel, totalMemberCount } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: store.channels.byId[id],
|
||||
totalMemberCount: store.contacts.ids.length
|
||||
};
|
||||
});
|
||||
console.log("channel item", id, channel);
|
||||
|
||||
if (!channel) return null;
|
||||
const { name, members = [], is_public, avatar } = channel;
|
||||
return (
|
||||
@@ -71,4 +79,6 @@ export default function Channel({ interactive = true, id = "", compact = false,
|
||||
)}
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Channel;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, FC, MouseEvent, ChangeEvent } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Modal from "../Modal";
|
||||
@@ -6,24 +6,35 @@ import Button from "../styled/Button";
|
||||
import ChannelIcon from "../ChannelIcon";
|
||||
import Contact from "../Contact";
|
||||
import StyledWrapper from "./styled";
|
||||
// import StyledToggle from "../../component/styled/Toggle";
|
||||
import StyledCheckbox from "../styled/Checkbox";
|
||||
import useFilteredUsers from "../../hook/useFilteredUsers";
|
||||
|
||||
import { useCreateChannelMutation } from "../../../app/services/channel";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
|
||||
export default function ChannelModal({ personal = false, closeModal }) {
|
||||
interface Props {
|
||||
personal?: boolean;
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
interface CreateChannelDTO {
|
||||
name: string;
|
||||
description: string;
|
||||
members?: number[];
|
||||
is_public: boolean;
|
||||
}
|
||||
|
||||
const ChannelModal: FC<Props> = ({ personal = false, closeModal }) => {
|
||||
const { contactsData, loginUid } = useAppSelector((store) => {
|
||||
return { contactsData: store.contacts.byId, loginUid: store.authData.uid };
|
||||
});
|
||||
const navigateTo = useNavigate();
|
||||
const [data, setData] = useState({
|
||||
const [data, setData] = useState<CreateChannelDTO>({
|
||||
name: "",
|
||||
description: "",
|
||||
members: [loginUid],
|
||||
is_public: !personal
|
||||
});
|
||||
|
||||
const { contacts, input, updateInput } = useFilteredUsers();
|
||||
const [createChannel, { isSuccess, isError, isLoading, data: newChannelId }] =
|
||||
useCreateChannelMutation();
|
||||
@@ -35,6 +46,7 @@ export default function ChannelModal({ personal = false, closeModal }) {
|
||||
// });
|
||||
// };
|
||||
const handleCreate = () => {
|
||||
// todo: add field validation (maxLength, text format, trim)
|
||||
if (!data.name) {
|
||||
toast("please input channel name");
|
||||
return;
|
||||
@@ -46,11 +58,13 @@ export default function ChannelModal({ personal = false, closeModal }) {
|
||||
createChannel(data);
|
||||
};
|
||||
|
||||
// todo: delete the following code and use common error handler instead
|
||||
useEffect(() => {
|
||||
if (isError) {
|
||||
toast.error("create new channel failed");
|
||||
}
|
||||
}, [isError]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
toast.success("create new channel success");
|
||||
@@ -59,26 +73,25 @@ export default function ChannelModal({ personal = false, closeModal }) {
|
||||
}
|
||||
}, [isSuccess, newChannelId]);
|
||||
|
||||
const handleNameInput = (evt) => {
|
||||
setData((prev) => {
|
||||
return { ...prev, name: evt.target.value };
|
||||
});
|
||||
const handleNameInput = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
setData((prev) => ({ ...prev, name: evt.target.value }));
|
||||
};
|
||||
const handleInputChange = (evt) => {
|
||||
|
||||
const handleInputChange = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
updateInput(evt.target.value);
|
||||
};
|
||||
const toggleCheckMember = ({ currentTarget }) => {
|
||||
|
||||
const toggleCheckMember = ({ currentTarget }: MouseEvent<HTMLLIElement>) => {
|
||||
const { members } = data;
|
||||
const { uid } = currentTarget.dataset;
|
||||
let tmp = members.includes(+uid) ? members.filter((m) => m != uid) : [...members, +uid];
|
||||
setData((prev) => {
|
||||
return { ...prev, members: tmp };
|
||||
});
|
||||
setData((prev) => ({ ...prev, members: tmp }));
|
||||
};
|
||||
|
||||
const loginUser = contactsData[loginUid];
|
||||
if (!loginUser) return null;
|
||||
const { name, members, is_public } = data;
|
||||
|
||||
return (
|
||||
<Modal>
|
||||
<StyledWrapper>
|
||||
@@ -152,4 +165,6 @@ export default function ChannelModal({ personal = false, closeModal }) {
|
||||
</StyledWrapper>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ChannelModal;
|
||||
|
||||
@@ -6,7 +6,7 @@ import ContextMenu from "../ContextMenu";
|
||||
interface Props {
|
||||
enable?: boolean;
|
||||
uid: number;
|
||||
cid: number;
|
||||
cid?: number;
|
||||
visible: boolean;
|
||||
hide: () => void;
|
||||
children: ReactElement;
|
||||
|
||||
@@ -10,8 +10,8 @@ import useContextMenu from "../../hook/useContextMenu";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
|
||||
interface Props {
|
||||
cid: number;
|
||||
uid: number;
|
||||
cid?: number;
|
||||
owner?: number;
|
||||
dm?: boolean;
|
||||
interactive?: boolean;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import styled from "styled-components";
|
||||
import { useSelector } from "react-redux";
|
||||
import soundIcon from "../../assets/icons/sound.on.svg?url";
|
||||
import micIcon from "../../assets/icons/mic.on.svg?url";
|
||||
import Avatar from "./Avatar";
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { useSelector } from "react-redux";
|
||||
import Styled from "./styled";
|
||||
import ImageMessage from "./ImageMessage";
|
||||
import useRemoveLocalMessage from "../../hook/useRemoveLocalMessage";
|
||||
import useUploadFile from "../../hook/useUploadFile";
|
||||
import useSendMessage from "../../hook/useSendMessage";
|
||||
import Progress from "./Progress";
|
||||
import { getFileIcon, formatBytes, isImage, getImageSize } from "../../utils";
|
||||
import { getFileIcon, formatBytes, isImage, getImageSize, ImageSize } from "../../utils";
|
||||
// import { ReactComponent as IconDownload } from "../../../assets/icons/download.svg";
|
||||
// import { ReactComponent as IconClose } from "../../../assets/icons/close.circle.svg";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import IconDownload from "../../../assets/icons/download.svg";
|
||||
import IconClose from "../../../assets/icons/close.circle.svg";
|
||||
|
||||
@@ -21,17 +21,33 @@ const isLocalFile = (content: string) => {
|
||||
return content.startsWith("blob:");
|
||||
};
|
||||
|
||||
export default function FileMessage({
|
||||
context = "",
|
||||
to = null,
|
||||
interface Props {
|
||||
context: "user" | "channel";
|
||||
to: number;
|
||||
created_at: number;
|
||||
from_uid?: number;
|
||||
content: string;
|
||||
download: string;
|
||||
thumbnail: string;
|
||||
properties: {
|
||||
local_id: number;
|
||||
name: string;
|
||||
size: number;
|
||||
content_type: string;
|
||||
};
|
||||
}
|
||||
|
||||
const FileMessage: FC<Props> = ({
|
||||
context,
|
||||
to,
|
||||
created_at,
|
||||
from_uid = null,
|
||||
content = "",
|
||||
download = "",
|
||||
thumbnail = "",
|
||||
properties = { local_id: 0, name: "", size: 0, content_type: "" }
|
||||
}) {
|
||||
const [imageSize, setImageSize] = useState(null);
|
||||
}) => {
|
||||
const [imageSize, setImageSize] = useState<ImageSize | null>(null);
|
||||
const [uploadingFile, setUploadingFile] = useState(false);
|
||||
const removeLocalMessage = useRemoveLocalMessage({ context, id: to });
|
||||
const {
|
||||
@@ -44,10 +60,18 @@ export default function FileMessage({
|
||||
to
|
||||
});
|
||||
const { stopUploading, data, uploadFile, progress, isSuccess: uploadSuccess } = useUploadFile();
|
||||
const fromUser = useSelector((store) => store.contacts.byId[from_uid]);
|
||||
const fromUser = useAppSelector((store) => store.contacts.byId[from_uid]);
|
||||
const { size, name, content_type } = properties ?? {};
|
||||
useEffect(() => {
|
||||
const handleUpSend = async ({ url, name, type }) => {
|
||||
const handleUpSend = async ({
|
||||
url,
|
||||
name,
|
||||
type
|
||||
}: {
|
||||
url: string;
|
||||
name: string;
|
||||
type: string;
|
||||
}) => {
|
||||
try {
|
||||
setUploadingFile(true);
|
||||
if (type.startsWith("image")) {
|
||||
@@ -102,7 +126,6 @@ export default function FileMessage({
|
||||
|
||||
if (!content || !name) return null;
|
||||
|
||||
console.log("file content", content, name, content_type, size);
|
||||
const sending = uploadingFile || isSending;
|
||||
|
||||
if (isImage(content_type, size))
|
||||
@@ -152,4 +175,6 @@ export default function FileMessage({
|
||||
</div>
|
||||
</Styled>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default FileMessage;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { useState, MouseEvent } from "react";
|
||||
// import toast from "react-hot-toast";
|
||||
import { useState, MouseEvent, FC, ChangeEvent } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import Modal from "../Modal";
|
||||
import Button from "../styled/Button";
|
||||
import Input from "../styled/Input";
|
||||
import Channel from "../Channel";
|
||||
import Contact from "../Contact";
|
||||
// import Channel from "../Channel";
|
||||
import Reply from "../Message/Reply";
|
||||
import StyledWrapper from "./styled";
|
||||
import useForwardMessage from "../../hook/useForwardMessage";
|
||||
@@ -14,14 +13,18 @@ import useFilteredChannels from "../../hook/useFilteredChannels";
|
||||
import useFilteredUsers from "../../hook/useFilteredUsers";
|
||||
import CloseIcon from "../../../assets/icons/close.circle.svg";
|
||||
import StyledCheckbox from "../styled/Checkbox";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
export default function ForwardModal({ mids, closeModal }) {
|
||||
interface Props {
|
||||
mids: number[];
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
const ForwardModal: FC<Props> = ({ mids, closeModal }) => {
|
||||
const [appendText, setAppendText] = useState("");
|
||||
const { sendMessages } = useSendMessage();
|
||||
const { forwardMessage, forwarding } = useForwardMessage();
|
||||
const [selectedMembers, setSelectedMembers] = useState([]);
|
||||
const [selectedChannels, setSelectedChannels] = useState([]);
|
||||
const [selectedMembers, setSelectedMembers] = useState<number[]>([]);
|
||||
const [selectedChannels, setSelectedChannels] = useState<number[]>([]);
|
||||
const {
|
||||
channels,
|
||||
// input: channelInput,
|
||||
@@ -31,17 +34,20 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
// const { conactsData, loginUid } = useSelector((store) => {
|
||||
// return { conactsData: store.contacts.byId, loginUid: store.authData.uid };
|
||||
// });
|
||||
|
||||
const toggleCheck = ({ currentTarget }: MouseEvent<HTMLLIElement>) => {
|
||||
const { id, type = "user" } = currentTarget.dataset;
|
||||
const ids = type == "user" ? selectedMembers : selectedChannels;
|
||||
const ids: number[] = type == "user" ? selectedMembers : selectedChannels;
|
||||
const updateState = type == "user" ? setSelectedMembers : setSelectedChannels;
|
||||
let tmp = ids.includes(+id) ? ids.filter((m) => m != id) : [...ids, +id];
|
||||
console.log(id, currentTarget);
|
||||
const id_num = Number(id);
|
||||
let tmp = ids.includes(id_num) ? ids.filter((m) => m !== id_num) : [...ids, id_num];
|
||||
updateState(tmp);
|
||||
};
|
||||
const updateAppendText = (evt) => {
|
||||
|
||||
const updateAppendText = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
setAppendText(evt.target.value);
|
||||
};
|
||||
|
||||
const handleForward = async () => {
|
||||
await forwardMessage({
|
||||
mids: mids.map((mid) => +mid),
|
||||
@@ -58,21 +64,25 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
toast.success("Forward Message Successfully");
|
||||
closeModal();
|
||||
};
|
||||
const removeSelected = (id, from = "user") => {
|
||||
|
||||
const removeSelected = (id: number, from = "user") => {
|
||||
if (from == "user") {
|
||||
setSelectedMembers(selectedMembers.filter((m) => m != id));
|
||||
} else {
|
||||
setSelectedChannels(selectedChannels.filter((cid) => cid != id));
|
||||
}
|
||||
};
|
||||
const handleSearchChange = (evt) => {
|
||||
|
||||
const handleSearchChange = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
const newVal = evt.target.value;
|
||||
updateChannelInput(newVal);
|
||||
updateInput(newVal);
|
||||
};
|
||||
|
||||
let selectedCount = selectedMembers.length + selectedChannels.length;
|
||||
const sendButtonDisabled =
|
||||
(selectedChannels.length == 0 && selectedMembers.length == 0) || forwarding;
|
||||
|
||||
return (
|
||||
<Modal>
|
||||
<StyledWrapper>
|
||||
@@ -89,7 +99,6 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
channels.map((c) => {
|
||||
const { gid } = c;
|
||||
const checked = selectedChannels.includes(gid);
|
||||
console.log({ checked });
|
||||
return (
|
||||
<li
|
||||
key={gid}
|
||||
@@ -107,7 +116,6 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
contacts.map((u) => {
|
||||
const { uid } = u;
|
||||
const checked = selectedMembers.includes(uid);
|
||||
console.log({ checked });
|
||||
return (
|
||||
<li
|
||||
key={uid}
|
||||
@@ -179,4 +187,6 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
</StyledWrapper>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ForwardModal;
|
||||
|
||||
@@ -60,7 +60,7 @@ const GoogleLoginButton: FC<Props> = ({ clientId }) => {
|
||||
return (
|
||||
<StyledSocialButton disabled={!loaded || isLoading} onClick={handleGoogleLogin}>
|
||||
<img className="icon" src={googleSvg} alt="google icon" />
|
||||
{loaded ? `Sign in with Google` : `Initailizing`}
|
||||
{loaded ? "Sign in with Google" : "Initializing"}
|
||||
</StyledSocialButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, FC, MouseEvent, ChangeEvent } from "react";
|
||||
import styled from "styled-components";
|
||||
import { useSelector } from "react-redux";
|
||||
import toast from "react-hot-toast";
|
||||
import Button from "../styled/Button";
|
||||
import Input from "../styled/Input";
|
||||
@@ -9,6 +8,7 @@ import StyledCheckbox from "../styled/Checkbox";
|
||||
import { useAddMembersMutation } from "../../../app/services/channel";
|
||||
import CloseIcon from "../../../assets/icons/close.svg";
|
||||
import useFilteredUsers from "../../hook/useFilteredUsers";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
|
||||
const Styled = styled.div`
|
||||
padding-top: 16px;
|
||||
@@ -21,7 +21,7 @@ const Styled = styled.div`
|
||||
margin-bottom: 12px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e5e7eb;
|
||||
box-shadow: 0px 1px 2px rgba(31, 41, 55, 0.08);
|
||||
box-shadow: 0 1px 2px rgba(31, 41, 55, 0.08);
|
||||
border-radius: 4px;
|
||||
.selects {
|
||||
display: flex;
|
||||
@@ -96,10 +96,16 @@ const Styled = styled.div`
|
||||
line-height: 20px;
|
||||
}
|
||||
`;
|
||||
export default function AddMembers({ cid = null, closeModal }) {
|
||||
|
||||
interface Props {
|
||||
cid: null | number;
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
const AddMembers: FC<Props> = ({ cid = null, closeModal }) => {
|
||||
const [addMembers, { isLoading: isAdding, isSuccess }] = useAddMembersMutation();
|
||||
const [selects, setSelects] = useState([]);
|
||||
const { channel, contactData } = useSelector((store) => {
|
||||
const { channel, contactData } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: store.channels.byId[cid],
|
||||
contactData: store.contacts.byId
|
||||
@@ -116,7 +122,8 @@ export default function AddMembers({ cid = null, closeModal }) {
|
||||
addMembers({ id: cid, members: selects });
|
||||
};
|
||||
const { input, updateInput, contacts = [] } = useFilteredUsers();
|
||||
const toggleCheckMember = ({ currentTarget }) => {
|
||||
|
||||
const toggleCheckMember = ({ currentTarget }: MouseEvent<SVGSVGElement | HTMLLIElement>) => {
|
||||
const { uid } = currentTarget.dataset;
|
||||
if (selects.includes(+uid)) {
|
||||
setSelects((prevs) => {
|
||||
@@ -126,13 +133,15 @@ export default function AddMembers({ cid = null, closeModal }) {
|
||||
setSelects([...selects, +uid]);
|
||||
}
|
||||
};
|
||||
const handleFilterInput = (evt) => {
|
||||
|
||||
const handleFilterInput = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
updateInput(evt.target.value);
|
||||
};
|
||||
|
||||
if (!channel) return null;
|
||||
const { members: uids } = channel;
|
||||
const contactIds = contacts.map(({ uid }) => uid);
|
||||
console.log("selects", selects);
|
||||
|
||||
return (
|
||||
<Styled>
|
||||
<div className="filter">
|
||||
@@ -164,7 +173,7 @@ export default function AddMembers({ cid = null, closeModal }) {
|
||||
key={uid}
|
||||
data-uid={uid}
|
||||
className="user"
|
||||
onClick={added ? null : toggleCheckMember}
|
||||
onClick={added ? undefined : toggleCheckMember}
|
||||
>
|
||||
<StyledCheckbox
|
||||
disabled={added}
|
||||
@@ -183,4 +192,6 @@ export default function AddMembers({ cid = null, closeModal }) {
|
||||
</Button>
|
||||
</Styled>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default AddMembers;
|
||||
|
||||
@@ -4,12 +4,13 @@ import AddMembers from "./AddMembers";
|
||||
import CloseIcon from "../../../assets/icons/close.svg";
|
||||
import Modal from "../Modal";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import { FC } from "react";
|
||||
|
||||
const Styled = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
box-shadow: 0px 25px 50px rgba(31, 41, 55, 0.25);
|
||||
box-shadow: 0 25px 50px rgba(31, 41, 55, 0.25);
|
||||
border-radius: var(--br);
|
||||
padding: 16px;
|
||||
min-width: 408px;
|
||||
@@ -29,7 +30,15 @@ const Styled = styled.div`
|
||||
`;
|
||||
|
||||
// type: server,channel
|
||||
export default function InviteModal({ type = "server", cid = null, title = "", closeModal }) {
|
||||
|
||||
interface Props {
|
||||
type?: "server" | "channel";
|
||||
cid?: null | number;
|
||||
title?: string;
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
const InviteModal: FC<Props> = ({ type = "server", cid = null, title = "", closeModal }) => {
|
||||
const { channel, server } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: store.channels.byId[cid],
|
||||
@@ -49,4 +58,6 @@ export default function InviteModal({ type = "server", cid = null, title = "", c
|
||||
</Styled>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default InviteModal;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect } from "react";
|
||||
import { FC, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
import Tippy from "@tippyjs/react";
|
||||
import { hideAll } from "tippy.js";
|
||||
@@ -115,7 +115,11 @@ const StyledWrapper = styled.section`
|
||||
}
|
||||
`;
|
||||
|
||||
export default function ManageMembers({ cid = null }) {
|
||||
interface Props {
|
||||
cid?: number;
|
||||
}
|
||||
|
||||
const ManageMembers: FC<Props> = ({ cid = null }) => {
|
||||
const { contacts, channels, loginUser } = useAppSelector((store) => {
|
||||
return {
|
||||
contacts: store.contacts,
|
||||
@@ -246,4 +250,6 @@ export default function ManageMembers({ cid = null }) {
|
||||
</ul>
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ManageMembers;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, useRef, FC } from "react";
|
||||
import { useEffect, useState, useRef, FC, MouseEvent } from "react";
|
||||
import "prismjs/themes/prism.css";
|
||||
import "@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css";
|
||||
import codeSyntaxHighlight from "@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight-all.js";
|
||||
@@ -11,7 +11,7 @@ import codeSyntaxHighlight from "@toast-ui/editor-plugin-code-syntax-highlight/d
|
||||
|
||||
import { Viewer } from "@toast-ui/react-editor";
|
||||
import styled from "styled-components";
|
||||
import ImagePreviewModal from "./ImagePreviewModal";
|
||||
import ImagePreviewModal, { PreviewImageData } from "./ImagePreviewModal";
|
||||
|
||||
const Styled = styled.div`
|
||||
* {
|
||||
@@ -28,9 +28,9 @@ interface Props {
|
||||
content: string;
|
||||
}
|
||||
|
||||
const MrakdownRender: FC<Props> = ({ content }) => {
|
||||
const MarkdownRender: FC<Props> = ({ content }) => {
|
||||
const mdContainer = useRef<HTMLDivElement>(null);
|
||||
const [previewImage, setPreviewImage] = useState(null);
|
||||
const [previewImage, setPreviewImage] = useState<PreviewImageData | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const container = mdContainer?.current;
|
||||
@@ -77,4 +77,4 @@ const MrakdownRender: FC<Props> = ({ content }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default MrakdownRender;
|
||||
export default MarkdownRender;
|
||||
@@ -3,8 +3,13 @@ import renderContent from "./renderContent";
|
||||
import Avatar from "../Avatar";
|
||||
import StyledWrapper from "./styled";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import { FC } from "react";
|
||||
|
||||
export default function PreviewMessage({ mid = 0 }) {
|
||||
interface Props {
|
||||
mid?: number;
|
||||
}
|
||||
|
||||
const PreviewMessage: FC<Props> = ({ mid = 0 }) => {
|
||||
const { msg, contactsData } = useAppSelector((store) => {
|
||||
return { msg: store.message[mid], contactsData: store.contacts.byId };
|
||||
});
|
||||
@@ -33,4 +38,6 @@ export default function PreviewMessage({ mid = 0 }) {
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default PreviewMessage;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { MouseEvent, FC } from "react";
|
||||
import styled from "styled-components";
|
||||
import reactStringReplace from "react-string-replace";
|
||||
import MrakdownRender from "../MrakdownRender";
|
||||
import MarkdownRender from "../MarkdownRender";
|
||||
import Mention from "./Mention";
|
||||
import { ContentTypes } from "../../../app/config";
|
||||
import { getFileIcon, isImage } from "../../utils";
|
||||
@@ -122,7 +122,7 @@ const renderContent = (data) => {
|
||||
case ContentTypes.markdown:
|
||||
res = (
|
||||
<div className="md">
|
||||
<MrakdownRender content={content} />
|
||||
<MarkdownRender content={content} />
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -5,7 +5,7 @@ import reactStringReplace from "react-string-replace";
|
||||
import { ContentTypes } from "../../../app/config";
|
||||
import Mention from "./Mention";
|
||||
import ForwardedMessage from "./ForwardedMessage";
|
||||
import MrakdownRender from "../MrakdownRender";
|
||||
import MarkdownRender from "../MarkdownRender";
|
||||
import FileMessage from "../FileMessage";
|
||||
import URLPreview from "./URLPreview";
|
||||
|
||||
@@ -54,7 +54,7 @@ const renderContent = ({
|
||||
break;
|
||||
case ContentTypes.markdown:
|
||||
{
|
||||
ctn = <MrakdownRender content={content} />;
|
||||
ctn = <MarkdownRender content={content} />;
|
||||
}
|
||||
break;
|
||||
case ContentTypes.file:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// import React from 'react'
|
||||
import { Helmet } from "react-helmet";
|
||||
import BASE_URL from "../../app/config";
|
||||
import { useGetServerQuery } from "../../app/services/server";
|
||||
@@ -7,11 +6,9 @@ export default function Meta() {
|
||||
const { data, isSuccess } = useGetServerQuery();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<link rel="icon" href={`${BASE_URL}/resource/organization/logo`} />
|
||||
{isSuccess && <title>{data.name} Web App</title>}
|
||||
</Helmet>
|
||||
</>
|
||||
<Helmet>
|
||||
<link rel="icon" href={`${BASE_URL}/resource/organization/logo`} />
|
||||
{isSuccess && <title>{data.name} Web App</title>}
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useAppSelector } from "../../../app/store";
|
||||
interface Props {
|
||||
uid: number;
|
||||
type: string;
|
||||
cid: number;
|
||||
cid?: number;
|
||||
}
|
||||
|
||||
const Profile: FC<Props> = ({ uid = null, type = "embed", cid = null }) => {
|
||||
|
||||
@@ -2,7 +2,7 @@ import reactStringReplace from "react-string-replace";
|
||||
import styled from "styled-components";
|
||||
import Mention from "../Message/Mention";
|
||||
import { ContentTypes } from "../../../app/config";
|
||||
import MrakdownRender from "../MrakdownRender";
|
||||
import MarkdownRender from "../MarkdownRender";
|
||||
import closeIcon from "../../../assets/icons/close.circle.svg?url";
|
||||
import pictureIcon from "../../../assets/icons/picture.svg?url";
|
||||
import { getFileIcon, isImage } from "../../utils";
|
||||
@@ -91,7 +91,7 @@ const renderContent = (data) => {
|
||||
case ContentTypes.markdown:
|
||||
res = (
|
||||
<div className="md">
|
||||
<MrakdownRender content={content} />
|
||||
<MarkdownRender content={content} />
|
||||
</div>
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -51,19 +51,21 @@ export default function Toolbar({
|
||||
to,
|
||||
context
|
||||
}) {
|
||||
// todo: check code logic
|
||||
const { addStageFile } = useUploadFile({ context, id: to });
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const handleUpload = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
const files = [...evt.target.files];
|
||||
console.log("files", files);
|
||||
if (!evt.target.files) return;
|
||||
const files = Array.from(evt.target.files);
|
||||
const filesData = files.map((file) => {
|
||||
const { size, type, name } = file;
|
||||
const url = URL.createObjectURL(file);
|
||||
return { size, type, name, url };
|
||||
});
|
||||
addStageFile(filesData);
|
||||
// todo: check code logic
|
||||
// @ts-ignore
|
||||
fileInputRef.current.value = null;
|
||||
// @ts-ignore
|
||||
fileInputRef.current.value = "";
|
||||
// setFiles([...evt.target.files]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user