feat: add expo mobile application source code

This commit is contained in:
2026-05-21 16:06:35 +07:00
parent 76d7a5c5c6
commit 0c65a7811b
77 changed files with 20356 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
import React, { useRef } from 'react';
import {
View, Text, StyleSheet, Image, TouchableOpacity, Dimensions, ScrollView, Animated, Platform
} from 'react-native';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { useAppTheme } from '../../context/ThemeContext';
import { Feather } from '@expo/vector-icons';
import { BlurView } from 'expo-blur';
import * as Haptics from 'expo-haptics';
import { LinearGradient } from 'expo-linear-gradient';
const { width } = Dimensions.get('window');
const LIME = '#C6F135';
const IMG_H = 340;
export default function DetailScreen() {
const { id, title, category, img, author } = useLocalSearchParams();
const { colors, isDark } = useAppTheme();
const router = useRouter();
const scrollY = useRef(new Animated.Value(0)).current;
const bg = isDark ? '#111111' : '#F5F5F5';
const cardBg = isDark ? '#1A1A1A' : '#FFFFFF';
const border = isDark ? '#2A2A2A' : '#EEEEEE';
const subText = isDark ? '#6B6B6B' : '#9B9B9B';
const imageTranslateY = scrollY.interpolate({
inputRange: [0, IMG_H],
outputRange: [0, -IMG_H / 3],
extrapolate: 'clamp'
});
return (
<View style={[styles.container, { backgroundColor: bg }]}>
<Animated.ScrollView
showsVerticalScrollIndicator={false}
scrollEventThrottle={16}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
{ useNativeDriver: true }
)}
>
{/* ── Hero image with parallax ── */}
<View style={styles.imageContainer}>
<Animated.View style={[StyleSheet.absoluteFill, { transform: [{ translateY: imageTranslateY }] }]}>
<Image source={{ uri: img as string }} style={styles.heroImg} />
</Animated.View>
<LinearGradient
colors={['transparent', isDark ? '#111111' : '#F5F5F5']}
style={styles.gradient}
/>
</View>
{/* ── Content card ── */}
<View style={[styles.contentCard, { backgroundColor: cardBg, borderColor: border }]}>
<View style={styles.badgeRow}>
<View style={[styles.catBadge, { backgroundColor: `${LIME}25` }]}>
<Text style={styles.catBadgeText}>{category}</Text>
</View>
</View>
<Text style={[styles.title, { color: colors.text }]}>{title}</Text>
<View style={[styles.authorRow, { borderBottomColor: border }]}>
<Image
source={{ uri: `https://i.pravatar.cc/100?u=${author}` }}
style={styles.authorImg}
/>
<View>
<Text style={[styles.authorName, { color: colors.text }]}>{author}</Text>
<Text style={[styles.date, { color: subText }]}>Published 2 hours ago</Text>
</View>
</View>
<Text style={[styles.paragraph, { color: subText }]}>
This is a deep dive into the topic of{' '}
<Text style={{ color: colors.text, fontFamily: 'Outfit_600SemiBold' }}>{title}</Text>.
Implementing modern technologies requires a balance between performance and aesthetics.
In biiproject, we prioritize the user experience by using the latest React Native features.
</Text>
<Text style={[styles.paragraph, { color: subText }]}>
Our modernization engine ensures that every pixel is optimized, every transition is smooth,
and every interaction feels alive with haptic feedback and fluid motion.
</Text>
<View style={[styles.highlightBox, { backgroundColor: isDark ? '#222222' : '#F5F5F5' }]}>
<Feather name="info" size={16} color={LIME} style={{ marginRight: 10 }} />
<Text style={[styles.highlightText, { color: subText }]}>
This content is curated by our AI engine and updated daily.
</Text>
</View>
</View>
<View style={{ height: 120 }} />
</Animated.ScrollView>
{/* ── Floating back button ── */}
<TouchableOpacity
style={styles.backBtn}
onPress={() => { Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); router.back(); }}
>
<BlurView intensity={40} tint="dark" style={styles.blurBtn}>
<Feather name="chevron-left" size={22} color="#FFFFFF" />
</BlurView>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
imageContainer: { width, height: IMG_H, overflow: 'hidden' },
heroImg: { width: '100%', height: IMG_H + 60, resizeMode: 'cover' },
gradient: { position: 'absolute', bottom: 0, left: 0, right: 0, height: 160 },
contentCard: { marginHorizontal: 16, marginTop: -32, borderRadius: 28, borderWidth: 1, padding: 24, shadowColor: '#000', shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.08, shadowRadius: 20, elevation: 6 },
badgeRow: { marginBottom: 12 },
catBadge: { alignSelf: 'flex-start', paddingHorizontal: 10, paddingVertical: 4, borderRadius: 8 },
catBadgeText: { fontSize: 10, fontFamily: 'Outfit_800ExtraBold', textTransform: 'uppercase', letterSpacing: 0.5, color: '#5A7000' },
title: { fontSize: 26, fontFamily: 'Outfit_800ExtraBold', lineHeight: 34, marginBottom: 20 },
authorRow: { flexDirection: 'row', alignItems: 'center', paddingBottom: 20, marginBottom: 20, borderBottomWidth: 1 },
authorImg: { width: 42, height: 42, borderRadius: 21, marginRight: 12 },
authorName: { fontSize: 15, fontFamily: 'Outfit_700Bold' },
date: { fontSize: 12, fontFamily: 'Outfit_400Regular', marginTop: 2 },
paragraph: { fontSize: 15, fontFamily: 'Outfit_400Regular', lineHeight: 26, marginBottom: 18 },
highlightBox: { flexDirection: 'row', alignItems: 'flex-start', borderRadius: 14, padding: 14, marginTop: 6 },
highlightText: { flex: 1, fontSize: 13, fontFamily: 'Outfit_400Regular', lineHeight: 20 },
backBtn: { position: 'absolute', top: Platform.OS === 'ios' ? 52 : 32, left: 20, zIndex: 100 },
blurBtn: { width: 44, height: 44, borderRadius: 22, alignItems: 'center', justifyContent: 'center', overflow: 'hidden' },
});