refactor: archive message

This commit is contained in:
Tristan Yang
2023-03-16 09:28:17 +08:00
parent 02f02709c1
commit 75df1f93c9
11 changed files with 119 additions and 35 deletions
+5 -1
View File
@@ -38,5 +38,9 @@
"delete_msg_these": "these messages",
"new_msg": "{{num}} new messages",
"mark_read": "Mark As Read"
"mark_read": "Mark As Read",
"file": "file",
"image": "image",
"forward": "forward"
}
+5 -1
View File
@@ -39,5 +39,9 @@
"delete_msg_these": "这些消息",
"new_msg": "{{num}} 条新消息",
"mark_read": "设为已读"
"mark_read": "设为已读",
"file": "文件",
"image": "图片",
"forward": "转发"
}
+5 -1
View File
@@ -28,7 +28,11 @@ const tables = [
},
{
storeName: "messageFile",
description: "store file message list refs"
description: "store file message list"
},
{
storeName: "messageArchive",
description: "store archive message"
},
{
storeName: "messageReaction",
@@ -0,0 +1,25 @@
import clearTable from "./clear.handler";
interface Params {
payload: any;
operation: string;
}
export default async function handler({ operation, payload = {} }: Params) {
const table = window.CACHE["messageArchive"];
if (operation.startsWith("reset")) {
clearTable("messageArchive");
return;
}
switch (operation) {
case "upsertArchiveMessage":
{
const { filePath, data } = payload;
console.log("archive message indexDB opt", payload);
if (filePath) {
await table?.setItem(filePath, data);
}
}
break;
default:
break;
}
}
+11 -1
View File
@@ -7,6 +7,7 @@ import dmMsgHandler from "./handler.dm.msg";
import serverHandler from "./handler.server";
import messageHandler from "./handler.message";
import fileMessageHandler from "./handler.file.msg";
import archiveMessageHandler from "./handler.archive.msg";
import reactionHandler from "./handler.reaction";
import UIHandler from "./handler.ui";
import footprintHandler from "./handler.footprint";
@@ -20,6 +21,7 @@ const operations = [
"userMessage",
"reactionMessage",
"fileMessage",
"archiveMessage",
"message",
"ui",
"footprint",
@@ -35,7 +37,7 @@ listenerMiddleware.startListening({
predicate: (action) => {
const { type = "" } = action;
const [prefix] = type.split("/");
// console.log("operation", type, operations.includes(prefix));
// console.log("operation", type);
return operations.includes(prefix);
// console.log("listener predicate", action, currentState, previousState);
// return true;
@@ -102,6 +104,14 @@ listenerMiddleware.startListening({
});
}
break;
case "archiveMessage":
{
await archiveMessageHandler({
operation,
payload
});
}
break;
case "message":
{
await messageHandler({
+12 -3
View File
@@ -9,6 +9,7 @@ import { Archive, FavoriteArchive, OG } from "../../types/resource";
import { ChatMessage, ContentTypeKey, UploadFileResponse } from "../../types/message";
import handleChatMessage from "../../common/hook/useStreaming/chat.handler";
import { RootState } from "../store";
import { upsertArchiveMessage } from "../slices/message.archive";
export const messageApi = createApi({
reducerPath: "messageApi",
@@ -85,9 +86,17 @@ export const messageApi = createApi({
}),
getArchiveMessage: builder.query<Archive, string>({
query: (file_path) => ({
url: `/resource/archive?file_path=${encodeURIComponent(file_path)}`
})
query: (filePath) => ({
url: `/resource/archive?file_path=${encodeURIComponent(filePath)}`
}),
async onQueryStarted(filePath, { dispatch, queryFulfilled }) {
try {
const { data } = await queryFulfilled;
dispatch(upsertArchiveMessage({ filePath, data }));
} catch (err) {
console.log("get archive error", err);
}
}
}),
pinMessage: builder.mutation<void, { gid: number; mid: number }>({
query: ({ gid, mid }) => ({
+35
View File
@@ -0,0 +1,35 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
// import { ContentTypes } from "../config";
// import { normalizeFileMessage } from "../../common/utils";
// import { ContentType } from "../../types/message";
import { Archive } from "../../types/resource";
export interface State {
[key: string]: Archive;
}
const initialState: State = {
};
const messageArchiveSlice = createSlice({
name: "archiveMessage",
initialState,
reducers: {
resetArchiveMessage() {
return initialState;
},
fillArchiveMessage(state, action) {
return Object.assign({ ...initialState }, action.payload);
},
upsertArchiveMessage(state, action: PayloadAction<{ filePath: string, data: Archive }>) {
const { filePath, data } = action.payload;
state[filePath] = data;
},
}
});
export const {
resetArchiveMessage,
fillArchiveMessage,
upsertArchiveMessage
} = messageArchiveSlice.actions;
export default messageArchiveSlice.reducer;
+2
View File
@@ -13,6 +13,7 @@ import channelMsgReducer from "./slices/message.channel";
import userMsgReducer from "./slices/message.user";
import favoritesReducer from "./slices/favorites";
import fileMsgReducer from "./slices/message.file";
import archiveMsgReducer from "./slices/message.archive";
import messageReducer from "./slices/message";
import { authApi } from "./services/auth";
import { userApi } from "./services/user";
@@ -32,6 +33,7 @@ const reducer = combineReducers({
userMessage: userMsgReducer,
channelMessage: channelMsgReducer,
fileMessage: fileMsgReducer,
archiveMessage: archiveMsgReducer,
message: messageReducer,
[authApi.reducerPath]: authApi.reducer,
[messageApi.reducerPath]: messageApi.reducer,
@@ -1,5 +1,4 @@
import { useEffect, useState, FC, ReactElement } from "react";
import StyledMsg from "./styled";
import renderContent from "./renderContent";
import Avatar from "../Avatar";
import IconForward from "../../../assets/icons/forward.svg";
@@ -14,13 +13,9 @@ type Props = {
};
const ForwardedMessage: FC<Props> = ({ context, to, from_uid, id }) => {
const { t } = useTranslation();
const { normalizeMessage, messages } = useNormalizeMessage();
const { messages, isLoading } = useNormalizeMessage(id);
const [forwards, setForwards] = useState<ReactElement | null>(null);
useEffect(() => {
if (id) {
normalizeMessage(id);
}
}, [id]);
useEffect(() => {
if (messages) {
const forward_mids = messages.map(({ from_mid }) => from_mid) || [];
@@ -67,6 +62,7 @@ const ForwardedMessage: FC<Props> = ({ context, to, from_uid, id }) => {
}
}, [messages, context, to, from_uid]);
if (!id) return null;
if (isLoading) return <span className="text-sm dark:text-white">Loading</span>;
return forwards;
};
+8 -14
View File
@@ -2,29 +2,23 @@ import { useState, useEffect } from "react";
import { normalizeArchiveData } from "../utils";
import { useLazyGetArchiveMessageQuery } from "../../app/services/message";
import { ArchiveMessage } from "../../types/resource";
import { useAppSelector } from "../../app/store";
export default function useNormalizeMessage() {
const [filePath, setFilePath] = useState<string | null>(null);
export default function useNormalizeMessage(filePath: string | null) {
const archiveData = useAppSelector(store => store.archiveMessage[filePath ?? ""]);
const [normalizedMessages, setNormalizedMessages] = useState<ArchiveMessage[] | null>(null);
const [getArchiveMessage, { data, isError, isLoading, isSuccess }] =
const [getArchiveMessage, { isError, isLoading, isSuccess }] =
useLazyGetArchiveMessageQuery();
useEffect(() => {
if (data && isSuccess) {
const msgs = normalizeArchiveData(data, filePath);
if (archiveData) {
const msgs = normalizeArchiveData(archiveData, filePath);
setNormalizedMessages(msgs);
}
}, [data, isSuccess, filePath]);
useEffect(() => {
if (filePath) {
} else if (filePath) {
getArchiveMessage(filePath);
}
}, [filePath]);
}, [archiveData, filePath]);
const normalizeMessage = (file_path: string) => {
setFilePath(file_path);
};
return {
normalizeMessage,
messages: normalizedMessages,
isError,
isLoading,
+8 -7
View File
@@ -9,6 +9,7 @@ import Message from "../../common/component/Message";
import { updateSelectMessages } from "../../app/slices/ui";
import { useAppSelector } from "../../app/store";
import LinkifyText from "../../common/component/LinkifyText";
import i18n from "../../i18n";
export function getUnreadCount({
mids = [],
@@ -63,18 +64,18 @@ export const renderPreviewMessage = (message = null) => {
res = `[markdown]`;
}
break;
// case ContentTypes.archive:
// {
// res = `[forward]`;
// }
// break;
case ContentTypes.archive:
{
res = `[${i18n.t("forward", { ns: "chat" })}]`;
}
break;
case ContentTypes.file:
{
const props = properties ?? {};
if (isImage(props.content_type, props.size)) {
res = `[image]`;
res = `[${i18n.t("image", { ns: "chat" })}]`;
} else {
res = `[file]`;
res = `[${i18n.t("file", { ns: "chat" })}]`;
}
}