From 475474d5b35dbc61159ccc90206e092f1af20719 Mon Sep 17 00:00:00 2001 From: Blair McIlroy Date: Thu, 18 Jun 2026 22:59:05 +0700 Subject: [PATCH 1/9] feat(ui): add mvp theme, typography, and landing shell --- app.config.js | 15 +- app/_layout.tsx | 16 +- app/index.tsx | 73 +--- app/landing.tsx | 212 ++++----- assets/adaptive-icon.png | Bin 295122 -> 43318 bytes assets/favicon.png | Bin 3085 -> 1610 bytes ...usJakartaSans-Italic-VariableFont_wght.ttf | Bin 0 -> 178708 bytes .../PlusJakartaSans-VariableFont_wght.ttf | Bin 0 -> 173760 bytes assets/icon.png | Bin 175349 -> 36820 bytes assets/images/android-icon-background.png | Bin 17549 -> 0 bytes assets/images/android-icon-foreground.png | Bin 78796 -> 0 bytes assets/images/android-icon-monochrome.png | Bin 4140 -> 0 bytes assets/images/favicon.png | Bin 1129 -> 0 bytes assets/images/icon.png | Bin 393493 -> 0 bytes assets/images/partial-react-logo.png | Bin 5075 -> 0 bytes assets/images/react-logo.png | Bin 6341 -> 0 bytes assets/images/react-logo@2x.png | Bin 14225 -> 0 bytes assets/images/react-logo@3x.png | Bin 21252 -> 0 bytes assets/images/splash-icon.png | Bin 17547 -> 0 bytes assets/partial-react-logo.png | Bin 49140 -> 7630 bytes assets/react-logo.png | Bin 8363 -> 3438 bytes assets/react-logo@2x.png | Bin 22172 -> 7072 bytes assets/react-logo@3x.png | Bin 40982 -> 10815 bytes assets/splash-icon.png | Bin 206114 -> 46813 bytes assets/splash.png | Bin 104288 -> 39799 bytes components/Button.tsx | 197 +++++++++ components/ChatRow.tsx | 92 ++++ components/MenuDrawer.tsx | 165 +++++++ components/ServiceSecretKeyVaultModal.tsx | 411 ++++++++++++++++++ components/Text.tsx | 104 +++++ components/WarningBanner.tsx | 43 ++ theme.ts | 253 +++++++++++ 32 files changed, 1422 insertions(+), 159 deletions(-) create mode 100644 assets/fonts/PlusJakartaSans-Italic-VariableFont_wght.ttf create mode 100644 assets/fonts/PlusJakartaSans-VariableFont_wght.ttf delete mode 100644 assets/images/android-icon-background.png delete mode 100644 assets/images/android-icon-foreground.png delete mode 100644 assets/images/android-icon-monochrome.png delete mode 100644 assets/images/favicon.png delete mode 100644 assets/images/icon.png delete mode 100644 assets/images/partial-react-logo.png delete mode 100644 assets/images/react-logo.png delete mode 100644 assets/images/react-logo@2x.png delete mode 100644 assets/images/react-logo@3x.png delete mode 100644 assets/images/splash-icon.png create mode 100644 components/Button.tsx create mode 100644 components/ChatRow.tsx create mode 100644 components/MenuDrawer.tsx create mode 100644 components/ServiceSecretKeyVaultModal.tsx create mode 100644 components/Text.tsx create mode 100644 components/WarningBanner.tsx create mode 100644 theme.ts diff --git a/app.config.js b/app.config.js index b435d40..098ecf5 100644 --- a/app.config.js +++ b/app.config.js @@ -65,13 +65,22 @@ module.exports = { }, plugins: [ 'expo-router', + [ + 'expo-font', + { + fonts: [ + './assets/fonts/PlusJakartaSans-VariableFont_wght.ttf', + './assets/fonts/PlusJakartaSans-Italic-VariableFont_wght.ttf', + ], + }, + ], [ 'expo-splash-screen', { - image: './assets/images/splash-icon.png', - imageWidth: 200, + image: './assets/splash-icon.png', + imageWidth: 578, resizeMode: 'contain', - backgroundColor: '#ffffff', + backgroundColor: '#1a73e8', dark: { backgroundColor: '#000000', }, diff --git a/app/_layout.tsx b/app/_layout.tsx index e75c769..cb49372 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -16,6 +16,12 @@ import { bootstrap } from '@/lib/keystore/bootstrap'; import { PreventScreenshotProvider } from '@/providers/PreventScreenshotProvider'; import React from 'react'; import { ReactKeystoreOptions } from '@algorandfoundation/react-native-keystore'; +import { GestureHandlerRootView } from 'react-native-gesture-handler'; +import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'; +import * as SplashScreen from 'expo-splash-screen'; + +// Keep the splash screen visible while we fetch resources +SplashScreen.preventAutoHideAsync(); globalPolyfill(); registerGlobals(); @@ -84,10 +90,14 @@ export default function RootLayout() { }); return ( - + - + + + + + - + ); } diff --git a/app/index.tsx b/app/index.tsx index a247f8a..fc9ba61 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -1,62 +1,31 @@ -import React from 'react'; -import { View, Text, StyleSheet, ActivityIndicator } from 'react-native'; -import { Redirect } from 'expo-router'; -import Constants from 'expo-constants'; -import { useStore } from '@tanstack/react-store'; -import { logsStore } from '@/stores/logs'; -import Logo from '@/components/Logo'; import { useProvider } from '@/hooks/useProvider'; +import FontAwesome6 from '@expo/vector-icons/FontAwesome6'; +import MaterialIcons from '@expo/vector-icons/MaterialIcons'; +import { useFonts } from 'expo-font'; +import { Redirect } from 'expo-router'; +import * as SplashScreen from 'expo-splash-screen'; +import React from 'react'; + export default function Index() { + const [fontsLoaded] = useFonts({ + 'PlusJakartaSans-Regular': require('../assets/fonts/PlusJakartaSans-VariableFont_wght.ttf'), + 'PlusJakartaSans-Medium': require('../assets/fonts/PlusJakartaSans-VariableFont_wght.ttf'), + 'PlusJakartaSans-SemiBold': require('../assets/fonts/PlusJakartaSans-VariableFont_wght.ttf'), + 'PlusJakartaSans-Bold': require('../assets/fonts/PlusJakartaSans-VariableFont_wght.ttf'), + 'PlusJakartaSans-Italic': require('../assets/fonts/PlusJakartaSans-Italic-VariableFont_wght.ttf'), + ...MaterialIcons.font, + ...FontAwesome6.font, + }); const { keys, status } = useProvider(); - const logs = useStore(logsStore, (state) => state.logs); - const lastLog = logs.length > 0 ? logs[0].message : 'Initializing...'; - const config = Constants.expoConfig?.extra?.provider || { - primaryColor: '#3B82F6', - }; + React.useEffect(() => { + SplashScreen.hideAsync(); + }, []); - if (status === 'loading') { - return ( - - - - - {lastLog} - Securing your keys and passkeys - - - ); + if (!fontsLoaded || status === 'loading') { + return null; } if (keys.length > 0) return ; return ; } - -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: '#F8FAFC', - padding: 24, - }, - logo: { - marginBottom: 40, - }, - content: { - marginTop: 24, - alignItems: 'center', - }, - text: { - fontSize: 18, - fontWeight: '600', - color: '#1E293B', - textAlign: 'center', - }, - subtext: { - marginTop: 8, - fontSize: 14, - color: '#64748B', - textAlign: 'center', - }, -}); diff --git a/app/landing.tsx b/app/landing.tsx index 72c197d..89437ce 100644 --- a/app/landing.tsx +++ b/app/landing.tsx @@ -1,124 +1,134 @@ -/** - * Minimal landing screen for the AC2 reference controller. - * - * Surface is intentionally tiny: - * - identifies the controller by its first identity DID, - * - links to `scan` to pair a new Liquid Auth session, - * - links to `connections` (the diagnostics panel) to inspect connections, - * their granted agent identity keys, and per-thread conversations. - * - * Everything else (accounts, passkeys browser, identities browser, import, - * balance/activity cards) was removed to keep this app as a reference for - * the AC2 SDK rather than a full wallet. - */ - -import React from 'react'; -import { View, Text, StyleSheet, TouchableOpacity, ScrollView } from 'react-native'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { useRouter } from 'expo-router'; +import { Button } from '@/components/Button'; +import { ChatRow } from '@/components/ChatRow'; +import { MenuDrawer, MenuDrawerHandle } from '@/components/MenuDrawer'; +import { AppText } from '@/components/Text'; +import { WarningBanner } from '@/components/WarningBanner'; +import { theme } from '@/theme'; import { MaterialIcons } from '@expo/vector-icons'; -import Logo from '../components/Logo'; -import { useProvider } from '@/hooks/useProvider'; +import { BottomSheetModal } from '@gorhom/bottom-sheet'; +import { Stack, useRouter } from 'expo-router'; +import React, { useRef } from 'react'; +import { Alert, FlatList, Pressable, StyleSheet, View } from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; + +// mock chat threads to display demo +import { mockChatThreads } from '@/__fixtures__/chat-threads'; +import { ServiceSecretKeyVaultModal } from '@/components/ServiceSecretKeyVaultModal'; +// dummy required actions for demo purposes +const REQUIRED_ACTIONS = ['Backup Mnemonic']; + +// ─── Screen ─────────────────────────────────────────────────────────────────── export default function LandingScreen() { + const hasRequiredActions = REQUIRED_ACTIONS.length > 0; + const drawerRef = useRef(null); + const vaultModalRef = useRef(null); + const connectNewAgentModalRef = useRef(null); + const router = useRouter(); - const { identities, sessions, key, account, identity, passkey } = useProvider(); - const activeIdentity = identities[0]; return ( - - - - - - AC2 Reference - Liquid Auth · AC2 SDK + + + + + + + drawerRef.current?.openDrawer()}> + + + + + AC2 Controller + - - - Controller DID - - {activeIdentity?.did || 'No identity found'} - - + +