refactor: add typescript support to project
This commit is contained in:
+1
-1
@@ -1,9 +1,9 @@
|
||||
// import React from 'react'
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
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 }) {
|
||||
const dispatch = useDispatch();
|
||||
const addContextMessage = context == "channel" ? addChannelMsg : addUserMsg;
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useRef, useEffect } from "react";
|
||||
// import { useDebounce } from "rooks";
|
||||
|
||||
function useChatScroll(deps = []) {
|
||||
// todo: ref should be initialized to null
|
||||
const ref = useRef();
|
||||
// useEffect(() => {
|
||||
// console.log("chat scroll", ref);
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { isObjectEqual } from "../utils";
|
||||
import toast from "react-hot-toast";
|
||||
import { isObjectEqual } from "../utils";
|
||||
import {
|
||||
useUpdateLoginConfigMutation,
|
||||
useUpdateSMTPConfigMutation,
|
||||
@@ -11,8 +11,10 @@ import {
|
||||
useLazyGetSMTPConfigQuery,
|
||||
useLazyGetLoginConfigQuery
|
||||
} from "../../app/services/server";
|
||||
|
||||
// config: smtp agora login firebase
|
||||
let originalValue = null;
|
||||
let originalValue: null | object = null;
|
||||
|
||||
export default function useConfig(config = "smtp") {
|
||||
const [changed, setChanged] = useState(false);
|
||||
const [values, setValues] = useState({});
|
||||
@@ -105,6 +107,7 @@ export default function useConfig(config = "smtp") {
|
||||
setChanged(false);
|
||||
}
|
||||
}, [values]);
|
||||
|
||||
return {
|
||||
reset,
|
||||
changed,
|
||||
@@ -1,15 +1,15 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
// import { ContentTypes } from "../../../app/config";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useNavigate, useMatch } from "react-router-dom";
|
||||
import { hideAll } from "tippy.js";
|
||||
import { useRemoveMembersMutation } from "../../app/services/channel";
|
||||
import { useLazyDeleteContactQuery } from "../../app/services/contact";
|
||||
import useConfig from "./useConfig";
|
||||
import useCopy from "./useCopy";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useContactOperation({ uid, cid }) {
|
||||
export default function useContactOperation({ uid, cid }: { uid: number; cid: number }) {
|
||||
const [passedUid, setPassedUid] = useState(undefined);
|
||||
const { values: agoraConfig } = useConfig("agora");
|
||||
const isUserDetailPath = useMatch(`/contacts/${uid}`);
|
||||
@@ -17,7 +17,7 @@ export default function useContactOperation({ uid, cid }) {
|
||||
const [removeInChannel, { isSuccess: removeSuccess }] = useRemoveMembersMutation();
|
||||
const navigateTo = useNavigate();
|
||||
const { copy } = useCopy();
|
||||
const { user, channel, loginUid, isAdmin } = useSelector((store) => {
|
||||
const { user, channel, loginUid, isAdmin } = useAppSelector((store) => {
|
||||
return {
|
||||
user: store.contacts.byId[uid],
|
||||
channel: store.channels.byId[cid],
|
||||
@@ -25,6 +25,7 @@ export default function useContactOperation({ uid, cid }) {
|
||||
isAdmin: store.contacts.byId[store.authData.uid]?.is_admin
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setPassedUid(uid ?? loginUid);
|
||||
}, [uid, loginUid]);
|
||||
@@ -37,35 +38,42 @@ export default function useContactOperation({ uid, cid }) {
|
||||
}
|
||||
}
|
||||
}, [removeSuccess, removeUserSuccess, isUserDetailPath]);
|
||||
|
||||
const handleRemoveFromChannel = (id) => {
|
||||
const isNumber = !Number.isNaN(+id);
|
||||
const finalId = isNumber ? id || passedUid : passedUid;
|
||||
removeInChannel({ id: +cid, members: [+finalId] });
|
||||
hideAll();
|
||||
};
|
||||
|
||||
const handleRemove = (id) => {
|
||||
const isNumber = !Number.isNaN(+id);
|
||||
const finalId = isNumber ? id || passedUid : passedUid;
|
||||
removeUser(finalId);
|
||||
hideAll();
|
||||
};
|
||||
|
||||
const copyEmail = (email) => {
|
||||
const isString = typeof email == "string";
|
||||
const finalEmail = isString ? email || user?.email : user?.email;
|
||||
copy(finalEmail);
|
||||
hideAll();
|
||||
};
|
||||
|
||||
const startChat = () => {
|
||||
navigateTo(`/chat/dm/${uid}`);
|
||||
};
|
||||
|
||||
const call = () => {
|
||||
toast.success("Cooming Soon...");
|
||||
hideAll();
|
||||
};
|
||||
|
||||
const canRemoveFromChannel =
|
||||
cid && !channel?.is_public && (isAdmin || channel?.owner == loginUid);
|
||||
const canCall = agoraConfig.enabled && loginUid != uid;
|
||||
const canRemove = isAdmin && loginUid != uid && !cid;
|
||||
|
||||
return {
|
||||
canRemove,
|
||||
removeUser: handleRemove,
|
||||
@@ -2,6 +2,7 @@ import { useState } from "react";
|
||||
import { hideAll } from "tippy.js";
|
||||
import Tippy from "@tippyjs/react";
|
||||
import Menu from "../component/ContextMenu";
|
||||
|
||||
export default function useContextMenu(placement = "right-start") {
|
||||
const [visible, setVisible] = useState(false);
|
||||
// for tippy.js
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useLazyDeleteMessageQuery } from "../../app/services/message";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useDeleteMessage() {
|
||||
const [deleting, setDeleting] = useState(false);
|
||||
const { loginUser, messageData } = useSelector((store) => {
|
||||
const { loginUser, messageData } = useAppSelector((store) => {
|
||||
return {
|
||||
messageData: store.message,
|
||||
loginUser: store.contacts.byId[store.authData.uid]
|
||||
@@ -1,10 +1,10 @@
|
||||
// import React from 'react'
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { updateDraftMarkdown, updateDraftMixedText } from "../../app/slices/ui";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useDraft({ context = "", id = "" }) {
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
const _key = `${context}_${id}`;
|
||||
const { draftMarkdown, draftMixedText } = useSelector((store) => {
|
||||
const { draftMarkdown, draftMixedText } = useAppSelector((store) => {
|
||||
return {
|
||||
draftMarkdown: store.ui.draftMarkdown,
|
||||
draftMixedText: store.ui.draftMixedText
|
||||
@@ -17,8 +17,10 @@ export default function useDraft({ context = "", id = "" }) {
|
||||
dispatch(update({ key: _key, value }));
|
||||
};
|
||||
};
|
||||
|
||||
const getDraft = (type = "mixed") => {
|
||||
return type == "mixed" ? draftMixedText[_key] : draftMarkdown[_key];
|
||||
};
|
||||
|
||||
return { getDraft, getUpdateDraft };
|
||||
}
|
||||
@@ -1,25 +1,27 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useLazyRemoveFavoriteQuery, useFavoriteMessageMutation } from "../../app/services/message";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useFavMessage({ cid = null, uid = null }) {
|
||||
const [removeFav] = useLazyRemoveFavoriteQuery();
|
||||
const [addFav] = useFavoriteMessageMutation();
|
||||
const [favorites, setFavorites] = useState([]);
|
||||
const { favs = [] } = useSelector((store) => {
|
||||
return {
|
||||
favs: store.favorites
|
||||
};
|
||||
const { favs = [] } = useAppSelector((store) => {
|
||||
return { favs: store.favorites };
|
||||
});
|
||||
|
||||
const addFavorite = async (mid = []) => {
|
||||
const mids = Array.isArray(mid) ? mid.map((i) => +i) : [+mid];
|
||||
if (mids.length == 0) return;
|
||||
const { error = null } = await addFav(mids);
|
||||
return !error;
|
||||
};
|
||||
|
||||
const removeFavorite = (id) => {
|
||||
if (!id) return;
|
||||
removeFav(id);
|
||||
};
|
||||
|
||||
const isFavorited = (mid = null) => {
|
||||
if (!mid) return false;
|
||||
let mids = [];
|
||||
@@ -31,6 +33,7 @@ export default function useFavMessage({ cid = null, uid = null }) {
|
||||
});
|
||||
return mids.findIndex((i) => i == mid) > -1;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let filtereds = [];
|
||||
filtereds = cid
|
||||
@@ -48,6 +51,7 @@ export default function useFavMessage({ cid = null, uid = null }) {
|
||||
|
||||
setFavorites(filtereds);
|
||||
}, [cid, uid, favs]);
|
||||
|
||||
// console.log("filtered", cid, uid, favs);
|
||||
return {
|
||||
isFavorited,
|
||||
@@ -1,25 +1,30 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
import { Channel } from "../../types/channel";
|
||||
|
||||
export default function useFilteredChannels() {
|
||||
const [input, setInput] = useState("");
|
||||
const channels = useSelector((store) => Object.values(store.channels.byId));
|
||||
const [filteredChannels, setfilteredChannels] = useState([]);
|
||||
const channels = useAppSelector((store) => Object.values(store.channels.byId));
|
||||
const [filteredChannels, setFilteredChannels] = useState<Channel[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!input) {
|
||||
setfilteredChannels(channels);
|
||||
setFilteredChannels(channels);
|
||||
} else {
|
||||
let str = ["", ...input.toLowerCase(), ""].join(".*");
|
||||
let reg = new RegExp(str);
|
||||
setfilteredChannels(
|
||||
setFilteredChannels(
|
||||
channels.filter((c) => {
|
||||
return reg.test(c.name.toLowerCase());
|
||||
})
|
||||
);
|
||||
}
|
||||
}, [input]);
|
||||
const updateInput = (val) => {
|
||||
|
||||
const updateInput = (val: string) => {
|
||||
setInput(val);
|
||||
};
|
||||
|
||||
return {
|
||||
input,
|
||||
channels: filteredChannels,
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useFilteredUsers() {
|
||||
const [input, setInput] = useState("");
|
||||
const contacts = useSelector((store) => Object.values(store.contacts.byId));
|
||||
const contacts = useAppSelector((store) => Object.values(store.contacts.byId));
|
||||
const [filteredUsers, setFilteredUsers] = useState([]);
|
||||
useEffect(() => {
|
||||
if (!input) {
|
||||
@@ -17,9 +18,11 @@ export default function useFilteredUsers() {
|
||||
);
|
||||
}
|
||||
}, [input]);
|
||||
const updateInput = (val) => {
|
||||
|
||||
const updateInput = (val: string) => {
|
||||
setInput(val);
|
||||
};
|
||||
|
||||
return {
|
||||
input,
|
||||
contacts: filteredUsers,
|
||||
@@ -2,6 +2,7 @@ import { useState } from "react";
|
||||
import { useSendChannelMsgMutation } from "../../app/services/channel";
|
||||
import { useSendMsgMutation } from "../../app/services/contact";
|
||||
import { useCreateArchiveMutation } from "../../app/services/message";
|
||||
|
||||
export default function useForwardMessage() {
|
||||
const [forwarding, setForwarding] = useState(false);
|
||||
const [
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useState, useEffect } from "react";
|
||||
// import toast from "react-hot-toast";
|
||||
import {
|
||||
useGetGithubAuthConfigQuery,
|
||||
useUpdateGithubAuthConfigMutation
|
||||
} from "../../app/services/server";
|
||||
|
||||
export default function useGithubAuthConfig() {
|
||||
const [changed, setChanged] = useState(false);
|
||||
const [config, setConfig] = useState({});
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useState, useEffect } from "react";
|
||||
// import toast from "react-hot-toast";
|
||||
import {
|
||||
useGetGoogleAuthConfigQuery,
|
||||
useUpdateGoogleAuthConfigMutation
|
||||
} from "../../app/services/server";
|
||||
|
||||
export default function useGoogleAuthConfig() {
|
||||
const [changed, setChanged] = useState(false);
|
||||
const [clientId, setClientId] = useState("");
|
||||
@@ -2,7 +2,8 @@ import { useState, useEffect } from "react";
|
||||
import useCopy from "./useCopy";
|
||||
import { useGetSMTPStatusQuery } from "../../app/services/server";
|
||||
import { useLazyCreateInviteLinkQuery as useCreateChannelInviteLinkQuery } from "../../app/services/channel";
|
||||
export default function useInviteLink(cid = "") {
|
||||
|
||||
export default function useInviteLink(cid: string | null = "") {
|
||||
const [finalLink, setFinalLink] = useState("");
|
||||
const { data: SMTPEnabled, isSuccess: smtpStatusFetchSuccess } = useGetSMTPStatusQuery();
|
||||
const [generateChannelInviteLink, { data: channelInviteLink, isLoading: generatingChannelLink }] =
|
||||
@@ -1,8 +1,8 @@
|
||||
// import React from 'react'
|
||||
import { useSelector } from "react-redux";
|
||||
import { useUpdateChannelMutation, useLazyLeaveChannelQuery } from "../../app/services/channel";
|
||||
export default function useLeaveChannel(cid = null) {
|
||||
const { channel, loginUid } = useSelector((store) => {
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useLeaveChannel(cid: number) {
|
||||
const { channel, loginUid } = useAppSelector((store) => {
|
||||
return { channel: store.channels.byId[cid], loginUid: store.authData.uid };
|
||||
});
|
||||
const [update, { isLoading: transfering, isSuccess: transferSuccess }] =
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { normalizeArchiveData } from "../../common/utils";
|
||||
import { normalizeArchiveData } from "../utils";
|
||||
import { useLazyGetArchiveMessageQuery } from "../../app/services/message";
|
||||
|
||||
export default function useNormalizeMessage() {
|
||||
const [filePath, setFilePath] = useState(null);
|
||||
const [filePath, setFilePath] = useState<string | null>(null);
|
||||
const [normalizedMessages, setNormalizedMessages] = useState(null);
|
||||
const [getArchiveMessage, { data, isError, isLoading, isSuccess }] =
|
||||
useLazyGetArchiveMessageQuery();
|
||||
@@ -18,7 +19,7 @@ export default function useNormalizeMessage() {
|
||||
}
|
||||
}, [filePath]);
|
||||
|
||||
const normalizeMessage = (file_path) => {
|
||||
const normalizeMessage = (file_path: string) => {
|
||||
setFilePath(file_path);
|
||||
};
|
||||
return {
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect } from "react";
|
||||
import PWABadge from "pwa-badge";
|
||||
|
||||
export default function usePWABadge() {
|
||||
// Create an Instance
|
||||
const badge = new PWABadge();
|
||||
@@ -1,9 +1,10 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { usePinMessageMutation, useUnpinMessageMutation } from "../../app/services/message";
|
||||
export default function usePinMessage(cid = null) {
|
||||
import { useAppSelector } from "../../app/store";
|
||||
|
||||
export default function usePinMessage(cid: number) {
|
||||
const [pins, setPins] = useState([]);
|
||||
const { channel, loginUser } = useSelector((store) => {
|
||||
const { channel, loginUser } = useAppSelector((store) => {
|
||||
return {
|
||||
channel: store.channels.byId[cid],
|
||||
loginUser: store.contacts.byId[store.authData.uid]
|
||||
+2
@@ -6,6 +6,7 @@ import { addFileMessage, removeFileMessage } from "../../../app/slices/message.f
|
||||
import { addUserMsg, removeUserMsg } from "../../../app/slices/message.user";
|
||||
import { updateAfterMid } from "../../../app/slices/footprint";
|
||||
import { ContentTypes } from "../../../app/config";
|
||||
|
||||
const handler = (data, dispatch, currState) => {
|
||||
const {
|
||||
mid,
|
||||
@@ -155,4 +156,5 @@ const handler = (data, dispatch, currState) => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export default handler;
|
||||
@@ -2,7 +2,6 @@ import { useEffect, useState } from "react";
|
||||
import { fetchEventSource, EventStreamContentType } from "@microsoft/fetch-event-source";
|
||||
import toast from "react-hot-toast";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import BASE_URL from "../../../app/config";
|
||||
import { setReady } from "../../../app/slices/ui";
|
||||
import { useRenewMutation } from "../../../app/services/auth";
|
||||
@@ -22,10 +21,12 @@ import {
|
||||
import { updateUsersByLogs, updateUsersStatus } from "../../../app/slices/contacts";
|
||||
import { resetAuthData } from "../../../app/slices/auth.data";
|
||||
import chatMessageHandler from "./chat.handler";
|
||||
import store from "../../../app/store";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import store, { useAppDispatch, useAppSelector } from "../../../app/store";
|
||||
|
||||
class RetriableError extends Error {}
|
||||
|
||||
class FatalError extends Error {}
|
||||
|
||||
const getQueryString = (params = {}) => {
|
||||
const sp = new URLSearchParams();
|
||||
Object.entries(params).forEach(([key, val]) => {
|
||||
@@ -40,19 +41,21 @@ const getQueryString = (params = {}) => {
|
||||
// initialized: "initialized",
|
||||
// streaming: "streaming",
|
||||
// };
|
||||
let inter = null;
|
||||
let inter: number | null = null;
|
||||
|
||||
export default function useStreaming() {
|
||||
const [readyPullData, setReadyPullData] = useState(false);
|
||||
const {
|
||||
authData: { uid: loginUid },
|
||||
ui: { ready, online },
|
||||
footprint: { afterMid, usersVersion, readUsers, readChannels }
|
||||
} = useSelector((store) => store);
|
||||
} = useAppSelector((store) => store);
|
||||
const [renewToken] = useRenewMutation();
|
||||
const dispatch = useDispatch();
|
||||
const dispatch = useAppDispatch();
|
||||
let initialized = false;
|
||||
let initializing = false;
|
||||
let controller = new AbortController();
|
||||
|
||||
const startStreaming = async () => {
|
||||
console.log("start streaming", initialized, initializing);
|
||||
if (initialized || initializing) return;
|
||||
@@ -310,15 +313,18 @@ export default function useStreaming() {
|
||||
// for controlling
|
||||
return controller;
|
||||
};
|
||||
|
||||
const stopStreaming = () => {
|
||||
console.log("stop st");
|
||||
if (controller && controller.abort) {
|
||||
controller.abort();
|
||||
}
|
||||
};
|
||||
|
||||
const setStreamingReady = (ready) => {
|
||||
setReadyPullData(ready);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log("network changed", online, readyPullData);
|
||||
if (readyPullData) {
|
||||
@@ -1,15 +1,14 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
// import { ContentTypes } from "../../app/config";
|
||||
import toast from "react-hot-toast";
|
||||
import { updateUploadFiles } from "../../app/slices/ui";
|
||||
import BASE_URL, { FILE_SLICE_SIZE } from "../../app/config";
|
||||
import { usePrepareUploadFileMutation, useUploadFileMutation } from "../../app/services/message";
|
||||
import toast from "react-hot-toast";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/store";
|
||||
|
||||
export default function useUploadFile(props = {}) {
|
||||
const { context = "", id = "" } = props;
|
||||
const dispatch = useDispatch();
|
||||
const { stageFiles, replying } = useSelector((store) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { stageFiles, replying } = useAppSelector((store) => {
|
||||
return {
|
||||
stageFiles: store.ui.uploadFiles[`${context}_${id}`] || [],
|
||||
replying: store.message.replying[`${context}_${id}`]
|
||||
@@ -35,6 +34,7 @@ export default function useUploadFile(props = {}) {
|
||||
formData.append("chunk_is_last", is_last);
|
||||
return uploadFileFn(formData);
|
||||
};
|
||||
|
||||
const uploadFile = async (file) => {
|
||||
if (!file) return;
|
||||
setData(null);
|
||||
@@ -107,12 +107,15 @@ export default function useUploadFile(props = {}) {
|
||||
setData(res);
|
||||
return res;
|
||||
};
|
||||
|
||||
const stopUploading = () => {
|
||||
canneledRef.current = true;
|
||||
};
|
||||
|
||||
const removeStageFile = (idx) => {
|
||||
dispatch(updateUploadFiles({ context, id, operation: "remove", index: idx }));
|
||||
};
|
||||
|
||||
const addStageFile = (fileData = {}) => {
|
||||
if (replying) {
|
||||
toast.error("Only text is supported when replying a message");
|
||||
@@ -120,9 +123,11 @@ export default function useUploadFile(props = {}) {
|
||||
}
|
||||
dispatch(updateUploadFiles({ context, id, data: fileData }));
|
||||
};
|
||||
|
||||
const resetStageFiles = () => {
|
||||
dispatch(updateUploadFiles({ context, id, operation: "reset" }));
|
||||
};
|
||||
|
||||
const updateStageFile = (idx, data = {}) => {
|
||||
dispatch(
|
||||
updateUploadFiles({
|
||||
@@ -134,6 +139,7 @@ export default function useUploadFile(props = {}) {
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return {
|
||||
stopUploading,
|
||||
data,
|
||||
Reference in New Issue
Block a user