Skip to content

Commit

Permalink
feat: adding loading status (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangvu12 authored Feb 3, 2024
1 parent 0ce361a commit 54665be
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useAtomValue, useSetAtom } from 'jotai/react';
import { RotateCwIcon } from 'lucide-react-native';
import React, { useEffect, useMemo } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import { Else, If, Then } from 'react-if';

import { type FragmentType, graphql, useFragment } from '@/gql';
Expand Down Expand Up @@ -38,8 +38,15 @@ const EpisodeContainer: React.FC<EpisodeContainerProps> = ({
}) => {
const media = useFragment(EpisodeContainerFragment, mediaFragment);
const currentModuleId = useAtomValue(currentModuleIdAtom);

const { data, isLoading, isRefetching, refetch } = useEpisodes(media);
const [episodeFetchingStatus, setEpisodeFetchingStatus] = useState<{
isError: boolean;
status: string;
}>({ isError: false, status: '' });

const { data, isLoading, isRefetching, refetch } = useEpisodes(
media,
setEpisodeFetchingStatus
);
const setSectionEpisodes = useSetAtom(sectionEpisodesAtom);
const setEpisodeChunk = useSetAtom(episodeChunkAtom);

Expand Down Expand Up @@ -106,15 +113,23 @@ const EpisodeContainer: React.FC<EpisodeContainerProps> = ({
<Then>
<View className="mt-8">
<ActivityIndicator color={colors.primary[500]} size={48} />

{!episodeFetchingStatus.isError && (
<Text className="mt-2 text-center font-semibold text-gray-300">
{episodeFetchingStatus.status}
</Text>
)}
</View>
</Then>

<Else>
<If condition={!data?.length}>
<Then>
<Text className="text-center">
There are no episodes for this anime
</Text>
{episodeFetchingStatus.isError && (
<Text className="text-center">
{episodeFetchingStatus.status}
</Text>
)}
</Then>

<Else>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,33 +34,47 @@ export const useAnimeEpisodeFragment = graphql(`
`);

const useEpisodes = (
mediaFragment: FragmentType<typeof useAnimeEpisodeFragment>
mediaFragment: FragmentType<typeof useAnimeEpisodeFragment>,
onStatusChange?: (change: { isError: boolean; status: string }) => void
) => {
const media = useFragment(useAnimeEpisodeFragment, mediaFragment);

const { data, isLoading: isAnimeIdLoading } = useAnimeId(media);
const { data: animeId, isLoading: isAnimeIdLoading } = useAnimeId(media);

const queryKey = ['episodes', media.id];

if (data?.data) {
queryKey.push(data.data);
if (animeId?.data) {
queryKey.push(animeId.data);
}

const episodes = useWebViewData(
queryKey,
async (webview) => {
if (!data?.data) {
onStatusChange?.({ isError: false, status: 'Loading anime id' });

if (!animeId?.data) {
if (isAnimeIdLoading) {
onStatusChange?.({ isError: false, status: 'Loading anime id' });
} else {
onStatusChange?.({ isError: true, status: 'Cannot find anime id' });
}

return [];
}

const nonValidatedEpisodesPromise = webview.sendMessage<Episode[]>(
'anime.getEpisodes',
{
animeId: data?.data,
extraData: data?.extraData,
animeId: animeId?.data,
extraData: animeId?.extraData,
}
);

onStatusChange?.({
isError: false,
status: 'Loading episodes',
});

const metadataEpisodesPromise = getEpisodeInfo(media);

const [nonValidatedEpisodesResult, metadataEpisodesResult] =
Expand All @@ -70,6 +84,11 @@ const useEpisodes = (
]);

if (nonValidatedEpisodesResult.status === 'rejected') {
onStatusChange?.({
isError: true,
status: 'Cannot find episodes',
});

return [];
}

Expand All @@ -78,10 +97,9 @@ const useEpisodes = (
.safeParse(nonValidatedEpisodesResult.value);

if (!validation.success) {
Toast.show({
type: 'error',
text1: 'Cannot find episodes',
text2: validation.error.message,
onStatusChange?.({
isError: true,
status: 'Cannot find episodes',
});

return [];
Expand Down Expand Up @@ -117,8 +135,6 @@ const useEpisodes = (
};
});

console.log('episodes', episodes);

return episodes;
},

Expand All @@ -130,7 +146,6 @@ const useEpisodes = (
text2: err,
});
},
enabled: !isAnimeIdLoading,
retry: 0,

// For some reason, when calling useEpisodes in watch screen, it will return empty episodes
Expand Down
20 changes: 16 additions & 4 deletions src/screens/anime/watch/components/error-message.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { useNavigation } from '@react-navigation/native';
import { ArrowLeft, RefreshCcw } from 'lucide-react-native';
import React from 'react';

import { Button, Text, View } from '@/ui';
import Sticker from '@/ui/sticker';

interface ErrorMessageProps {
message: string;
onRetry?: () => void;
}

const ErrorMessage: React.FC<ErrorMessageProps> = ({ message }) => {
const ErrorMessage: React.FC<ErrorMessageProps> = ({ message, onRetry }) => {
const navigation = useNavigation();

const handleGoBack = () => {
Expand All @@ -25,9 +27,19 @@ const ErrorMessage: React.FC<ErrorMessageProps> = ({ message }) => {

<Text>{message}</Text>

<Button className="mt-2" onPress={handleGoBack}>
<Text>Go back</Text>
</Button>
<View className="mt-2 flex flex-row items-center space-x-2">
<Button onPress={handleGoBack}>
<ArrowLeft size={16} style={{ color: 'white' }} />

<Text>Go back</Text>
</Button>

<Button className="bg-gray-600" onPress={onRetry}>
<RefreshCcw size={16} style={{ color: 'white' }} />

<Text className="ml-2">Retry</Text>
</Button>
</View>
</View>
);
};
Expand Down
27 changes: 23 additions & 4 deletions src/screens/anime/watch/components/media-container.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useSetAtom } from 'jotai/react';
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';

import type { FragmentType } from '@/gql';
import { ActivityIndicator, View } from '@/ui';
import { ActivityIndicator, Text, View } from '@/ui';
import colors from '@/ui/theme/colors';

import type { useAnimeEpisodeFragment } from '../../details/screens/episode-screen/hooks/use-episodes';
Expand All @@ -29,6 +29,11 @@ const MediaContainer: React.FC<MediaContainerProps> = ({
const setMediaId = useSetAtom(mediaIdAtom);
const setIsAdult = useSetAtom(isAdultAtom);

const [episodeFetchingStatus, setEpisodeFetchingStatus] = useState<{
isError: boolean;
status: string;
}>({ isError: false, status: '' });

useEffect(() => {
setMediaId({
anilistId,
Expand All @@ -40,18 +45,32 @@ const MediaContainer: React.FC<MediaContainerProps> = ({
setIsAdult(isAdult);
}, [setIsAdult, isAdult]);

const { data, isLoading } = useEpisodes(mediaFragment);
const { data, isLoading, refetch } = useEpisodes(
mediaFragment,
setEpisodeFetchingStatus
);

if (isLoading) {
return (
<View className="flex h-full w-full flex-1 items-center justify-center">
<ActivityIndicator color={colors.primary[500]} size={48} />

{!episodeFetchingStatus.isError && (
<Text className="mt-2 text-center font-semibold text-gray-300">
{episodeFetchingStatus.status}
</Text>
)}
</View>
);
}

if (!data?.length) {
return <ErrorMessage message="Cannot find episodes. Please try again" />;
return (
<ErrorMessage
onRetry={refetch}
message="Cannot find episodes. Please try again"
/>
);
}

return (
Expand Down
4 changes: 4 additions & 0 deletions src/screens/anime/watch/components/player-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ const PlayerContainer: React.FC<PlayerContainerProps> = ({
{isLoading || isServerLoading ? (
<View className="absolute z-10 flex h-full w-full items-center justify-center whitespace-pre-wrap">
<ActivityIndicator size={48} color={colors.primary[500]} />

<Text className="mt-2 text-center font-semibold text-gray-300">
{isLoading ? 'Loading video...' : 'Loading server...'}
</Text>
</View>
) : null}

Expand Down
12 changes: 9 additions & 3 deletions src/screens/anime/watch/components/servers-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ const ServersContainer: React.FC<ServersContainerProps> = ({
const setServers = useSetAtom(serversAtom);
const [currentServer, setCurrentServer] = useAtom(currentServerAtom);

const { data: videoServers, isLoading: videoServersLoading } =
useLoadVideoServers(currentEpisode.id, currentEpisode.extra || undefined);
const {
data: videoServers,
isLoading: videoServersLoading,
refetch,
} = useLoadVideoServers(currentEpisode.id, currentEpisode.extra || undefined);

useEffect(() => {
if (!videoServers?.length) {
Expand All @@ -35,7 +38,10 @@ const ServersContainer: React.FC<ServersContainerProps> = ({

if (!videoServers?.length && !videoServersLoading)
return (
<ErrorMessage message="Cannot find video servers. Please try again" />
<ErrorMessage
onRetry={refetch}
message="Cannot find video servers. Please try again"
/>
);

return (
Expand Down

0 comments on commit 54665be

Please sign in to comment.