Skip to content

Commit

Permalink
refactor: Add watch history and preference page
Browse files Browse the repository at this point in the history
  • Loading branch information
himanshu8443 committed Aug 2, 2024
1 parent 5051ef0 commit 9f90f7c
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 71 deletions.
3 changes: 3 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import About, {checkForUpdate} from './screens/settings/About';
import {MMKV} from './lib/Mmkv';
import BootSplash from 'react-native-bootsplash';
import {enableFreeze, enableScreens} from 'react-native-screens';
import Preferences from './screens/settings/Preference';

enableScreens(true);
enableFreeze(true);
Expand Down Expand Up @@ -60,6 +61,7 @@ export type SettingsStackParamList = {
Settings: undefined;
DisableProviders: undefined;
About: undefined;
Preferences: undefined;
};
const Tab = createBottomTabNavigator();
const App = () => {
Expand Down Expand Up @@ -135,6 +137,7 @@ const App = () => {
component={DisableProviders}
/>
<SettingsStack.Screen name="About" component={About} />
<SettingsStack.Screen name="Preferences" component={Preferences} />
</SettingsStack.Navigator>
);
}
Expand Down
16 changes: 16 additions & 0 deletions src/components/SeasonList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,26 @@ import {manifest} from '../lib/Manifest';
import SharedGroupPreferences from 'react-native-shared-group-preferences';
import RNReactNativeHapticFeedback from 'react-native-haptic-feedback';
import Feather from '@expo/vector-icons/Feather';
import useWatchHistoryStore from '../lib/zustand/watchHistrory';

const SeasonList = ({
LinkList,
poster,
metaTitle,
providerValue,
refreshing,
routeParams,
}: {
LinkList: Link[];
poster: string;
metaTitle: string;
providerValue: string;
refreshing?: boolean;
routeParams: Readonly<{
link: string;
provider?: string;
poster?: string;
}>;
}) => {
const navigation =
useNavigation<NativeStackNavigationProp<RootStackParamList>>();
Expand All @@ -57,6 +64,8 @@ const SeasonList = ({
LinkList[0],
);

const {addItem} = useWatchHistoryStore(state => state);

useEffect(() => {
const fetchList = async () => {
if (!ActiveSeason?.episodesLink) {
Expand Down Expand Up @@ -158,7 +167,14 @@ const SeasonList = ({
return;
}
};

const playHandler = async ({link, type, title, file}: playHandlerProps) => {
addItem({
link: routeParams.link,
title: metaTitle,
image: routeParams.poster!,
provider: providerValue,
});
const externalPlayer = MMKV.getString('externalPlayer');
const downloaded = await ifExists(file);
if (externalPlayer && !downloaded) {
Expand Down
67 changes: 49 additions & 18 deletions src/components/Slider.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {Image, Text, TouchableOpacity, View} from 'react-native';
import {Image, Pressable, Text, TouchableOpacity, View} from 'react-native';
import React from 'react';
import type {Post} from '../lib/providers/types';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
import {useNavigation} from '@react-navigation/native';
import {HomeStackParamList} from '../App';
import {Skeleton} from 'moti/skeleton';
import useContentStore from '../lib/zustand/contentStore';
import {FlashList} from '@shopify/flash-list';
import SkeletonLoader from './Skeleton';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import AntDesign from '@expo/vector-icons/AntDesign';
import useWatchHistoryStore from '../lib/zustand/watchHistrory';

export default function Slider({
isLoading,
Expand All @@ -25,21 +27,25 @@ export default function Slider({
const {provider} = useContentStore(state => state);
const navigation =
useNavigation<NativeStackNavigationProp<HomeStackParamList>>();
const [isSelected, setSelected] = React.useState('');
const {removeItem} = useWatchHistoryStore(state => state);

return (
<View className="gap-3 mt-7">
<Pressable onPress={() => setSelected('')} className="gap-3 mt-7">
<View className="flex flex-row items-center justify-between px-2">
<Text className="text-2xl text-primary font-semibold">{title}</Text>
<TouchableOpacity
onPress={() =>
navigation.navigate('ScrollList', {
title: title,
filter: filter,
providerValue: providerValue,
})
}>
<Text className="text-white text-sm">more</Text>
</TouchableOpacity>
{filter && (
<TouchableOpacity
onPress={() =>
navigation.navigate('ScrollList', {
title: title,
filter: filter,
providerValue: providerValue,
})
}>
<Text className="text-white text-sm">more</Text>
</TouchableOpacity>
)}
</View>
{isLoading ? (
<View className="flex flex-row gap-2 overflow-hidden">
Expand All @@ -57,18 +63,29 @@ export default function Slider({
estimatedItemSize={30}
showsHorizontalScrollIndicator={false}
data={posts}
extraData={isSelected}
horizontal
contentContainerStyle={{paddingHorizontal: 3, paddingTop: 7}}
renderItem={({item}) => (
<View className="flex flex-col mx-2">
<TouchableOpacity
onPress={() =>
onLongPress={e => {
e.stopPropagation();
ReactNativeHapticFeedback.trigger('effectClick', {
enableVibrateFallback: true,
ignoreAndroidSystemSettings: false,
});
setSelected(item.link);
}}
onPress={e => {
e.stopPropagation();
setSelected('');
navigation.navigate('Info', {
link: item.link,
provider: providerValue || provider?.value,
provider: item.provider || providerValue || provider?.value,
poster: item?.image,
})
}>
});
}}>
<Image
className="rounded-md"
source={{
Expand All @@ -78,6 +95,20 @@ export default function Slider({
}}
style={{width: 100, height: 150}}
/>
{isSelected === item.link && (
<View className="absolute top-0 left-0 w-full h-full bg-black/50 flex justify-center items-center z-50">
<AntDesign
name="delete"
size={24}
color="white"
onPress={() => {
console.log('remove', item);
setSelected('');
removeItem(item);
}}
/>
</View>
)}
</TouchableOpacity>
<Text className="text-white text-center truncate w-24 text-xs">
{item.title.length > 24
Expand All @@ -98,6 +129,6 @@ export default function Slider({
keyExtractor={item => item.link}
/>
)}
</View>
</Pressable>
);
}
7 changes: 1 addition & 6 deletions src/lib/getHomepagedata.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import {Content} from './zustand/contentStore';
import {manifest} from './Manifest';

export interface Post {
title: string;
link: string;
image: string;
}
import {Post} from './providers/types';

export interface HomePageData {
title: string;
Expand Down
1 change: 1 addition & 0 deletions src/lib/providers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export interface Post {
title: string;
link: string;
image: string;
provider?: string;
}

// getStream
Expand Down
2 changes: 1 addition & 1 deletion src/lib/zustand/herostore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {create} from 'zustand';
import {Post} from '../providers/vega/getPosts';
import {Post} from '../providers/types';

export interface Hero {
hero: Post;
Expand Down
35 changes: 35 additions & 0 deletions src/lib/zustand/watchHistrory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {create} from 'zustand';
import {Post} from '../providers/types';
import {MMKV} from '../Mmkv';
export interface History {
history: Post[];
removeItem: (item: Post) => void;
addItem: (item: Post) => void;
clearHistory: () => void;
}
const showWatchHistory = MMKV.getBool('showRecentlyWatched');

const useWatchHistoryStore = create<History>(set => ({
history: JSON.parse(MMKV.getString('recentlyWatched') || '[]'),
removeItem: item => {
const history = JSON.parse(MMKV.getString('recentlyWatched') || '[]');
const newHistory = history.filter((i: Post) => i.link !== item.link);
MMKV.setString('recentlyWatched', JSON.stringify(newHistory));
set({history: newHistory});
},
addItem: item => {
if (showWatchHistory) {
const history = JSON.parse(MMKV.getString('recentlyWatched') || '[]');
const newHistory = history.filter((i: Post) => i.link !== item.link);
newHistory.unshift(item);
MMKV.setString('recentlyWatched', JSON.stringify(newHistory));
set({history: newHistory});
}
},
clearHistory: () => {
MMKV.setString('recentlyWatched', '[]');
set({history: []});
},
}));

export default useWatchHistoryStore;
13 changes: 12 additions & 1 deletion src/screens/home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,24 @@ import React, {useEffect, useState} from 'react';
import Hero from '../../components/Hero';
import {View} from 'moti';
import {getHomePageData, HomePageData} from '../../lib/getHomepagedata';
import {MmmkvCache} from '../../lib/Mmkv';
import {MMKV, MmmkvCache} from '../../lib/Mmkv';
import useContentStore from '../../lib/zustand/contentStore';
import useHeroStore from '../../lib/zustand/herostore';
import {manifest} from '../../lib/Manifest';
import notifee, {EventDetail, EventType} from '@notifee/react-native';
import RNFS from 'react-native-fs';
import useDownloadsStore from '../../lib/zustand/downloadsStore';
import {FFmpegKit} from 'ffmpeg-kit-react-native';
import useWatchHistoryStore from '../../lib/zustand/watchHistrory';

const Home = () => {
const [refreshing, setRefreshing] = useState(false);
const [homeData, setHomeData] = useState<HomePageData[]>([]);
const [loading, setLoading] = useState(true);
const [backgroundColor, setBackgroundColor] = useState('transparent');
const downloadStore = useDownloadsStore(state => state);
const recentlyWatched = useWatchHistoryStore(state => state).history;
const ShowRecentlyWatched = MMKV.getBool('showRecentlyWatched');

const {provider} = useContentStore(state => state);
const {setHero} = useHeroStore(state => state);
Expand Down Expand Up @@ -142,6 +145,14 @@ const Home = () => {
}>
<Hero />
<View className="p-4">
{!loading && recentlyWatched?.length > 0 && ShowRecentlyWatched && (
<Slider
isLoading={loading}
title={'Recently Watched'}
posts={recentlyWatched}
filter={''}
/>
)}
{loading
? manifest[provider.value].catalog.map((item, index) => (
<Slider
Expand Down
9 changes: 5 additions & 4 deletions src/screens/home/Info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,14 @@ export default function Info({route, navigation}: Props): React.JSX.Element {
{meta?.cast?.slice(0, 3).map((actor: string) => (
<Text
key={actor}
className="text-white text-xs bg-tertiary p-1 rounded-md">
className="text-white text-xs bg-tertiary p-1 rounded-sm">
{actor}
</Text>
))}
{info?.cast?.slice(0, 3).map((actor: string) => (
<Text
key={actor}
className="text-white text-xs bg-tertiary p-1 rounded-md">
className="text-white text-xs bg-tertiary p-1 rounded-sm">
{actor}
</Text>
))}
Expand All @@ -274,7 +274,7 @@ export default function Info({route, navigation}: Props): React.JSX.Element {
<Text className="text-white text-xl font-semibold">
Synopsis
</Text>
<Text className="text-white text-xs bg-tertiary p-1 px-2 rounded-md">
<Text className="text-white text-xs bg-tertiary p-1 px-2 rounded-sm">
{route.params.provider || provider.value}
</Text>
</View>
Expand Down Expand Up @@ -308,7 +308,7 @@ export default function Info({route, navigation}: Props): React.JSX.Element {
</View>
</View>
<Skeleton show={infoLoading} colorMode="dark" height={20}>
<Text className="text-white text-xs">
<Text className="text-white text-xs px-1">
{meta?.description
? meta?.description.length > 180
? meta?.description.slice(0, 180) + '...'
Expand Down Expand Up @@ -365,6 +365,7 @@ export default function Info({route, navigation}: Props): React.JSX.Element {
}
poster={meta?.logo || ''}
metaTitle={meta?.name || info?.title}
routeParams={route.params}
/>
)}
</View>
Expand Down
Loading

0 comments on commit 9f90f7c

Please sign in to comment.