From 869f21ee2efaefed6a5aa4fbd417c25df8dec02a Mon Sep 17 00:00:00 2001 From: soryu Date: Sun, 18 Jan 2026 17:44:50 +0000 Subject: Add React Native mobile app for Makima (#3) * [WIP] Heartbeat checkpoint - 2026-01-18 02:58:27 UTC * feat(mobile): complete mobile app integration and verification - Add ThemeColors type export to Colors.ts for type safety - Export SUPABASE_URL from supabase.ts and use environment variables - Update .env.example with correct default URLs - Add comprehensive README.md with setup instructions Verified: - TypeScript compiles without errors - App exports successfully for iOS and Android - All screens accessible (login, dashboard, tasks, settings, task detail) - Auth flow working with Zustand store and Supabase Co-Authored-By: Claude Opus 4.5 * Task completion checkpoint --------- Co-authored-by: Claude Opus 4.5 --- apps/mobile/components/TaskListSkeleton.tsx | 119 ++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 apps/mobile/components/TaskListSkeleton.tsx (limited to 'apps/mobile/components/TaskListSkeleton.tsx') diff --git a/apps/mobile/components/TaskListSkeleton.tsx b/apps/mobile/components/TaskListSkeleton.tsx new file mode 100644 index 0000000..60e747d --- /dev/null +++ b/apps/mobile/components/TaskListSkeleton.tsx @@ -0,0 +1,119 @@ +import React, { useEffect, useRef } from 'react'; +import { + View, + StyleSheet, + Animated, + useColorScheme, +} from 'react-native'; +import { Colors } from '../constants/Colors'; + +interface SkeletonRowProps { + delay?: number; +} + +function SkeletonRow({ delay = 0 }: SkeletonRowProps) { + const colorScheme = useColorScheme() ?? 'light'; + const colors = Colors[colorScheme]; + const opacity = useRef(new Animated.Value(0.3)).current; + + useEffect(() => { + const animation = Animated.loop( + Animated.sequence([ + Animated.timing(opacity, { + toValue: 0.7, + duration: 800, + useNativeDriver: true, + delay, + }), + Animated.timing(opacity, { + toValue: 0.3, + duration: 800, + useNativeDriver: true, + }), + ]) + ); + animation.start(); + return () => animation.stop(); + }, [opacity, delay]); + + const bgColor = colorScheme === 'dark' ? '#374151' : '#e5e7eb'; + + return ( + + + + + + + + ); +} + +export function TaskListSkeleton() { + return ( + + + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + row: { + flexDirection: 'row', + alignItems: 'center', + paddingVertical: 16, + paddingHorizontal: 16, + borderBottomWidth: StyleSheet.hairlineWidth, + minHeight: 64, + }, + dot: { + width: 10, + height: 10, + borderRadius: 5, + marginRight: 12, + }, + content: { + flex: 1, + gap: 8, + }, + titleBar: { + height: 16, + width: '70%', + borderRadius: 4, + }, + subtitleBar: { + height: 12, + width: '40%', + borderRadius: 4, + }, +}); -- cgit v1.2.3