feat:暗黑模式支持

This commit is contained in:
Developer
2026-03-24 23:48:04 +08:00
parent 12e770a0bf
commit bfca7a1ff2
2 changed files with 99 additions and 26 deletions

View File

@@ -75,14 +75,21 @@ export default function VideoDetailScreen() {
<TouchableOpacity onPress={() => router.back()} style={styles.backBtn}> <TouchableOpacity onPress={() => router.back()} style={styles.backBtn}>
<Ionicons name="chevron-back" size={24} color={theme.text} /> <Ionicons name="chevron-back" size={24} color={theme.text} />
</TouchableOpacity> </TouchableOpacity>
<Text style={[styles.topTitle, { color: theme.text }]} numberOfLines={1}> <Text
style={[styles.topTitle, { color: theme.text }]}
numberOfLines={1}
>
{video?.title ?? "视频详情"} {video?.title ?? "视频详情"}
</Text> </Text>
<TouchableOpacity <TouchableOpacity
style={styles.miniBtn} style={styles.miniBtn}
onPress={() => setShowDownload(true)} onPress={() => setShowDownload(true)}
> >
<Ionicons name="cloud-download-outline" size={22} color={theme.text} /> <Ionicons
name="cloud-download-outline"
size={22}
color={theme.text}
/>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
@@ -115,7 +122,11 @@ export default function VideoDetailScreen() {
onPress={() => setTab("intro")} onPress={() => setTab("intro")}
> >
<Text <Text
style={[styles.tabLabel, { color: theme.textSub }, tab === "intro" && styles.tabActive]} style={[
styles.tabLabel,
{ color: theme.textSub },
tab === "intro" && styles.tabActive,
]}
> >
</Text> </Text>
@@ -126,7 +137,11 @@ export default function VideoDetailScreen() {
onPress={() => setTab("comments")} onPress={() => setTab("comments")}
> >
<Text <Text
style={[styles.tabLabel, { color: theme.textSub }, tab === "comments" && styles.tabActive]} style={[
styles.tabLabel,
{ color: theme.textSub },
tab === "comments" && styles.tabActive,
]}
> >
{video.stat?.reply > 0 ? ` ${formatCount(video.stat.reply)}` : ""} {video.stat?.reply > 0 ? ` ${formatCount(video.stat.reply)}` : ""}
@@ -138,7 +153,11 @@ export default function VideoDetailScreen() {
onPress={() => setTab("danmaku")} onPress={() => setTab("danmaku")}
> >
<Text <Text
style={[styles.tabLabel, { color: theme.textSub }, tab === "danmaku" && styles.tabActive]} style={[
styles.tabLabel,
{ color: theme.textSub },
tab === "danmaku" && styles.tabActive,
]}
> >
{danmakus.length > 0 ? ` ${formatCount(danmakus.length)}` : ""} {danmakus.length > 0 ? ` ${formatCount(danmakus.length)}` : ""}
@@ -170,13 +189,25 @@ export default function VideoDetailScreen() {
source={{ uri: proxyImageUrl(video.owner.face) }} source={{ uri: proxyImageUrl(video.owner.face) }}
style={styles.avatar} style={styles.avatar}
/> />
<Text style={[styles.upName, { color: theme.text }]}>{video.owner.name}</Text> <Text style={[styles.upName, { color: theme.text }]}>
{video.owner.name}
</Text>
<TouchableOpacity style={styles.followBtn}> <TouchableOpacity style={styles.followBtn}>
<Text style={styles.followTxt}>+ </Text> <Text style={styles.followTxt}>+ </Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<View style={[styles.titleSection, { borderBottomColor: theme.border }]}> <View
<Text style={[styles.title, { color: theme.text }]}>{video.title}</Text> style={[
styles.titleSection,
{ borderBottomColor: theme.border },
]}
>
<Text style={[styles.title, { color: theme.text }]}>
{video.title}
</Text>
<Text style={[styles.subTitle, { color: theme.text }]}>
{video.desc || "暂无简介"}
</Text>
<View style={styles.statsRow}> <View style={styles.statsRow}>
<StatBadge icon="play" count={video.stat.view} /> <StatBadge icon="play" count={video.stat.view} />
<StatBadge icon="heart" count={video.stat.like} /> <StatBadge icon="heart" count={video.stat.like} />
@@ -193,23 +224,42 @@ export default function VideoDetailScreen() {
} }
/> />
)} )}
<View style={styles.descBox}> <View
<Text style={[styles.descText, { color: theme.text }]}> style={[
{video.desc || "暂无简介"} styles.relatedHeader,
{
backgroundColor: theme.card,
},
]}
>
<Text
style={[styles.relatedHeaderText, { color: theme.text }]}
>
</Text> </Text>
</View> </View>
<View style={[styles.relatedHeader, { backgroundColor: theme.bg, borderTopColor: theme.border }]}>
<Text style={[styles.relatedHeaderText, { color: theme.text }]}></Text>
</View>
</> </>
} }
renderItem={({ item }) => ( renderItem={({ item }) => (
<TouchableOpacity <TouchableOpacity
style={[styles.relatedCard, { backgroundColor: theme.card, borderBottomColor: theme.border }]} style={[
styles.relatedCard,
{
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: theme.border,
backgroundColor: theme.card,
borderBottomColor: theme.border,
},
]}
onPress={() => router.push(`/video/${item.bvid}` as any)} onPress={() => router.push(`/video/${item.bvid}` as any)}
activeOpacity={0.85} activeOpacity={0.85}
> >
<View style={[styles.relatedThumbWrap, { backgroundColor: theme.card }]}> <View
style={[
styles.relatedThumbWrap,
{ backgroundColor: theme.card },
]}
>
<Image <Image
source={{ uri: proxyImageUrl(item.pic) }} source={{ uri: proxyImageUrl(item.pic) }}
style={styles.relatedThumb} style={styles.relatedThumb}
@@ -222,7 +272,10 @@ export default function VideoDetailScreen() {
</View> </View>
</View> </View>
<View style={styles.relatedInfo}> <View style={styles.relatedInfo}>
<Text style={[styles.relatedTitle, { color: theme.text }]} numberOfLines={2}> <Text
style={[styles.relatedTitle, { color: theme.text }]}
numberOfLines={2}
>
{item.title} {item.title}
</Text> </Text>
<View <View
@@ -267,7 +320,9 @@ export default function VideoDetailScreen() {
onEndReachedThreshold={0.3} onEndReachedThreshold={0.3}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
ListHeaderComponent={ ListHeaderComponent={
<View style={[styles.sortRow, { borderBottomColor: theme.border }]}> <View
style={[styles.sortRow, { borderBottomColor: theme.border }]}
>
<Text style={styles.sortLabel}></Text> <Text style={styles.sortLabel}></Text>
<TouchableOpacity <TouchableOpacity
style={[ style={[
@@ -372,9 +427,16 @@ function SeasonSection({
}, [currentIndex, episodes.length]); }, [currentIndex, episodes.length]);
return ( return (
<View style={[styles.seasonBox, { borderTopColor: theme.border }]}> <View
style={[
styles.seasonBox,
{ borderTopColor: theme.border, backgroundColor: theme.card },
]}
>
<View style={styles.seasonHeader}> <View style={styles.seasonHeader}>
<Text style={[styles.seasonTitle, { color: theme.text }]}> · {season.title}</Text> <Text style={[styles.seasonTitle, { color: theme.text }]}>
· {season.title}
</Text>
<Text style={styles.seasonCount}>{season.ep_count}</Text> <Text style={styles.seasonCount}>{season.ep_count}</Text>
<Ionicons name="chevron-forward" size={14} color="#999" /> <Ionicons name="chevron-forward" size={14} color="#999" />
</View> </View>
@@ -395,7 +457,11 @@ function SeasonSection({
const isCurrent = ep.bvid === currentBvid; const isCurrent = ep.bvid === currentBvid;
return ( return (
<TouchableOpacity <TouchableOpacity
style={[styles.epCard, { backgroundColor: theme.bg }, isCurrent && styles.epCardActive]} style={[
styles.epCard,
{ backgroundColor: theme.card },
isCurrent && styles.epCardActive,
]}
onPress={() => !isCurrent && onEpisodePress(ep.bvid)} onPress={() => !isCurrent && onEpisodePress(ep.bvid)}
activeOpacity={0.8} activeOpacity={0.8}
> >
@@ -408,7 +474,10 @@ function SeasonSection({
<Text style={[styles.epNum, isCurrent && styles.epNumActive]}> <Text style={[styles.epNum, isCurrent && styles.epNumActive]}>
{index + 1} {index + 1}
</Text> </Text>
<Text style={[styles.epTitle, { color: theme.text }]} numberOfLines={2}> <Text
style={[styles.epTitle, { color: theme.text }]}
numberOfLines={2}
>
{ep.title} {ep.title}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
@@ -447,6 +516,10 @@ const styles = StyleSheet.create({
lineHeight: 22, lineHeight: 22,
marginBottom: 8, marginBottom: 8,
}, },
subTitle: {
fontSize: 10,
marginBottom: 8,
},
statsRow: { flexDirection: "row", gap: 16 }, statsRow: { flexDirection: "row", gap: 16 },
stat: { flexDirection: "row", alignItems: "center", gap: 3 }, stat: { flexDirection: "row", alignItems: "center", gap: 3 },
statText: { fontSize: 12, color: "#999" }, statText: { fontSize: 12, color: "#999" },
@@ -522,9 +595,9 @@ const styles = StyleSheet.create({
danmakuTab: { flex: 1 }, danmakuTab: { flex: 1 },
emptyTxt: { textAlign: "center", color: "#bbb", padding: 30 }, emptyTxt: { textAlign: "center", color: "#bbb", padding: 30 },
relatedHeader: { relatedHeader: {
paddingHorizontal: 14, paddingLeft: 12,
paddingVertical: 10, paddingBottom: 8,
borderTopWidth: StyleSheet.hairlineWidth, paddingTop: 8,
}, },
relatedHeaderText: { relatedHeaderText: {
fontSize: 13, fontSize: 13,

View File

@@ -65,7 +65,7 @@ export function FollowedLiveStrip() {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
backgroundColor: "#f4f4f4", backgroundColor: "#f4f4f4",
paddingHorizontal: 12, paddingHorizontal: 3,
paddingVertical: 8, paddingVertical: 8,
}, },
scrollContent: { scrollContent: {