refactor: more TS code

This commit is contained in:
Tristan Yang
2022-07-04 23:13:09 +08:00
parent 627082eacb
commit e0872b1dd3
28 changed files with 56 additions and 126 deletions
+5 -5
View File
@@ -3,7 +3,7 @@ import { createApi } from "@reduxjs/toolkit/query/react";
import baseQuery from "./base.query";
import BASE_URL, { ContentTypes } from "../config";
import { updateChannel, removeChannel } from "../slices/channels";
import { updateRemeberedNavs } from "../slices/ui";
import { updateRememberedNavs } from "../slices/ui";
import { removeMessage } from "../slices/message";
import { removeChannelSession } from "../slices/message.channel";
import { removeReactionMessage } from "../slices/message.reaction";
@@ -72,8 +72,8 @@ export const channelApi = createApi({
}
}
}),
createInviteLink: builder.query({
query: (gid = "") => ({
createInviteLink: builder.query<string, number | void>({
query: (gid) => ({
headers: {
"content-type": "text/plain",
accept: "text/plain"
@@ -98,7 +98,7 @@ export const channelApi = createApi({
const {
channelMessage,
ui: {
remeberedNavs: { chat: remeberedPath }
rememberedNavs: { chat: remeberedPath }
}
} = getState() as RootState;
try {
@@ -106,7 +106,7 @@ export const channelApi = createApi({
// 删掉该channel下的所有消息&reaction
const mids = channelMessage[id];
if (remeberedPath == `/chat/channel/${id}`) {
dispatch(updateRemeberedNavs({ path: null }));
dispatch(updateRememberedNavs({ path: null }));
}
if (mids) {
dispatch(removeChannelSession(id));
+5 -5
View File
@@ -12,7 +12,7 @@ export interface State {
selectMessages: { [key: string]: any };
draftMarkdown: { [key: string]: any };
draftMixedText: { [key: string]: any };
remeberedNavs: {
rememberedNavs: {
chat: null | string;
user: null | string;
};
@@ -29,7 +29,7 @@ const initialState: State = {
draftMarkdown: {},
draftMixedText: {},
// todo: typo
remeberedNavs: {
rememberedNavs: {
chat: null,
user: null
}
@@ -57,9 +57,9 @@ const uiSlice = createSlice({
updateFileListView(state, action) {
state.fileListView = action.payload;
},
updateRemeberedNavs(state, action: PayloadAction<{ key?: string; path: string | null }>) {
updateRememberedNavs(state, action: PayloadAction<{ key?: string; path: string | null }>) {
const { key = "chat", path = null } = action.payload || {};
state.remeberedNavs[key] = path;
state.rememberedNavs[key] = path;
},
updateDraftMarkdown(state, action) {
const { key, value } = action.payload;
@@ -165,7 +165,7 @@ export const {
updateSelectMessages,
updateDraftMarkdown,
updateDraftMixedText,
updateRemeberedNavs
updateRememberedNavs
} = uiSlice.actions;
export default uiSlice.reducer;
+1 -2
View File
@@ -7,9 +7,8 @@ const Styled = styled.div`
border-radius: 6px;
width: 370px;
height: 66px;
/* height: fit-content; */
&.sending {
/* opacity: 0.9; */
opacity: 0.9;
}
* {
user-select: text;
+7 -7
View File
@@ -1,4 +1,4 @@
import { useState, MouseEvent } from "react";
import { useState, MouseEvent, ChangeEvent } from "react";
// import toast from "react-hot-toast";
import Modal from "../Modal";
import Button from "../styled/Button";
@@ -20,8 +20,8 @@ export default function ForwardModal({ 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,
@@ -29,14 +29,14 @@ export default function ForwardModal({ mids, closeModal }) {
} = useFilteredChannels();
const { users, input, updateInput } = useFilteredUsers();
const toggleCheck = ({ currentTarget }: MouseEvent<HTMLLIElement>) => {
const { id, type = "user" } = currentTarget.dataset;
const { id = 0, type = "user" } = currentTarget.dataset;
const ids = 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);
updateState(tmp);
};
const updateAppendText = (evt) => {
const updateAppendText = (evt: ChangeEvent<HTMLInputElement>) => {
setAppendText(evt.target.value);
};
const handleForward = async () => {
@@ -55,14 +55,14 @@ 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);
@@ -2,7 +2,6 @@ import styled from "styled-components";
const StyledWrapper = styled.div`
display: flex;
/* max-width: 604px; */
max-height: 514px;
min-height: 400px;
background: #fff;
@@ -12,7 +11,6 @@ const StyledWrapper = styled.div`
overflow: hidden;
.left {
width: 276px;
/* height: 100%; */
box-shadow: inset -1px 0px 0px rgba(0, 0, 0, 0.1);
overflow-y: scroll;
.search {
@@ -36,15 +34,12 @@ const StyledWrapper = styled.div`
.users {
display: flex;
flex-direction: column;
/* height: 260px; */
padding-bottom: 20px;
/* overflow-y: scroll; */
.user {
cursor: pointer;
display: flex;
align-items: center;
padding: 0 16px;
/* margin: 0 4px; */
width: -webkit-fill-available;
border-radius: 4px;
&:hover {
@@ -60,8 +55,6 @@ const StyledWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
/* height: 100%; */
/* justify-content: space-between; */
padding: 16px;
box-sizing: border-box;
.title {
+1 -5
View File
@@ -17,7 +17,6 @@ const StyledSocialButton = styled(Button)`
color: #344054;
border: 1px solid #d0d5dd;
background: none !important;
.icon {
width: 24px;
height: 24px;
@@ -48,12 +47,11 @@ const GithubLoginButton: FC<Props> = ({ type = "login", client_id }) => {
useEffect(() => {
if (isSuccess) {
toast.success("Login Successfully");
// navigateTo("/");
}
}, [isSuccess]);
useEffect(() => {
if (error) {
switch (error.status) {
switch (error?.status) {
case 410:
toast.error(
"No associated account found, please user admin for an invitation link to join."
@@ -68,9 +66,7 @@ const GithubLoginButton: FC<Props> = ({ type = "login", client_id }) => {
}, [error]);
const handleGithubLogin = () => {
location.href = `https://github.com/login/oauth/authorize?client_id=${client_id}`;
// console.log("github login");
};
// console.log("google login ", loaded);
return (
<StyledSocialButton onClick={handleGithubLogin} disabled={isLoading}>
<IconGithub className="icon" />
@@ -30,8 +30,6 @@ const Styled = styled.div`
gap: 5px;
width: 100%;
overflow: scroll;
/* white-space: nowrap; */
&::-webkit-scrollbar {
width: 0; /* Remove scrollbar space */
height: 0; /* Remove scrollbar space */
@@ -57,7 +55,6 @@ const Styled = styled.div`
fill: #fff;
fill-opacity: 1;
}
/* filter: invert(1); */
}
}
.input {
@@ -68,7 +65,6 @@ const Styled = styled.div`
.users {
display: flex;
flex-direction: column;
/* height: 260px; */
padding-bottom: 20px;
max-height: 364px;
overflow: scroll;
@@ -77,7 +73,6 @@ const Styled = styled.div`
display: flex;
align-items: center;
padding: 4px 8px;
/* margin: 0 4px; */
width: -webkit-fill-available;
border-radius: 8px;
&:hover {
@@ -104,10 +99,10 @@ interface Props {
const AddMembers: FC<Props> = ({ cid, closeModal }) => {
const [addMembers, { isLoading: isAdding, isSuccess }] = useAddMembersMutation();
const [selects, setSelects] = useState([]);
const [selects, setSelects] = useState<number[]>([]);
const { channel, userData } = useAppSelector((store) => {
return {
channel: store.channels.byId[cid],
channel: cid ? store.channels.byId[cid] : null,
userData: store.users.byId
};
});
@@ -124,8 +119,8 @@ const AddMembers: FC<Props> = ({ cid, closeModal }) => {
const { input, updateInput, users = [] } = useFilteredUsers();
const toggleCheckMember = ({ currentTarget }: MouseEvent<SVGSVGElement | HTMLLIElement>) => {
const { uid } = currentTarget.dataset;
if (selects.includes(+uid)) {
const uid = Number(currentTarget.dataset.uid);
if (selects.includes(uid)) {
setSelects((prevs) => {
return prevs.filter((id) => id != uid);
});
@@ -150,7 +145,7 @@ const AddMembers: FC<Props> = ({ cid, closeModal }) => {
{selects.map((uid) => {
return (
<li className="select" key={uid}>
{userData[uid].name}
{userData[uid]?.name}
<CloseIcon data-uid={uid} onClick={toggleCheckMember} className="close" />
</li>
);
@@ -39,14 +39,12 @@ const Styled = styled.div`
flex-direction: column;
gap: 16px;
margin-bottom: 16px;
/* position: relative; */
}
> .link {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 12px;
/* position: relative; */
}
label {
color: #6b7280;
+1 -1
View File
@@ -41,7 +41,7 @@ interface Props {
const InviteModal: FC<Props> = ({ type = "server", cid, title = "", closeModal }) => {
const { channel, server } = useAppSelector((store) => {
return {
channel: store.channels.byId[cid],
channel: cid ? store.channels.byId[cid] : undefined,
server: store.server
};
});
@@ -44,13 +44,13 @@ const TransferOwnerModal: FC<Props> = ({ id, closeModal, withLeave = true }) =>
leaveChannel,
leaveSuccess,
transferSuccess,
transfering
transferring
} = useLeaveChannel(id);
const [uid, setUid] = useState(null);
const [uid, setUid] = useState<number | null>(null);
const navigateTo = useNavigate();
const handleSelectUser = (uid) => {
const handleSelectUser = (uid: number) => {
setUid(uid);
};
const handleTransferAndLeave = async () => {
@@ -70,7 +70,7 @@ const TransferOwnerModal: FC<Props> = ({ id, closeModal, withLeave = true }) =>
}, [leaveSuccess, transferSuccess, withLeave]);
if (!id) return null;
const operating = leaving || transfering;
const operating = leaving || transferring;
return (
<Modal id="modal-modal">
<StyledModal
@@ -90,7 +90,6 @@ const TransferOwnerModal: FC<Props> = ({ id, closeModal, withLeave = true }) =>
>
<UserList>
{otherMembers.map((id) => {
// const { uid } = u;
return (
<li
key={id}
-1
View File
@@ -2,7 +2,6 @@ import { FC } from "react";
import styled from "styled-components";
import Modal from "../Modal";
import IconClose from "../../../assets/icons/close.svg";
// import { ReactComponent as IconClose } from "../../../assets/icons/close.svg";
import Button from "../styled/Button";
const Styled = styled.div`
@@ -1,20 +0,0 @@
{
"name": "VoceChat",
"short_name": "Your private chat APP",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}
+1 -1
View File
@@ -6,7 +6,7 @@ export default function usePrompt() {
localStorage.removeItem(KEY_PWA_INSTALLED);
};
const setPrompt = () => {
localStorage.setItem(KEY_PWA_INSTALLED, true);
localStorage.setItem(KEY_PWA_INSTALLED, "true");
};
return {
+6 -10
View File
@@ -18,7 +18,7 @@ function MarkdownEditor({
sendMarkdown,
setEditorInstance
}) {
const editorRef = useRef(undefined);
const editorRef = useRef<Editor | undefined>(undefined);
const { uploadFile } = useUploadFile();
// const [pHolder, setPHolder] = useState(placeholder);
useEffect(() => {
@@ -46,11 +46,12 @@ function MarkdownEditor({
}, []);
const send = () => {
const edtr = editorRef.current.getInstance();
const md = edtr.getMarkdown().trim();
if (!editorRef.current) return;
const editor = editorRef.current.getInstance();
const md = editor.getMarkdown().trim();
if (md) {
sendMarkdown(edtr.getMarkdown());
edtr.reset();
sendMarkdown(editor.getMarkdown());
editor.reset();
}
};
return (
@@ -59,11 +60,9 @@ function MarkdownEditor({
initialValue={initialValue}
plugins={[codeSyntaxHighlight]}
placeholder={placeholder}
// onChange={handleChange}
ref={editorRef}
toolbarItems={[]}
hideModeSwitch={true}
// initialValue="hello world!"
previewStyle="vertical"
height={height}
initialEditType="markdown"
@@ -76,6 +75,3 @@ function MarkdownEditor({
);
}
export default MarkdownEditor;
// export default memo(MarkdownEditor, (prevs, nexts) => {
// return prevs.placeholder == nexts.placeholder;
// });
+2 -2
View File
@@ -1,4 +1,4 @@
import { FC } from "react";
import { FC, ReactNode } from "react";
import Tippy from "@tippyjs/react";
import styled from "styled-components";
import Profile from "../Profile";
@@ -15,7 +15,7 @@ const Styled = styled.span`
interface Props {
uid: number;
popover?: boolean;
cid: number;
cid?: number;
textOnly?: boolean;
}
+1 -1
View File
@@ -113,7 +113,7 @@ const renderContent = (data) => {
(match, idx) => {
console.log("match", match);
const uid = match.trim().slice(1);
return <Mention key={idx} uid={uid} popover={false} />;
return <Mention key={idx} uid={+uid} popover={false} />;
}
)}
</span>
-1
View File
@@ -12,7 +12,6 @@ const StyledWrapper = styled.div`
justify-content: space-between;
color: #333;
background: #fff;
/* gap: 20px; */
border: 1px solid #e5e7eb;
box-shadow: 0 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);
border-radius: 25px;
-1
View File
@@ -14,7 +14,6 @@ const StyledWrapper = styled.div`
align-items: center;
justify-content: space-between;
gap: 8px;
/* margin-bottom: 10px; */
.server {
display: flex;
align-items: center;
@@ -78,7 +78,6 @@ const StyledWrapper = styled.div`
background-color: #fff;
width: 100%;
max-height: 100%;
/* max-height: -webkit-fill-available; */
overflow: auto;
padding: 32px;
+1 -3
View File
@@ -3,7 +3,7 @@ import useCopy from "./useCopy";
import { useGetSMTPStatusQuery } from "../../app/services/server";
import { useLazyCreateInviteLinkQuery as useCreateChannelInviteLinkQuery } from "../../app/services/channel";
export default function useInviteLink(cid: string | null = "") {
export default function useInviteLink(cid?: number) {
const [finalLink, setFinalLink] = useState("");
const { data: SMTPEnabled, isSuccess: smtpStatusFetchSuccess } = useGetSMTPStatusQuery();
const [generateChannelInviteLink, { data: channelInviteLink, isLoading: generatingChannelLink }] =
@@ -20,8 +20,6 @@ export default function useInviteLink(cid: string | null = "") {
useEffect(() => {
const _link = channelInviteLink;
if (_link && smtpStatusFetchSuccess) {
// const tmpURL = new URL(_link);
// tmpURL.searchParams.set("code", SMTPEnabled);
setFinalLink(_link);
}
}, [channelInviteLink, smtpStatusFetchSuccess]);
+5 -5
View File
@@ -5,10 +5,10 @@ export default function useLeaveChannel(cid: number) {
const { channel, loginUid } = useAppSelector((store) => {
return { channel: store.channels.byId[cid], loginUid: store.authData.user?.uid };
});
const [update, { isLoading: transfering, isSuccess: transferSuccess }] =
const [update, { isLoading: transferring, isSuccess: transferSuccess }] =
useUpdateChannelMutation();
const [leave, { isLoading: leaving, isSuccess: leaveSuccess }] = useLazyLeaveChannelQuery();
const transferOwner = (uid = null) => {
const transferOwner = (uid: number) => {
if (!uid) return;
update({ id: cid, owner: uid });
};
@@ -16,8 +16,8 @@ export default function useLeaveChannel(cid: number) {
if (!cid) return;
leave(cid);
};
const isOwner = loginUid == channel.owner;
const otherMembers = channel.members.filter((m) => m != loginUid);
const isOwner = loginUid == channel?.owner;
const otherMembers = channel?.members.filter((m) => m != loginUid) || [];
return {
otherMembers,
transferOwner,
@@ -25,7 +25,7 @@ export default function useLeaveChannel(cid: number) {
leaving,
leaveSuccess,
isOwner,
transfering,
transferring,
transferSuccess
};
}
+3 -1
View File
@@ -144,7 +144,9 @@ export default function useUploadFile(props: { context: string; id: string } | o
stopUploading,
data,
isUploading: isPreparing || isUploading,
progress: Number((sliceUploadedCountRef.current / totalSliceCountRef.current) * 100).toFixed(2),
progress: +Number((sliceUploadedCountRef.current / totalSliceCountRef.current) * 100).toFixed(
2
),
uploadFile,
isError: uploadFileError,
isSuccess: !!data,
+1 -4
View File
@@ -127,7 +127,7 @@ export function sliceFile(file, chunksAmount) {
return chunks;
}
export const getFileIcon = (type, name = "") => {
export const getFileIcon = (type: string, name = "") => {
let icon = null;
const checks = {
@@ -198,10 +198,7 @@ export const normalizeArchiveData = (data = null, filePath = null, uid = null) =
thumbnail_id,
avatar: user.avatar
});
user.avatar = avatarUrl;
// console.log("user data", transformedContent, user);
return {
source,
from_mid: mid,
+3 -3
View File
@@ -6,7 +6,7 @@ import { useDispatch, useSelector } from "react-redux";
import PinList from "./PinList";
import FavList from "../FavList";
import { useReadMessageMutation } from "../../../app/services/message";
import { updateRemeberedNavs } from "../../../app/slices/ui";
import { updateRememberedNavs } from "../../../app/slices/ui";
import useMessageFeed from "../../../common/hook/useMessageFeed";
import useConfig from "../../../common/hook/useConfig";
import ChannelIcon from "../../../common/component/ChannelIcon";
@@ -76,9 +76,9 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
// dispatch(readMessage(msgIds));
// };
useEffect(() => {
dispatch(updateRemeberedNavs());
dispatch(updateRememberedNavs());
return () => {
dispatch(updateRemeberedNavs({ path: pathname }));
dispatch(updateRememberedNavs({ path: pathname }));
};
}, [pathname]);
+1 -1
View File
@@ -27,7 +27,7 @@ export default function HomePage() {
loginUid,
ui: {
ready,
remeberedNavs: { chat: chatPath, user: userPath }
rememberedNavs: { chat: chatPath, user: userPath }
}
} = useAppSelector((store) => {
return {
-1
View File
@@ -138,7 +138,6 @@ export default function Overview({ id = 0 }) {
</div>
</div>
{changed && <SaveTip saveHandler={handleUpdate} resetHandler={handleReset} />}
{/* <button onClick={handleUpdate} className="btn">update</button> */}
</StyledWrapper>
);
}
-18
View File
@@ -29,26 +29,8 @@ const useNavs = (cid: number): Nav[] => {
title: "Members",
component: <ManageMembers cid={cid} />
}
// {
// name: "permissions",
// title: "Permissions",
// },
// {
// name: "invites",
// title: "Invites",
// },
// {
// name: "integrations",
// title: "Integrations",
// },
]
}
// {
// title: "User Management",
// items: [
// ],
// },
];
};
+3 -3
View File
@@ -1,7 +1,7 @@
import { useEffect } from "react";
import { NavLink, useParams, useLocation } from "react-router-dom";
import { useDispatch, useSelector } from "react-redux";
import { updateRemeberedNavs } from "../../app/slices/ui";
import { updateRememberedNavs } from "../../app/slices/ui";
import Search from "../../common/component/Search";
import User from "../../common/component/User";
import Profile from "../../common/component/Profile";
@@ -16,9 +16,9 @@ export default function UsersPage() {
const { user_id } = useParams();
const userIds = useSelector((store) => store.users.ids);
useEffect(() => {
dispatch(updateRemeberedNavs({ key: "user" }));
dispatch(updateRememberedNavs({ key: "user" }));
return () => {
dispatch(updateRemeberedNavs({ key: "user", path: pathname }));
dispatch(updateRememberedNavs({ key: "user", path: pathname }));
};
}, [pathname]);