subtracks/app/screens/LibraryAlbums.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

142 lines
4.0 KiB
TypeScript

import { AlbumContextPressable } from '@app/components/ContextMenu'
import CoverArt from '@app/components/CoverArt'
import FilterButton from '@app/components/FilterButton'
import GradientFlatList from '@app/components/GradientFlatList'
import { withSuspenseMemo } from '@app/components/withSuspense'
import { useQueryAlbumList } from '@app/hooks/query'
import { Album } from '@app/models/library'
import { useStore, 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 { StyleSheet, Text, useWindowDimensions, View } from 'react-native'
const AlbumItem = React.memo<{
album: Album
size: number
height: number
}>(({ album, size, height }) => {
const navigation = useNavigation()
if (!album) {
return <></>
}
return (
<AlbumContextPressable
album={album}
menuStyle={[styles.itemMenu, { width: size }]}
triggerWrapperStyle={[styles.itemWrapper, { height }]}
onPress={() => navigation.navigate('album', { id: album.id, title: album.name, album })}>
<CoverArt
type="cover"
coverArt={album.coverArt}
style={{ height: size, width: size }}
resizeMode="cover"
size="thumbnail"
/>
<View style={styles.itemDetails}>
<Text style={styles.title} numberOfLines={1}>
{album.name}
</Text>
<Text style={styles.subtitle} numberOfLines={1}>
{album.artist}
</Text>
</View>
</AlbumContextPressable>
)
}, equal)
const AlbumListRenderItem: React.FC<{
item: { album: Album; size: number; height: number }
}> = ({ item }) => <AlbumItem album={item.album} size={item.size} height={item.height} />
const filterValues: GetAlbumList2TypeBase[] = [
'alphabeticalByName', //
'alphabeticalByArtist',
'newest',
'frequent',
'recent',
'starred',
'random',
]
const AlbumFilterButton = withSuspenseMemo(() => {
const { t } = useTranslation('resources.album.lists')
const filterType = useStoreDeep(store => store.settings.screens.library.albumsFilter.type)
const setFilterType = useStore(store => store.setLibraryAlbumFilterType)
return (
<FilterButton
data={filterValues.map(value => ({ value, text: t(value) }))}
value={filterType}
onSelect={selection => {
setFilterType(selection as GetAlbumList2TypeBase)
}}
title={t('sort')}
/>
)
})
const AlbumsList = () => {
const filterType = useStoreDeep(store => store.settings.screens.library.albumsFilter.type)
const { isLoading, data, fetchNextPage, refetch } = useQueryAlbumList(filterType as GetAlbumList2TypeBase, 300)
const layout = useWindowDimensions()
const size = layout.width / 3 - styles.itemWrapper.marginHorizontal * 2
const height = size + 36
return (
<View style={styles.container}>
<GradientFlatList
data={data ? data.pages.flatMap(albums => albums.map(album => ({ album, size, height }))) : []}
renderItem={AlbumListRenderItem}
keyExtractor={item => item.album.id}
numColumns={3}
removeClippedSubviews={true}
refreshing={isLoading}
onRefresh={refetch}
overScrollMode="never"
onEndReached={() => fetchNextPage()}
onEndReachedThreshold={6}
windowSize={5}
/>
<AlbumFilterButton />
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
itemMenu: {
flex: 1 / 3,
},
itemWrapper: {
marginVertical: 4,
marginHorizontal: 2,
},
itemDetails: {
flex: 1,
},
title: {
fontSize: 12,
fontFamily: font.semiBold,
color: colors.text.primary,
marginTop: 4,
},
subtitle: {
fontSize: 11,
fontFamily: font.regular,
color: colors.text.secondary,
},
})
export default React.memo(AlbumsList)