Skip to content

Commit

Permalink
😹 Categorized content on home view (Joystream#6414)
Browse files Browse the repository at this point in the history
* Adjust toggle button group

* Rework homeview

* Adjust config for testing

* Bring back language filtering

* Add new categories

* Shuffle the categories and add analytics

* Remove some categories after the testing

* Revert "Adjust config for testing"

This reverts commit 885464f.
  • Loading branch information
ikprk committed Jul 22, 2024
1 parent 6ec0a9f commit 0d71114
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,13 @@ export type ToggleButtonFilterTypeProps = {
filters: FilterButtonProps[]
} & SharedToggleButtonProps

export type ToggleButtonGroupProps<T = string> = ToggleButtonFilterTypeProps | ToggleButtonOptionTypeProps<T>
export type ToggleButtonGroupProps<T = string> =
| {
size?: 'small' | 'medium' | 'large'
} & (ToggleButtonFilterTypeProps | ToggleButtonOptionTypeProps<T>)

export function ToggleButtonGroup<T = string>(props: ToggleButtonGroupProps<T>) {
const { type, label, width = 'auto', className } = props
const { type, label, width = 'auto', className, size = 'small' } = props
const optionWrapperRef = useRef<HTMLDivElement>(null)

const { handleArrowScroll, handleMouseDown, isOverflow, visibleShadows } = useHorizonthalFade(optionWrapperRef)
Expand Down Expand Up @@ -74,7 +77,7 @@ export function ToggleButtonGroup<T = string>(props: ToggleButtonGroupProps<T>)
fullWidth
variant={option.value !== props.value ? 'tertiary' : 'secondary'}
onClick={() => props.onChange(option.value)}
size="small"
size={size}
disabled={option.disabled}
>
{option.label}
Expand Down
4 changes: 2 additions & 2 deletions packages/atlas/src/config/contentFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ export const cancelledVideoFilter: VideoWhereInput = {
},
}

// const browserLanguage = navigator.language?.split('-')[0]
const browserLanguage = navigator.language?.split('-')[0]

export const singlePublicCryptoVideoFilter: VideoWhereInput = {
isPublic_eq: true,
isCensored_eq: false,
// orionLanguage_in: [...(browserLanguage ? [browserLanguage] : []), 'en'],
orionLanguage_in: [...(browserLanguage ? [browserLanguage] : []), 'en'],
media: {
isAccepted_eq: true,
},
Expand Down
11 changes: 11 additions & 0 deletions packages/atlas/src/hooks/useSegmentAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ export const useSegmentAnalytics = () => {
[analytics]
)

const trackHomepageCategorySelection = useCallback(
(categoryName: string) => {
analytics.track('Homepage Category Clicked', {
categoryName,
...getUTMParams(),
})
},
[analytics, getUTMParams]
)

const trackMembershipCreation = useCallback(
(handle: string, email: string) => {
analytics.track('Membership created', {
Expand Down Expand Up @@ -703,5 +713,6 @@ export const useSegmentAnalytics = () => {
trackRewardsReferralLinkClicked,
trackRoundtableEventsClicked,
trackRewardsCreateChannelButtonClick,
trackHomepageCategorySelection,
}
}
126 changes: 123 additions & 3 deletions packages/atlas/src/views/viewer/HomeView.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,141 @@
import styled from '@emotion/styled'
import { FC } from 'react'
import { shuffle } from 'lodash-es'
import { FC, useCallback } from 'react'
import { useSearchParams } from 'react-router-dom'

import { VideoOrderByInput } from '@/api/queries/__generated__/baseTypes.generated'
import {
GetBasicVideosConnectionLightweightDocument,
useGetCuratedHompageVideosQuery,
} from '@/api/queries/__generated__/videos.generated'
import { Section } from '@/components/Section/Section'
import { ToggleButtonGroup } from '@/components/_inputs/ToggleButtonGroup'
import { ReferralsBanner } from '@/components/_referrals/ReferralsBanner/ReferralsBanner'
import { VideoContentTemplate } from '@/components/_templates/VideoContentTemplate'
import { VideoTileViewer } from '@/components/_video/VideoTileViewer'
import { atlasConfig } from '@/config'
import { getPublicCryptoVideoFilter } from '@/config/contentFilter'
import { useHeadTags } from '@/hooks/useHeadTags'
import { useInfiniteVideoGrid } from '@/hooks/useInfiniteVideoGrid'
import { useSegmentAnalytics } from '@/hooks/useSegmentAnalytics'
import { useVideoGridRows } from '@/hooks/useVideoGridRows'
import { DEFAULT_VIDEO_GRID, sizes } from '@/styles'
import { createPlaceholderData } from '@/utils/data'
import { InfiniteLoadingOffsets } from '@/utils/loading.contants'

const _options = [
{
label: 'Crypto',
configLabel: 'Crypto',
value: '5',
queryValue: atlasConfig.content.categories.find((category) => category.name === 'Crypto')?.videoCategories ?? [],
},
{
label: 'Entertainment',
configLabel: 'Entertainment',
value: '8',
queryValue:
atlasConfig.content.categories.find((category) => category.name === 'Entertainment')?.videoCategories ?? [],
},
{
label: 'Gaming',
configLabel: 'Video Games',
value: '20',
queryValue:
atlasConfig.content.categories.find((category) => category.name === 'Video Games')?.videoCategories ?? [],
},
{
label: 'Music',
configLabel: 'Music and Music Videos',
value: '11',
queryValue:
atlasConfig.content.categories.find((category) => category.name === 'Music and Music Videos')?.videoCategories ??
[],
},
{
label: 'Blogs',
configLabel: 'People and Blogs',
value: '14',
queryValue:
atlasConfig.content.categories.find((category) => category.name === 'People and Blogs')?.videoCategories ?? [],
},
{
label: 'Animation',
configLabel: 'Animation and Film',
value: '2',
queryValue:
atlasConfig.content.categories.find((category) => category.name === 'Animation and Film')?.videoCategories ?? [],
},
{
label: 'Technology',
configLabel: 'Technology',
value: '17',
queryValue:
atlasConfig.content.categories.find((category) => category.name === 'Technology')?.videoCategories ?? [],
},
{
label: 'Art',
configLabel: 'Art',
value: '1',
queryValue: atlasConfig.content.categories.find((category) => category.name === 'Art')?.videoCategories ?? [],
},
{
label: 'Memes',
configLabel: 'Memes and Humour',
value: '10',
queryValue:
atlasConfig.content.categories.find((category) => category.name === 'Memes and Humour')?.videoCategories ?? [],
},
]

const options = [
...shuffle(_options),
{
label: 'Other',
value: 'other',
queryValue:
atlasConfig.content.categories
.filter(
(category) =>
!_options.reduce((prev, next) => [...prev, next.configLabel], [] as string[]).includes(category.name)
)
.map((cat) => cat.videoCategories)
.flat() ?? [],
},
]

export const HomeView: FC = () => {
const headTags = useHeadTags()
const { columns, fetchMore, tiles, loading, pageInfo } = useHomeVideos()
const [searchParams, setSearchParams] = useSearchParams()
const category = searchParams.get('category') ?? options[0].value
const { columns, fetchMore, tiles, loading, pageInfo } = useHomeVideos(
options.find((opt) => opt.value === category)?.queryValue
)
const { trackHomepageCategorySelection } = useSegmentAnalytics()

const setCategory = useCallback(
(value: string) => {
const categoryLabel = options.find((category) => category.value === value)?.label
if (categoryLabel) {
trackHomepageCategorySelection(categoryLabel)
}

setSearchParams({ category: value })
},
[setSearchParams, trackHomepageCategorySelection]
)

return (
<VideoContentTemplate>
<ReferralsBanner />
{headTags}
<StyledToggleButtonGroup
size="medium"
value={category}
type="options"
onChange={(newCategory) => setCategory(newCategory as string)}
options={options}
/>
<StyledSection
contentProps={{
type: 'grid',
Expand Down Expand Up @@ -54,14 +164,21 @@ const StyledSection = styled(Section)`
padding: ${sizes(8)} 0;
`

const useHomeVideos = () => {
const StyledToggleButtonGroup = styled(ToggleButtonGroup)`
margin-top: ${sizes(8)};
`

const useHomeVideos = (categories?: string[]) => {
const initialRowsToLoad = useVideoGridRows('main')
const { data, loading } = useGetCuratedHompageVideosQuery({
notifyOnNetworkStatusChange: true,
variables: {
where: getPublicCryptoVideoFilter({
orionLanguage_in: undefined,
includeInHomeFeed_eq: true,
category: {
id_in: categories,
},
}),
skipVideoIds: ['-1'],
},
Expand All @@ -72,6 +189,9 @@ const useHomeVideos = () => {
variables: {
where: getPublicCryptoVideoFilter({
id_not_in: avoidIds,
category: {
id_in: categories,
},
}),
orderBy: VideoOrderByInput.VideoRelevanceDesc,
},
Expand Down

0 comments on commit 0d71114

Please sign in to comment.