diff --git a/.vscode/settings.json b/.vscode/settings.json index 8a37b8d8..a9b7e1ec 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -26,5 +26,7 @@ "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "cSpell.words": ["btns", "oidc", "tippyjs", "vocechat"] + "cSpell.words": ["btns", "oidc", "tippyjs", "vocechat"], + "reactSnippets.settings.prettierEnabled": true, + "reactSnippets.settings.importReactOnTop": false } diff --git a/src/app/slices/channels.ts b/src/app/slices/channels.ts index 6ac87b0e..45a0805f 100644 --- a/src/app/slices/channels.ts +++ b/src/app/slices/channels.ts @@ -4,7 +4,7 @@ import BASE_URL from "../config"; import { Channel, UpdateChannelDTO, UpdatePinnedMessageDTO } from "../../types/channel"; interface StoredChannel extends Channel { - icon: string; + icon?: string; } interface State { diff --git a/src/app/slices/message.channel.ts b/src/app/slices/message.channel.ts index a18420d4..1f94cd98 100644 --- a/src/app/slices/message.channel.ts +++ b/src/app/slices/message.channel.ts @@ -1,6 +1,4 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit"; -import { EntityId } from "../../types/common"; -import { ChatEvent } from "../../types/sse"; export interface State { [gid: number]: number[] | undefined; @@ -18,7 +16,7 @@ const channelMsgSlice = createSlice({ fullfillChannelMsg(state, action: PayloadAction) { return action.payload; }, - addChannelMsg(state, action: PayloadAction) { + addChannelMsg(state, action: PayloadAction<{ id: number; mid: number; local_id?: any }>) { const { id, mid, local_id = null } = action.payload; if (state[id]) { const midExsited = state[id]!.findIndex((id) => id == mid) > -1; @@ -29,7 +27,7 @@ const channelMsgSlice = createSlice({ state[id] = [+mid]; } }, - removeChannelMsg(state, action: PayloadAction) { + removeChannelMsg(state, action: PayloadAction<{ id: number; mid: number }>) { const { id, mid } = action.payload; if (state[id]) { const idx = state[id]!.findIndex((i) => i == mid); diff --git a/src/app/slices/ui.ts b/src/app/slices/ui.ts index d8770ed3..924d706b 100644 --- a/src/app/slices/ui.ts +++ b/src/app/slices/ui.ts @@ -4,10 +4,6 @@ import { Views } from "../config"; export interface State { online: boolean; ready: boolean; - userGuide: { - visible: boolean; - step: number; - }; inputMode: "text"; menuExpand: boolean; // todo @@ -25,10 +21,6 @@ export interface State { const initialState: State = { online: true, ready: false, - userGuide: { - visible: false, - step: 1 - }, inputMode: "text", menuExpand: false, fileListView: Views.grid, @@ -77,12 +69,6 @@ const uiSlice = createSlice({ const { key, value } = action.payload; state.draftMixedText[key] = value; }, - updateUserGuide(state, action) { - const obj = action.payload || {}; - Object.keys(obj).forEach((key) => { - state.userGuide[key] = obj[key]; - }); - }, updateUploadFiles(state, action) { const { context = "channel", id = null, operation = "add", ...rest } = action.payload; if (!id || !context) return; @@ -177,7 +163,6 @@ export const { updateFileListView, updateUploadFiles, updateSelectMessages, - updateUserGuide, updateDraftMarkdown, updateDraftMixedText, updateRemeberedNavs diff --git a/src/common/component/Avatar.tsx b/src/common/component/Avatar.tsx index f834fbba..588df387 100644 --- a/src/common/component/Avatar.tsx +++ b/src/common/component/Avatar.tsx @@ -2,6 +2,8 @@ import { useState, useEffect, memo, SyntheticEvent, FC } from "react"; import { getInitials, getInitialsAvatar } from "../utils"; interface Props { + className?: string; + alt?: string; url?: string; name?: string; type?: "user" | "channel"; diff --git a/src/common/component/AvatarUploader.tsx b/src/common/component/AvatarUploader.tsx index 2e648c50..3b6b1fc1 100644 --- a/src/common/component/AvatarUploader.tsx +++ b/src/common/component/AvatarUploader.tsx @@ -15,7 +15,6 @@ const StyledWrapper = styled.div` height: 100%; border-radius: 50%; background-color: #eee; - /* border: 1px solid #eee; */ img { object-fit: cover; width: 100%; diff --git a/src/common/component/Channel.tsx b/src/common/component/Channel.tsx index b5910e24..be59fa90 100644 --- a/src/common/component/Channel.tsx +++ b/src/common/component/Channel.tsx @@ -63,14 +63,14 @@ const Channel: FC = ({ interactive = true, id, compact = false, avatarSiz }); if (!channel) return null; - const { name, members = [], is_public, avatar } = channel; + const { name, members = [], is_public, icon } = channel; return (
- +
{!compact && (
diff --git a/src/common/component/CurrentUser.tsx b/src/common/component/CurrentUser.tsx index 1294517c..8a3449c3 100644 --- a/src/common/component/CurrentUser.tsx +++ b/src/common/component/CurrentUser.tsx @@ -70,7 +70,6 @@ export default function CurrentUser() { if (!currUser) return null; const { uid, name, avatar } = currUser; return ( - //
@@ -86,6 +85,5 @@ export default function CurrentUser() {
)}
- //
); } diff --git a/src/common/component/DeleteMessageConfirm.tsx b/src/common/component/DeleteMessageConfirm.tsx index 68717925..afbe44ee 100644 --- a/src/common/component/DeleteMessageConfirm.tsx +++ b/src/common/component/DeleteMessageConfirm.tsx @@ -23,7 +23,6 @@ const DeleteMessageConfirmModal: FC = ({ closeModal, mids = [] }) => { return ( - -
- - } - > - {children} - - - ); -}; - -export default UserGuide; diff --git a/src/common/component/UserGuide/steps.ts b/src/common/component/UserGuide/steps.ts deleted file mode 100644 index dc8c982d..00000000 --- a/src/common/component/UserGuide/steps.ts +++ /dev/null @@ -1,29 +0,0 @@ -interface Step { - title: string; - description: string; -} - -const steps: Step[] = [ - { - title: "Step 1", - description: "hello world 1" - }, - { - title: "Step 2", - description: "hello world 1" - }, - { - title: "Step 3", - description: "hello world 1" - }, - { - title: "Step 4", - description: "hello world 1" - }, - { - title: "Step 5", - description: "hello world 1" - } -]; - -export default steps; diff --git a/src/common/hook/useAddLocalFileMessage.ts b/src/common/hook/useAddLocalFileMessage.ts index 3a5a41e9..d95913d6 100644 --- a/src/common/hook/useAddLocalFileMessage.ts +++ b/src/common/hook/useAddLocalFileMessage.ts @@ -4,7 +4,12 @@ import { addMessage } from "../../app/slices/message"; import { addChannelMsg } from "../../app/slices/message.channel"; import { addUserMsg } from "../../app/slices/message.user"; -export default function useAddLocalFileMessage({ context, to }) { +interface IProps { + context: "channel" | "uesr"; + to: number; +} + +export default function useAddLocalFileMessage({ context, to }: IProps) { const dispatch = useDispatch(); const addContextMessage = context == "channel" ? addChannelMsg : addUserMsg; const addLocalFileMesage = (data) => { diff --git a/src/common/hook/useCopy.ts b/src/common/hook/useCopy.ts index 999c76e7..87cd72a6 100644 --- a/src/common/hook/useCopy.ts +++ b/src/common/hook/useCopy.ts @@ -2,7 +2,7 @@ import { useState, useEffect } from "react"; import { copyImageToClipboard } from "copy-image-clipboard"; import toast from "react-hot-toast"; -const useCopy = (config) => { +const useCopy = (config: { enableToast: boolean } | void) => { const { enableToast = true } = config || {}; const [copied, setCopied] = useState(false); @@ -12,26 +12,27 @@ const useCopy = (config) => { } }, [copied]); - const copyToClipboard = (str) => { + const copyToClipboard = (str: string) => { const el = document.createElement("textarea"); el.value = str; el.setAttribute("readonly", ""); el.style.position = "absolute"; el.style.left = "-9999px"; document.body.appendChild(el); - const selected = - document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false; + const selection = document.getSelection(); + if (!selection) return false; + const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false; el.select(); const success = document.execCommand("copy"); document.body.removeChild(el); if (selected) { - document.getSelection().removeAllRanges(); - document.getSelection().addRange(selected); + selection.removeAllRanges(); + selection.addRange(selected); } return success; }; - const copy = (text, isImage = false) => { + const copy = (text: string, isImage = false) => { let inter = 0; console.log("copy", text, isImage); if (!copied) { diff --git a/src/common/hook/useUserOperation.ts b/src/common/hook/useUserOperation.ts index 873abb6f..81769aba 100644 --- a/src/common/hook/useUserOperation.ts +++ b/src/common/hook/useUserOperation.ts @@ -8,12 +8,12 @@ import { useLazyDeleteUserQuery } from "../../app/services/user"; import useConfig from "./useConfig"; import useCopy from "./useCopy"; import { useAppSelector } from "../../app/store"; -interface Props { +interface IProps { uid?: number; cid?: number; } -const useUserOperation: FC = ({ uid, cid }) => { - const [passedUid, setPassedUid] = useState(undefined); +const useUserOperation = ({ uid, cid }: IProps) => { + const [passedUid, setPassedUid] = useState(undefined); const { values: agoraConfig } = useConfig("agora"); const isUserDetailPath = useMatch(`/users/${uid}`); const [removeUser, { isSuccess: removeUserSuccess }] = useLazyDeleteUserQuery(); @@ -29,7 +29,7 @@ const useUserOperation: FC = ({ uid, cid }) => { }); useEffect(() => { - setPassedUid(uid ?? loginUser.uid); + setPassedUid(uid ?? loginUser?.uid); }, [uid, loginUser]); useEffect(() => { @@ -41,21 +41,23 @@ const useUserOperation: FC = ({ uid, cid }) => { } }, [removeSuccess, removeUserSuccess, isUserDetailPath]); - const handleRemoveFromChannel = (id) => { + const handleRemoveFromChannel = (id: number) => { + if (!cid) return; const isNumber = !Number.isNaN(+id); const finalId = isNumber ? id || passedUid : passedUid; + if (!finalId) return; removeInChannel({ id: +cid, members: [+finalId] }); hideAll(); }; - const handleRemove = (id) => { + const handleRemove = (id: number) => { const isNumber = !Number.isNaN(+id); const finalId = isNumber ? id || passedUid : passedUid; removeUser(finalId); hideAll(); }; - const copyEmail = (email) => { + const copyEmail = (email: string) => { const isString = typeof email == "string"; const finalEmail = isString ? email || user?.email : user?.email; copy(finalEmail); @@ -67,15 +69,15 @@ const useUserOperation: FC = ({ uid, cid }) => { }; const call = () => { - toast.success("Cooming Soon..."); + toast.success("Coming Soon..."); hideAll(); }; const isAdmin = loginUser?.is_admin; const loginUid = loginUser?.uid; const canRemoveFromChannel = cid && !channel?.is_public && (isAdmin || channel?.owner == loginUid); - const canCall = agoraConfig.enabled && loginUid != uid; - const canRemove = isAdmin && loginUid != uid && !cid; + const canCall: boolean = agoraConfig.enabled && loginUid != uid; + const canRemove: boolean = isAdmin && loginUid != uid && !cid; return { canRemove,