读取剪贴板,注册时绑定主播,登录后显示主播弹窗

This commit is contained in:
yezian 2024-01-12 18:56:10 +08:00
parent 1e599f02dc
commit d518750660
5 changed files with 188 additions and 21 deletions

101
App.jsx
View File

@ -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() {
</>
)}
</RootStack.Navigator>
<StreamerNavigatorModal
status={streamerNavigatorModalStatus}
setStatus={setStreamerNavigatorModalStatus}
/>
</NavigationContainer>
</View>
<Toast />

View File

@ -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 (
<Modal
visible={status.open}
transparent={true}
statusBarTranslucent
animationType="fade"
>
<TouchableOpacity
activeOpacity={1}
onPress={() => setStatus({ ...status, open: false })}
style={{
backgroundColor: "#00000080",
...tailwind("flex-1 justify-center items-center"),
}}
>
<TouchableOpacity
activeOpacity={1}
style={tailwind(
"rounded-2xl bg-[#1E1C29] items-center w-3/4 overflow-hidden"
)}
>
<View style={tailwind("flex flex-col w-full")}>
<Image
source={status.data?.cover?.images[0]?.urls[0]}
contentFit="cover"
transition={1000}
placeholder={blurhash}
cachePolicy="disk"
style={{ aspectRatio: 1, ...tailwind("w-full") }}
/>
<View style={tailwind("p-4")}>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind("text-xl text-white font-medium mr-1")}
numberOfLines={1}
ellipsizeMode="tail"
>
{status.data?.name}
</Text>
<NativeImage
source={require("../../assets/icon/others/verification.png")}
/>
</View>
<Text style={tailwind("text-sm text-[#FFFFFFB2] mt-1")}>
{status.data?.bio}
</Text>
<Button
onPress={() => {
navigation.navigate("StreamerProfile", {
mid: status.data?.mid,
});
setStatus({ ...status, open: false });
}}
color="#FF669E"
radius="999"
size="md"
titleStyle={tailwind("text-base")}
containerStyle={tailwind("w-full px-4 mt-4")}
>
查看主页
</Button>
</View>
</View>
</TouchableOpacity>
</TouchableOpacity>
</Modal>
);
}

View File

@ -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,
}),
}

View File

@ -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

View File

@ -955,16 +955,6 @@
"textAlign": "right"
}
},
"text-start": {
"style": {
"textAlign": "start"
}
},
"text-end": {
"style": {
"textAlign": "end"
}
},
"text-2xl": {
"style": {
"fontSize": 24,