From 7de2046e5ca0fc2e96910289c7c6b7c7e34c5a7b Mon Sep 17 00:00:00 2001 From: Kyle Ramachandran Date: Mon, 15 Apr 2024 16:30:59 -0700 Subject: [PATCH] working on recently viewed --- src/app/(tabs)/home/index.tsx | 42 +++++++++++++++++++++++++++++++--- src/queries/recommendations.js | 42 ---------------------------------- src/queries/stories.tsx | 35 ++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 47 deletions(-) delete mode 100644 src/queries/recommendations.js diff --git a/src/app/(tabs)/home/index.tsx b/src/app/(tabs)/home/index.tsx index 871b0ee..e7cc41b 100644 --- a/src/app/(tabs)/home/index.tsx +++ b/src/app/(tabs)/home/index.tsx @@ -7,6 +7,7 @@ import styles from './styles'; import Icon from '../../../../assets/icons'; import ContentCard from '../../../components/ContentCard/ContentCard'; import PreviewCard from '../../../components/PreviewCard/PreviewCard'; +import AsyncStorage from '@react-native-async-storage/async-storage'; import { fetchUsername } from '../../../queries/profiles'; import { fetchFeaturedStoriesDescription, @@ -14,7 +15,7 @@ import { fetchNewStories, fetchRecommendedStories, } from '../../../queries/stories'; -import { StoryCard, StoryPreview } from '../../../queries/types'; +import { StoryCard, StoryPreview, Story } from '../../../queries/types'; import globalStyles from '../../../styles/globalStyles'; import { useSession } from '../../../utils/AuthContext'; @@ -23,12 +24,33 @@ function HomeScreen() { const [username, setUsername] = useState(''); const [loading, setLoading] = useState(true); const [featuredStories, setFeaturedStories] = useState([]); + const [recentlyViewed, setRecentlyViewed] = useState([]); const [featuredStoriesDescription, setFeaturedStoriesDescription] = useState(''); const [recommendedStories, setRecommendedStories] = useState([]); const [newStories, setNewStories] = useState([]); + const setRecentStory = async (recentStories: StoryPreview[]) => { + try { + const jsonValue = JSON.stringify(recentStories); + await AsyncStorage.setItem('GWN_RECENT_STORIES_ARRAY', jsonValue); + } catch (error) { + console.log(error); + } + }; + useEffect(() => { + const getRecentStory = async () => { + try { + const jsonValue = await AsyncStorage.getItem( + 'GWN_RECENT_STORIES_ARRAY', + ); + return jsonValue != null ? JSON.parse(jsonValue) : []; + } catch (error) { + console.log(error); + } + }; + (async () => { const [ usernameResponse, @@ -36,24 +58,38 @@ function HomeScreen() { featuredStoryDescriptionResponse, recommendedStoriesResponse, newStoriesResponse, + recentStoryResponse, ] = await Promise.all([ fetchUsername(user?.id).catch(() => ''), fetchFeaturedStoryPreviews().catch(() => []), fetchFeaturedStoriesDescription().catch(() => ''), - fetchRecommendedStories().catch(() => []), + fetchRecommendedStories(recentlyViewed).catch(() => []), fetchNewStories().catch(() => []), + getRecentStory(), ]); - setUsername(usernameResponse); setFeaturedStories(featuredStoryResponse); setFeaturedStoriesDescription(featuredStoryDescriptionResponse); setRecommendedStories(recommendedStoriesResponse); setNewStories(newStoriesResponse); + setRecentlyViewed(recentStoryResponse); })().finally(() => { setLoading(false); + async () => { + const recommendedStoriesResponse = await fetchRecommendedStories( + recentlyViewed, + ).catch(() => []); + setRecommendedStories(recommendedStoriesResponse); + }; }); }, [user]); + // useEffect(() => { + // (async () => { + + // }) + // }, [recentlyViewed]) + return ( { - await pipeline('feature-extraction', 'Supabase/gte-small'); -}; - -// Generate the embedding from the user input -const generateEmbedding = async text => { - const output = await pipe(text, { - pooling: 'mean', - normalize: true, - }); - - // Extract the embedding output - return Array.from(output.data); -}; - -const getStories = () => { - return supabase.from('stories').select('*').is('embedding', null); -}; - -const addStoryEmbedding = async story => { - const embedding = await generateEmbedding(story.title); - await supabase.from('stories').update({ embedding }).eq('id', story.id); - console.log('Generated embeddings for story: ', story.id); -}; - -const processAllStories = async () => { - const { data: stories } = await getStories(); - - if (!stories?.length) { - return; - } - await Promise.all(stories.map(story => addStoryEmbedding(story))); - processAllStories(); -}; - -processAllStories(); diff --git a/src/queries/stories.tsx b/src/queries/stories.tsx index 86747ad..c2fee41 100644 --- a/src/queries/stories.tsx +++ b/src/queries/stories.tsx @@ -1,5 +1,7 @@ import { Story, StoryPreview, StoryCard } from './types'; +import AsyncStorage from '@react-native-async-storage/async-storage'; import supabase from '../utils/supabase'; +import { useState } from 'react'; export async function fetchAllStoryPreviews(): Promise { const { data, error } = await supabase.rpc('fetch_all_story_previews'); @@ -57,8 +59,37 @@ export async function fetchFeaturedStoriesDescription(): Promise { } } -export async function fetchRecommendedStories(): Promise { - const { data, error } = await supabase.rpc('fetch_recommended_stories'); +export async function fetchRecommendedStories( + recentlyViewed: StoryCard[], +): Promise { + const recentlyViewedID = recentlyViewed[0].id; //change to take in multiple stories + + const getStoryEmbedding = async () => { + const { data } = await supabase + .from('stories') + .select('embedding') + .eq('id', recentlyViewedID); + + if (error) { + console.log(error); + throw new Error( + `An error occured when trying to fetch embeddings: ${error.details}`, + ); + } else { + if (data) return data[0].embedding as number; + } + }; + + const embedding = await getStoryEmbedding(); + + const { data, error } = await supabase.rpc( + 'fetch_users_recommended_stories', + { + query_embedding: embedding, + match_threshold: 0.0, + match_count: 5, + }, + ); if (error) { console.log(error);