Skip to content

Commit b6b72d4

Browse files
author
Developer
committed
refactor: replace real API with mock data layer
1 parent 1c0a564 commit b6b72d4

File tree

9 files changed

+440
-716
lines changed

9 files changed

+440
-716
lines changed

components/BigVideoCard.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ import { useLiveStore } from "../store/liveStore";
2727
import { formatCount, formatDuration } from "../utils/format";
2828
import type { VideoItem } from "../services/types";
2929

30-
const HEADERS = {
31-
Referer: "https://www.bilibili.com",
32-
"User-Agent":
33-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
34-
};
30+
const HEADERS = {};
3531

3632
const BAR_H = 3;
3733
// Minimum horizontal distance (px) before treating the gesture as a seek

components/LiveMiniPlayer.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@ import { proxyImageUrl } from '../utils/imageUrl';
1919
const MINI_W = 160;
2020
const MINI_H = 90;
2121

22-
const LIVE_HEADERS = {
23-
Referer: 'https://live.bilibili.com',
24-
'User-Agent':
25-
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
26-
};
22+
const LIVE_HEADERS = {};
2723

2824
function snapRelease(
2925
pan: Animated.ValueXY,

components/LivePlayer.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ interface Props {
2323

2424
const HIDE_DELAY = 3000;
2525

26-
const HEADERS = {
27-
Referer: "https://live.bilibili.com",
28-
"User-Agent":
29-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
30-
};
26+
const HEADERS = {};
3127

3228
export function LivePlayer({
3329
hlsUrl,

components/LoginModal.tsx

Lines changed: 37 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,14 @@
1-
import React, { useEffect, useState, useRef } from "react";
1+
import React, { useRef } from "react";
22
import {
33
Modal,
44
View,
55
Text,
66
StyleSheet,
77
TouchableOpacity,
8-
ActivityIndicator,
98
Animated,
10-
Alert,
11-
Linking,
129
} from "react-native";
13-
import * as FileSystem from "expo-file-system/legacy";
14-
import * as MediaLibrary from "expo-media-library";
15-
import QRCode from "react-native-qrcode-svg";
1610
import { Ionicons } from "@expo/vector-icons";
17-
import { generateQRCode, pollQRCode } from "../services/api";
11+
import { pollQRCode } from "../services/api";
1812
import { useAuthStore } from "../store/authStore";
1913
import { useTheme } from "../utils/theme";
2014

@@ -24,21 +18,12 @@ interface Props {
2418
}
2519

2620
export function LoginModal({ visible, onClose }: Props) {
27-
const [qrData, setQrData] = useState<string | null>(null);
28-
const [qrKey, setQrKey] = useState<string | null>(null);
29-
const [saving, setSaving] = useState(false);
30-
const qrRef = useRef<any>(null);
31-
const [status, setStatus] = useState<
32-
"loading" | "waiting" | "scanned" | "done" | "error"
33-
>("loading");
34-
const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
3521
const login = useAuthStore((s) => s.login);
3622
const theme = useTheme();
3723

38-
// sheet 滑入动画
3924
const slideY = useRef(new Animated.Value(300)).current;
4025

41-
useEffect(() => {
26+
React.useEffect(() => {
4227
if (visible) {
4328
Animated.spring(slideY, {
4429
toValue: 0,
@@ -50,85 +35,11 @@ export function LoginModal({ visible, onClose }: Props) {
5035
}
5136
}, [visible]);
5237

53-
useEffect(() => {
54-
if (!visible) return;
55-
setStatus("loading");
56-
setQrData(null);
57-
setQrKey(null);
58-
generateQRCode()
59-
.then((data) => {
60-
setQrData(data.url);
61-
setQrKey(data.qrcode_key);
62-
setStatus("waiting");
63-
})
64-
.catch(() => setStatus("error"));
65-
66-
return () => {
67-
if (pollRef.current) clearInterval(pollRef.current);
68-
};
69-
}, [visible]);
70-
71-
useEffect(() => {
72-
if (!qrKey || status !== "waiting") return;
73-
let cancelled = false;
74-
pollRef.current = setInterval(async () => {
75-
if (cancelled) return;
76-
try {
77-
const result = await pollQRCode(qrKey);
78-
if (cancelled) return;
79-
if (result.code === 86038) {
80-
setStatus("error");
81-
clearInterval(pollRef.current!);
82-
}
83-
if (result.code === 86090) setStatus("scanned");
84-
if (result.code === 0 && result.cookie) {
85-
clearInterval(pollRef.current!);
86-
try {
87-
await login(result.cookie, "", "");
88-
} catch {
89-
if (!cancelled) setStatus("error");
90-
return;
91-
}
92-
if (!cancelled) onClose();
93-
}
94-
} catch {
95-
// Network error during poll — ignore, will retry next interval
96-
}
97-
}, 2000);
98-
return () => {
99-
cancelled = true;
100-
if (pollRef.current) clearInterval(pollRef.current);
101-
};
102-
}, [qrKey, status]);
103-
104-
async function handleSaveQR() {
105-
if (!qrRef.current) return;
106-
setSaving(true);
107-
try {
108-
const { status: perm } = await MediaLibrary.requestPermissionsAsync();
109-
if (perm !== "granted") {
110-
Alert.alert("提示", "需要相册权限才能保存图片");
111-
return;
112-
}
113-
qrRef.current.toDataURL(async (base64: string) => {
114-
try {
115-
const dest = `${FileSystem.cacheDirectory}qrcode_temp.png`;
116-
await FileSystem.writeAsStringAsync(dest, base64, {
117-
encoding: FileSystem.EncodingType.Base64,
118-
});
119-
await MediaLibrary.saveToLibraryAsync(dest);
120-
Alert.alert("已保存", "二维码已存入相册,请扫码登录", [
121-
{ text: "关闭", style: "cancel" },
122-
]);
123-
} catch {
124-
Alert.alert("失败", "保存失败,请重试");
125-
} finally {
126-
setSaving(false);
127-
}
128-
});
129-
} catch {
130-
Alert.alert("失败", "保存失败,请重试");
131-
setSaving(false);
38+
async function handleLogin() {
39+
const result = await pollQRCode('mock-key');
40+
if (result.code === 0 && result.cookie) {
41+
await login(result.cookie, '', '');
42+
onClose();
13243
}
13344
}
13445

@@ -139,54 +50,32 @@ export function LoginModal({ visible, onClose }: Props) {
13950
animationType="none"
14051
onRequestClose={onClose}
14152
>
142-
{/* 遮罩固定不动 */}
14353
<View style={styles.overlay} pointerEvents="box-none" />
14454

145-
{/* sheet 独立滑入 */}
14655
<Animated.View
14756
style={[styles.sheetWrapper, { transform: [{ translateY: slideY }] }]}
14857
>
14958
<View style={[styles.sheet, { backgroundColor: theme.sheetBg }]}>
150-
<Text style={[styles.title, { color: theme.modalText }]}>扫码登录</Text>
151-
{status === "loading" && (
152-
<ActivityIndicator
153-
size="large"
154-
color="#00AEEC"
155-
style={styles.loader}
156-
/>
157-
)}
158-
{(status === "waiting" || status === "scanned") && qrData && (
159-
<>
160-
<View style={styles.qrWrapper}>
161-
<QRCode
162-
value={qrData}
163-
size={200}
164-
getRef={(ref) => { qrRef.current = ref; }}
165-
/>
166-
<TouchableOpacity
167-
style={styles.saveBtn}
168-
onPress={handleSaveQR}
169-
disabled={saving}
170-
>
171-
{saving ? (
172-
<ActivityIndicator size="small" color="#fff" />
173-
) : (
174-
<Ionicons name="download-outline" size={16} color="#fff" />
175-
)}
176-
</TouchableOpacity>
177-
</View>
178-
<Text style={[styles.hint, { color: theme.modalTextSub }]}>
179-
{status === "scanned"
180-
? "扫描成功,请在手机确认"
181-
: "使用手机 APP 扫一扫"}
182-
</Text>
183-
</>
184-
)}
185-
{status === "error" && (
186-
<Text style={[styles.hint, { color: theme.modalTextSub }]}>二维码已过期,请关闭重试</Text>
187-
)}
59+
<Text style={[styles.title, { color: theme.modalText }]}>登录</Text>
60+
61+
<View style={styles.iconWrap}>
62+
<Ionicons name="person-circle-outline" size={72} color="#00AEEC" />
63+
</View>
64+
65+
<Text style={[styles.hint, { color: theme.modalTextSub }]}>
66+
演示模式:点击下方按钮一键登录
67+
</Text>
68+
69+
<TouchableOpacity
70+
style={styles.loginBtn}
71+
onPress={handleLogin}
72+
activeOpacity={0.85}
73+
>
74+
<Text style={styles.loginBtnText}>一键登录</Text>
75+
</TouchableOpacity>
76+
18877
<TouchableOpacity style={styles.closeBtn} onPress={onClose}>
189-
<Text style={styles.closeTxt}>关闭</Text>
78+
<Text style={[styles.closeTxt, { color: "#00AEEC" }]}>关闭</Text>
19079
</TouchableOpacity>
19180
</View>
19281
</Animated.View>
@@ -206,27 +95,22 @@ const styles = StyleSheet.create({
20695
right: 0,
20796
},
20897
sheet: {
209-
backgroundColor: "#fff",
21098
borderTopLeftRadius: 16,
21199
borderTopRightRadius: 16,
212100
padding: 24,
213101
alignItems: "center",
214102
},
215103
title: { fontSize: 18, fontWeight: "600", marginBottom: 20 },
216-
loader: { marginVertical: 40 },
217-
qrWrapper: { width: 200, height: 200, marginBottom: 12 },
218-
saveBtn: {
219-
position: "absolute",
220-
bottom: 6,
221-
right: 6,
222-
backgroundColor: "rgba(0,0,0,0.45)",
223-
borderRadius: 14,
224-
width: 28,
225-
height: 28,
226-
alignItems: "center",
227-
justifyContent: "center",
104+
iconWrap: { marginBottom: 16 },
105+
hint: { fontSize: 13, marginBottom: 24, textAlign: "center" },
106+
loginBtn: {
107+
backgroundColor: "#00AEEC",
108+
borderRadius: 24,
109+
paddingVertical: 12,
110+
paddingHorizontal: 48,
111+
marginBottom: 8,
228112
},
229-
hint: { fontSize: 13, color: "#666", marginBottom: 20 },
113+
loginBtnText: { color: "#fff", fontSize: 16, fontWeight: "600" },
230114
closeBtn: { padding: 12 },
231-
closeTxt: { fontSize: 14, color: "#00AEEC" },
115+
closeTxt: { fontSize: 14 },
232116
});

components/NativeVideoPlayer.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,7 @@ const BALL = 12;
3838
const BALL_ACTIVE = 16;
3939
const HIDE_DELAY = 3000;
4040

41-
const HEADERS = {
42-
Referer: "https://www.bilibili.com",
43-
"User-Agent":
44-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
45-
};
41+
const HEADERS = {};
4642

4743
function clamp(v: number, lo: number, hi: number) {
4844
return Math.max(lo, Math.min(hi, v));

hooks/useDownload.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as FileSystem from 'expo-file-system/legacy';
2-
import AsyncStorage from '@react-native-async-storage/async-storage';
32
import { AppState } from 'react-native';
43
import { useDownloadStore } from '../store/downloadStore';
54
import { getPlayUrlForDownload } from '../services/api';
@@ -73,23 +72,9 @@ export function useDownload() {
7372
key: string, bvid: string, cid: number, qn: number,
7473
): Promise<'done' | 'error' | 'retry'> {
7574
try {
76-
const [url, buvid3, sessdata] = await Promise.all([
77-
getPlayUrlForDownload(bvid, cid, qn),
78-
AsyncStorage.getItem('buvid3'),
79-
AsyncStorage.getItem('SESSDATA'),
80-
]);
75+
const url = await getPlayUrlForDownload(bvid, cid, qn);
8176
const dest = localPath(bvid, qn);
82-
83-
const cookies: string[] = [];
84-
if (buvid3) cookies.push(`buvid3=${buvid3}`);
85-
if (sessdata) cookies.push(`SESSDATA=${sessdata}`);
86-
87-
const headers = {
88-
Referer: 'https://www.bilibili.com',
89-
Origin: 'https://www.bilibili.com',
90-
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
91-
...(cookies.length > 0 && { Cookie: cookies.join('; ') }),
92-
};
77+
const headers = {};
9378

9479
const progressCallback = (p: FileSystem.DownloadProgressData) => {
9580
const { totalBytesWritten, totalBytesExpectedToWrite } = p;

0 commit comments

Comments
 (0)