Skip to content

Commit

Permalink
feat: add title to banis
Browse files Browse the repository at this point in the history
Restructure content templates

Closes #287
  • Loading branch information
Harjot1Singh committed Apr 20, 2024
1 parent 2d713ce commit ec46821
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 100 deletions.
38 changes: 38 additions & 0 deletions src/components/templates/Content/Bani/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useSuspenseQuery } from '@tanstack/react-query'
import { StyleSheet } from 'react-native'

import Container from '~/components/atoms/Container'
import GurmukhiLine from '~/components/molecules/GurmukhiLine'
import { baniQuery } from '~/services/data'
import { units } from '~/themes'

import Lines from '../Lines'

const styles = StyleSheet.create( {
header: {
textAlign: 'center',
fontSize: units.title1,
paddingTop: units.base * 2,
},
} )

type BaniProps = {
id: string,
}

const Bani = ( { id }: BaniProps ) => {
const { data } = useSuspenseQuery( baniQuery( id ) )

const header = <GurmukhiLine style={styles.header}>{data.nameGurmukhi}</GurmukhiLine>

return (
<Container>
<Lines
Header={() => header}
lines={data.lines}
/>
</Container>
)
}

export default Bani
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { toUnicode } from 'gurmukhi-utils'

import * as factories from '~/test/factories'

import DefaultLines from '.'
import GroupedLines from '.'

describe( '<DefaultLines />', () => {
describe( '<GroupedLines />', () => {
const lines = factories.line.buildList( 15 )

it( 'should render lines', () => {
render( <DefaultLines lines={lines} /> )
render( <GroupedLines lines={lines} /> )

expect( screen.queryByText( toUnicode( lines[ 0 ].gurmukhi ) ) ).toBeTruthy()
} )
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FlashList } from '@shopify/flash-list'
import { ComponentType } from 'react'
import { StyleSheet, View } from 'react-native'

import { units } from '~/themes'
Expand Down Expand Up @@ -30,14 +31,16 @@ const renderLine = ( { item: { gurmukhi, translations } }: RenderItem ) => (
)

export type NormalLinesProps = {
Header?: ComponentType,
lines: LineData[],
}

const NormalLines = ( { lines }: NormalLinesProps ) => (
const NormalLines = ( { lines, Header }: NormalLinesProps ) => (
<View style={styles.root}>
<FlashList
contentContainerStyle={styles.container}
keyExtractor={( { id } ) => id}
ListHeaderComponent={Header}
data={lines}
renderItem={renderLine}
estimatedItemSize={120}
Expand Down
37 changes: 37 additions & 0 deletions src/components/templates/Content/Lines/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { render, screen } from '@testing-library/react-native'

import { settings } from '~/services/settings'
import * as factories from '~/test/factories'
import AtomProvider from '~/test/providers/AtomProvider'

import Lines from '.'

describe( '<Lines />', () => {
describe( 'given reader mode is off', () => {
it( 'should load and render lines in grouped mode', () => {
const lines = factories.line.buildList( 15 )

render(
<AtomProvider initialValues={[ [ settings.readerMode, false ] ]}>
<Lines lines={lines} />
</AtomProvider>
)

expect( screen.queryByText( lines[ 0 ].translations[ 0 ].translation ) ).toBeTruthy()
} )
} )

describe( 'given reader mode is on', () => {
it( 'should load and render lines in reader mode', () => {
const lines = factories.line.buildList( 15 )

render(
<AtomProvider initialValues={[ [ settings.readerMode, true ] ]}>
<Lines lines={lines} />
</AtomProvider>
)

expect( screen.queryByText( lines[ 0 ].translations[ 0 ].translation ) ).toBeFalsy()
} )
} )
} )
22 changes: 22 additions & 0 deletions src/components/templates/Content/Lines/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentType } from 'react'

import { settings, useSetting } from '~/services/settings'
import { LineData } from '~/types/data'

import GroupedLines from '../GroupedLines'
import ReaderLines from '../ReaderLines'

type LinesProps = {
lines: LineData[],
Header?: ComponentType,
}

const Lines = ( { lines, Header }: LinesProps ) => {
const [ isReaderMode ] = useSetting( settings.readerMode )

return isReaderMode
? <ReaderLines lines={lines} Header={Header} />
: <GroupedLines lines={lines} Header={Header} />
}

export default Lines
6 changes: 4 additions & 2 deletions src/components/templates/Content/ReaderLines/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FlashList } from '@shopify/flash-list'
import { useMemo } from 'react'
import { ComponentType, useMemo } from 'react'
import { StyleSheet, View } from 'react-native'

import { getLineSections } from '~/helpers/lines'
Expand All @@ -19,14 +19,16 @@ const renderLineSection = ( { item }: RenderItem ) => <Section lines={item} />

export type ReaderLinesProps = {
lines: LineData[],
Header?: ComponentType,
}

const ReaderLines = ( { lines }: ReaderLinesProps ) => {
const ReaderLines = ( { lines, Header }: ReaderLinesProps ) => {
const groupedLines = useMemo( () => getLineSections( lines ), [ lines ] )

return (
<View style={styles.root}>
<FlashList
ListHeaderComponent={Header}
data={groupedLines}
renderItem={renderLineSection}
estimatedItemSize={200}
Expand Down
22 changes: 22 additions & 0 deletions src/components/templates/Content/Shabad/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useSuspenseQuery } from '@tanstack/react-query'

import Container from '~/components/atoms/Container'
import { shabadQuery } from '~/services/data'

import Lines from '../Lines'

type ShabadProps = {
id: string,
}

const Shabad = ( { id }: ShabadProps ) => {
const { data } = useSuspenseQuery( shabadQuery( id ) )

return (
<Container>
<Lines lines={data.lines} />
</Container>
)
}

export default Shabad
59 changes: 0 additions & 59 deletions src/components/templates/Content/index.int.spec.tsx

This file was deleted.

47 changes: 14 additions & 33 deletions src/components/templates/Content/index.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,27 @@
import { useSuspenseQuery } from '@tanstack/react-query'
import { ComponentType } from 'react'

import Container from '~/components/atoms/Container'
import { getBani, getShabad } from '~/services/data'
import { settings, useSetting } from '~/services/settings'
import { ContentType, LineData } from '~/types/data'
import Empty from '~/components/atoms/Empty'
import { ContentType } from '~/types/data'

import DefaultLines from './DefaultLines'
import ReaderLines from './ReaderLines'
import Bani from './Bani'
import Shabad from './Shabad'

type Loaders = {
[screen in ContentType]: ( id: string ) => Promise<{ id: string, lines: LineData[] }>
}

// ? Loaders return a common interface. Is there a better way to deal with specifics of each type?
const loaders: Loaders = {
shabad: ( id: string ) => getShabad( id ),
bani: ( id: string ) => getBani( id ),
ang: () => Promise.resolve( { id: '', lines: [] } ),
}
// Maybe these should be moved into their own standalone templates entirely
const templates = {
ang: Empty,
bani: Bani,
shabad: Shabad,
} satisfies Record<ContentType, ComponentType<{ id: string }>>

type ContentTemplateProps = {
id: string,
type: ContentType,
}

const ContentTemplate = ( {
id,
type,
}: ContentTemplateProps ) => {
const { data } = useSuspenseQuery( {
queryKey: [ 'content', type, id ],
queryFn: () => loaders[ type ]( id ),
} )

const [ isReaderMode ] = useSetting( settings.readerMode )
const Lines = isReaderMode ? ReaderLines : DefaultLines
const ContentTemplate = ( { id, type }: ContentTemplateProps ) => {
const Template = templates[ type ]

return (
<Container>
<Lines key={data.id} lines={data.lines} />
</Container>
)
return <Template id={id} />
}

export default ContentTemplate
7 changes: 7 additions & 0 deletions src/services/data/banis.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useQuery } from '@tanstack/react-query'

import { languages } from '~/helpers/languages'
import * as gurbaniNow from '~/services/gurbaninow'
import { BaniData } from '~/types/data'
Expand Down Expand Up @@ -44,3 +46,8 @@ export const getBani = async ( id: string ): Promise<BaniData> => {
} ) ),
}
}

export const baniQuery = ( id: string ) => ( {
queryFn: () => getBani( id ),
queryKey: [ 'content', 'bani', id ],
} )
7 changes: 7 additions & 0 deletions src/services/data/shabads.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useQuery } from '@tanstack/react-query'

import { languages } from '~/helpers/languages'
import * as gurbaniNow from '~/services/gurbaninow'
import { ShabadData } from '~/types/data'
Expand Down Expand Up @@ -44,3 +46,8 @@ export const getShabad = async ( id: string ): Promise<ShabadData> => {
} ) ),
}
}

export const shabadQuery = ( id: string ) => ( {
queryKey: [ 'shabad', id ],
queryFn: () => getShabad( id ),
} )
1 change: 1 addition & 0 deletions src/services/kv-storage/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { default as atomWithKvStorage } from './atom-with-kv-storage'
export { default as mmkv } from './mmkv'
5 changes: 3 additions & 2 deletions src/with-contexts.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'
import { ThemeProvider } from '@react-navigation/native'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { Provider } from 'jotai'
import { createStore, Provider } from 'jotai'
import { PostHogProvider, PostHogProviderProps } from 'posthog-react-native'
import { ElementType } from 'react'
import { GestureHandlerRootView } from 'react-native-gesture-handler'
Expand All @@ -12,6 +12,7 @@ import configuration from '~/services/configuration'
import { reactNavigationTheme } from './themes'

export const queryClient = new QueryClient()
export const atomStore = createStore()

const getPostHogProviderProps = () => ( configuration.postHog.enabled
? { apiKey: configuration.postHog.apiKey }
Expand All @@ -22,7 +23,7 @@ const getPostHogProviderProps = () => ( configuration.postHog.enabled

const withContexts = ( Component: ElementType ) => {
const WithContexts = () => (
<Provider>
<Provider store={atomStore}>
<SafeAreaProvider>
<ThemeProvider value={reactNavigationTheme}>
<GestureHandlerRootView style={{ flex: 1 }}>
Expand Down
29 changes: 29 additions & 0 deletions test/providers/AtomProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Provider, WritableAtom } from 'jotai'
import { INTERNAL_InferAtomTuples } from 'jotai/react/utils/useHydrateAtoms'
import { useHydrateAtoms } from 'jotai/utils'
import { ReactNode } from 'react'

type HydrateAtomsProps<T> = {
initialValues: INTERNAL_InferAtomTuples<T>,
children?: ReactNode,
}

const HydrateAtoms = <T extends ( readonly [
WritableAtom<unknown, never[], unknown>,
unknown,
] )[],>( { initialValues, children }: HydrateAtomsProps<T> ) => {
useHydrateAtoms( initialValues )

return children
}

const AtomProvider = <T extends ( readonly [
WritableAtom<unknown, never[], unknown>,
unknown,
] )[],>( { initialValues, children }: HydrateAtomsProps<T> ) => (
<Provider>
<HydrateAtoms initialValues={initialValues}>{children}</HydrateAtoms>
</Provider>
)

export default AtomProvider

0 comments on commit ec46821

Please sign in to comment.