refactor: more TS code
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { FC, MouseEvent } from "react";
|
||||
import { FC, MouseEvent, ReactElement } from "react";
|
||||
import StyledMenu from "./styled/Menu";
|
||||
|
||||
export interface Item {
|
||||
title: string;
|
||||
icon?: string;
|
||||
icon?: string | ReactElement;
|
||||
handler: (e: MouseEvent) => void;
|
||||
underline?: boolean;
|
||||
danger?: boolean;
|
||||
|
||||
@@ -97,12 +97,12 @@ interface Props {
|
||||
closeModal: () => void;
|
||||
}
|
||||
|
||||
const AddMembers: FC<Props> = ({ cid, closeModal }) => {
|
||||
const AddMembers: FC<Props> = ({ cid = 0, closeModal }) => {
|
||||
const [addMembers, { isLoading: isAdding, isSuccess }] = useAddMembersMutation();
|
||||
const [selects, setSelects] = useState<number[]>([]);
|
||||
const { channel, userData } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: cid ? store.channels.byId[cid] : null,
|
||||
channel: store.channels.byId[cid],
|
||||
userData: store.users.byId
|
||||
};
|
||||
});
|
||||
|
||||
@@ -29,8 +29,6 @@ const Styled = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
// type: server,channel
|
||||
|
||||
interface Props {
|
||||
type?: "server" | "channel";
|
||||
cid?: number;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRef, useEffect } from "react";
|
||||
import { useRef, useEffect, FC } from "react";
|
||||
import "@toast-ui/editor/dist/toastui-editor.css";
|
||||
import { Editor } from "@toast-ui/react-editor";
|
||||
import "prismjs/themes/prism.css";
|
||||
@@ -9,15 +9,22 @@ import StyledWrapper from "./styled";
|
||||
import useUploadFile from "../../hook/useUploadFile";
|
||||
|
||||
import Button from "../styled/Button";
|
||||
|
||||
function MarkdownEditor({
|
||||
type Props = {
|
||||
updateDraft?: (draft: string) => void;
|
||||
initialValue: string;
|
||||
height: string;
|
||||
placeholder: string;
|
||||
sendMarkdown: (md: string) => void;
|
||||
setEditorInstance: () => void;
|
||||
};
|
||||
const MarkdownEditor: FC<Props> = ({
|
||||
updateDraft = null,
|
||||
initialValue = "",
|
||||
height = "50vh",
|
||||
placeholder,
|
||||
sendMarkdown,
|
||||
setEditorInstance
|
||||
}) {
|
||||
}) => {
|
||||
const editorRef = useRef<Editor | undefined>(undefined);
|
||||
const { uploadFile } = useUploadFile();
|
||||
// const [pHolder, setPHolder] = useState(placeholder);
|
||||
@@ -73,5 +80,5 @@ function MarkdownEditor({
|
||||
</Button>
|
||||
</StyledWrapper>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default MarkdownEditor;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useState, useRef, FC } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import styled from "styled-components";
|
||||
import Tippy from "@tippyjs/react";
|
||||
@@ -61,8 +61,13 @@ const StyledCmds = styled.ul`
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
`;
|
||||
|
||||
export default function Commands({ context = "user", contextId = 0, mid = 0, toggleEditMessage }) {
|
||||
type Props = {
|
||||
context: "user" | "channel";
|
||||
contextId: number;
|
||||
mid: number;
|
||||
toggleEditMessage: () => void;
|
||||
};
|
||||
const Commands: FC<Props> = ({ context = "user", contextId = 0, mid = 0, toggleEditMessage }) => {
|
||||
const {
|
||||
canDelete,
|
||||
canReply,
|
||||
@@ -84,19 +89,17 @@ export default function Commands({ context = "user", contextId = 0, mid = 0, tog
|
||||
const dispatch = useDispatch();
|
||||
const [tippyVisible, setTippyVisible] = useState(false);
|
||||
const cmdsRef = useRef(null);
|
||||
const handleReply = (fromMenu) => {
|
||||
const handleReply = () => {
|
||||
if (contextId) {
|
||||
setReplying(mid);
|
||||
}
|
||||
if (fromMenu) {
|
||||
hideAll();
|
||||
}
|
||||
hideAll();
|
||||
};
|
||||
|
||||
const handleTippyVisible = (visible = true) => {
|
||||
setTippyVisible(visible);
|
||||
};
|
||||
const handleSelect = (mid) => {
|
||||
const handleSelect = (mid: number) => {
|
||||
dispatch(updateSelectMessages({ context, id: contextId, data: mid }));
|
||||
hideAll();
|
||||
};
|
||||
@@ -202,4 +205,5 @@ export default function Commands({ context = "user", contextId = 0, mid = 0, tog
|
||||
{DeleteModal}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default Commands;
|
||||
|
||||
@@ -8,11 +8,6 @@ const StyledMsg = styled.div`
|
||||
padding: 4px 8px;
|
||||
margin: 8px 0;
|
||||
border-radius: 8px;
|
||||
/* content-visibility: auto;
|
||||
contain-intrinsic-size: auto 150px; */
|
||||
/* &.in_view {
|
||||
content-visibility: visible;
|
||||
} */
|
||||
&[data-highlight="true"] {
|
||||
background: #f5f6f7;
|
||||
}
|
||||
@@ -22,8 +17,6 @@ const StyledMsg = styled.div`
|
||||
&:hover,
|
||||
&.contextVisible,
|
||||
&.preview {
|
||||
/* content-visibility: inherit;
|
||||
contain-intrinsic-size: inherit; */
|
||||
background: #f5f6f7;
|
||||
.cmds {
|
||||
visibility: visible;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useOutsideClick } from "rooks";
|
||||
import Tooltip from "../Tooltip";
|
||||
import Picker from "../EmojiPicker";
|
||||
import SmileIcon from "../../../assets/icons/emoji.smile.svg";
|
||||
import { BaseEmoji, EmojiData } from "emoji-mart";
|
||||
|
||||
const Styled = styled.div`
|
||||
position: relative;
|
||||
@@ -29,7 +30,7 @@ const Styled = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export default function EmojiPicker({ selectEmoji }) {
|
||||
export default function EmojiPicker({ selectEmoji }: { selectEmoji: (e: string) => void }) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const [visible, setVisible] = useState(false);
|
||||
|
||||
@@ -37,9 +38,9 @@ export default function EmojiPicker({ selectEmoji }) {
|
||||
setVisible((prev) => !prev);
|
||||
};
|
||||
|
||||
const handleSelect = (emoji) => {
|
||||
const handleSelect = (emoji: EmojiData) => {
|
||||
console.log("semojii", emoji);
|
||||
selectEmoji(emoji.native);
|
||||
selectEmoji((emoji as BaseEmoji).native);
|
||||
};
|
||||
|
||||
useOutsideClick(
|
||||
@@ -49,9 +50,7 @@ export default function EmojiPicker({ selectEmoji }) {
|
||||
const ignore =
|
||||
(clickEle.nodeName == "svg" && clickEle.dataset.emoji == "toggler") ||
|
||||
(clickEle.nodeName == "path" && clickEle.parentElement.dataset.emoji == "toggler");
|
||||
// console.log("outside click", clickEle, clickEle.parentElement, ignore);
|
||||
if (ignore) return;
|
||||
// if(clickEle)
|
||||
setVisible(false);
|
||||
},
|
||||
visible
|
||||
|
||||
@@ -64,7 +64,7 @@ const Send: FC<IProps> = ({
|
||||
}
|
||||
}, [replying_mid]);
|
||||
|
||||
const insertEmoji = (emoji) => {
|
||||
const insertEmoji = (emoji: string) => {
|
||||
if (mode == Modes.markdown && markdownEditor) {
|
||||
// markdown insert emoji
|
||||
markdownEditor.insertText(emoji);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useAppSelector } from "../../../app/store";
|
||||
interface Props {
|
||||
uid: number;
|
||||
cid?: number;
|
||||
owner?: number;
|
||||
owner?: boolean;
|
||||
dm?: boolean;
|
||||
interactive?: boolean;
|
||||
popover?: boolean;
|
||||
|
||||
@@ -2,7 +2,13 @@ import { useState, useEffect } from "react";
|
||||
import { useLazyRemoveFavoriteQuery, useFavoriteMessageMutation } from "../../app/services/message";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useFavMessage({ cid = null, uid = null }) {
|
||||
export default function useFavMessage({
|
||||
cid = null,
|
||||
uid = null
|
||||
}: {
|
||||
cid?: number | null;
|
||||
uid?: number | null;
|
||||
}) {
|
||||
const [removeFav] = useLazyRemoveFavoriteQuery();
|
||||
const [addFav] = useFavoriteMessageMutation();
|
||||
const [favorites, setFavorites] = useState([]);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { useAppDispatch, useAppSelector } from "../../app/store";
|
||||
|
||||
interface Props {
|
||||
context: "user" | "channel";
|
||||
from: number;
|
||||
from?: number;
|
||||
to: number;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ interface SendMessageDTO {
|
||||
}
|
||||
|
||||
const useSendMessage = (props?: Props) => {
|
||||
const { context = "user", from, to = null } = props || {};
|
||||
const { context = "user", from = 0, to = null } = props || {};
|
||||
const dispatch = useAppDispatch();
|
||||
const stageFiles = useAppSelector((store) => store.ui.uploadFiles[`${context}_${to}`] || []);
|
||||
const [replyMessage, { isError: replyErr, isLoading: replying, isSuccess: replySuccess }] =
|
||||
|
||||
@@ -4,13 +4,14 @@ import { updateUploadFiles } from "../../app/slices/ui";
|
||||
import BASE_URL, { FILE_SLICE_SIZE } from "../../app/config";
|
||||
import { usePrepareUploadFileMutation, useUploadFileMutation } from "../../app/services/message";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/store";
|
||||
import { Message } from "../../types/channel";
|
||||
|
||||
// todo: check props type
|
||||
interface IProps {
|
||||
context: "channel" | "user";
|
||||
id: number;
|
||||
}
|
||||
const useUploadFile = (props: IProps) => {
|
||||
const useUploadFile = (props?: IProps) => {
|
||||
const { context, id } = props ? props : { context: "channel", id: 0 };
|
||||
const dispatch = useAppDispatch();
|
||||
const { stageFiles, replying } = useAppSelector((store) => {
|
||||
@@ -19,8 +20,7 @@ const useUploadFile = (props: IProps) => {
|
||||
replying: store.message.replying[`${context}_${id}`]
|
||||
};
|
||||
});
|
||||
const [data, setData] = useState(null);
|
||||
// const [uploadingFile, setUploadingFile] = useState(false);
|
||||
const [data, setData] = useState<Message | null>(null);
|
||||
const canceledRef = useRef(false);
|
||||
const sliceUploadedCountRef = useRef(0);
|
||||
const totalSliceCountRef = useRef(1);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useLazyDeleteUserQuery } from "../../app/services/user";
|
||||
import useConfig from "./useConfig";
|
||||
import useCopy from "./useCopy";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
import { AgoraConfig } from "../../types/server";
|
||||
interface IProps {
|
||||
uid?: number;
|
||||
cid?: number;
|
||||
@@ -79,7 +80,7 @@ const useUserOperation = ({ uid, cid }: IProps) => {
|
||||
const canDeleteChannel = cid && !channel?.is_public && isAdmin;
|
||||
const canRemoveFromChannel =
|
||||
cid && !channel?.is_public && (isAdmin || channel?.owner == loginUid) && uid != channel?.owner;
|
||||
const canCall: boolean = agoraConfig.enabled && loginUid != uid;
|
||||
const canCall: boolean = (agoraConfig as AgoraConfig)?.enabled && loginUid != uid;
|
||||
const canRemove: boolean = isAdmin && loginUid != uid && !cid;
|
||||
|
||||
return {
|
||||
|
||||
@@ -9,7 +9,8 @@ const Styled = styled.div`
|
||||
background: #f9fafb;
|
||||
filter: drop-shadow(0px 25px 50px rgba(31, 41, 55, 0.25));
|
||||
border-radius: 12px;
|
||||
min-width: 406px;
|
||||
min-width: 486px;
|
||||
/* width: fit-content; */
|
||||
> .head {
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
@@ -106,13 +107,6 @@ const PinList: FC<Props> = ({ id }: Props) => {
|
||||
<li key={mid} className="pin">
|
||||
<PreviewMessage mid={mid} />
|
||||
<div className="opts">
|
||||
{/* <button
|
||||
className="btn"
|
||||
data-mid={mid}
|
||||
// onClick={handleUnpin}
|
||||
>
|
||||
<IconForward />
|
||||
</button> */}
|
||||
{canPin && (
|
||||
<button className="btn" data-mid={mid} onClick={handleUnpin}>
|
||||
<IconClose />
|
||||
|
||||
@@ -27,6 +27,7 @@ import { StyledUsers, StyledChannelChat, StyledHeader } from "./styled";
|
||||
import InviteModal from "../../../common/component/InviteModal";
|
||||
import LoadMore from "../LoadMore";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
import { AgoraConfig } from "../../../types/server";
|
||||
type Props = {
|
||||
cid?: number;
|
||||
dropFiles?: File[];
|
||||
@@ -42,7 +43,6 @@ export default function ChannelChat({ cid = 0, dropFiles = [] }: Props) {
|
||||
context: "channel",
|
||||
id: cid
|
||||
});
|
||||
const [toolVisible, setToolVisible] = useState("");
|
||||
const { pathname } = useLocation();
|
||||
const dispatch = useDispatch();
|
||||
const [updateReadIndex] = useReadMessageMutation();
|
||||
@@ -99,57 +99,37 @@ export default function ChannelChat({ cid = 0, dropFiles = [] }: Props) {
|
||||
aside={
|
||||
<>
|
||||
<ul className="tools">
|
||||
{agoraConfig.enabled && (
|
||||
{(agoraConfig as AgoraConfig)?.enabled && (
|
||||
<li className="tool">
|
||||
<Tooltip tip="Voice/Video Chat" placement="left">
|
||||
<IconHeadphone />
|
||||
</Tooltip>
|
||||
</li>
|
||||
)}
|
||||
<Tooltip tip="Pin" placement="left" disabled={toolVisible == "pin"}>
|
||||
<Tooltip tip="Pin" placement="left">
|
||||
<Tippy
|
||||
onShow={() => {
|
||||
setToolVisible("pin");
|
||||
}}
|
||||
onHide={() => {
|
||||
setToolVisible("");
|
||||
}}
|
||||
placement="left-start"
|
||||
popperOptions={{ strategy: "fixed" }}
|
||||
offset={[0, 80]}
|
||||
offset={[0, 150]}
|
||||
interactive
|
||||
trigger="click"
|
||||
content={<PinList id={cid} />}
|
||||
>
|
||||
<li
|
||||
className={`tool ${pinCount > 0 ? "badge" : ""} ${
|
||||
toolVisible == "pin" ? "active" : ""
|
||||
} `}
|
||||
data-count={pinCount}
|
||||
>
|
||||
<li className={`tool ${pinCount > 0 ? "badge" : ""}`} data-count={pinCount}>
|
||||
<IconPin />
|
||||
</li>
|
||||
</Tippy>
|
||||
</Tooltip>
|
||||
<Tooltip tip="Favorite" placement="left" disabled={toolVisible == "favorite"}>
|
||||
<Tooltip tip="Favorite" placement="left">
|
||||
<Tippy
|
||||
onShow={() => {
|
||||
setToolVisible("favorite");
|
||||
}}
|
||||
onHide={() => {
|
||||
setToolVisible("");
|
||||
}}
|
||||
placement="left-start"
|
||||
popperOptions={{ strategy: "fixed" }}
|
||||
offset={[0, 180]}
|
||||
offset={[0, 162]}
|
||||
interactive
|
||||
trigger="click"
|
||||
content={<FavList cid={cid} />}
|
||||
>
|
||||
<li
|
||||
className={`tool fav ${toolVisible == "favorite" ? "active" : ""} `}
|
||||
data-count={pinCount}
|
||||
>
|
||||
<li className={`tool fav`} data-count={pinCount}>
|
||||
<IconFav />
|
||||
</li>
|
||||
</Tippy>
|
||||
@@ -184,7 +164,7 @@ export default function ChannelChat({ cid = 0, dropFiles = [] }: Props) {
|
||||
<div className="txt">Add members</div>
|
||||
</div>
|
||||
)}
|
||||
{memberIds.map((uid) => {
|
||||
{memberIds.map((uid: number) => {
|
||||
return (
|
||||
<User
|
||||
enableContextMenu={true}
|
||||
|
||||
@@ -17,7 +17,7 @@ import useMessageFeed from "../../../common/hook/useMessageFeed";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
type Props = {
|
||||
uid: number;
|
||||
dropFiles: [File];
|
||||
dropFiles?: [File];
|
||||
};
|
||||
const DMChat: FC<Props> = ({ uid = 0, dropFiles }) => {
|
||||
const {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MouseEvent } from "react";
|
||||
import { MouseEvent, FC } from "react";
|
||||
import styled from "styled-components";
|
||||
import FavoredMessage from "../../common/component/Message/FavoredMessage";
|
||||
import IconSurprise from "../../assets/icons/emoji.surprise.svg";
|
||||
@@ -82,8 +82,8 @@ const Styled = styled.div`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default function FavList({ cid = null, uid = null }) {
|
||||
type Props = { cid?: number; uid?: number };
|
||||
const FavList: FC<Props> = ({ cid = null, uid = null }) => {
|
||||
const { favorites, removeFavorite } = useFavMessage({ cid, uid });
|
||||
const handleRemove = (evt: MouseEvent<HTMLButtonElement>) => {
|
||||
const { id } = evt.currentTarget.dataset;
|
||||
@@ -106,13 +106,6 @@ export default function FavList({ cid = null, uid = null }) {
|
||||
<li key={id} className="fav">
|
||||
<FavoredMessage id={id} />
|
||||
<div className="opts">
|
||||
{/* <button
|
||||
className="btn"
|
||||
data-mid={mid}
|
||||
// onClick={handleRemove}
|
||||
>
|
||||
<IconForward />
|
||||
</button> */}
|
||||
<button className="btn" data-id={id} onClick={handleRemove}>
|
||||
<IconRemove />
|
||||
</button>
|
||||
@@ -124,4 +117,5 @@ export default function FavList({ cid = null, uid = null }) {
|
||||
)}
|
||||
</Styled>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default FavList;
|
||||
|
||||
@@ -14,7 +14,7 @@ interface Props {
|
||||
header: ReactElement;
|
||||
aside: ReactElement | null;
|
||||
users?: ReactElement;
|
||||
dropFiles: File[];
|
||||
dropFiles?: File[];
|
||||
context: "channel" | "user";
|
||||
to: number;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useAppSelector } from "../../app/store";
|
||||
export default function ChatPage() {
|
||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||
const [usersModalVisible, setUsersModalVisible] = useState(false);
|
||||
const { channel_id, user_id } = useParams();
|
||||
const { channel_id = 0, user_id = 0 } = useParams();
|
||||
const { sessionUids } = useAppSelector((store) => {
|
||||
return {
|
||||
sessionUids: store.userMessage.ids
|
||||
@@ -47,7 +47,7 @@ export default function ChatPage() {
|
||||
</div>
|
||||
<div className={`right ${placeholderVisible ? "placeholder" : ""}`}>
|
||||
{placeholderVisible && <BlankPlaceholder />}
|
||||
{channel_id && <ChannelChat cid={channel_id} />}
|
||||
{channel_id && <ChannelChat cid={+channel_id} />}
|
||||
{user_id && <DMChat uid={+user_id} />}
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
|
||||
@@ -9,6 +9,7 @@ import Tooltip from "./Tooltip";
|
||||
import IssuerList from "./IssuerList";
|
||||
import useGoogleAuthConfig from "../../../common/hook/useGoogleAuthConfig";
|
||||
import useGithubAuthConfig from "../../../common/hook/useGithubAuthConfig";
|
||||
import { LoginConfig } from "../../../types/server";
|
||||
|
||||
export default function Logins() {
|
||||
const {
|
||||
@@ -25,7 +26,7 @@ export default function Logins() {
|
||||
} = useGithubAuthConfig();
|
||||
const { values, updateConfig, setValues, reset, changed } = useConfig("login");
|
||||
const handleUpdate = async () => {
|
||||
const { google } = values;
|
||||
const { google } = values as LoginConfig;
|
||||
if (changed) {
|
||||
updateConfig(values);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import Toggle from "../../../common/component/styled/Toggle";
|
||||
import Label from "../../../common/component/styled/Label";
|
||||
import SaveTip from "../../../common/component/SaveTip";
|
||||
import toast from "react-hot-toast";
|
||||
import { SMTPConfig } from "../../../types/server";
|
||||
|
||||
export default function ConfigSMTP() {
|
||||
const [testEmail, setTestEmail] = useState("");
|
||||
@@ -24,7 +25,7 @@ export default function ConfigSMTP() {
|
||||
|
||||
const handleUpdate = () => {
|
||||
// const { token_url, description } = values;
|
||||
updateConfig({ ...values, port: Number(values.port ?? 0) });
|
||||
updateConfig({ ...values, port: Number((values as SMTPConfig)?.port ?? 0) });
|
||||
};
|
||||
const handleChange = (evt) => {
|
||||
const newValue = evt.target.value;
|
||||
|
||||
Reference in New Issue
Block a user