Skip to content

Commit

Permalink
Merge pull request #16 from Circle-Company/add-skeleton-view
Browse files Browse the repository at this point in the history
Add Skeleton Loading on Account Screen + AllMemoriesScreen
  • Loading branch information
tiagosavioli authored Aug 6, 2024
2 parents 7c82084 + 792f1aa commit ddc6cb4
Show file tree
Hide file tree
Showing 13 changed files with 415 additions and 63 deletions.
5 changes: 5 additions & 0 deletions src/components/skeleton/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SkeletonView } from "./skeleton-view"

export const Skeleton = {
View: SkeletonView,
}
76 changes: 76 additions & 0 deletions src/components/skeleton/skeleton-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from "react"
import { StyleSheet, ViewProps, useColorScheme } from "react-native"
import LinearGradient from "react-native-linear-gradient"
import Animated, {
interpolate,
useAnimatedStyle,
useSharedValue,
withRepeat,
withTiming,
} from "react-native-reanimated"
import { View } from "../../components/Themed"
import { colors } from "../../layout/constants/colors"
import sizes from "../../layout/constants/sizes"

const width = sizes.screens.width
const AnimatedLinearGradient = Animated.createAnimatedComponent(LinearGradient)

interface SkeletonViewProps extends ViewProps {
children?: React.ReactNode
delay?: number
backgroundColor?: string
gradientColor?: string
}

export const SkeletonView = React.memo(
({
children,
style,
delay = 0,
backgroundColor,
gradientColor,
...props
}: SkeletonViewProps) => {
const isDarkMode = useColorScheme() === "dark"
const x = useSharedValue(0)

React.useEffect(() => {
const startAnimation = () => {
x.value = withRepeat(withTiming(1, { duration: 1500 }), -1, false)
}
const timeoutId = setTimeout(startAnimation, delay)
return () => clearTimeout(timeoutId)
}, [delay])

const containerStyle = React.useMemo(
() => ({
backgroundColor:
backgroundColor || isDarkMode ? colors.gray.grey_08 : colors.gray.grey_02,
overflow: "hidden",
}),
[backgroundColor]
)

const lineStyle = React.useMemo(() => StyleSheet.absoluteFillObject, [])

const animatedStyle = useAnimatedStyle(() => ({
transform: [{ translateX: interpolate(x.value, [0, 1], [-width, width]) }],
}))

return (
<View style={[containerStyle, style]} {...props}>
<AnimatedLinearGradient
colors={[
backgroundColor || isDarkMode ? colors.gray.grey_08 : colors.gray.grey_02,
gradientColor || isDarkMode ? colors.gray.grey_06 : colors.gray.grey_01,
backgroundColor || isDarkMode ? colors.gray.grey_08 : colors.gray.grey_02,
]}
style={[animatedStyle, lineStyle]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
/>
{children}
</View>
)
}
)
3 changes: 2 additions & 1 deletion src/config/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
API_VERSION,
APP_VERSION,
DEBUG,
DEVELOPMENT_API_ENDPOINT,
LOG_DEBUG,
LOG_LEVEL,
MIXPANEL_KEY,
Expand All @@ -21,7 +22,7 @@ const environment = {

const api = {
API_VERSION: API_VERSION,
ENDPOINT: NODE_ENV == "production" ? PRODUCTION_API_ENDPOINT : "192.168.15.9:3000",
ENDPOINT: environment.PRODUCTION ? PRODUCTION_API_ENDPOINT : DEVELOPMENT_API_ENDPOINT,
}

const analytics = {
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/bottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BottomSheet, { BottomSheetModalProvider, BottomSheetProps } from "@gorhom/bottom-sheet"
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
import { useColorScheme, View } from "react-native"
import { View, useColorScheme } from "react-native"
import { CustomBackdrop } from "../components/general/bottomSheet/backdrop"
import { colors } from "../layout/constants/colors"
import sizes from "../layout/constants/sizes"
Expand Down
40 changes: 22 additions & 18 deletions src/features/list-memories/list-memories-all/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from "react"
import { useColorScheme } from "react-native"
import OfflineCard from "../../../components/general/offline"
import { Loading } from "../../../components/loading"
import LanguageContext from "../../../contexts/Preferences/language"
import MemoryContext from "../../../contexts/memory"
import NetworkContext from "../../../contexts/network"
Expand All @@ -11,6 +10,7 @@ import { AnimatedVerticalFlatlist } from "../../../lib/hooks/useAnimatedFlatList
import api from "../../../services/Api"
import EndReached from "./components/end-reached"
import { ListMemoriesAll } from "./components/list-memories-date_group"
import { ListMemoriesAllSkeleton } from "./skeleton"

export default function ListMemoriesAllSeparatedbyDate() {
const { t } = React.useContext(LanguageContext)
Expand Down Expand Up @@ -57,15 +57,16 @@ export default function ListMemoriesAllSeparatedbyDate() {

const handleRefresh = async () => {
setPage(1)
setLoading(true)
await fetchData().finally(() => {
setLoading(false)
setTimeout(() => {
setRefreshing(false)
}, 200)
})
}

const data_to_render = groupObjectsByDate(allMemories, TimeInterval.DAY)

if (networkStats == "OFFLINE" && allMemories.length == 0)
return <OfflineCard height={sizes.screens.height - sizes.headers.height} />
return (
Expand All @@ -74,28 +75,31 @@ export default function ListMemoriesAllSeparatedbyDate() {
onEndReached={fetchData}
onEndReachedThreshold={0.1}
handleRefresh={handleRefresh}
showRefreshSpinner={false}
renderItem={({ item, index }) => {
return (
<ListMemoriesAll
key={index}
data={item}
date_text={item.date}
count={item.count}
user={allMemoriesUser}
/>
)
if (refreshing || loading) return <ListMemoriesAllSkeleton />
else
return (
<ListMemoriesAll
key={index}
data={item}
date_text={item.date}
count={item.count}
user={allMemoriesUser}
/>
)
}}
ListFooterComponent={() => {
if (endReached) return <EndReached text={t("No more Memories")} />
else
else if (data_to_render.length <= 0)
return (
<Loading.Container
width={sizes.screens.width}
height={sizes.headers.height * 2}
>
<Loading.ActivityIndicator />
</Loading.Container>
<>
<ListMemoriesAllSkeleton />
<ListMemoriesAllSkeleton />
<ListMemoriesAllSkeleton />
</>
)
else return <ListMemoriesAllSkeleton />
}}
/>
)
Expand Down
104 changes: 104 additions & 0 deletions src/features/list-memories/list-memories-all/skeleton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { useColorScheme } from "react-native"
import { View } from "../../../components/Themed"
import { Skeleton } from "../../../components/skeleton"
import { colors } from "../../../layout/constants/colors"
import sizes from "../../../layout/constants/sizes"

export function ListMemoriesAllSkeleton() {
const isDarkMode = useColorScheme() === "dark"
const container = {
paddingTop: sizes.paddings["1sm"] * 0.5,
width: sizes.screens.width,
alignItems: "center",
justifyContent: "flex-start",
}

const memory = {
width: sizes.moment.tiny.width * 0.8,
}

const header = {
width: sizes.screens.width,
height: sizes.headers.height * 0.6,
alignItems: "center",
justifyContent: "center",
flexDirection: "row",
paddingHorizontal: sizes.margins["1md"],
}
return (
<View style={container}>
<View style={header}>
<View style={{ flex: 1 }}>
<Skeleton.View style={{ width: 100, height: 16, borderRadius: 10 }} />
</View>
<Skeleton.View style={{ width: 40, height: 16, borderRadius: 10 }} />
</View>
<View
style={{
flexDirection: "row",
width: sizes.screens.width,
paddingTop: sizes.paddings["1sm"],
paddingBottom: sizes.paddings["1lg"],
marginBottom: sizes.margins["1sm"],
borderBottomWidth: 1,
borderColor: isDarkMode ? colors.gray.grey_08 : colors.gray.grey_02,
}}
>
<View style={[memory, { marginLeft: sizes.margins["2sm"] }]}>
<Skeleton.View
style={{
width: sizes.moment.tiny.width * 0.8,
height: sizes.moment.tiny.height * 0.8,
borderRadius: sizes.moment.tiny.borderRadius * 0.8,
}}
/>
<Skeleton.View
style={{
alignSelf: "center",
width: 70,
height: 16,
borderRadius: 10,
marginTop: sizes.margins["2sm"],
}}
/>
</View>
<View style={[memory, { marginLeft: sizes.margins["2sm"] }]}>
<Skeleton.View
style={{
width: sizes.moment.tiny.width * 0.8,
height: sizes.moment.tiny.height * 0.8,
borderRadius: sizes.moment.tiny.borderRadius * 0.8,
}}
/>
<Skeleton.View
style={{
alignSelf: "center",
width: 70,
height: 16,
borderRadius: 10,
marginTop: sizes.margins["2sm"],
}}
/>
</View>
<View style={[memory, { marginLeft: sizes.margins["2sm"] }]}>
<Skeleton.View
style={{
width: sizes.moment.tiny.width * 0.8,
height: sizes.moment.tiny.height * 0.8,
borderRadius: sizes.moment.tiny.borderRadius * 0.8,
}}
/>
<Skeleton.View
style={{
alignSelf: "center",
width: 70,
height: 16,
borderRadius: 10,
marginTop: sizes.margins["2sm"],
}}
/>
</View>
</View>
</View>
)
}
24 changes: 3 additions & 21 deletions src/features/list-memories/list-memories-preview/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useNavigation } from "@react-navigation/native"
import React from "react"
import { FlatList, RefreshControl, useColorScheme, View } from "react-native"
import { FlatList, useColorScheme, View } from "react-native"
import Animated, { FadeInLeft } from "react-native-reanimated"
import ViewMorebutton from "../../../components/buttons/view_more"
import OfflineCard from "../../../components/general/offline"
Expand All @@ -14,13 +14,13 @@ import NetworkContext from "../../../contexts/network"
import PersistedContext from "../../../contexts/Persisted"
import LanguageContext from "../../../contexts/Preferences/language"
import ViewProfileContext from "../../../contexts/viewProfile"
import { colors } from "../../../layout/constants/colors"
import fonts from "../../../layout/constants/fonts"
import sizes from "../../../layout/constants/sizes"
import api from "../../../services/Api"
import RenderMemory from "../components/render-memory"
import AnyMemoryCard from "./components/any_memory-card"
import EndReached from "./components/end-reached"
import { ListMemoriesPreviewSkeleton } from "./skeleton"

type RenderMemoriesPreviewProps = {
enableScroll?: boolean
Expand Down Expand Up @@ -118,12 +118,7 @@ export default function ListMemoriesPreview({
if (networkStats == "OFFLINE" && memories.length == 0)
return <OfflineCard height={(sizes.screens.height - sizes.headers.height) / 2} />

if (loading)
return (
<Loading.Container width={sizes.screens.width} height={sizes.screens.height / 2.2}>
<Loading.ActivityIndicator />
</Loading.Container>
)
if (loading) return <ListMemoriesPreviewSkeleton />
if (memories.length === 0) return <AnyMemoryCard isAccountScreen={isAccountScreen} />
return (
<View style={container}>
Expand Down Expand Up @@ -153,19 +148,6 @@ export default function ListMemoriesPreview({
onEndReached={async () => {
fetchData()
}}
refreshControl={
<RefreshControl
progressBackgroundColor={String(
isDarkMode ? colors.gray.grey_08 : colors.gray.grey_02
)}
colors={[
String(isDarkMode ? colors.gray.grey_04 : colors.gray.grey_04),
"#00000000",
]}
refreshing={refreshing}
onRefresh={async () => await handleRefresh()}
/>
}
ListHeaderComponent={() => {
return <View style={{ width: 15 }} />
}}
Expand Down
Loading

0 comments on commit ddc6cb4

Please sign in to comment.