diff --git a/mobile/app/(tabs)/_layout.tsx b/mobile/app/(tabs)/_layout.tsx deleted file mode 100644 index cfbc1e23..00000000 --- a/mobile/app/(tabs)/_layout.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Tabs } from 'expo-router'; -import React from 'react'; -import { Platform } from 'react-native'; - -import { HapticTab } from '@/components/HapticTab'; -import { IconSymbol } from '@/components/ui/IconSymbol'; -import TabBarBackground from '@/components/ui/TabBarBackground'; -import { Colors } from '@/constants/Colors'; -import { useColorScheme } from '@/hooks/useColorScheme'; - -export default function TabLayout() { - const colorScheme = useColorScheme(); - - return ( - - , - }} - /> - , - }} - /> - - ); -} diff --git a/mobile/app/(tabs)/explore.tsx b/mobile/app/(tabs)/explore.tsx deleted file mode 100644 index 06e70c4f..00000000 --- a/mobile/app/(tabs)/explore.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import { StyleSheet, Image, Platform } from 'react-native'; - -import { Collapsible } from '@/components/Collapsible'; -import { ExternalLink } from '@/components/ExternalLink'; -import ParallaxScrollView from '@/components/ParallaxScrollView'; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; -import { IconSymbol } from '@/components/ui/IconSymbol'; - -export default function TabTwoScreen() { - return ( - - }> - - Explore - - This app includes example code to help you get started. - - - This app has two screens:{' '} - app/(tabs)/index.tsx and{' '} - app/(tabs)/explore.tsx - - - The layout file in app/(tabs)/_layout.tsx{' '} - sets up the tab navigator. - - - Learn more - - - - - You can open this project on Android, iOS, and the web. To open the web version, press{' '} - w in the terminal running this project. - - - - - For static images, you can use the @2x and{' '} - @3x suffixes to provide files for - different screen densities - - - - Learn more - - - - - Open app/_layout.tsx to see how to load{' '} - - custom fonts such as this one. - - - - Learn more - - - - - This template has light and dark mode support. The{' '} - useColorScheme() hook lets you inspect - what the user's current color scheme is, and so you can adjust UI colors accordingly. - - - Learn more - - - - - This template includes an example of an animated component. The{' '} - components/HelloWave.tsx component uses - the powerful react-native-reanimated{' '} - library to create a waving hand animation. - - {Platform.select({ - ios: ( - - The components/ParallaxScrollView.tsx{' '} - component provides a parallax effect for the header image. - - ), - })} - - - ); -} - -const styles = StyleSheet.create({ - headerImage: { - color: '#808080', - bottom: -90, - left: -35, - position: 'absolute', - }, - titleContainer: { - flexDirection: 'row', - gap: 8, - }, -}); diff --git a/mobile/app/(tabs)/index.tsx b/mobile/app/(tabs)/index.tsx deleted file mode 100644 index 886b0796..00000000 --- a/mobile/app/(tabs)/index.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { Image, StyleSheet, Platform } from 'react-native'; - -import { HelloWave } from '@/components/HelloWave'; -import ParallaxScrollView from '@/components/ParallaxScrollView'; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; - -export default function HomeScreen() { - return ( - - }> - - Welcome! - - - - Step 1: Try it - - Edit app/(tabs)/index.tsx to see changes. - Press{' '} - - {Platform.select({ - ios: 'cmd + d', - android: 'cmd + m', - web: 'F12' - })} - {' '} - to open developer tools. - - - - Step 2: Explore - - Tap the Explore tab to learn more about what's included in this starter app. - - - - Step 3: Get a fresh start - - When you're ready, run{' '} - npm run reset-project to get a fresh{' '} - app directory. This will move the current{' '} - app to{' '} - app-example. - - - - ); -} - -const styles = StyleSheet.create({ - titleContainer: { - flexDirection: 'row', - alignItems: 'center', - gap: 8, - }, - stepContainer: { - gap: 8, - marginBottom: 8, - }, - reactLogo: { - height: 178, - width: 290, - bottom: 0, - left: 0, - position: 'absolute', - }, -}); diff --git a/mobile/app/+not-found.tsx b/mobile/app/+not-found.tsx deleted file mode 100644 index 963b04fb..00000000 --- a/mobile/app/+not-found.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Link, Stack } from 'expo-router'; -import { StyleSheet } from 'react-native'; - -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; - -export default function NotFoundScreen() { - return ( - <> - - - This screen doesn't exist. - - Go to home screen! - - - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - alignItems: 'center', - justifyContent: 'center', - padding: 20, - }, - link: { - marginTop: 15, - paddingVertical: 15, - }, -}); diff --git a/mobile/app/_layout.tsx b/mobile/app/_layout.tsx index db745789..3540bbda 100644 --- a/mobile/app/_layout.tsx +++ b/mobile/app/_layout.tsx @@ -1,39 +1,33 @@ -import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; -import { useFonts } from 'expo-font'; -import { Stack } from 'expo-router'; -import * as SplashScreen from 'expo-splash-screen'; -import { StatusBar } from 'expo-status-bar'; -import { useEffect } from 'react'; -import 'react-native-reanimated'; +import * as Font from "expo-font"; +import { Stack } from "expo-router"; +import { StatusBar } from "expo-status-bar"; +import { useEffect, useState } from "react"; +import { Text, View } from "react-native"; -import { useColorScheme } from '@/hooks/useColorScheme'; - -// Prevent the splash screen from auto-hiding before asset loading is complete. -SplashScreen.preventAutoHideAsync(); - -export default function RootLayout() { - const colorScheme = useColorScheme(); - const [loaded] = useFonts({ - SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), - }); +export default function Layout() { + const [loaded, setLoaded] = useState(false); useEffect(() => { - if (loaded) { - SplashScreen.hideAsync(); - } - }, [loaded]); + Font.loadAsync({ + Billabong: require("../assets/fonts/SpaceMono-Regular.ttf"), + }).then(() => setLoaded(true)); + }, []); if (!loaded) { - return null; + return ( + + Loading fonts... + + ); } return ( - - - - - + - + + + + + ); } diff --git a/mobile/app/home.tsx b/mobile/app/home.tsx new file mode 100644 index 00000000..9fa4aba8 --- /dev/null +++ b/mobile/app/home.tsx @@ -0,0 +1,290 @@ +import { Ionicons } from "@expo/vector-icons"; +import React from "react"; +import { + FlatList, + Image, + ListRenderItem, + ScrollView, + StatusBar, + StyleSheet, + Text, + TouchableOpacity, + View +} from "react-native"; +import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context"; + + +type Story = { + id: number; + name: string; + image: string; + isLive: boolean; +}; + +type Post = { + id: number; + user: string; + avatar: string; + verified: boolean; + country: string; + time: string; + text: string; + postImage: string; + likes: number; + comments: number; +}; + +const stories: Story[] = [ + { id: 1, name: "Jeanne", image: "https://randomuser.me/api/portraits/women/1.jpg", isLive: false }, + { id: 2, name: "Julia", image: "https://randomuser.me/api/portraits/women/2.jpg", isLive: true }, + { id: 3, name: "Brinda", image: "https://randomuser.me/api/portraits/men/3.jpg", isLive: false }, + { id: 4, name: "John", image: "https://randomuser.me/api/portraits/men/4.jpg", isLive: false }, + { id: 5, name: "Shui", image: "https://randomuser.me/api/portraits/women/5.jpg", isLive: false }, +]; + +const posts: Post[] = [ + { + id: 1, + user: "Terrance Mertz", + avatar: "https://randomuser.me/api/portraits/men/6.jpg", + verified: true, + country: "๐Ÿ‡ฌ๐Ÿ‡ง", + time: "8 min", + text: "Absorbeo alias adnuo cogito tergum deepio creptio curo molestias minus.", + postImage: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&h=600&fit=crop", + likes: 720, + comments: 60, + }, + { + id: 2, + user: "Anabel Stracke", + avatar: "https://randomuser.me/api/portraits/women/7.jpg", + verified: false, + country: "๐Ÿ‡ฌ๐Ÿ‡ง", + time: "3 hrs", + text: "Veritas crux theologus col praesentium...", + postImage: "https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=600&h=600&fit=crop", + likes: 450, + comments: 34, + }, +]; + +export default function HomeScreen() { + const insets = useSafeAreaInsets(); + + const renderStory: ListRenderItem = ({ item }) => ( + + + + + + + + {item.isLive && ( + + LIVE + + )} + {item.name} + + ); + + const renderPost: ListRenderItem = ({ item }) => ( + + + + + + + {item.user} + {item.verified && ( + + )} + {item.country} + + + {item.time} + + + + + + + {item.text} + + + + + + + + + + + + + + {item.comments} comments ยท {item.likes} likes + + + ); + + return ( + + + {/* Header */} + + + Instagram + + + + + + + {/* Content */} + + item.id.toString()} + contentContainerStyle={styles.storiesContainer} + renderItem={renderStory} + /> + + item.id.toString()} + renderItem={renderPost} + scrollEnabled={false} + /> + + + {/* Bottom Navigation */} + 0 ? insets.bottom : 12, + }, + ]} + > + + + + + + + + ); +} + +// ============ Styles ============ // +const styles = StyleSheet.create({ + safeArea: { flex: 1, backgroundColor: "#fff" }, + header: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + paddingHorizontal: 16, + paddingVertical: 12, + borderBottomWidth: 0.5, + borderBottomColor: "#dbdbdb", + }, + logoText: { fontSize: 26, fontWeight: "600", fontFamily: "serif" }, + headerRight: { flexDirection: "row", alignItems: "center" }, + headerIcon: { marginLeft: 20 }, + + // Stories + storiesContainer: { paddingHorizontal: 10, paddingVertical: 14 }, + storyItem: { alignItems: "center", marginRight: 14, position: "relative" }, + storyBorder: { padding: 2.5, borderRadius: 40 }, + gradientBorder: { backgroundColor: "#E1306C" }, + liveBorder: { backgroundColor: "#8B3DFF" }, + storyInnerBorder: { padding: 2.5, borderRadius: 37, backgroundColor: "#fff" }, + storyImage: { width: 64, height: 64, borderRadius: 32 }, + storyText: { marginTop: 4, fontSize: 12, color: "#262626" }, + liveBadge: { + position: "absolute", + bottom: 16, + backgroundColor: "#8B3DFF", + paddingHorizontal: 6, + paddingVertical: 2, + borderRadius: 3, + borderWidth: 1.5, + borderColor: "#fff", + }, + liveText: { color: "#fff", fontSize: 9, fontWeight: "700" }, + divider: { height: 0.5, backgroundColor: "#dbdbdb" }, + + // Posts + postContainer: { marginBottom: 16 }, + postHeader: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + paddingHorizontal: 12, + paddingVertical: 10, + }, + postHeaderLeft: { flexDirection: "row", alignItems: "center", flex: 1 }, + postAvatar: { width: 32, height: 32, borderRadius: 16 }, + postUserInfo: { marginLeft: 10, flex: 1 }, + usernameRow: { flexDirection: "row", alignItems: "center" }, + postUsername: { fontSize: 13, fontWeight: "600", color: "#262626" }, + countryFlag: { marginLeft: 8, fontSize: 12 }, + postTime: { fontSize: 12, color: "#8e8e8e", marginRight: 8 }, + postText: { + paddingHorizontal: 12, + fontSize: 13, + lineHeight: 18, + color: "#000", + marginBottom: 8, + }, + postImage: { width: "100%", height: 400, backgroundColor: "#f0f0f0" }, + actionButtons: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + paddingHorizontal: 12, + paddingVertical: 8, + }, + leftActions: { flexDirection: "row" }, + actionIcon: { marginRight: 16 }, + postStats: { + paddingHorizontal: 12, + fontSize: 12, + color: "#8e8e8e", + marginBottom: 8, + }, + + // Bottom Nav fixed + bottomNav: { + position: "absolute", + bottom: 0, + left: 0, + right: 0, + flexDirection: "row", + justifyContent: "space-around", + alignItems: "center", + borderTopWidth: 0.5, + borderTopColor: "#dbdbdb", + backgroundColor: "#fff", + paddingVertical: 10, + }, + navProfile: { + width: 26, + height: 26, + borderRadius: 13, + borderWidth: 1.5, + borderColor: "#dbdbdb", + }, +}); diff --git a/mobile/app/index.tsx b/mobile/app/index.tsx new file mode 100644 index 00000000..60da46f3 --- /dev/null +++ b/mobile/app/index.tsx @@ -0,0 +1,4 @@ +import { Redirect } from "expo-router"; +export default function Index() { + return ; +} diff --git a/mobile/app/login.tsx b/mobile/app/login.tsx new file mode 100644 index 00000000..ea72d2e4 --- /dev/null +++ b/mobile/app/login.tsx @@ -0,0 +1,179 @@ +import { Ionicons } from '@expo/vector-icons'; +import { useRouter } from "expo-router"; +import React, { useState } from "react"; +import { StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native"; + +export default function LoginScreen() { + const router = useRouter(); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [rememberMe, setRememberMe] = useState(false); + + return ( + + Instagram + + + + + + setRememberMe(!rememberMe)} + > + + {rememberMe && ( + + )} + + Remember Me + + + Forgot password? + + + + router.push("/home")}> + Login + + + + + + Login with facebook + + + OR + + Don't have an account? Sign up + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: "center", + alignItems: "center", + backgroundColor: "#fff", + paddingHorizontal: 24, + }, + logoText: { + fontFamily: "SpaceMono-Regular", + fontSize: 50, + fontWeight: "300", + marginBottom: 50, + color: "#000", + }, + input: { + width: "100%", + height: 44, + borderWidth: 1, + borderColor: "#e0e0e0", + borderRadius: 6, + paddingHorizontal: 16, + marginBottom: 10, + backgroundColor: "#fafafa", + fontSize: 14, + }, + rememberRow: { + flexDirection: "row", + justifyContent: "space-between", + alignItems: "center", + width: "100%", + marginBottom: 18, + marginTop: 6, + }, + checkboxContainer: { + flexDirection: "row", + alignItems: "center", + }, + checkbox: { + width: 16, + height: 16, + borderWidth: 1.5, + borderColor: "#d0d0d0", + borderRadius: 2, + marginRight: 8, + justifyContent: "center", + alignItems: "center", + }, + checkboxChecked: { + borderColor: "#000", + backgroundColor: "#fff", + }, + rememberText: { + fontSize: 13, + color: "#000", + }, + forgot: { + color: "#e1306c", + fontSize: 13, + }, + loginBtn: { + backgroundColor: "#e1306c", + width: "100%", + height: 48, + borderRadius: 8, + alignItems: "center", + justifyContent: "center", + marginBottom: 12, + }, + loginText: { + color: "#fff", + fontWeight: "600", + fontSize: 14, + }, + fbBtn: { + borderWidth: 1, + borderColor: "#e1306c", + width: "100%", + height: 44, + borderRadius: 8, + alignItems: "center", + justifyContent: "center", + marginBottom: 24, + backgroundColor: "#fff", + }, + fbContent: { + flexDirection: "row", + alignItems: "center", + }, + fbIcon: { + marginRight: 10, + }, + fbText: { + color: "#e1306c", + fontWeight: "600", + fontSize: 14, + }, + orText: { + fontSize: 14, + color: "#8e8e8e", + marginBottom: 24, + }, + signUpText: { + color: "#000", + fontSize: 14, + }, + signUpLink: { + color: "#e1306c", + fontWeight: "600" + }, +}); \ No newline at end of file