diff --git a/App.jsx b/App.jsx
index 6c5f735..c234d2d 100644
--- a/App.jsx
+++ b/App.jsx
@@ -69,7 +69,7 @@ import * as Clipboard from "expo-clipboard";
import PrivatyModal from "./components/PrivatyModal";
import * as Sentry from "@sentry/react-native";
import { ImageViewerProvider } from "./context/ImageViewProvider";
-
+import WebSocketComponent from "./components/Websocket";
import store from "./store";
import { Provider as ReduxProvider } from "react-redux";
@@ -122,7 +122,6 @@ const App = () => {
isSignin: false,
userToken: null,
});
-
const authContext = useMemo(
() => ({
signIn: async (data, mobilePhone, regionCode) => {
@@ -158,6 +157,7 @@ const App = () => {
dispatch({ type: "SIGN_OUT" });
}
},
+ state,
inviterCode: inviterCode,
checked: checked,
setChecked: setChecked,
@@ -228,7 +228,25 @@ const App = () => {
}
prepare();
}, []);
-
+ const handleGetWebsocketData = (data) => {
+ if (data.d.unread_cnt > 0) {
+ const { n_type, title } = data.d.notif;
+ Toast.show({
+ type: "info",
+ text1: `🔔 收到一条${
+ n_type === 0
+ ? "系统"
+ : n_type === 1
+ ? "审核"
+ : n_type === 2
+ ? "付费"
+ : "活动"
+ }通知`,
+ text2: title,
+ topOffset: 60,
+ });
+ }
+ };
//获取用户剪贴板内容
const getClipboardContent = useCallback(async () => {
const content = await Clipboard.getStringAsync();
@@ -242,7 +260,6 @@ const App = () => {
}
setInviterCode(null);
}, []);
-
//登录后获取用户剪贴板内容
useEffect(() => {
if (!state.isSignin) return;
@@ -911,6 +928,10 @@ const App = () => {
setVisible={setIsUpdateModalVisible}
data={versionData}
/>
+
diff --git a/components/Websocket/index.jsx b/components/Websocket/index.jsx
index a3c1530..24ab903 100644
--- a/components/Websocket/index.jsx
+++ b/components/Websocket/index.jsx
@@ -2,86 +2,116 @@ import React, { useEffect, useState } from "react";
import { View } from "react-native";
import baseRequest from "../../utils/baseRequest";
import { get } from "../../utils/storeInfo";
+import { getNoticeCount } from "../../store/reducer";
+import { connect } from "react-redux";
import "text-encoding";
-const WebSocketComponent = ({ getData }) => {
+var retryInterval = 1000;
+const maxInterval = 60000;
+let interval = null;
+let timer = null;
+var messageQueue = [];
+let socket = null;
+const WebSocketComponent = ({ getData, state, changeCount }) => {
const [messages, setMessages] = useState([]);
-
useEffect(() => {
- let socket = null;
- let interval = null;
- async function connect_socket() {
- const appInfo = await get("app_info");
- const base = await baseRequest();
- if (socket && socket.readyState === 1) return;
- // 创建WebSocket连接
- if (!socket) {
- socket = new WebSocket(
- `${process.env.EXPO_PUBLIC_WEBSOCKET_URL}/ws?b_mid=${base.b_mid}&b_did=${base.b_did}&b_dt=1&b_token=${base.b_token}&b_ch${appInfo.b_ch}`
- );
- // console.log("------------++++++++++++++++", socket);
- socket.onopen = () => {
- console.log("WebSocket connected.");
- // 可以在这里发送消息到服务器,例如:socket.send('Hello Server!');
- socket.send(JSON.stringify({ t: 1 }));
- };
-
- // 处理收到的消息
- socket.onmessage = (event) => {
- if (
- Object.prototype.toString.call(event.data) ===
- "[object ArrayBuffer]"
- ) {
- let enc = new TextDecoder("utf-8");
- const view = new Uint8Array(event.data);
- let temp = enc.decode(view);
- try {
- const data = JSON.parse(temp);
- if (data.t === 2 && data.msg.ping_interval) {
- socket.send("ping");
- interval = setInterval(() => {
- // 发送 ping 给服务器
- socket.send("ping");
- // 响应服务器的 ping
- // socket.on("ping", () => {
- // socket.senrd("pong");
- // });
- }, data.msg.ping_interval * 1000);
- }
- if (data.t === 3) {
- getData(data.msg);
- setMessages((prevMessages) => [...prevMessages, data]);
- }
- } catch (error) {}
- }
- };
-
- // 连接关闭时触发
- socket.onclose = () => {
- clearInterval(interval);
- // connect_socket();
- console.log("WebSocket disconnected.");
- };
-
- // 连接错误时触发
- socket.onerror = (error) => {
- console.error("WebSocket error:", error);
- };
- }
- // 响应服务器的 ping
- // socket.on("ping", () => {
- // socket.send("pong");
- // });
- }
-
- connect_socket();
-
// 组件卸载时关闭WebSocket连接
return () => {
+ console.log("卸载了socket");
socket?.readyState === WebSocket.OPEN && socket?.close();
clearInterval(interval);
};
}, []); // 空依赖数组表示这个effect只在组件挂载时运行一次
+ useEffect(() => {
+ socket?.close();
+ if (state.isSignin) {
+ connect_socket();
+ } else {
+ // changeCount(0);
+ clearInterval(interval);
+ clearTimeout(timer);
+ socket?.close();
+ socket = null;
+ }
+ }, [state]); // 空依赖数组表示这个effect只在组件挂载时运行一次
+ async function connect_socket() {
+ const appInfo = await get("app_info");
+ const base = await baseRequest();
+ if (socket && socket.readyState === 1) return;
+ // 创建WebSocket连接
+ socket = new WebSocket(
+ `${process.env.EXPO_PUBLIC_WEBSOCKET_URL}/ws?b_mid=${base.b_mid}&b_did=${base.b_did}&b_dt=1&b_token=${base.b_token}&b_ch${appInfo.b_ch}`
+ );
+ socket.onopen = () => {
+ console.log("WebSocket connected.");
+ retryInterval = 1000;
+ // 可以在这里发送消息到服务器,例如:socket.send('Hello Server!');
+ if (socket.readyState == WebSocket.OPEN)
+ socket.send(JSON.stringify({ t: 1 }));
+ };
+ // 处理收到的消息
+ socket.onmessage = (event) => {
+ if (
+ Object.prototype.toString.call(event.data) === "[object ArrayBuffer]"
+ ) {
+ let enc = new TextDecoder("utf-8");
+ const view = new Uint8Array(event.data);
+ let temp = enc.decode(view);
+ try {
+ const data = JSON.parse(temp);
+ if (data.t === 2 && data.msg.ping_interval) {
+ if (socket.readyState == WebSocket.OPEN) socket.send("ping");
+ interval = setInterval(() => {
+ // 发送 ping 给服务器
+ if (socket.readyState == WebSocket.OPEN) socket.send("ping");
+ // 响应服务器的 ping
+ // socket.on("ping", () => {
+ // socket.senrd("pong");
+ // });
+ }, data.msg.ping_interval * 1000);
+ }
+ if (data.t === 3) {
+ getData(data.msg);
+ changeCount(data.msg.d.unread_cnt);
+ setMessages((prevMessages) => [...prevMessages, data]);
+ }
+ } catch (error) {}
+ }
+ };
+
+ // 连接关闭时触发
+ socket.onclose = async () => {
+ clearTimeout(timer);
+ const account = await get("account");
+ if (state.isSignin && typeof account?.mid === "number") {
+ timer = setTimeout(() => {
+ if (!state.isSignin) {
+ clearTimeout(timer);
+ return;
+ }
+ retryInterval = Math.min(retryInterval * 2, maxInterval);
+ try {
+ connect_socket();
+ } catch (error) {
+ console.log(error);
+ }
+ }, retryInterval);
+ }
+ // changeCount(0);
+ console.log("WebSocket disconnected.");
+ };
+
+ // 连接错误时触发
+ socket.onerror = (error) => {
+ clearTimeout(timer);
+ socket?.close();
+ console.error("WebSocket error:", error);
+ };
+ // 响应服务器的 ping
+ // socket.on("ping", () => {
+ // socket.send("pong");
+ // });
+ }
return (
{/* WebSocket Messages
@@ -94,4 +124,13 @@ const WebSocketComponent = ({ getData }) => {
);
};
-export default WebSocketComponent;
+const mapDispatchFromProps = (dispatch) => {
+ return {
+ changeCount: (num) => {
+ // 调用dispatch方法,传递actions
+ dispatch(getNoticeCount(num));
+ },
+ };
+};
+
+export default connect(null, mapDispatchFromProps)(WebSocketComponent);
diff --git a/screeens/HomeTab/index.jsx b/screeens/HomeTab/index.jsx
index 17b908f..32272bc 100644
--- a/screeens/HomeTab/index.jsx
+++ b/screeens/HomeTab/index.jsx
@@ -9,18 +9,15 @@ import Posts from "../Posts";
import Space from "../Space";
import { get } from "../../utils/storeInfo";
import CreatePostModal from "../../components/CreatePostModal";
-import WebSocketComponent from "../../components/Websocket";
+import { connect } from "react-redux";
import Toast from "react-native-toast-message";
import baseRequest from "../../utils/baseRequest";
import { generateSignature } from "../../utils/crypto";
-import { useSelector, useDispatch } from "react-redux";
import { getNoticeCount } from "../../store/reducer";
const Tab = createBottomTabNavigator();
-export default function HomeTab({ navigation, route }) {
+function HomeTab({ changeCount, noticeCount, authInfo }) {
const [isCreatePostTabVisible, setIsCreatePostTabVisible] = useState(false);
- const noticeCount = useSelector((state) => state.noticeCount);
- const dispatch = useDispatch();
useEffect(() => {
const checkRole = async () => {
const account = await get("account");
@@ -51,10 +48,10 @@ export default function HomeTab({ navigation, route }) {
});
return;
}
- dispatch(getNoticeCount(_data.data.total));
+ changeCount(_data.data.total);
};
checkRole();
- }, [noticeCount]);
+ }, [noticeCount, authInfo]);
const CustomTabBarButton = useCallback(({ children }) => {
const [visible, setVisible] = useState(false);
return (
@@ -80,26 +77,6 @@ export default function HomeTab({ navigation, route }) {
);
}, []);
- const handleGetWebsocketData = (data) => {
- if (data.d.unread_cnt > 0) {
- dispatch(getNoticeCount(data.d.unread_cnt));
- const { n_type, title } = data.d.notif;
- Toast.show({
- type: "info",
- text1: `🔔 收到一条${
- n_type === 0
- ? "系统"
- : n_type === 1
- ? "审核"
- : n_type === 2
- ? "付费"
- : "活动"
- }通知`,
- text2: title,
- topOffset: 60,
- });
- }
- };
const EmptyComponent = () => <>>;
return (
@@ -281,7 +258,26 @@ export default function HomeTab({ navigation, route }) {
}}
/>
-
>
);
}
+
+// 获取store中的数据的方法
+const mapstateFromProps = (state) => {
+ // state: store仓库中的数据
+ return {
+ noticeCount: state.noticeCount,
+ authInfo: state.authInfo,
+ };
+};
+// 修改store中的数据的方法
+const mapDispatchFromProps = (dispatch) => {
+ return {
+ changeCount: (num) => {
+ // 调用dispatch方法,传递actions
+ dispatch(getNoticeCount(num));
+ },
+ };
+};
+
+export default connect(mapstateFromProps, mapDispatchFromProps)(HomeTab);
diff --git a/screeens/NoticeDetail/components/MessageList/index.jsx b/screeens/NoticeDetail/components/MessageList/index.jsx
index 3552f4f..0eaf17c 100644
--- a/screeens/NoticeDetail/components/MessageList/index.jsx
+++ b/screeens/NoticeDetail/components/MessageList/index.jsx
@@ -19,7 +19,8 @@ import { useDispatch } from "react-redux";
import { getNoticeCount } from "../../../../store/reducer";
import requireAPI from "../../../../utils/requireAPI";
import { Image } from "expo-image";
-const MessageList = forwardRef(({ navigation }, ref) => {
+import { connect } from "react-redux";
+const MessageList = ({ navigation, noticeCount, refInstance }) => {
const dispatch = useDispatch();
const [data, setData] = useState([]);
const [scollNotice, setScollNotice] = useState("");
@@ -59,7 +60,7 @@ const MessageList = forwardRef(({ navigation }, ref) => {
icon: require(`../../../../assets/icon/others/m_active.png`),
},
]);
- useImperativeHandle(ref, () => ({
+ useImperativeHandle(refInstance, () => ({
readAllMsg: async (types) => {
try {
const body = {
@@ -98,11 +99,9 @@ const MessageList = forwardRef(({ navigation }, ref) => {
},
}));
useEffect(() => {
- navigation.addListener("focus", () => {
- getData();
- getActiveNotice();
- });
- }, []);
+ getData();
+ getActiveNotice();
+ }, [noticeCount]);
const getData = async () => {
try {
const base = await baseRequest();
@@ -339,6 +338,17 @@ const MessageList = forwardRef(({ navigation }, ref) => {
);
-});
+};
-export default MessageList;
+// 获取store中的数据的方法
+const mapstateFromProps = (state) => {
+ // state: store仓库中的数据
+ return {
+ noticeCount: state.noticeCount,
+ };
+};
+
+const Component = connect(mapstateFromProps, null)(MessageList);
+export default forwardRef((props, ref) => (
+
+));
diff --git a/screeens/Setting/SwitchAccount/index.jsx b/screeens/Setting/SwitchAccount/index.jsx
index 231f4d6..f4ff00f 100644
--- a/screeens/Setting/SwitchAccount/index.jsx
+++ b/screeens/Setting/SwitchAccount/index.jsx
@@ -25,8 +25,9 @@ import baseRequest from "../../../utils/baseRequest";
import { generateSignature } from "../../../utils/crypto";
import MyModal from "../../../components/MyModal";
import Toast from "react-native-toast-message";
-
-export default function SwitchAccount({ navigation, route }) {
+import { handleLogin } from "../../../store/reducer";
+import { connect } from "react-redux";
+function SwitchAccount({ changeLogin }) {
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
const tailwind = useTailwind();
@@ -115,6 +116,12 @@ export default function SwitchAccount({ navigation, route }) {
login_time: new Date().getTime(),
});
signIn(_data, data.mobile_phone_origion, data.region_code);
+ changeLogin({
+ isSignin: true,
+ userToken: data.token,
+ recommendMid: null,
+ inviter: null,
+ });
setAccountList((pre) =>
pre.map((item) => ({
...item,
@@ -162,6 +169,12 @@ export default function SwitchAccount({ navigation, route }) {
await remove(key);
if (online) {
signOut();
+ changeLogin({
+ isSignin: false,
+ userToken: null,
+ recommendMid: null,
+ inviter: null,
+ });
return;
}
setAccountList((pre) => pre.filter((item) => item.key !== key));
@@ -316,3 +329,14 @@ export default function SwitchAccount({ navigation, route }) {
);
}
+
+const mapDispatchFromProps = (dispatch) => {
+ return {
+ changeLogin: (data) => {
+ // 调用dispatch方法,传递actions
+ dispatch(handleLogin(data));
+ },
+ };
+};
+
+export default connect(null, mapDispatchFromProps)(SwitchAccount);
diff --git a/store/reducer.js b/store/reducer.js
index d5d5d8d..42bf64f 100644
--- a/store/reducer.js
+++ b/store/reducer.js
@@ -5,14 +5,23 @@ export const appSlice = createSlice({
initialState: {
noticeCount: 0,
},
+ authInfo: {
+ isSignin: false,
+ userToken: null,
+ recommendMid: null,
+ inviter: null,
+ },
reducers: {
getNoticeCount: (state, { payload }) => {
state.noticeCount = payload;
},
+ handleLogin: (state, { payload }) => {
+ state.authInfo = payload;
+ },
},
});
// Action creators are generated for each case reducer function
-export const { getNoticeCount } = appSlice.actions;
+export const { getNoticeCount, handleLogin } = appSlice.actions;
export default appSlice.reducer;