diff --git a/App.jsx b/App.jsx
index 1ec6b0f..5aaab0d 100644
--- a/App.jsx
+++ b/App.jsx
@@ -1,12 +1,13 @@
import React, {
useState,
useEffect,
+ useRef,
useReducer,
useMemo,
createContext,
useCallback,
} from "react";
-import { View } from "react-native";
+import { View, AppState } from "react-native";
import * as SplashScreen from "expo-splash-screen";
import HomeTab from "./screeens/HomeTab";
import Login from "./screeens/Login";
@@ -35,11 +36,13 @@ import WechatWaitingToAdd from "./screeens/WechatWaitingToAdd";
import Search from "./screeens/Search";
import WebWithHeader from "./screeens/WebWithHeader";
import UpdateModal from "./components/UpdateModal";
+import StreamerNavigatorModal from "./components/StreamerNavigatorModal";
import { Icon } from "@rneui/themed";
import { StatusBar } from "expo-status-bar";
import { save, get, remove, storeAppInfo } from "./utils/storeInfo";
import baseRequest from "./utils/baseRequest";
import { generateSignature } from "./utils/crypto";
+import * as Clipboard from "expo-clipboard";
const RootStack = createNativeStackNavigator();
@@ -57,6 +60,9 @@ export default function App() {
},
};
+ //保存用户剪贴板内容
+ const [inviterCode, setInviterCode] = useState();
+
//获取环境变量
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
//登录逻辑
@@ -99,8 +105,9 @@ export default function App() {
dispatch({ type: "SIGN_OUT" });
}
},
+ inviterCode: inviterCode,
}),
- []
+ [inviterCode]
);
//控制开屏图片出现
const [appIsReady, setAppIsReady] = useState(false);
@@ -166,6 +173,92 @@ export default function App() {
prepare();
}, []);
+ //获取用户剪贴板内容
+ const getClipboardContent = useCallback(async () => {
+ const content = await Clipboard.getStringAsync();
+ const pattern = /https:\/\/tiefen\.fun\/(\d+)/;
+ const match = content.match(pattern);
+ if (match && match[1]) {
+ const intInviterCode = parseInt(match[1], 10);
+ setInviterCode(intInviterCode);
+ await Clipboard.setStringAsync("");
+ return;
+ }
+ setInviterCode(null);
+ }, []);
+
+ //当用户未登录时,获取剪贴板内容,用于绑定邀请人
+ useEffect(() => {
+ if (state.isSignin) return;
+ getClipboardContent();
+ }, []);
+
+ //每次从后台切换到前台时,获取用户剪贴板内容
+ const appState = useRef(AppState.currentState);
+ useEffect(() => {
+ if (!state.isSignin) return;
+ const subscription = AppState.addEventListener("change", (nextAppState) => {
+ if (
+ appState.current.match(/inactive|background/) &&
+ nextAppState === "active"
+ ) {
+ getClipboardContent();
+ }
+ appState.current = nextAppState;
+ });
+
+ return () => {
+ subscription.remove();
+ };
+ }, [state.isSignin]);
+
+ //当用户已经登录,查看根据剪贴板内容展示主播Modal
+ const [streamerNavigatorModalStatus, setStreamerNavigatorModalStatus] =
+ useState({
+ open: false,
+ data: {},
+ });
+ useEffect(() => {
+ const getInviterData = async () => {
+ //获取主播数据
+ if (!inviterCode) return;
+ if (!state.isSignin) return;
+ if (isUpdateModalVisible) return;
+ try {
+ const base = await baseRequest();
+ const signature = await generateSignature({
+ user_id: inviterCode,
+ ...base,
+ });
+ const inviterResponse = await fetch(
+ `${apiUrl}/api/streamer/list_ext_by_user_id?signature=${signature}`,
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ user_id: inviterCode,
+ ...base,
+ }),
+ }
+ );
+ const inviterData = await inviterResponse.json();
+ if (inviterData.ret === -1) {
+ return;
+ }
+ setStreamerNavigatorModalStatus({
+ open: true,
+ data: inviterData.data.streamer_ext,
+ });
+ } catch (e) {
+ console.warn(e);
+ }
+ };
+ getInviterData();
+ }, [state.isSignin, inviterCode, isUpdateModalVisible]);
+
+ //展示和隐藏splash
const onLayoutRootView = useCallback(async () => {
if (appIsReady) {
await SplashScreen.hideAsync();
@@ -454,6 +547,10 @@ export default function App() {
>
)}
+
diff --git a/components/StreamerNavigatorModal/index.jsx b/components/StreamerNavigatorModal/index.jsx
new file mode 100644
index 0000000..e4041d7
--- /dev/null
+++ b/components/StreamerNavigatorModal/index.jsx
@@ -0,0 +1,86 @@
+import {
+ View,
+ Text,
+ Modal,
+ TouchableOpacity,
+ Image as NativeImage,
+} from "react-native";
+import React from "react";
+import { useTailwind } from "tailwind-rn";
+import { Button } from "@rneui/themed";
+import { Image } from "expo-image";
+import { useNavigation } from "@react-navigation/native";
+
+export default function StreamerNavigatorModal({ status, setStatus }) {
+ const tailwind = useTailwind();
+ const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
+ const navigation = useNavigation();
+
+ return (
+
+ setStatus({ ...status, open: false })}
+ style={{
+ backgroundColor: "#00000080",
+ ...tailwind("flex-1 justify-center items-center"),
+ }}
+ >
+
+
+
+
+
+
+ {status.data?.name}
+
+
+
+
+ {status.data?.bio}
+
+
+
+
+
+
+
+ );
+}
diff --git a/screeens/Login/PhoneNumLogin/index.jsx b/screeens/Login/PhoneNumLogin/index.jsx
index 6d3e9f0..3896dd0 100644
--- a/screeens/Login/PhoneNumLogin/index.jsx
+++ b/screeens/Login/PhoneNumLogin/index.jsx
@@ -12,7 +12,7 @@ import { get, save } from "../../../utils/storeInfo";
import { generateSignature } from "../../../utils/crypto";
export default function PhoneNumLogin() {
- const { signIn } = useContext(AuthContext);
+ const { signIn, inviterCode } = useContext(AuthContext);
const navigation = useNavigation();
const tailwind = useTailwind();
//设置checkbox
@@ -137,6 +137,7 @@ export default function PhoneNumLogin() {
mobile_phone: mobile_phone,
region_code: regionCode,
veri_code: veriCode,
+ inviter: inviterCode,
...base,
});
try {
@@ -151,6 +152,7 @@ export default function PhoneNumLogin() {
mobile_phone: mobile_phone,
region_code: regionCode,
veri_code: veriCode,
+ inviter: inviterCode,
...base,
}),
}
diff --git a/tailwind.css b/tailwind.css
index 779ba3b..7088f4b 100644
--- a/tailwind.css
+++ b/tailwind.css
@@ -717,14 +717,6 @@
text-align: right
}
-.text-start {
- text-align: start
-}
-
-.text-end {
- text-align: end
-}
-
.text-2xl {
font-size: 1.5rem;
line-height: 2rem
diff --git a/tailwind.json b/tailwind.json
index 054f3b3..af18246 100644
--- a/tailwind.json
+++ b/tailwind.json
@@ -955,16 +955,6 @@
"textAlign": "right"
}
},
- "text-start": {
- "style": {
- "textAlign": "start"
- }
- },
- "text-end": {
- "style": {
- "textAlign": "end"
- }
- },
"text-2xl": {
"style": {
"fontSize": 24,