diff options
author | polwex <polwex@sortug.com> | 2025-07-16 09:58:34 +0700 |
---|---|---|
committer | polwex <polwex@sortug.com> | 2025-07-16 09:58:34 +0700 |
commit | dc0ad21f0e857adb87d710dd0f2f9affd0a9cbc9 (patch) | |
tree | 3d556ead415654e03b511b007365bcdff6d612ee | |
parent | 697ed671f394cbd07ea9751fe17f262744d99a49 (diff) |
kinda works
-rw-r--r-- | app/(tabs)/_layout.tsx | 54 | ||||
-rw-r--r-- | app/(tabs)/explore.tsx | 110 | ||||
-rw-r--r-- | app/(tabs)/index.tsx | 75 | ||||
-rw-r--r-- | app/(tabs)/login.tsx | 122 | ||||
-rw-r--r-- | app/+not-found.tsx | 36 | ||||
-rw-r--r-- | app/_layout.tsx | 57 | ||||
-rw-r--r-- | app/index.tsx | 203 | ||||
-rw-r--r-- | components/Collapsible.tsx | 33 | ||||
-rw-r--r-- | components/ParallaxScrollView.tsx | 33 | ||||
-rw-r--r-- | components/PrimaryButton.tsx | 1 | ||||
-rw-r--r-- | components/ThemedText.tsx | 29 | ||||
-rw-r--r-- | components/ThemedView.tsx | 17 | ||||
-rw-r--r-- | components/login/ShipCredsForm.tsx | 105 | ||||
-rw-r--r-- | constants/config.ts | 2 |
14 files changed, 435 insertions, 442 deletions
diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx deleted file mode 100644 index a102c45..0000000 --- a/app/(tabs)/_layout.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { Tabs } from "expo-router"; -import { Toaster } from "react-hot-toast"; -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 ( - <> - <Tabs - screenOptions={{ - tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint, - headerShown: false, - tabBarButton: HapticTab, - tabBarBackground: TabBarBackground, - tabBarStyle: Platform.select({ - ios: { - // Use a transparent background on iOS to show the blur effect - position: "absolute", - }, - default: {}, - }), - }} - > - <Tabs.Screen - name="index" - options={{ - title: "Home", - tabBarIcon: ({ color }) => ( - <IconSymbol size={28} name="house.fill" color={color} /> - ), - }} - /> - <Tabs.Screen - name="explore" - options={{ - title: "Explore", - tabBarIcon: ({ color }) => ( - <IconSymbol size={28} name="paperplane.fill" color={color} /> - ), - }} - /> - </Tabs> - <Toaster position="top-center" /> - </> - ); -} diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx deleted file mode 100644 index d4fbcaa..0000000 --- a/app/(tabs)/explore.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { Image } from 'expo-image'; -import { Platform, StyleSheet } 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 ( - <ParallaxScrollView - headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }} - headerImage={ - <IconSymbol - size={310} - color="#808080" - name="chevron.left.forwardslash.chevron.right" - style={styles.headerImage} - /> - }> - <ThemedView style={styles.titleContainer}> - <ThemedText type="title">Explore</ThemedText> - </ThemedView> - <ThemedText>This app includes example code to help you get started.</ThemedText> - <Collapsible title="File-based routing"> - <ThemedText> - This app has two screens:{' '} - <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> and{' '} - <ThemedText type="defaultSemiBold">app/(tabs)/explore.tsx</ThemedText> - </ThemedText> - <ThemedText> - The layout file in <ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{' '} - sets up the tab navigator. - </ThemedText> - <ExternalLink href="https://docs.expo.dev/router/introduction"> - <ThemedText type="link">Learn more</ThemedText> - </ExternalLink> - </Collapsible> - <Collapsible title="Android, iOS, and web support"> - <ThemedText> - You can open this project on Android, iOS, and the web. To open the web version, press{' '} - <ThemedText type="defaultSemiBold">w</ThemedText> in the terminal running this project. - </ThemedText> - </Collapsible> - <Collapsible title="Images"> - <ThemedText> - For static images, you can use the <ThemedText type="defaultSemiBold">@2x</ThemedText> and{' '} - <ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for - different screen densities - </ThemedText> - <Image source={require('@/assets/images/react-logo.png')} style={{ alignSelf: 'center' }} /> - <ExternalLink href="https://reactnative.dev/docs/images"> - <ThemedText type="link">Learn more</ThemedText> - </ExternalLink> - </Collapsible> - <Collapsible title="Custom fonts"> - <ThemedText> - Open <ThemedText type="defaultSemiBold">app/_layout.tsx</ThemedText> to see how to load{' '} - <ThemedText style={{ fontFamily: 'SpaceMono' }}> - custom fonts such as this one. - </ThemedText> - </ThemedText> - <ExternalLink href="https://docs.expo.dev/versions/latest/sdk/font"> - <ThemedText type="link">Learn more</ThemedText> - </ExternalLink> - </Collapsible> - <Collapsible title="Light and dark mode components"> - <ThemedText> - This template has light and dark mode support. The{' '} - <ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook lets you inspect - what the user's current color scheme is, and so you can adjust UI colors accordingly. - </ThemedText> - <ExternalLink href="https://docs.expo.dev/develop/user-interface/color-themes/"> - <ThemedText type="link">Learn more</ThemedText> - </ExternalLink> - </Collapsible> - <Collapsible title="Animations"> - <ThemedText> - This template includes an example of an animated component. The{' '} - <ThemedText type="defaultSemiBold">components/HelloWave.tsx</ThemedText> component uses - the powerful <ThemedText type="defaultSemiBold">react-native-reanimated</ThemedText>{' '} - library to create a waving hand animation. - </ThemedText> - {Platform.select({ - ios: ( - <ThemedText> - The <ThemedText type="defaultSemiBold">components/ParallaxScrollView.tsx</ThemedText>{' '} - component provides a parallax effect for the header image. - </ThemedText> - ), - })} - </Collapsible> - </ParallaxScrollView> - ); -} - -const styles = StyleSheet.create({ - headerImage: { - color: '#808080', - bottom: -90, - left: -35, - position: 'absolute', - }, - titleContainer: { - flexDirection: 'row', - gap: 8, - }, -}); diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx deleted file mode 100644 index 462e8cd..0000000 --- a/app/(tabs)/index.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Image } from 'expo-image'; -import { Platform, StyleSheet } 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 ( - <ParallaxScrollView - headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }} - headerImage={ - <Image - source={require('@/assets/images/partial-react-logo.png')} - style={styles.reactLogo} - /> - }> - <ThemedView style={styles.titleContainer}> - <ThemedText type="title">Welcome!</ThemedText> - <HelloWave /> - </ThemedView> - <ThemedView style={styles.stepContainer}> - <ThemedText type="subtitle">Step 1: Try it</ThemedText> - <ThemedText> - Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes. - Press{' '} - <ThemedText type="defaultSemiBold"> - {Platform.select({ - ios: 'cmd + d', - android: 'cmd + m', - web: 'F12', - })} - </ThemedText>{' '} - to open developer tools. - </ThemedText> - </ThemedView> - <ThemedView style={styles.stepContainer}> - <ThemedText type="subtitle">Step 2: Explore</ThemedText> - <ThemedText> - {`Tap the Explore tab to learn more about what's included in this starter app.`} - </ThemedText> - </ThemedView> - <ThemedView style={styles.stepContainer}> - <ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText> - <ThemedText> - {`When you're ready, run `} - <ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '} - <ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '} - <ThemedText type="defaultSemiBold">app</ThemedText> to{' '} - <ThemedText type="defaultSemiBold">app-example</ThemedText>. - </ThemedText> - </ThemedView> - </ParallaxScrollView> - ); -} - -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/app/(tabs)/login.tsx b/app/(tabs)/login.tsx deleted file mode 100644 index c5f826d..0000000 --- a/app/(tabs)/login.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import React, { useState } from "react"; -import { - View, - Text, - StyleSheet, - Image, - KeyboardAvoidingView, - Platform, - Alert, -} from "react-native"; -import PrimaryButton from "../../components/PrimaryButton"; -import ScreenWrapper from "../../components/ScreenWrapper"; -import { useThemeColors, ColorScheme } from "../../constants"; -import { ROUTES } from "../../constants/routes"; -import { Passkee } from "@/components/auth/Auth"; - -// import { useSettingsStore } from "../store/useSettingsStore"; -// import useAuthStore from "../store/useAuthStore"; -// import { createPasskey, isPasskeySupported } from "../lib/passkey"; -// import { navigationRef } from "../lib/navigationRef"; - -const PasskeySetupScreen = async () => { - const [isLoading, setIsLoading] = useState(false); - // const isDarkMode = useSettingsStore((s) => s.isDarkMode); - const isDarkMode = false; - const colors = useThemeColors(); - const styles = getStyles(colors); - // const { setHasPasskey, setHasSeenPasskeyPrompt } = useAuthStore(); - - const logoSource = isDarkMode - ? require("../../assets/urbit-logo-dark.png") - : require("../../assets/urbit-logo-light.png"); - - const handleSkip = () => { - // setHasSeenPasskeyPrompt(true); - // navigationRef.current?.navigate(ROUTES.LOGIN as never); - }; - - return ( - <KeyboardAvoidingView - style={styles.container} - behavior={Platform.OS === "ios" ? "padding" : undefined} - > - <ScreenWrapper> - <View style={styles.topSection}> - <Image - source={logoSource} - style={styles.walletIcon} - resizeMode="contain" - /> - <Text style={styles.title}>Secure Your Wallet</Text> - <Text style={styles.subtitle}> - Create a passkey for easy and secure access to your Urbit wallet - </Text> - </View> - - <View style={styles.bottomSection}> - <Passkee /> - <PrimaryButton - label="Skip for Now" - onPress={handleSkip} - style={{ - backgroundColor: colors.card, - borderWidth: 1, - borderColor: colors.border, - }} - textStyle={{ color: colors.text }} - /> - - <Text style={styles.infoText}> - You can always set up a passkey later in settings - </Text> - </View> - </ScreenWrapper> - </KeyboardAvoidingView> - ); -}; - -export const getStyles = (colors: ColorScheme) => - StyleSheet.create({ - container: { - flex: 1, - backgroundColor: colors.background, - justifyContent: "space-between", - padding: 20, - }, - topSection: { - flex: 1, - justifyContent: "center", - alignItems: "center", - }, - walletIcon: { - width: 64, - height: 64, - marginBottom: 24, - }, - title: { - fontSize: 24, - color: colors.text, - fontWeight: "600", - marginBottom: 12, - textAlign: "center", - }, - subtitle: { - fontSize: 16, - color: colors.secondary, - textAlign: "center", - paddingHorizontal: 20, - lineHeight: 24, - }, - bottomSection: { - marginBottom: 40, - }, - infoText: { - color: colors.secondary, - fontSize: 14, - textAlign: "center", - marginTop: 16, - }, - }); - -export default PasskeySetupScreen; diff --git a/app/+not-found.tsx b/app/+not-found.tsx index 215b0ed..68601c6 100644 --- a/app/+not-found.tsx +++ b/app/+not-found.tsx @@ -1,19 +1,19 @@ -import { Link, Stack } from 'expo-router'; -import { StyleSheet } from 'react-native'; +import { Link, Stack } from "expo-router"; +import { View, Text, StyleSheet } from "react-native"; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; +// import { ThemedText } from '@/components/ThemedText'; +// import { ThemedView } from '@/components/ThemedView'; export default function NotFoundScreen() { return ( <> - <Stack.Screen options={{ title: 'Oops!' }} /> - <ThemedView style={styles.container}> - <ThemedText type="title">This screen does not exist.</ThemedText> + <Stack.Screen options={{ title: "Oops!" }} /> + <View style={styles.container}> + <Text style={styles.title}>This screen does not exist.</Text> <Link href="/" style={styles.link}> - <ThemedText type="link">Go to home screen!</ThemedText> + <Text style={styles.linkText}>Go to home screen!</Text> </Link> - </ThemedView> + </View> </> ); } @@ -21,12 +21,26 @@ export default function NotFoundScreen() { const styles = StyleSheet.create({ container: { flex: 1, - alignItems: 'center', - justifyContent: 'center', + alignItems: "center", + justifyContent: "center", padding: 20, }, link: { marginTop: 15, paddingVertical: 15, }, + title: { + fontSize: 32, + fontWeight: "bold", + lineHeight: 32, + }, + subtitle: { + fontSize: 20, + fontWeight: "bold", + }, + linkText: { + lineHeight: 30, + fontSize: 16, + color: "#0a7ea4", + }, }); diff --git a/app/_layout.tsx b/app/_layout.tsx index 8d506f7..6974539 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,29 +1,38 @@ -import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; -import { useFonts } from 'expo-font'; -import { Stack } from 'expo-router'; -import { StatusBar } from 'expo-status-bar'; -import 'react-native-reanimated'; +// import { +// DarkTheme, +// DefaultTheme, +// ThemeProvider, +// } from "@react-navigation/native"; +// import { useFonts } from "expo-font"; +// import { Stack } from "expo-router"; +// import { StatusBar } from "expo-status-bar"; +// import "react-native-reanimated"; +// import { Toaster } from "react-hot-toast"; -import { useColorScheme } from '@/hooks/useColorScheme'; +// import { useColorScheme } from "@/hooks/useColorScheme"; -export default function RootLayout() { - const colorScheme = useColorScheme(); - const [loaded] = useFonts({ - SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), - }); +// export default function RootLayout() { +// const colorScheme = useColorScheme(); +// const [loaded] = useFonts({ +// SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"), +// }); - if (!loaded) { - // Async font loading only occurs in development. - return null; - } +// if (!loaded) { +// // Async font loading only occurs in development. +// return null; +// } - return ( - <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}> - <Stack> - <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> - <Stack.Screen name="+not-found" /> - </Stack> - <StatusBar style="auto" /> - </ThemeProvider> - ); +// return ( +// <ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}> +// <Stack> +// <Stack.Screen name="index" options={{ headerShown: false }} /> +// <Stack.Screen name="+not-found" /> +// </Stack> +// <StatusBar style="auto" /> +// <Toaster position="top-center" /> +// </ThemeProvider> +// ); +// } +export default function RootLayout() { + return <></>; } diff --git a/app/index.tsx b/app/index.tsx new file mode 100644 index 0000000..4d13c90 --- /dev/null +++ b/app/index.tsx @@ -0,0 +1,203 @@ +import "server-only"; +import { + View, + Text, + StyleSheet, + Image, + KeyboardAvoidingView, + Platform, + Alert, +} from "react-native"; +import PrimaryButton from "@/components/PrimaryButton"; +import ScreenWrapper from "@/components/ScreenWrapper"; +// // import { useThemeColors, ColorScheme } from "../constants"; +// import { ROUTES } from "@/constants/routes"; +// import { Passkee } from "@/components/auth/Auth"; +import { type ColorScheme, lightColors } from "@/constants"; +import { ShipForm } from "@/components/login/ShipCredsForm"; + +// // import { useSettingsStore } from "../store/useSettingsStore"; +// // import useAuthStore from "../store/useAuthStore"; +// // import { createPasskey, isPasskeySupported } from "../lib/passkey"; +// // import { navigationRef } from "../lib/navigationRef"; + +// const PasskeySetupScreen = async () => { +// // const isDarkMode = useSettingsStore((s) => s.isDarkMode); +// const isDarkMode = false; +// // const colors = useThemeColors(); +// const colors = lightColors; +// const styles = getStyles(colors); +// // const { setHasPasskey, setHasSeenPasskeyPrompt } = useAuthStore(); + +// const logoSource = isDarkMode +// ? require("../assets/urbit-logo-dark.png") +// : require("../assets/urbit-logo-light.png"); + +// const handleSkip = () => { +// // setHasSeenPasskeyPrompt(true); +// // navigationRef.current?.navigate(ROUTES.LOGIN as never); +// }; + +// return ( +// <KeyboardAvoidingView +// style={styles.container} +// behavior={Platform.OS === "ios" ? "padding" : undefined} +// > +// <ScreenWrapper> +// <View style={styles.topSection}> +// <Image +// source={logoSource} +// style={styles.walletIcon} +// resizeMode="contain" +// /> +// <Text style={styles.title}>Secure Your Wallet</Text> +// <Text style={styles.subtitle}> +// Create a passkey for easy and secure access to your Urbit wallet +// </Text> +// </View> + +// <View style={styles.bottomSection}> +// <Passkee /> +// <PrimaryButton +// label="Skip for Now" +// onPress={handleSkip} +// style={{ +// backgroundColor: colors.card, +// borderWidth: 1, +// borderColor: colors.border, +// }} +// textStyle={{ color: colors.text }} +// /> + +// <Text style={styles.infoText}> +// You can always set up a passkey later in settings +// </Text> +// </View> +// </ScreenWrapper> +// </KeyboardAvoidingView> +// ); +// }; + +// export const getStyles = (colors: ColorScheme) => +// StyleSheet.create({ +// container: { +// flex: 1, +// backgroundColor: colors.background, +// justifyContent: "space-between", +// padding: 20, +// }, +// topSection: { +// flex: 1, +// justifyContent: "center", +// alignItems: "center", +// }, +// walletIcon: { +// width: 64, +// height: 64, +// marginBottom: 24, +// }, +// title: { +// fontSize: 24, +// color: colors.text, +// fontWeight: "600", +// marginBottom: 12, +// textAlign: "center", +// }, +// subtitle: { +// fontSize: 16, +// color: colors.secondary, +// textAlign: "center", +// paddingHorizontal: 20, +// lineHeight: 24, +// }, +// bottomSection: { +// marginBottom: 40, +// }, +// infoText: { +// color: colors.secondary, +// fontSize: 14, +// textAlign: "center", +// marginTop: 16, +// }, +// }); + +// export default PasskeySetupScreen; +// +// + +// export const unstable_settings = { +// // This component will be rendered at build-time and never re-rendered in production. +// render: "static", +// }; + +export default async function Index() { + async function handleSubmit() { + // + } + return ( + <View style={styles.container}> + <ScreenWrapper> + <View style={styles.topSection}> + <Image + source={require("../assets/urbit-logo-light.png")} + style={styles.walletIcon} + resizeMode="contain" + /> + <Text style={styles.title}>Secure Your Wallet</Text> + <Text style={styles.subtitle}> + Create a passkey for easy and secure access to your Urbit wallet + </Text> + </View> + <ShipForm /> + + <View style={styles.bottomSection}> + <Text style={styles.infoText}> + You can always set up a passkey later in settings + </Text> + </View> + </ScreenWrapper> + </View> + ); +} + +export const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: "#F7F7F7", + justifyContent: "space-between", + padding: 20, + }, + topSection: { + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + walletIcon: { + width: 64, + height: 64, + marginBottom: 24, + }, + title: { + fontSize: 24, + color: "#171717", + fontWeight: "600", + marginBottom: 12, + textAlign: "center", + }, + subtitle: { + fontSize: 16, + color: "#737373", + textAlign: "center", + paddingHorizontal: 20, + lineHeight: 24, + }, + bottomSection: { + marginBottom: 40, + }, + infoText: { + color: "#737373", + fontSize: 14, + textAlign: "center", + marginTop: 16, + }, +}); diff --git a/components/Collapsible.tsx b/components/Collapsible.tsx index 55bff2f..5820251 100644 --- a/components/Collapsible.tsx +++ b/components/Collapsible.tsx @@ -1,28 +1,33 @@ -import { PropsWithChildren, useState } from 'react'; -import { StyleSheet, TouchableOpacity } from 'react-native'; +"use client"; +import { PropsWithChildren, useState } from "react"; +import { StyleSheet, TouchableOpacity } from "react-native"; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; -import { IconSymbol } from '@/components/ui/IconSymbol'; -import { Colors } from '@/constants/Colors'; -import { useColorScheme } from '@/hooks/useColorScheme'; +import { ThemedText } from "@/components/ThemedText"; +import { ThemedView } from "@/components/ThemedView"; +import { IconSymbol } from "@/components/ui/IconSymbol"; +import { Colors } from "@/constants/Colors"; +import { useColorScheme } from "@/hooks/useColorScheme"; -export function Collapsible({ children, title }: PropsWithChildren & { title: string }) { +export function Collapsible({ + children, + title, +}: PropsWithChildren & { title: string }) { const [isOpen, setIsOpen] = useState(false); - const theme = useColorScheme() ?? 'light'; + const theme = useColorScheme() ?? "light"; return ( <ThemedView> <TouchableOpacity style={styles.heading} onPress={() => setIsOpen((value) => !value)} - activeOpacity={0.8}> + activeOpacity={0.8} + > <IconSymbol name="chevron.right" size={18} weight="medium" - color={theme === 'light' ? Colors.light.icon : Colors.dark.icon} - style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }} + color={theme === "light" ? Colors.light.icon : Colors.dark.icon} + style={{ transform: [{ rotate: isOpen ? "90deg" : "0deg" }] }} /> <ThemedText type="defaultSemiBold">{title}</ThemedText> @@ -34,8 +39,8 @@ export function Collapsible({ children, title }: PropsWithChildren & { title: st const styles = StyleSheet.create({ heading: { - flexDirection: 'row', - alignItems: 'center', + flexDirection: "row", + alignItems: "center", gap: 6, }, content: { diff --git a/components/ParallaxScrollView.tsx b/components/ParallaxScrollView.tsx index 5df1d75..46ed68e 100644 --- a/components/ParallaxScrollView.tsx +++ b/components/ParallaxScrollView.tsx @@ -1,15 +1,16 @@ -import type { PropsWithChildren, ReactElement } from 'react'; -import { StyleSheet } from 'react-native'; +"use client"; +import type { PropsWithChildren, ReactElement } from "react"; +import { StyleSheet } from "react-native"; import Animated, { interpolate, useAnimatedRef, useAnimatedStyle, useScrollViewOffset, -} from 'react-native-reanimated'; +} from "react-native-reanimated"; -import { ThemedView } from '@/components/ThemedView'; -import { useBottomTabOverflow } from '@/components/ui/TabBarBackground'; -import { useColorScheme } from '@/hooks/useColorScheme'; +import { ThemedView } from "@/components/ThemedView"; +import { useBottomTabOverflow } from "@/components/ui/TabBarBackground"; +import { useColorScheme } from "@/hooks/useColorScheme"; const HEADER_HEIGHT = 250; @@ -23,7 +24,7 @@ export default function ParallaxScrollView({ headerImage, headerBackgroundColor, }: Props) { - const colorScheme = useColorScheme() ?? 'light'; + const colorScheme = useColorScheme() ?? "light"; const scrollRef = useAnimatedRef<Animated.ScrollView>(); const scrollOffset = useScrollViewOffset(scrollRef); const bottom = useBottomTabOverflow(); @@ -34,11 +35,15 @@ export default function ParallaxScrollView({ translateY: interpolate( scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], - [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75] + [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75], ), }, { - scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]), + scale: interpolate( + scrollOffset.value, + [-HEADER_HEIGHT, 0, HEADER_HEIGHT], + [2, 1, 1], + ), }, ], }; @@ -50,13 +55,15 @@ export default function ParallaxScrollView({ ref={scrollRef} scrollEventThrottle={16} scrollIndicatorInsets={{ bottom }} - contentContainerStyle={{ paddingBottom: bottom }}> + contentContainerStyle={{ paddingBottom: bottom }} + > <Animated.View style={[ styles.header, { backgroundColor: headerBackgroundColor[colorScheme] }, headerAnimatedStyle, - ]}> + ]} + > {headerImage} </Animated.View> <ThemedView style={styles.content}>{children}</ThemedView> @@ -71,12 +78,12 @@ const styles = StyleSheet.create({ }, header: { height: HEADER_HEIGHT, - overflow: 'hidden', + overflow: "hidden", }, content: { flex: 1, padding: 32, gap: 16, - overflow: 'hidden', + overflow: "hidden", }, }); diff --git a/components/PrimaryButton.tsx b/components/PrimaryButton.tsx index 94bd8ce..b515818 100644 --- a/components/PrimaryButton.tsx +++ b/components/PrimaryButton.tsx @@ -1,3 +1,4 @@ +"use client"; import React from "react"; import { TouchableOpacity, diff --git a/components/ThemedText.tsx b/components/ThemedText.tsx index 9d214a2..c545b1c 100644 --- a/components/ThemedText.tsx +++ b/components/ThemedText.tsx @@ -1,31 +1,32 @@ -import { StyleSheet, Text, type TextProps } from 'react-native'; +"use client"; +import { StyleSheet, Text, type TextProps } from "react-native"; -import { useThemeColor } from '@/hooks/useThemeColor'; +import { useThemeColor } from "@/hooks/useThemeColor"; export type ThemedTextProps = TextProps & { lightColor?: string; darkColor?: string; - type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link'; + type?: "default" | "title" | "defaultSemiBold" | "subtitle" | "link"; }; export function ThemedText({ style, lightColor, darkColor, - type = 'default', + type = "default", ...rest }: ThemedTextProps) { - const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text'); + const color = useThemeColor({ light: lightColor, dark: darkColor }, "text"); return ( <Text style={[ { color }, - type === 'default' ? styles.default : undefined, - type === 'title' ? styles.title : undefined, - type === 'defaultSemiBold' ? styles.defaultSemiBold : undefined, - type === 'subtitle' ? styles.subtitle : undefined, - type === 'link' ? styles.link : undefined, + type === "default" ? styles.default : undefined, + type === "title" ? styles.title : undefined, + type === "defaultSemiBold" ? styles.defaultSemiBold : undefined, + type === "subtitle" ? styles.subtitle : undefined, + type === "link" ? styles.link : undefined, style, ]} {...rest} @@ -41,20 +42,20 @@ const styles = StyleSheet.create({ defaultSemiBold: { fontSize: 16, lineHeight: 24, - fontWeight: '600', + fontWeight: "600", }, title: { fontSize: 32, - fontWeight: 'bold', + fontWeight: "bold", lineHeight: 32, }, subtitle: { fontSize: 20, - fontWeight: 'bold', + fontWeight: "bold", }, link: { lineHeight: 30, fontSize: 16, - color: '#0a7ea4', + color: "#0a7ea4", }, }); diff --git a/components/ThemedView.tsx b/components/ThemedView.tsx index 4d2cb09..fe06be6 100644 --- a/components/ThemedView.tsx +++ b/components/ThemedView.tsx @@ -1,14 +1,23 @@ -import { View, type ViewProps } from 'react-native'; +"use client"; +import { View, type ViewProps } from "react-native"; -import { useThemeColor } from '@/hooks/useThemeColor'; +import { useThemeColor } from "@/hooks/useThemeColor"; export type ThemedViewProps = ViewProps & { lightColor?: string; darkColor?: string; }; -export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) { - const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background'); +export function ThemedView({ + style, + lightColor, + darkColor, + ...otherProps +}: ThemedViewProps) { + const backgroundColor = useThemeColor( + { light: lightColor, dark: darkColor }, + "background", + ); return <View style={[{ backgroundColor }, style]} {...otherProps} />; } diff --git a/components/login/ShipCredsForm.tsx b/components/login/ShipCredsForm.tsx new file mode 100644 index 0000000..15712c2 --- /dev/null +++ b/components/login/ShipCredsForm.tsx @@ -0,0 +1,105 @@ +"use client"; +import { ColorScheme, lightColors } from "@/constants"; +import { BottomTabBarButtonProps } from "@react-navigation/bottom-tabs"; +import { + StyleSheet, + TextInput, + TouchableOpacity, + View, + Text, +} from "react-native"; +import PrimaryButton from "../PrimaryButton"; +import { useState } from "react"; + +export function ShipForm() { + const colors = lightColors; + const styles = getStyles(colors); + const [patp, setPatp] = useState("~mirtyl-wacdec"); + const [ticket, setTicket] = useState("~posseg-winnub-fogluc-dirmes"); + const [isLoading, setIsLoading] = useState(false); + async function onSubmit() { + console.log({ patp, ticket }); + } + return ( + <View style={styles.bottomSection}> + <TextInput + style={styles.input} + placeholder="~sampel-palnet" + placeholderTextColor={colors.secondary} + value={patp} + onChangeText={setPatp} + autoCapitalize="none" + autoCorrect={false} + /> + <TextInput + style={styles.input} + placeholder="~sampel-ticlyt-migfun-falmel" + placeholderTextColor={colors.secondary} + value={ticket} + onChangeText={setTicket} + autoCapitalize="none" + autoCorrect={false} + secureTextEntry + /> + + <PrimaryButton + label="Log in" + onPress={onSubmit} + style={{ marginTop: 0 }} + isLoading={isLoading} + /> + + <TouchableOpacity style={styles.footer}> + <Text style={styles.footerText}>No Urbit ID? Get yours.</Text> + </TouchableOpacity> + </View> + ); +} +export const getStyles = (colors: ColorScheme) => + StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.background, + justifyContent: "space-between", + padding: 20, + }, + topSection: { + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + walletIcon: { + width: 64, + height: 64, + marginBottom: 12, + }, + logoText: { + fontSize: 18, + color: colors.text, + fontWeight: "400", + }, + bottomSection: { + gap: 8, + marginBottom: 40, + }, + input: { + height: 48, + backgroundColor: colors.card, + borderColor: colors.border, + borderWidth: 1, + borderRadius: 8, + paddingHorizontal: 16, + paddingVertical: 12, + color: colors.text, + fontWeight: "500", + fontSize: 16, + }, + footer: { + marginTop: 50, + alignItems: "center", + }, + footerText: { + color: colors.text, + fontSize: 16, + }, + }); diff --git a/constants/config.ts b/constants/config.ts index 6fa09b6..11379a5 100644 --- a/constants/config.ts +++ b/constants/config.ts @@ -1,5 +1,5 @@ import { JsonRpcProvider, WebSocketProvider } from "ethers"; -import { ETHEREUM_NETWORK } from "../constants"; +import { ETHEREUM_NETWORK } from "../constants/constants"; const isLocal = false; |