Sooo... i'm doing this thing haha. Is this good or bad!
So i've come up with a pretty "dynamic" way to render my video feed and though id share, and hopefully hear some thoughts and maybe get some feedback?
feed.tsx
// ... imports
const categories = ['diy', 'kunst', 'sport', 'science', 'natur', 'mad', 'viden'] as const
type CategorizedVideos<T extends string> =
| {
[K in T]?: VideoEnriched[]
}
| undefined
const titleDictionary = {
diy: 'DIY 🛠️',
kunst: 'Kunst 🎨',
sport: 'Sport ⚽️',
science: 'Science 🧬',
natur: 'Natur 🌳',
mad: 'Mad 🥘',
viden: 'Viden 🧠',
}
export function HomeScreen() {
const isWeb = Platform.OS === 'web'
const highlightedVideos = useQuery(api.videos.queries.listByHighlighted)
const videos: CategorizedVideos<(typeof categories)[number]> = useQuery(
api.videos.queries.getByCategories,
{
categories: ['diy', 'kunst'],
}
)
return (
<YStack>
<ScrollView p="$3" pr="$0" showsVerticalScrollIndicator={false}>
<YStack space="$1">
<H4>Vi anbefaler 🌟</H4>
<VideoCarousel height={300} videos={shuffle(highlightedVideos)} />
</YStack>
{categories.map((category) => (
<YStack space="$1">
<H4>{titleDictionary[category]}</H4>
<VideoCarousel height={240} videos={shuffle(videos?.[`${category}`])} />
</YStack>
))}
</ScrollView>
</YStack>
)
}
function shuffle(array: VideoEnriched[] | undefined) {
if (!array) return []
let currentIndex = array.length,
randomIndex
// While there remain elements to shuffle.
while (currentIndex > 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex)
currentIndex--
// And swap it with the current element.
;[array[currentIndex], array[randomIndex]] = [array[randomIndex]!, array[currentIndex]!]
}
return array
}
// ... imports
const categories = ['diy', 'kunst', 'sport', 'science', 'natur', 'mad', 'viden'] as const
type CategorizedVideos<T extends string> =
| {
[K in T]?: VideoEnriched[]
}
| undefined
const titleDictionary = {
diy: 'DIY 🛠️',
kunst: 'Kunst 🎨',
sport: 'Sport ⚽️',
science: 'Science 🧬',
natur: 'Natur 🌳',
mad: 'Mad 🥘',
viden: 'Viden 🧠',
}
export function HomeScreen() {
const isWeb = Platform.OS === 'web'
const highlightedVideos = useQuery(api.videos.queries.listByHighlighted)
const videos: CategorizedVideos<(typeof categories)[number]> = useQuery(
api.videos.queries.getByCategories,
{
categories: ['diy', 'kunst'],
}
)
return (
<YStack>
<ScrollView p="$3" pr="$0" showsVerticalScrollIndicator={false}>
<YStack space="$1">
<H4>Vi anbefaler 🌟</H4>
<VideoCarousel height={300} videos={shuffle(highlightedVideos)} />
</YStack>
{categories.map((category) => (
<YStack space="$1">
<H4>{titleDictionary[category]}</H4>
<VideoCarousel height={240} videos={shuffle(videos?.[`${category}`])} />
</YStack>
))}
</ScrollView>
</YStack>
)
}
function shuffle(array: VideoEnriched[] | undefined) {
if (!array) return []
let currentIndex = array.length,
randomIndex
// While there remain elements to shuffle.
while (currentIndex > 0) {
// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex)
currentIndex--
// And swap it with the current element.
;[array[currentIndex], array[randomIndex]] = [array[randomIndex]!, array[currentIndex]!]
}
return array
}
1 Reply
The query:
Just curious what peoples opinion are on doing this over a more "static" approach. I feel like i def like the dynamic approach im going with here. But the more dynamic stuff get, the more i feel like im walking on thin ice haha. But that might just be me.
Ohh and btw, this is super much for testing and fun right now. There is obviously the whole aspect of if we were to return a very large amount videos. That would probably introduce and issue
export const getByCategories = query({
args: { categories: v.array(v.string()) },
handler: async (ctx, { categories }) => {
const categorizedVideos: { [key: string]: VideoEnriched[] | undefined } = {}
for (const category of categories) {
const videos = await ctx.db
.query('videos')
.filter((q) => q.eq(q.field('category'), category))
.order('desc')
.collect()
categorizedVideos[category] =
videos.length > 0
? await Promise.all(videos.map((video) => enrichVideo(ctx, video)))
: undefined
}
return categorizedVideos
},
})
export const getByCategories = query({
args: { categories: v.array(v.string()) },
handler: async (ctx, { categories }) => {
const categorizedVideos: { [key: string]: VideoEnriched[] | undefined } = {}
for (const category of categories) {
const videos = await ctx.db
.query('videos')
.filter((q) => q.eq(q.field('category'), category))
.order('desc')
.collect()
categorizedVideos[category] =
videos.length > 0
? await Promise.all(videos.map((video) => enrichVideo(ctx, video)))
: undefined
}
return categorizedVideos
},
})