subtracks/app/screens/Home.tsx
austinried 860a4cec16
Localization support (#99)
* basic i18n poc

* translate home, filters, tabs

support dot notation in backend for namespaces

* i18n context menu, artist filters, list controls

also nothings here
fix backend not caching fallback

* i18n queue, artist view, search/results

* i18n settings and server view

* Added translation using Weblate (Norwegian Bokmål)

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (6 of 6 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/nb_NO/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/

* fix url escaping

* added some mostly naive text overflow fixes

rewrote filter context menu as a slide in because the old one apparently can't handle dynamic width

* Added translation using Weblate (French)

* Translated using Weblate (French)

Currently translated at 17.4% (11 of 63 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/fr/

* Translated using Weblate (French)

Currently translated at 19.0% (12 of 63 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/fr/

* Translated using Weblate (French)

Currently translated at 40.0% (26 of 65 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/fr/

* add weblate and some pretty badges to readme

* fix link

* Translated using Weblate (French)

Currently translated at 50.7% (33 of 65 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/fr/

* Translated using Weblate (English)

Currently translated at 100.0% (65 of 65 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/en/

* Translated using Weblate (French)

Currently translated at 90.7% (59 of 65 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/fr/

* i18n now playing context type

fix overscroll on new filter menu
fix getting default namespace from the i18n backend

* Translated using Weblate (French)

Currently translated at 96.9% (63 of 65 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/fr/

* Translated using Weblate (French)

Currently translated at 100.0% (66 of 66 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/fr/

* Translated using Weblate (Japanese) (#98)

Currently translated at 7.5% (5 of 66 strings)

Translation: Subtracks/subtracks
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/ja/

Co-authored-by: Austin Riedhammer <austinried@functionkey.xyz>

* little note to remind me why that's there

* update licenses

Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Clyhtsuriva <aimeric@adjutor.xyz>
2022-04-15 12:11:00 +09:00

155 lines
4.1 KiB
TypeScript

import { AlbumContextPressable } from '@app/components/ContextMenu'
import CoverArt from '@app/components/CoverArt'
import GradientScrollView from '@app/components/GradientScrollView'
import Header from '@app/components/Header'
import NothingHere from '@app/components/NothingHere'
import { withSuspenseMemo } from '@app/components/withSuspense'
import { useQueryHomeLists } from '@app/hooks/query'
import { Album } from '@app/models/library'
import { useStoreDeep } from '@app/state/store'
import colors from '@app/styles/colors'
import font from '@app/styles/font'
import { GetAlbumList2TypeBase } from '@app/subsonic/params'
import { useNavigation } from '@react-navigation/native'
import equal from 'fast-deep-equal/es6/react'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { RefreshControl, ScrollView, StyleSheet, Text, View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
const AlbumItem = React.memo<{
album: Album
}>(({ album }) => {
const navigation = useNavigation()
return (
<AlbumContextPressable
album={album}
triggerWrapperStyle={styles.item}
onPress={() => navigation.navigate('album', { id: album.id, title: album.name, album })}>
<CoverArt
type="cover"
coverArt={album.coverArt}
style={{ height: styles.item.width, width: styles.item.width }}
resizeMode="cover"
size="thumbnail"
/>
<Text style={styles.title} numberOfLines={1}>
{album.name}
</Text>
<Text style={styles.subtitle} numberOfLines={1}>
{album.artist}
</Text>
</AlbumContextPressable>
)
}, equal)
const CategoryHeader = withSuspenseMemo<{ type: string }>(({ type }) => {
const { t } = useTranslation('resources.album.lists')
console.log('type', type, t(type))
return <Header style={styles.header}>{t(type)}</Header>
})
const Category = React.memo<{
type: string
albums: Album[]
}>(({ type, albums }) => {
const Albums = () => (
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false}
overScrollMode={'never'}
style={styles.artScroll}
contentContainerStyle={styles.artScrollContent}>
{albums.map(a => (
<AlbumItem key={a.id} album={a} />
))}
</ScrollView>
)
const Nothing = () => (
<View style={styles.nothingHereContent}>
<NothingHere height={160} width={160} />
</View>
)
return (
<View style={styles.category}>
<CategoryHeader type={type} />
{albums.length > 0 ? <Albums /> : <Nothing />}
</View>
)
}, equal)
const Home = () => {
const types = useStoreDeep(store => store.settings.screens.home.listTypes)
const listQueries = useQueryHomeLists(types as GetAlbumList2TypeBase[], 20)
const paddingTop = useSafeAreaInsets().top
return (
<GradientScrollView
style={styles.scroll}
contentContainerStyle={{ paddingTop }}
refreshControl={
<RefreshControl
refreshing={listQueries.some(q => q.isLoading)}
onRefresh={() => listQueries.forEach(q => q.refetch())}
colors={[colors.accent, colors.accentLow]}
progressViewOffset={paddingTop}
/>
}>
<View style={styles.content}>
{types.map(type => {
const query = listQueries.find(list => list.data?.type === type)
return <Category key={type} type={type} albums={query?.data?.albums || []} />
})}
</View>
</GradientScrollView>
)
}
const styles = StyleSheet.create({
scroll: {
flex: 1,
},
content: {
paddingBottom: 20,
},
header: {
paddingHorizontal: 20,
},
category: {
// marginTop: 12,
},
nothingHereContent: {
width: '100%',
height: 190,
justifyContent: 'center',
alignItems: 'center',
},
artScroll: {
height: 190,
},
artScrollContent: {
paddingLeft: 20,
},
item: {
flex: 1,
marginRight: 10,
width: 150,
},
title: {
fontFamily: font.semiBold,
fontSize: 13,
color: colors.text.primary,
marginTop: 4,
},
subtitle: {
fontFamily: font.regular,
fontSize: 12,
color: colors.text.secondary,
},
})
export default Home