-
Notifications
You must be signed in to change notification settings - Fork 23
[jules] enhance: Add skeleton loading for HomeScreen groups #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,63 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { View, StyleSheet, FlatList } from 'react-native'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Card } from 'react-native-paper'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import Skeleton from '../ui/Skeleton'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const GroupListSkeleton = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const renderSkeletonItem = ({ item }) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Card style={styles.card}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Card.Title | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title={<Skeleton width={120} height={20} borderRadius={4} />} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| left={(props) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <View style={[props.style, styles.avatarPlaceholder]}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Skeleton width={40} height={40} borderRadius={20} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </View> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Card.Content> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Skeleton width={180} height={16} borderRadius={4} style={styles.contentSkeleton} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Card.Content> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </Card> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+7
to
+21
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Unused The ♻️ Proposed fix- const renderSkeletonItem = ({ item }) => (
+ const renderSkeletonItem = ({ item: _item }) => (
<Card style={styles.card}>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Render 5 placeholder items | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const skeletonData = Array.from({ length: 5 }).map((_, i) => ({ id: `skeleton-${i}` })); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <View | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| style={styles.container} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| accessible={true} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| accessibilityRole="progressbar" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| accessibilityLabel="Loading groups" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <FlatList | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data={skeletonData} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| renderItem={renderSkeletonItem} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| keyExtractor={(item) => item.id} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contentContainerStyle={styles.list} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scrollEnabled={false} // Disable scrolling for skeleton list | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </View> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const styles = StyleSheet.create({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| container: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| flex: 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| list: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| padding: 16, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| card: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| marginBottom: 16, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| avatarPlaceholder: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| justifyContent: 'center', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| alignItems: 'center', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contentSkeleton: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| marginTop: 4, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default GroupListSkeleton; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,52 @@ | ||||||||||||||
| import React, { useEffect, useRef } from 'react'; | ||||||||||||||
| import { Animated, View, StyleSheet } from 'react-native'; | ||||||||||||||
| import { useTheme } from 'react-native-paper'; | ||||||||||||||
|
Comment on lines
+1
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused The 🧹 Proposed fix import React, { useEffect, useRef } from 'react';
-import { Animated, View, StyleSheet } from 'react-native';
+import { Animated, StyleSheet } from 'react-native';
import { useTheme } from 'react-native-paper';📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||
|
|
||||||||||||||
| const Skeleton = ({ width, height, borderRadius = 4, style }) => { | ||||||||||||||
| const theme = useTheme(); | ||||||||||||||
| const animatedValue = useRef(new Animated.Value(0.3)).current; | ||||||||||||||
|
|
||||||||||||||
| useEffect(() => { | ||||||||||||||
| const animation = Animated.loop( | ||||||||||||||
| Animated.sequence([ | ||||||||||||||
| Animated.timing(animatedValue, { | ||||||||||||||
| toValue: 0.7, | ||||||||||||||
| duration: 800, | ||||||||||||||
| useNativeDriver: true, | ||||||||||||||
| }), | ||||||||||||||
| Animated.timing(animatedValue, { | ||||||||||||||
| toValue: 0.3, | ||||||||||||||
| duration: 800, | ||||||||||||||
| useNativeDriver: true, | ||||||||||||||
| }), | ||||||||||||||
| ]) | ||||||||||||||
| ); | ||||||||||||||
| animation.start(); | ||||||||||||||
|
|
||||||||||||||
| return () => animation.stop(); | ||||||||||||||
| }, [animatedValue]); | ||||||||||||||
|
|
||||||||||||||
| return ( | ||||||||||||||
| <Animated.View | ||||||||||||||
| style={[ | ||||||||||||||
| styles.skeleton, | ||||||||||||||
| { | ||||||||||||||
| width, | ||||||||||||||
| height, | ||||||||||||||
| borderRadius, | ||||||||||||||
| backgroundColor: theme.colors.surfaceVariant, | ||||||||||||||
| opacity: animatedValue, | ||||||||||||||
| }, | ||||||||||||||
| style, | ||||||||||||||
| ]} | ||||||||||||||
| /> | ||||||||||||||
| ); | ||||||||||||||
| }; | ||||||||||||||
|
|
||||||||||||||
| const styles = StyleSheet.create({ | ||||||||||||||
| skeleton: { | ||||||||||||||
| overflow: 'hidden', | ||||||||||||||
| }, | ||||||||||||||
| }); | ||||||||||||||
|
|
||||||||||||||
| export default Skeleton; | ||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 3573
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 231
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 472
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 231
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 161
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 234
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 95
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 43
🏁 Script executed:
# Read HapticCard component to understand its structure cat mobile/components/ui/HapticCard.jsRepository: Devasy/splitwiser
Length of output: 413
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 1586
🏁 Script executed:
# Read the complete GroupListSkeleton file cat mobile/components/skeletons/GroupListSkeleton.jsRepository: Devasy/splitwiser
Length of output: 1635
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 241
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 518
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 92
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 849
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 450
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 43
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 198
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 43
🌐 Web query:
React Native Paper v5 Avatar default size when not specified💡 Result:
The default size for Avatar components (Avatar.Image, Avatar.Icon, Avatar.Text) in React Native Paper v5, when the size prop is not specified, is 64 pixels.
Citations:
🌐 Web query:
React Native Paper Card.Title default height dimensions💡 Result:
React Native Paper's Card.Title component does not have a fixed default height. Its height is content-driven and auto-adjusts based on the title text (default variant: bodyLarge, 1 line), optional subtitle (default variant: bodyMedium, 1 line), and optional left/right icons/avatars. Key dimensions from official theme (MD3): - bodyLarge: fontSize 16, lineHeight 24 - bodyMedium: fontSize 14, lineHeight 20 The component uses a flex row layout with padding (likely similar to CardContent's 16 horizontal, vertical varies by position). Without subtitle or icons, height approximates the title's lineHeight (~24dp) plus minimal padding. With subtitle stacked below, height sums both lineHeights plus spacing (~48-56dp total, depending on padding). No explicit height is defined in docs or source snippets; use style={{ height: X }} to set custom height. For precise measurement, render in app and inspect with React Native Debugger.
Citations:
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 43
🏁 Script executed:
Repository: Devasy/splitwiser
Length of output: 43
Avatar skeleton dimensions incorrect—causing layout shift instead of preventing it.
The Avatar skeleton is 40×40, but HomeScreen's Avatar components use the React Native Paper v5 default size of 64×64 (no explicit size prop is passed). When the skeleton is replaced with real content, this 24px difference causes layout shift. Update the skeleton to use 64×64 for the avatar to match the actual component:
<Skeleton width={40} height={40} borderRadius={20} />should be:
<Skeleton width={64} height={64} borderRadius={32} />Also consider extracting these dimensions (64 for avatar, 32 for borderRadius) as shared constants to prevent future mismatches.
📝 Committable suggestion
🤖 Prompt for AI Agents