refactor: more TS code
This commit is contained in:
@@ -68,7 +68,7 @@ const Styled = styled.div`
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
type?: "chat";
|
||||
type?: "chat" | "user";
|
||||
}
|
||||
|
||||
const BlankPlaceholder: FC<Props> = ({ type = "chat" }) => {
|
||||
|
||||
@@ -32,7 +32,6 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
.name {
|
||||
/* user-select: text; */
|
||||
display: flex;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
|
||||
@@ -3,18 +3,17 @@ import styled from "styled-components";
|
||||
import HashIcon from "../../assets/icons/channel.svg";
|
||||
import LockHashIcon from "../../assets/icons/channel.private.svg";
|
||||
|
||||
interface Props {
|
||||
personal?: boolean;
|
||||
muted?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const Styled = styled.div`
|
||||
display: flex;
|
||||
&.muted path {
|
||||
fill: #d0d5dd;
|
||||
}
|
||||
`;
|
||||
interface Props {
|
||||
personal?: boolean;
|
||||
muted?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ChannelIcon: FC<Props> = ({ personal = false, muted = false, className = "" }) => {
|
||||
return (
|
||||
|
||||
@@ -4,6 +4,7 @@ import micIcon from "../../assets/icons/mic.on.svg?url";
|
||||
import Avatar from "./Avatar";
|
||||
import useConfig from "../hook/useConfig";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
import { FC } from "react";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
background-color: #f4f4f5;
|
||||
@@ -60,8 +61,8 @@ const StyledWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function CurrentUser() {
|
||||
type Props = {};
|
||||
const CurrentUser: FC<Props> = () => {
|
||||
const { values: agoraConfig } = useConfig("agora");
|
||||
const currUser = useAppSelector((store) => {
|
||||
return store.authData.user;
|
||||
@@ -86,4 +87,5 @@ export default function CurrentUser() {
|
||||
)}
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default CurrentUser;
|
||||
|
||||
@@ -11,8 +11,6 @@ interface Props {
|
||||
const StyledWrapper = styled.div`
|
||||
filter: drop-shadow(0px 25px 50px rgba(31, 41, 55, 0.25));
|
||||
border-radius: 12px;
|
||||
/* height: 358px;
|
||||
overflow: hidden; */
|
||||
.emoji-mart {
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
@@ -43,10 +41,6 @@ const EmojiPicker: FC<Props> = ({ onSelect, ...rest }) => {
|
||||
perLine={10}
|
||||
emojiSize={24}
|
||||
emojiTooltip={true}
|
||||
// set="twitter"
|
||||
// data={data}
|
||||
// set="twitter"
|
||||
// showPreview={false}
|
||||
showSkinTones={false}
|
||||
onSelect={onSelect}
|
||||
{...rest}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { FC } from "react";
|
||||
import styled from "styled-components";
|
||||
import { useGetServerVersionQuery } from "../../app/services/server";
|
||||
|
||||
@@ -6,8 +7,8 @@ const Styled = styled.div`
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
`;
|
||||
|
||||
export default function FAQ() {
|
||||
type Props = {};
|
||||
const FAQ: FC<Props> = () => {
|
||||
const { data: serverVersion } = useGetServerVersionQuery();
|
||||
return (
|
||||
<Styled>
|
||||
@@ -16,4 +17,5 @@ export default function FAQ() {
|
||||
<div className="item">Build Timestamp: {process.env.REACT_APP_BUILD_TIME}</div>
|
||||
</Styled>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default FAQ;
|
||||
|
||||
@@ -25,7 +25,7 @@ interface Props {
|
||||
context: "user" | "channel";
|
||||
to: number;
|
||||
created_at: number;
|
||||
from_uid?: number;
|
||||
from_uid: number;
|
||||
content: string;
|
||||
download: string;
|
||||
thumbnail: string;
|
||||
@@ -41,7 +41,7 @@ const FileMessage: FC<Props> = ({
|
||||
context,
|
||||
to,
|
||||
created_at,
|
||||
from_uid = null,
|
||||
from_uid,
|
||||
content = "",
|
||||
download = "",
|
||||
thumbnail = "",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, MouseEvent, ChangeEvent } from "react";
|
||||
import { useState, MouseEvent, ChangeEvent, FC } from "react";
|
||||
// import toast from "react-hot-toast";
|
||||
import Modal from "../Modal";
|
||||
import Button from "../styled/Button";
|
||||
@@ -15,8 +15,12 @@ import useFilteredUsers from "../../hook/useFilteredUsers";
|
||||
import CloseIcon from "../../../assets/icons/close.circle.svg";
|
||||
import StyledCheckbox from "../styled/Checkbox";
|
||||
import toast from "react-hot-toast";
|
||||
interface IProps {
|
||||
mids: number[];
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
export default function ForwardModal({ mids, closeModal }) {
|
||||
const ForwardModal: FC<IProps> = ({ mids, closeModal }) => {
|
||||
const [appendText, setAppendText] = useState("");
|
||||
const { sendMessages } = useSendMessage();
|
||||
const { forwardMessage, forwarding } = useForwardMessage();
|
||||
@@ -176,4 +180,5 @@ export default function ForwardModal({ mids, closeModal }) {
|
||||
</StyledWrapper>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default ForwardModal;
|
||||
|
||||
@@ -6,6 +6,7 @@ import { KEY_LOCAL_MAGIC_TOKEN } from "../../app/config";
|
||||
import Button from "./styled/Button";
|
||||
import { useLoginMutation } from "../../app/services/auth";
|
||||
import toast from "react-hot-toast";
|
||||
import { FetchBaseQueryError } from "@reduxjs/toolkit/dist/query";
|
||||
|
||||
const StyledSocialButton = styled(Button)`
|
||||
width: 100%;
|
||||
@@ -51,7 +52,8 @@ const GithubLoginButton: FC<Props> = ({ type = "login", client_id }) => {
|
||||
}, [isSuccess]);
|
||||
useEffect(() => {
|
||||
if (error) {
|
||||
switch (error?.status) {
|
||||
// todo: why?
|
||||
switch ((error as FetchBaseQueryError).status) {
|
||||
case 410:
|
||||
toast.error(
|
||||
"No associated account found, please user admin for an invitation link to join."
|
||||
|
||||
@@ -66,13 +66,13 @@ const GoogleLoginInner: FC<Props> = ({ type = "login", loaded, loadError }) => {
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<StyledSocialButton disabled={!loaded || isLoading} onClick={null}>
|
||||
<StyledSocialButton disabled={!loaded || isLoading}>
|
||||
<div className="invisible">
|
||||
<GoogleLogin
|
||||
onSuccess={(res) => {
|
||||
login({
|
||||
magic_token,
|
||||
id_token: res.credential,
|
||||
id_token: res.credential || "",
|
||||
type: "google"
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -66,10 +66,10 @@ const StyledWrapper = styled.div`
|
||||
|
||||
export interface PreviewImageData {
|
||||
originUrl: string;
|
||||
thumbnail: string;
|
||||
downloadLink: string;
|
||||
name: string;
|
||||
type: string;
|
||||
thumbnail?: string;
|
||||
downloadLink?: string;
|
||||
name?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
||||
@@ -2,6 +2,7 @@ import styled from "styled-components";
|
||||
import useInviteLink from "../hook/useInviteLink";
|
||||
import Input from "./styled/Input";
|
||||
import Button from "./styled/Button";
|
||||
import { FC } from "react";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
display: flex;
|
||||
@@ -37,8 +38,8 @@ const StyledWrapper = styled.div`
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function InviteLink() {
|
||||
type Props = {};
|
||||
const InviteLink: FC<Props> = () => {
|
||||
const { generating, link, linkCopied, copyLink, generateNewLink } = useInviteLink();
|
||||
const handleNewLink = () => {
|
||||
generateNewLink();
|
||||
@@ -59,4 +60,6 @@ export default function InviteLink() {
|
||||
</Button>
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default InviteLink;
|
||||
|
||||
@@ -135,7 +135,15 @@ const ManageMembers: FC<Props> = ({ cid }) => {
|
||||
}
|
||||
}, [updateSuccess]);
|
||||
|
||||
const handleToggleRole = ({ ignore = false, uid = null, isAdmin = true }) => {
|
||||
const handleToggleRole = ({
|
||||
ignore = false,
|
||||
uid,
|
||||
isAdmin = true
|
||||
}: {
|
||||
ignore: boolean;
|
||||
uid: number;
|
||||
isAdmin: boolean;
|
||||
}) => {
|
||||
hideAll();
|
||||
if (ignore) return;
|
||||
updateUser({ id: uid, is_admin: isAdmin });
|
||||
@@ -154,7 +162,9 @@ const ManageMembers: FC<Props> = ({ cid }) => {
|
||||
</div>
|
||||
<ul className="members">
|
||||
{uids.map((uid) => {
|
||||
const { name, email, is_admin } = users.byId[uid];
|
||||
const currUser = users.byId[uid];
|
||||
if (!currUser) return null;
|
||||
const { name, email, is_admin } = currUser;
|
||||
const owner = channel && channel.owner == uid;
|
||||
const switchRoleVisible = loginUser.is_admin && loginUser.uid !== uid;
|
||||
const dotsVisible = email || loginUser?.is_admin;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { useEffect, useState, useRef, SyntheticEvent } from "react";
|
||||
import { useEffect, useState, useRef, FC } from "react";
|
||||
import { BeforeInstallPromptEvent } from "../../../types/global";
|
||||
import Prompt from "./Prompt";
|
||||
import usePrompt from "./usePrompt";
|
||||
|
||||
export default function Manifest() {
|
||||
interface IProps {}
|
||||
const Manifest: FC<IProps> = () => {
|
||||
const { setCanceled: setCanceled, prompted } = usePrompt();
|
||||
const deferredPromptRef = useRef(null);
|
||||
const deferredPromptRef = useRef<null | BeforeInstallPromptEvent>(null);
|
||||
const [popup, setPopup] = useState(false);
|
||||
useEffect(() => {
|
||||
const handleInstallPromotion = (e: SyntheticEvent) => {
|
||||
const handleInstallPromotion = (e: BeforeInstallPromptEvent) => {
|
||||
// Prevent the mini-infobar from appearing on mobile
|
||||
e.preventDefault();
|
||||
// Stash the event so it can be triggered later.
|
||||
@@ -21,20 +22,6 @@ export default function Manifest() {
|
||||
deferredPromptRef.current = null;
|
||||
setPopup(false);
|
||||
};
|
||||
// if (isSuccess && data) {
|
||||
// console.log("server", data);
|
||||
// manifest.name = `${data.name}'s Chat`;
|
||||
// // const stringManifest = JSON.stringify(manifest);
|
||||
// // const blob = new Blob([stringManifest], { type: "application/json" });
|
||||
// // const manifestURL = URL.createObjectURL(blob);
|
||||
// let content = encodeURIComponent(JSON.stringify(manifest));
|
||||
// let manifestURL = "data:application/manifest+json," + content;
|
||||
// const manifestEle = document.querySelector("#my-manifest-placeholder");
|
||||
// if (manifestEle) {
|
||||
// manifestEle.setAttribute("href", manifestURL);
|
||||
// }
|
||||
|
||||
// }
|
||||
window.addEventListener("beforeinstallprompt", handleInstallPromotion, true);
|
||||
window.addEventListener("appinstalled", handleInstalled);
|
||||
return () => {
|
||||
@@ -61,4 +48,5 @@ export default function Manifest() {
|
||||
};
|
||||
if (!popup || prompted) return null;
|
||||
return <Prompt handleInstall={handleInstall} closePrompt={handleClose} />;
|
||||
}
|
||||
};
|
||||
export default Manifest;
|
||||
|
||||
@@ -27,7 +27,7 @@ function MarkdownEditor({
|
||||
const editorInstance = editor.getInstance();
|
||||
editorInstance.removeHook("addImageBlobHook");
|
||||
editorInstance.addHook("addImageBlobHook", async (blob, callback) => {
|
||||
const { thumbnail = "" } = await uploadFile(blob);
|
||||
const { thumbnail = "" } = (await uploadFile(blob)) || {};
|
||||
callback(thumbnail);
|
||||
});
|
||||
setEditorInstance(editorInstance);
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import { useEffect, useState, useRef, FC, MouseEvent } from "react";
|
||||
import { useEffect, useState, useRef, FC } 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";
|
||||
|
||||
// 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";
|
||||
// Import prismjs
|
||||
// import Prism from "prismjs";
|
||||
|
||||
import { Viewer } from "@toast-ui/react-editor";
|
||||
import styled from "styled-components";
|
||||
import ImagePreviewModal, { PreviewImageData } from "./ImagePreviewModal";
|
||||
@@ -24,37 +18,37 @@ const Styled = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
interface IProps {
|
||||
content: string;
|
||||
}
|
||||
|
||||
const MarkdownRender: FC<Props> = ({ content }) => {
|
||||
const mdContainer = useRef<HTMLDivElement>(null);
|
||||
const MarkdownRender: FC<IProps> = ({ content }) => {
|
||||
const mdContainer = useRef<HTMLDivElement>();
|
||||
const [previewImage, setPreviewImage] = useState<PreviewImageData | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const container = mdContainer?.current;
|
||||
if (container) {
|
||||
// 点击查看大图
|
||||
container.addEventListener(
|
||||
"click",
|
||||
(evt) => {
|
||||
console.log(evt);
|
||||
evt.stopPropagation();
|
||||
const { target } = evt;
|
||||
// 图片
|
||||
if (target.nodeName == "IMG") {
|
||||
const urlObj = new URL(target.src);
|
||||
const originUrl = `${urlObj.origin}${
|
||||
urlObj.pathname
|
||||
}?file_path=${urlObj.searchParams.get("file_path")}`;
|
||||
const data = { originUrl };
|
||||
setPreviewImage(data);
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
if (!container) return;
|
||||
// 点击查看大图
|
||||
// todo: 事件代理
|
||||
container.addEventListener(
|
||||
"click",
|
||||
(evt) => {
|
||||
console.log(evt);
|
||||
evt.stopPropagation();
|
||||
const target = evt.target as HTMLImageElement;
|
||||
if (!target) return;
|
||||
// 图片
|
||||
if (target.nodeName == "IMG") {
|
||||
const urlObj = new URL(target.src);
|
||||
const originUrl = `${urlObj.origin}${urlObj.pathname}?file_path=${urlObj.searchParams.get(
|
||||
"file_path"
|
||||
)}`;
|
||||
const data = { originUrl };
|
||||
setPreviewImage(data);
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
}, []);
|
||||
|
||||
const closePreviewModal = () => {
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
import { FC, ReactElement, useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import StyledMsg from "./styled";
|
||||
import renderContent from "./renderContent";
|
||||
import Avatar from "../Avatar";
|
||||
import useFavMessage from "../../hook/useFavMessage";
|
||||
|
||||
const StyledFav = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: var(--br);
|
||||
background-color: #f4f4f5;
|
||||
`;
|
||||
type Props = {
|
||||
id?: number;
|
||||
};
|
||||
const FavoredMessage: FC<Props> = ({ id }) => {
|
||||
const { favorites } = useFavMessage({});
|
||||
const [msgs, setMsgs] = useState<ReactElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const current = favorites.find((f) => f.id == id);
|
||||
const { messages } = current || {};
|
||||
if (!messages) return;
|
||||
const favorite_mids = messages.map(({ from_mid }) => +from_mid) || [];
|
||||
|
||||
setMsgs(
|
||||
<StyledFav data-favorite-mids={favorite_mids.join(",")} className="favorite">
|
||||
<div className="list">
|
||||
{messages.map((msg, idx) => {
|
||||
const { user = {}, download, content, content_type, properties, thumbnail } = msg;
|
||||
return (
|
||||
<StyledMsg className="archive" key={idx}>
|
||||
{user && (
|
||||
<div className="avatar">
|
||||
<Avatar url={user.avatar} name={user.name} />
|
||||
</div>
|
||||
)}
|
||||
<div className="details">
|
||||
<div className="up">
|
||||
<span className="name">{user?.name}</span>
|
||||
</div>
|
||||
<div className="down">
|
||||
{renderContent({
|
||||
download,
|
||||
content,
|
||||
content_type,
|
||||
properties,
|
||||
thumbnail
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</StyledMsg>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</StyledFav>
|
||||
);
|
||||
}, [favorites, id]);
|
||||
|
||||
if (!id) return null;
|
||||
|
||||
return msgs;
|
||||
};
|
||||
|
||||
export default FavoredMessage;
|
||||
@@ -1,65 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import StyledMsg from "./styled";
|
||||
import renderContent from "./renderContent";
|
||||
import Avatar from "../Avatar";
|
||||
import useFavMessage from "../../hook/useFavMessage";
|
||||
|
||||
const StyledFav = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-radius: var(--br);
|
||||
background-color: #f4f4f5;
|
||||
`;
|
||||
|
||||
const FavoritedMessage = ({ id }) => {
|
||||
const { favorites } = useFavMessage({});
|
||||
const [msgs, setMsgs] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const current = favorites.find((f) => f.id == id);
|
||||
const { messages } = current || {};
|
||||
if (messages) {
|
||||
const favorite_mids = messages.map(({ from_mid }) => from_mid) || [];
|
||||
|
||||
setMsgs(
|
||||
<StyledFav data-favorite-mids={favorite_mids.join(",")} className="favorite">
|
||||
<div className="list">
|
||||
{messages.map((msg, idx) => {
|
||||
const { user = {}, download, content, content_type, properties, thumbnail } = msg;
|
||||
return (
|
||||
<StyledMsg className="archive" key={idx}>
|
||||
{user && (
|
||||
<div className="avatar">
|
||||
<Avatar url={user.avatar} name={user.name} />
|
||||
</div>
|
||||
)}
|
||||
<div className="details">
|
||||
<div className="up">
|
||||
<span className="name">{user?.name}</span>
|
||||
</div>
|
||||
<div className="down">
|
||||
{renderContent({
|
||||
download,
|
||||
content,
|
||||
content_type,
|
||||
properties,
|
||||
thumbnail
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</StyledMsg>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</StyledFav>
|
||||
);
|
||||
}
|
||||
}, [favorites, id]);
|
||||
|
||||
if (!id) return null;
|
||||
|
||||
return msgs;
|
||||
};
|
||||
|
||||
export default FavoritedMessage;
|
||||
@@ -1,8 +1,9 @@
|
||||
import { FC } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import BASE_URL from "../../app/config";
|
||||
import { useGetServerQuery } from "../../app/services/server";
|
||||
|
||||
export default function Meta() {
|
||||
type Props = {};
|
||||
const Meta: FC<Props> = () => {
|
||||
const { data, isSuccess } = useGetServerQuery();
|
||||
|
||||
return (
|
||||
@@ -11,4 +12,5 @@ export default function Meta() {
|
||||
{isSuccess && <title>{data.name} Web App</title>}
|
||||
</Helmet>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default Meta;
|
||||
|
||||
@@ -2,9 +2,8 @@ import { useState } from "react";
|
||||
import { initializeApp } from "firebase/app";
|
||||
import { getToken, getMessaging } from "firebase/messaging";
|
||||
import { firebaseConfig } from "../../../app/config";
|
||||
|
||||
const useDeviceToken = (vapidKey) => {
|
||||
const [token, setToken] = useState(null);
|
||||
const useDeviceToken = (vapidKey: string) => {
|
||||
const [token, setToken] = useState<string | null>(null);
|
||||
// https only
|
||||
if (navigator.serviceWorker) {
|
||||
const messaging = getMessaging(initializeApp(firebaseConfig));
|
||||
@@ -17,7 +16,7 @@ const useDeviceToken = (vapidKey) => {
|
||||
console.log("current token for client: ", currentToken);
|
||||
setToken(currentToken);
|
||||
// updateDeviceToken(currentToken)
|
||||
// Perform any other neccessary action with the token
|
||||
// Perform any other necessary action with the token
|
||||
} else {
|
||||
// Show permission request UI
|
||||
console.log("No registration token available. Request permission to generate one.");
|
||||
|
||||
@@ -11,8 +11,8 @@ import useUserOperation from "../../hook/useUserOperation";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
|
||||
interface Props {
|
||||
uid?: number;
|
||||
type: string;
|
||||
uid: number;
|
||||
type?: "embed" | "card";
|
||||
cid?: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import searchIcon from "../../assets/icons/search.svg?url";
|
||||
import addIcon from "../../assets/icons/add.svg?url";
|
||||
import AddEntriesMenu from "./AddEntriesMenu";
|
||||
import Tooltip from "./Tooltip";
|
||||
import { FC } from "react";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
position: relative;
|
||||
@@ -32,8 +33,8 @@ const StyledWrapper = styled.div`
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Search() {
|
||||
type Props = {};
|
||||
const Search: FC<Props> = () => {
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="search">
|
||||
@@ -47,4 +48,5 @@ export default function Search() {
|
||||
</Tooltip>
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default Search;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, FC } from "react";
|
||||
import useSendMessage from "../../hook/useSendMessage";
|
||||
import useAddLocalFileMessage from "../../hook/useAddLocalFileMessage";
|
||||
import { updateInputMode } from "../../../app/slices/ui";
|
||||
@@ -20,11 +20,15 @@ const Modes = {
|
||||
text: "text",
|
||||
markdown: "markdown"
|
||||
};
|
||||
function Send({
|
||||
interface IProps {
|
||||
context?: "channel" | "user";
|
||||
id: number;
|
||||
}
|
||||
const Send: FC<IProps> = ({
|
||||
// 发给谁,或者是channel,或者是user
|
||||
context = "channel",
|
||||
id = ""
|
||||
}) {
|
||||
id
|
||||
}) => {
|
||||
const { resetStageFiles } = useUploadFile({ context, id });
|
||||
const { getDraft, getUpdateDraft } = useDraft({ context, id });
|
||||
const editor = useMixedEditor(`${context}_${id}`);
|
||||
@@ -111,7 +115,7 @@ function Send({
|
||||
resetStageFiles();
|
||||
}
|
||||
};
|
||||
const sendMarkdown = async (content) => {
|
||||
const sendMarkdown = async (content: string) => {
|
||||
sendMessage({
|
||||
id,
|
||||
reply_mid: replying_mid,
|
||||
@@ -173,7 +177,7 @@ function Send({
|
||||
</div>
|
||||
</StyledSend>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Send;
|
||||
// export default memo(Send, (prevs, nexts) => {
|
||||
|
||||
Reference in New Issue
Block a user