20260629154839
This commit is contained in:
1 parent
e687846eb4
commit
bb596f3245
41 files changed
+5735
-86
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { createContext, ReactNode, useCallback, useContext, useEffect, useRef } from "react";
|
||||
import { usePathname } from "expo-router";
|
||||
import { toast } from "sonner-native";
|
||||
import { useUserStore, useFamilyStore } from "@/store";
|
||||
import { useChatStore } from "@/store/chat";
|
||||
@@ -24,7 +25,9 @@ const ChatWebSocketContext = createContext<ChatWebSocketValue | null>(null);
|
||||
|
||||
function useChatWebSocketConnection(): ChatWebSocketValue {
|
||||
const token = useUserStore((s) => s.userInfo?.token);
|
||||
const userId = useUserStore((s) => s.userInfo?.id);
|
||||
const familyId = useFamilyStore((s) => s.currentFamily?.family_id);
|
||||
const pathname = usePathname();
|
||||
const messages = useChatStore((s) => s.messages);
|
||||
const onlineUsers = useChatStore((s) => s.onlineUsers);
|
||||
const isConnected = useChatStore((s) => s.isConnected);
|
||||
@@ -38,6 +41,8 @@ function useChatWebSocketConnection(): ChatWebSocketValue {
|
||||
const mounted = useRef(true);
|
||||
const wasConnected = useRef(false);
|
||||
const shouldReconnect = useRef(false);
|
||||
const pathnameRef = useRef(pathname);
|
||||
const userIdRef = useRef(userId);
|
||||
|
||||
const buildWsUrl = useCallback(() => {
|
||||
const apiUrl = process.env.EXPO_PUBLIC_API_URL || "";
|
||||
@@ -103,10 +108,17 @@ function useChatWebSocketConnection(): ChatWebSocketValue {
|
||||
const handleMessage = useCallback((msg: any) => {
|
||||
switch (msg.type) {
|
||||
case "message": {
|
||||
const data = msg.data as ChatMessage;
|
||||
const data = normalizeChatMessage(msg.data as ChatMessage);
|
||||
if (data.id <= lastReceivedId.current) return;
|
||||
lastReceivedId.current = data.id;
|
||||
useChatStore.getState().addMessage(normalizeChatMessage(data));
|
||||
useChatStore.getState().addMessage(data);
|
||||
|
||||
const inChatPage =
|
||||
pathnameRef.current === "/chat" || pathnameRef.current.startsWith("/chat/");
|
||||
const fromCurrentUser = String(data.user_id) === String(userIdRef.current);
|
||||
if (!inChatPage && !fromCurrentUser) {
|
||||
toast(`${data.nickname || "有人"}发送了一条信息`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "message_recalled": {
|
||||
@@ -143,6 +155,14 @@ function useChatWebSocketConnection(): ChatWebSocketValue {
|
||||
wsRef.current.send(JSON.stringify({ type: "delete", message_id: messageId }));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
pathnameRef.current = pathname;
|
||||
}, [pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
userIdRef.current = userId;
|
||||
}, [userId]);
|
||||
|
||||
useEffect(() => {
|
||||
mounted.current = true;
|
||||
shouldReconnect.current = !!token && !!familyId;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { useCallback } from "react";
|
||||
import { useChatWebSocket } from "@/hooks/useChatWebSocket";
|
||||
import { ChatMsgType } from "@/types/chat";
|
||||
|
||||
interface ModuleOperationNotifyPayload {
|
||||
module: string;
|
||||
action: string;
|
||||
target?: string;
|
||||
detail?: string;
|
||||
sourceTable?: string;
|
||||
sourceId?: number;
|
||||
}
|
||||
|
||||
export function useModuleChatNotifier() {
|
||||
const chat = useChatWebSocket();
|
||||
|
||||
return useCallback(
|
||||
({ module, action, target, detail, sourceTable, sourceId }: ModuleOperationNotifyPayload) => {
|
||||
const content = [
|
||||
`【${module}】${action}`,
|
||||
target ? `:${target}` : "",
|
||||
detail ? `(${detail})` : "",
|
||||
].join("");
|
||||
|
||||
chat.send({
|
||||
type: "send",
|
||||
msg_type: ChatMsgType.System,
|
||||
content,
|
||||
source_table: sourceTable,
|
||||
source_id: sourceId,
|
||||
});
|
||||
},
|
||||
[chat],
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user