diff --git a/src/app/services/message.js b/src/app/services/message.js index 928ad702..27bec067 100644 --- a/src/app/services/message.js +++ b/src/app/services/message.js @@ -3,6 +3,7 @@ import { createApi } from "@reduxjs/toolkit/query/react"; import { ContentTypes } from "../config"; import { updateReadChannels, updateReadUsers } from "../slices/footprint"; +import { fullfillFavorites, populateFavorite } from "../slices/favorites"; import { onMessageSendStarted } from "./handlers"; // import { updateMessage } from "../slices/message"; @@ -83,6 +84,50 @@ export const messageApi = createApi({ body: { mid }, }), }), + unpinMessage: builder.mutation({ + query: ({ gid, mid }) => ({ + url: `/group/${gid}/unpin`, + method: "POST", + body: { mid }, + }), + }), + favoriteMessage: builder.mutation({ + query: (mids) => ({ + url: `/favorite`, + method: "POST", + body: { mid_list: mids }, + }), + }), + getFavoriteDetails: builder.query({ + query: (id) => ({ + url: `/favorite/${id}`, + }), + async onQueryStarted(id, { dispatch, queryFulfilled }) { + try { + const { data } = await queryFulfilled; + dispatch(populateFavorite({ id, data })); + } catch (err) { + console.log("get favorite list error", err); + } + }, + }), + getFavorites: builder.query({ + query: () => ({ + url: `/favorite`, + }), + async onQueryStarted(data, { dispatch, queryFulfilled }) { + try { + const { data: favorites } = await queryFulfilled; + dispatch(fullfillFavorites(favorites)); + for (const fav of favorites) { + const { id } = fav; + dispatch(messageApi.endpoints.getFavoriteDetails.initiate(id)); + } + } catch (err) { + console.log("get favorite list error", err); + } + }, + }), replyMessage: builder.mutation({ query: ({ reply_mid, content, type = "text" }) => ({ headers: { @@ -121,6 +166,9 @@ export const messageApi = createApi({ }); export const { + useUnpinMessageMutation, + useLazyGetFavoritesQuery, + useFavoriteMessageMutation, usePinMessageMutation, useLazyGetArchiveMessageQuery, useGetArchiveMessageQuery, diff --git a/src/app/slices/favorites.js b/src/app/slices/favorites.js new file mode 100644 index 00000000..b9c487c8 --- /dev/null +++ b/src/app/slices/favorites.js @@ -0,0 +1,21 @@ +import { createSlice } from "@reduxjs/toolkit"; +// import BASE_URL from "../config"; +const initialState = []; +const favoritesSlice = createSlice({ + name: `favorites`, + initialState, + reducers: { + fullfillFavorites(state, action) { + return action.payload; + }, + populateFavorite(state, action) { + const { id, data } = action.payload; + const idx = state.findIndex((fav) => fav.id == id); + if (idx > -1) { + state[idx].data = data; + } + }, + }, +}); +export const { fullfillFavorites, populateFavorite } = favoritesSlice.actions; +export default favoritesSlice.reducer; diff --git a/src/app/store.js b/src/app/store.js index 7f126a63..89974d3f 100644 --- a/src/app/store.js +++ b/src/app/store.js @@ -10,6 +10,7 @@ import contactsReducer from "./slices/contacts"; import reactionMsgReducer from "./slices/message.reaction"; import channelMsgReducer from "./slices/message.channel"; import userMsgReducer from "./slices/message.user"; +import favoritesReducer from "./slices/favorites"; import fileMsgReducer from "./slices/message.file"; import messageReducer from "./slices/message"; import { authApi } from "./services/auth"; @@ -23,6 +24,7 @@ const reducer = combineReducers({ ui: uiReducer, footprint: footprintReducer, server: serverReducer, + favorites: favoritesReducer, contacts: contactsReducer, channels: channelsReducer, reactionMessage: reactionMsgReducer, diff --git a/src/common/component/DeleteMessageConfirm.js b/src/common/component/DeleteMessageConfirm.js new file mode 100644 index 00000000..b3ef515d --- /dev/null +++ b/src/common/component/DeleteMessageConfirm.js @@ -0,0 +1,44 @@ +// import React from "react"; +import { useState } from "react"; +import useDeleteMessage from "../hook/useDeleteMessage"; +import StyledModal from "./styled/Modal"; +import Button from "./styled/Button"; +import Modal from "./Modal"; +import PreviewMessage from "./Message/PreviewMessage"; +export default function DeleteMessageConfirmModal({ closeModal, mids = [] }) { + // const dispatch = useDispatch(); + const mid_arr = mids ? (Array.isArray(mids) ? mids : [mids]) : []; + const [ids] = useState(mid_arr); + const { deleteMessage, isDeleting } = useDeleteMessage(); + const handleDelete = async () => { + await deleteMessage(ids); + closeModal(true); + }; + + if (ids.length == 0) return null; + return ( + + + + + + } + title="Delete Message" + description={`Are you sure want to delete ${ + ids.length > 1 ? "these messages" : "this message" + }?`} + > + {ids.length == 1 && } + + + ); +} diff --git a/src/common/component/FileMessage/index.js b/src/common/component/FileMessage/index.js index 9984f4d5..85238e2e 100644 --- a/src/common/component/FileMessage/index.js +++ b/src/common/component/FileMessage/index.js @@ -70,7 +70,15 @@ export default function FileMessage({ useEffect(() => { const props = properties ?? {}; const propsV2 = imageSize ? { ...props, ...imageSize } : props; - if (uploadSuccess) { + // 本地文件 并且上传成功 + if (uploadSuccess && content.startsWith("blob:")) { + console.log( + "send local file message", + uploadSuccess, + propsV2, + data, + content + ); // 把已经上传的东西当做消息发出去 const { path } = data; sendMessage({ @@ -80,15 +88,16 @@ export default function FileMessage({ properties: propsV2, }); } - }, [uploadSuccess, data, properties]); + }, [uploadSuccess, data, properties, content]); useEffect(() => { if (sendMessageSuccess) { // 回收本地资源 - // URL.revokeObjectURL(content); + URL.revokeObjectURL(content); } }, [sendMessageSuccess, content]); const handleCancel = () => { stopUploading(); + URL.revokeObjectURL(content); removeLocalMessage(properties.local_id); }; if (!properties) return null; diff --git a/src/routes/home/usePreload.js b/src/routes/home/usePreload.js index 405556cf..e8d69a4e 100644 --- a/src/routes/home/usePreload.js +++ b/src/routes/home/usePreload.js @@ -1,6 +1,7 @@ import { useEffect } from "react"; import { useSelector } from "react-redux"; import initCache, { useRehydrate } from "../../app/cache"; +import { useLazyGetFavoritesQuery } from "../../app/services/message"; import { useLazyGetContactsQuery } from "../../app/services/contact"; import { useLazyGetServerQuery } from "../../app/services/server"; import useStreaming from "../../common/hook/useStreaming"; @@ -13,6 +14,15 @@ export default function usePreload() { const { rehydrate, rehydrated } = useRehydrate(); const loginUid = useSelector((store) => store.authData.uid); const { setStreamingReady } = useStreaming(); + const [ + getFavorites, + { + isLoading: favoritesLoading, + isSuccess: favoritesSuccess, + isError: favoritesError, + data: favorites, + }, + ] = useLazyGetFavoritesQuery(); const [ getContacts, { @@ -43,6 +53,7 @@ export default function usePreload() { if (rehydrated) { getContacts(); getServer(); + getFavorites(); } }, [rehydrated]); const canStreaming = loginUid && rehydrated; @@ -53,12 +64,14 @@ export default function usePreload() { }, [canStreaming]); return { - loading: contactsLoading || serverLoading || !rehydrated, - error: contactsError && serverError, - success: contactsSuccess && serverSuccess, + loading: + contactsLoading || serverLoading || favoritesLoading || !rehydrated, + error: contactsError && serverError && favoritesError, + success: contactsSuccess && serverSuccess && favoritesSuccess, data: { contacts, server, + favorites, }, }; }