Skip to content

Commit

Permalink
Merge pull request #3220 from KBVE/patch-atomic-adding-a-profile-comp…
Browse files Browse the repository at this point in the history
…onent-11-14-2024-1731598928

[CI] Merge patch-atomic-adding-a-profile-component-11-14-2024-1731598928 into dev
  • Loading branch information
h0lybyte authored Nov 15, 2024
2 parents 4461c57 + 5f5fb1b commit 9f5a875
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 6 deletions.
2 changes: 1 addition & 1 deletion apps/expo-lcagents/src/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function RootLayoutNav() {
<Stack.Screen name="login" options={{ animation: 'fade' }} />
<Stack.Screen name="profile" options={{ animation: 'fade' }} />
<Stack.Screen name="onboard" options={{ animation: 'fade' }} />

<Stack.Screen name="users" options={{ animation: 'fade'}} />

</Stack>

Expand Down
115 changes: 115 additions & 0 deletions apps/expo-lcagents/src/app/users.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React, { useMemo, useCallback, useEffect } from 'react';
import { YStack, XStack, SizableText, Separator, ScrollView } from 'tamagui';
import {
TamaUserCard,
LottieAnimation,
createSupabaseClient,
TamaProfileContainer,
} from '@kbve/expo-bbq';
import { useNavigation, useLocalSearchParams } from 'expo-router';

const Users = () => {
const navigation = useNavigation();

const { username = 'h0lybyte' } = useLocalSearchParams<{
username?: string;
}>();

const supabaseUrl = 'https://supabase.kbve.com';
const supabaseAnonKey =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJyb2xlIjogImFub24iLAogICJpc3MiOiAic3VwYWJhc2UiLAogICJpYXQiOiAxNzI0NTM2ODAwLAogICJleHAiOiAxODgyMzAzMjAwCn0._fmEmblm0afeLoPXxt8wP2mYpa9gzU-ufx3v8oRTFGg';

const supabase = useMemo(
() => createSupabaseClient(supabaseUrl, supabaseAnonKey),
[supabaseUrl, supabaseAnonKey],
);

const lottieProfileAnimation = useMemo(
() => require('../../assets/json/profile.json'),
[],
);

const updateNavigationOptions = useCallback(() => {
navigation.setOptions({
title: 'KBVE Users',
headerBackTitle: 'Back',
});
}, [navigation]);

useEffect(() => {
updateNavigationOptions();
}, [updateNavigationOptions]);

const MemoizedLottieAnimation = React.memo(LottieAnimation);

return (
<ScrollView contentContainerStyle={{ flexGrow: 1 }}>
<XStack
f={1}
jc="center"
ai="center"
padding="$1"
flexDirection="column"
$gtMd={{
flexDirection: 'row',
justifyContent: 'space-between',
maxWidth: '90%',
gap: '$6',
}}
$gtLg={{
flexDirection: 'row',
justifyContent: 'space-between',
maxWidth: '80%',
gap: '$8',
}}>
<YStack
jc="center"
ai="center"
$sm={{ width: '50%', display: 'block' }}
$gtLg={{
flex: 1,
maxWidth: '100%',
}}>
<MemoizedLottieAnimation
lottieJSON={lottieProfileAnimation}
style={{
width: '100%',
height: 'auto',
aspectRatio: 1,
maxWidth: 800,
}}
/>
</YStack>

<YStack
jc="center"
ai="center"
$sm={{ width: '100%' }}
$gtLg={{
flex: 1,
maxWidth: '40%',
paddingLeft: '$8',
}}>
<SizableText size="$4" theme="alt1" $gtLg={{ size: '$6' }}>
KBVE Users
</SizableText>
<Separator
borderColor="cyan"
paddingVertical="$2"
alignSelf="stretch"
$gtLg={{
paddingVertical: '$5',
}}
/>

<TamaProfileContainer
username={username}
supabase={supabase}
/>
</YStack>
</XStack>
</ScrollView>
);
};

export default Users;
8 changes: 8 additions & 0 deletions apps/kbve.com/src/content/journal/11-14.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,11 @@ import { Adsense, Tasks } from '@kbve/astropad';
The `useMemory` hook is almost done, but we still need to fix the offscreen integration and maybe even utilize the `useIdleCallback`.
Let me get this all pushed out and I will enter the testing realm again tonight.

After making the hook, we can test it out with a profile component?
The idea would be to create two files for us to use, the general profile container and then a wrapper around that said container for the rendering and caching.
The first file would be the Profile itself and the second would be a contaijner that would hold the profile and add the useMemory hook around it?

I am wondering what would be the best way to handle this without causing too many renders but also making it super fast to load and unload profiles.
I am also thinking that after we get the useMemory hook to work, we can add another hook that would help us create a pool of the objects that we could render offscreen and then transition them in.
In theory we would be creating one of those infinite scrolling situations but having it render as they scroll through the application.
The goal would also be to make sure that it does not pull any additional data, by having it cache the results and then use the cache to help build the profiles.
66 changes: 66 additions & 0 deletions packages/expo-bbq/src/components/card/TamaProfileCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { memo } from 'react';
import {
YStack,
XStack,
SizableText,
Avatar,
Button,
Separator,
} from 'tamagui';
import { MessageCircle, Heart, MoreVertical } from '@tamagui/lucide-icons';
import { type IUserCardsPublic } from '../../type';



interface TamaProfileCardProps {
data: IUserCardsPublic;
loading: boolean;
onAction: (actionState: string, content: string) => void;
}

export const TamaProfileCard = memo(function TamaProfileCard({
data,
loading,
onAction,
}: TamaProfileCardProps) {
if (loading) {
return <div>Loading...</div>;
}

return (
<YStack
width={400}
backgroundColor="$background"
borderRadius="$4"
padding="$4"
shadowColor="$shadowColor"
shadowOffset={{ width: 0, height: 4 }}
shadowOpacity={0.1}
shadowRadius={20}>

<XStack justifyContent="space-between" alignItems="center">
<XStack alignItems="center" gap="$2">
{/* <Avatar circular size="$5">
<Avatar.Image source={{ uri: data.avatarUrl }} width="100%" height="100%" />
</Avatar> */}
<YStack>
<SizableText fontWeight="600" fontSize="$2">{data.username}</SizableText>
<SizableText fontSize="$1" color="$gray10">{data.bio}</SizableText>
</YStack>
</XStack>
<Button iconAfter={MoreVertical} onPress={() => onAction("Options", "Options menu opened")} />
</XStack>

<YStack paddingVertical="$3">
<SizableText fontSize="$2" color="$gray11">{data.bio}</SizableText>
</YStack>

<Separator marginVertical="$3" />

<XStack justifyContent="space-between" alignItems="center">
<Button iconAfter={MessageCircle} onPress={() => onAction("Send Message", "Message sent")} />
<Button iconAfter={Heart} onPress={() => onAction("Follow", "User followed")} />
</XStack>
</YStack>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { Suspense, useCallback } from 'react';
import { TamaProfileCard } from '../card/TamaProfileCard';
import { useMemory } from '../../core/useMemory';
import { Spinner as SkeletonLoader, YStack, Button } from 'tamagui';
import { type IUserCardsPublic } from '../../type';

export const TamaProfileContainer = ({
username,
supabase,
}: {
username: string;
supabase: any;
}) => {
const fetchProfileData =
useCallback(async (): Promise<IUserCardsPublic> => {
const { data, error } = await supabase
.from('user_cards_public')
.select('username, bio, socials, style')
.eq('username', username)
.single();

if (error) {
console.error('Error fetching profile:', error);
return { username: '', socials: '', style: '', bio: '' };
}
return data;
}, [supabase, username]);

const { LazyLoadedComponent: MemoizedProfileCard, refreshData } = useMemory(
`profile_${username}`,
fetchProfileData,
TamaProfileCard,
SkeletonLoader,
{
onAction: (actionState: string, content: string) =>
console.log(`Action: ${actionState}, Content: ${content}`),
},
);

return (
<YStack space="$4" padding="$4" alignItems="center">
<Suspense fallback={<SkeletonLoader />}>
<MemoizedProfileCard />
</Suspense>
<Button onPress={refreshData}>Refresh Profile</Button>
</YStack>
);
};

export default TamaProfileContainer;
10 changes: 5 additions & 5 deletions packages/expo-bbq/src/core/useMemory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ type LazyComponentProps<T> = {
loading: boolean;
};

export const useMemory = <T,>(
export const useMemory = <T, P, >(
key: string,
fetchData: () => Promise<T>,
Component: React.ComponentType<LazyComponentProps<T>>,
Component: React.ComponentType<LazyComponentProps<T> & P>,
Skeleton?: React.ComponentType,
extraProps?: P,
) => {
const { data, loading } = useCache<T>(key, fetchData);

Expand All @@ -21,11 +22,10 @@ export const useMemory = <T,>(

const LazyLoadedComponent = useMemo(() => {
const LazyComponent = React.lazy(async () => {
await fetchData();
return {
default: () =>
data ? (
<Component data={data} loading={loading} />
<Component data={data} loading={loading} {...(extraProps as P)} />
) : Skeleton ? (
<Skeleton />
) : (
Expand All @@ -42,7 +42,7 @@ export const useMemory = <T,>(
<LazyComponent />
</Suspense>
);
}, [data, loading, fetchData, Component, Skeleton]);
}, [data, loading, Component, Skeleton, extraProps]);

return { LazyLoadedComponent, refreshData };
};
Expand Down
6 changes: 6 additions & 0 deletions packages/expo-bbq/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export { LottieAnimation } from './components/animation/LottieAnimation';
export { LottieHero } from './components/animation/LottieHero';
export { MaskedView } from './components/creative/MaskedView';

// [WRAPPER]
export { createSupabaseClient } from './components/wrapper/Supabase';

// [CONTAINER]
export { TamaProfileContainer } from './components/container/TamaProfileContainer';

// [CORE]
export { useBBQ } from './core/BBQ';
export { payloadInstance } from './core/Payload';
Expand Down
7 changes: 7 additions & 0 deletions packages/expo-bbq/src/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export interface IUserCardsPublic {
username: string;
bio: string;
socials: string;
style: string;
}

0 comments on commit 9f5a875

Please sign in to comment.