From c7058d3e85712c1b195b0ddac507203d1467d4bf Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 2 Feb 2026 20:01:13 +0000 Subject: [PATCH 1/2] [jules] ux: Complete skeleton loading for HomeScreen groups Co-authored-by: Devasy <110348311+Devasy@users.noreply.github.com> --- .Jules/changelog.md | 8 +++ .Jules/todo.md | 10 +-- mobile/components/SkeletonGroupCard.js | 87 ++++++++++++++++++++++++++ mobile/screens/HomeScreen.js | 8 ++- 4 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 mobile/components/SkeletonGroupCard.js diff --git a/.Jules/changelog.md b/.Jules/changelog.md index 007d653..50c1129 100644 --- a/.Jules/changelog.md +++ b/.Jules/changelog.md @@ -7,6 +7,14 @@ ## [Unreleased] ### Added +- **Mobile Skeleton Loading:** Implemented skeleton loading state for HomeScreen. + - **Features:** + - Created `SkeletonGroupCard` component mimicking the actual group card layout. + - Implemented pulsing opacity animation (`Animated.loop`) for visual feedback. + - Used `useTheme` to ensure placeholders match the active theme (Dark/Light). + - Replaced generic `ActivityIndicator` with a list of skeletons. + - **Technical:** Created `mobile/components/SkeletonGroupCard.js` and updated `mobile/screens/HomeScreen.js`. + - **Mobile Accessibility:** Completed accessibility audit for all mobile screens. - **Features:** - Added `accessibilityLabel` to all interactive elements (buttons, inputs, list items). diff --git a/.Jules/todo.md b/.Jules/todo.md index de49cb8..5f6b553 100644 --- a/.Jules/todo.md +++ b/.Jules/todo.md @@ -57,12 +57,12 @@ - Impact: Native feel, users can easily refresh data - Size: ~150 lines -- [ ] **[ux]** Complete skeleton loading for HomeScreen groups - - File: `mobile/screens/HomeScreen.js` - - Context: Replace ActivityIndicator with skeleton group cards +- [x] **[ux]** Complete skeleton loading for HomeScreen groups + - Completed: 2026-02-04 + - Files: `mobile/screens/HomeScreen.js`, `mobile/components/SkeletonGroupCard.js` + - Context: Replaced ActivityIndicator with pulsing skeleton cards matching list layout - Impact: Better loading experience, less jarring - - Size: ~40 lines - - Added: 2026-01-01 + - Size: ~70 lines - [x] **[a11y]** Complete accessibility labels for all screens - Completed: 2026-01-29 diff --git a/mobile/components/SkeletonGroupCard.js b/mobile/components/SkeletonGroupCard.js new file mode 100644 index 0000000..c7d17ab --- /dev/null +++ b/mobile/components/SkeletonGroupCard.js @@ -0,0 +1,87 @@ +import React, { useEffect, useRef } from "react"; +import { View, StyleSheet, Animated } from "react-native"; +import { Card, useTheme } from "react-native-paper"; + +const SkeletonGroupCard = () => { + const theme = useTheme(); + const opacity = useRef(new Animated.Value(0.3)).current; + + useEffect(() => { + Animated.loop( + Animated.sequence([ + Animated.timing(opacity, { + toValue: 0.7, + duration: 800, + useNativeDriver: true, + }), + Animated.timing(opacity, { + toValue: 0.3, + duration: 800, + useNativeDriver: true, + }), + ]) + ).start(); + }, []); + + const styles = StyleSheet.create({ + card: { + marginBottom: 16, + backgroundColor: theme.colors.surface, + }, + row: { + flexDirection: "row", + alignItems: "center", + padding: 16, + }, + avatarPlaceholder: { + width: 40, + height: 40, + borderRadius: 20, + backgroundColor: theme.colors.surfaceVariant, + marginRight: 16, + }, + textContainer: { + flex: 1, + justifyContent: "center", + }, + titlePlaceholder: { + height: 20, + width: "60%", + backgroundColor: theme.colors.surfaceVariant, + borderRadius: 4, + }, + cardContent: { + paddingHorizontal: 16, + paddingBottom: 16, + }, + statusPlaceholder: { + height: 14, + width: "40%", + backgroundColor: theme.colors.surfaceVariant, + borderRadius: 4, + }, + }); + + return ( + + + + + + + + + + + + + + ); +}; + +export default SkeletonGroupCard; diff --git a/mobile/screens/HomeScreen.js b/mobile/screens/HomeScreen.js index 373bb0a..8c72a3b 100644 --- a/mobile/screens/HomeScreen.js +++ b/mobile/screens/HomeScreen.js @@ -1,7 +1,6 @@ import { useContext, useEffect, useState } from "react"; import { Alert, FlatList, RefreshControl, StyleSheet, View } from "react-native"; import { - ActivityIndicator, Appbar, Avatar, Button, @@ -12,6 +11,7 @@ import { TextInput, useTheme, } from "react-native-paper"; +import SkeletonGroupCard from "../components/SkeletonGroupCard"; import * as Haptics from "expo-haptics"; import { createGroup, getGroups, getOptimizedSettlements } from "../api/groups"; import { AuthContext } from "../context/AuthContext"; @@ -256,8 +256,10 @@ const HomeScreen = ({ navigation }) => { {isLoading ? ( - - + + {[1, 2, 3, 4].map((i) => ( + + ))} ) : ( Date: Mon, 2 Feb 2026 20:24:46 +0000 Subject: [PATCH 2/2] [jules] ux: Complete skeleton loading for HomeScreen groups Co-authored-by: Devasy <110348311+Devasy@users.noreply.github.com> --- mobile/screens/HomeScreen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/screens/HomeScreen.js b/mobile/screens/HomeScreen.js index 8c72a3b..93f5b45 100644 --- a/mobile/screens/HomeScreen.js +++ b/mobile/screens/HomeScreen.js @@ -33,7 +33,7 @@ const HomeScreen = ({ navigation }) => { const showModal = () => setModalVisible(true); const hideModal = () => setModalVisible(false); - // Calculate settlement status for a group + // Calculate settlement status for a group (owes/owed) const calculateSettlementStatus = async (groupId, userId) => { try { const response = await getOptimizedSettlements(groupId);