Skip to content

Commit

Permalink
feat: added skeleton loaders
Browse files Browse the repository at this point in the history
  • Loading branch information
MAXOUXAX committed Apr 9, 2024
1 parent cca2af0 commit 154c49f
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 7 deletions.
24 changes: 21 additions & 3 deletions expo/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,23 @@ import H2 from "../../components/text/H2";
import { getApiUrl } from "../../lib/apiUrl";
import { useUserProfile } from "../../lib/userProfile";

function RecentMusics() {
function RecentMusicsSkeletonLoader() {
return (
<FlatList
data={[{}, {}, {}, {}, {}]}
renderItem={() => <TrackCard.Skeleton />}
ItemSeparatorComponent={() => <View style={{ height: 12 }} />}
/>
);
}

type RecentMusicsProps = {
loading?: React.ReactElement;
};

function RecentMusics({ loading }: RecentMusicsProps) {
const userProfile = useUserProfile();
const [recentMusics, setRecentMusics] = useState<JSONTrack[]>([]);
const [recentMusics, setRecentMusics] = useState<JSONTrack[]>();
const apiUrl = getApiUrl();

useEffect(() => {
Expand All @@ -38,6 +52,10 @@ function RecentMusics() {
fetchRecentMusics();
}, [userProfile]);

if (recentMusics === undefined) {
return loading ?? <View />;
}

return (
<FlatList
data={recentMusics}
Expand Down Expand Up @@ -80,7 +98,7 @@ export default function HomeTab() {
icon={<MusicNote />}
/>
<View style={{ width: "100%" }}>
<RecentMusics />
<RecentMusics loading={<RecentMusicsSkeletonLoader />} />
</View>
</View>
</ScrollView>
Expand Down
78 changes: 74 additions & 4 deletions expo/components/Music.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ type TrackCardProps = {
music: JSONTrack;
};

export const TrackCard: React.FC<TrackCardProps> = ({ music }) => {
type TrackCardSubComponents = {
Skeleton: typeof TrackCardSkeleton;
};

export const TrackCard: React.FC<TrackCardProps> & TrackCardSubComponents = ({
music,
}) => {
return (
<View style={styles.musicContainer}>
<View style={styles.musicDetails}>
Expand All @@ -26,6 +32,19 @@ export const TrackCard: React.FC<TrackCardProps> = ({ music }) => {
);
};

const TrackCardSkeleton: React.FC = () => {
return (
<View style={styles.musicContainer}>
<View style={styles.musicDetails}>
<MusicArtwork.Skeleton />
<MusicContent.Skeleton />
</View>
</View>
);
};

TrackCard.Skeleton = TrackCardSkeleton;

const InactiveMusic: React.FC<InactiveMusicProps> = ({ music }) => {
return (
<View style={styles.musicContainer}>
Expand All @@ -47,9 +66,14 @@ type MusicArtworkProps = {
addedBy?: string;
};

const MusicArtwork: React.FC<MusicArtworkProps> = ({ imageUrl, addedBy }) => {
// TODO: Use a component to load the avatar of an user
type MusicArtworkSubComponents = {
Skeleton: typeof MusicArtworkSkeleton;
};

const MusicArtwork: React.FC<MusicArtworkProps> & MusicArtworkSubComponents = ({
imageUrl,
addedBy,
}) => {
return (
<View style={styles.artworkContainer}>
<Image source={{ uri: imageUrl }} style={styles.artwork} />
Expand All @@ -58,13 +82,32 @@ const MusicArtwork: React.FC<MusicArtworkProps> = ({ imageUrl, addedBy }) => {
);
};

const MusicArtworkSkeleton: React.FC = () => {
return (
<View style={styles.artworkContainer}>
<View
style={{
backgroundColor: "#E6E6E6",
...styles.artwork,
}}
/>
</View>
);
};

MusicArtwork.Skeleton = MusicArtworkSkeleton;

type MusicContentProps = {
title: string;
artists: string;
position?: number;
};

const MusicContent: React.FC<MusicContentProps> = ({
type MusicContentSubComponents = {
Skeleton: typeof MusicContentSkeleton;
};

const MusicContent: React.FC<MusicContentProps> & MusicContentSubComponents = ({
title,
artists,
position,
Expand All @@ -80,6 +123,33 @@ const MusicContent: React.FC<MusicContentProps> = ({
);
};

const MusicContentSkeleton: React.FC = () => {
return (
<View style={styles.musicContent}>
<View style={{ flexDirection: "row", gap: 4 }}>
<View
style={{
width: 256 + Math.random() * 100,
height: 19,
backgroundColor: "#E6E6E6",
...styles.title,
}}
/>
</View>
<View
style={{
width: 128 + Math.random() * 70,
height: 19,
backgroundColor: "#E6E6E6",
...styles.artists,
}}
/>
</View>
);
};

MusicContent.Skeleton = MusicContentSkeleton;

const MusicActions: React.FC = () => {
return (
<View
Expand Down

0 comments on commit 154c49f

Please sign in to comment.