mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 23:59:08 +00:00
fix: improve music page design, mostly headers
This commit is contained in:
@@ -56,7 +56,12 @@ export default function AlbumDetailScreen() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({ title: album?.Name ?? "" });
|
navigation.setOptions({
|
||||||
|
title: album?.Name ?? "",
|
||||||
|
headerTransparent: true,
|
||||||
|
headerStyle: { backgroundColor: "transparent" },
|
||||||
|
headerShadowVisible: false,
|
||||||
|
});
|
||||||
}, [album?.Name, navigation]);
|
}, [album?.Name, navigation]);
|
||||||
|
|
||||||
const imageUrl = useMemo(
|
const imageUrl = useMemo(
|
||||||
@@ -111,7 +116,10 @@ export default function AlbumDetailScreen() {
|
|||||||
paddingBottom: insets.bottom + 100,
|
paddingBottom: insets.bottom + 100,
|
||||||
}}
|
}}
|
||||||
ListHeaderComponent={
|
ListHeaderComponent={
|
||||||
<View className='items-center px-4 pt-4 pb-6'>
|
<View
|
||||||
|
className='items-center px-4 pb-6 bg-black'
|
||||||
|
style={{ paddingTop: insets.top + 60 }}
|
||||||
|
>
|
||||||
{/* Album artwork */}
|
{/* Album artwork */}
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -77,7 +77,12 @@ export default function ArtistDetailScreen() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({ title: artist?.Name ?? "" });
|
navigation.setOptions({
|
||||||
|
title: artist?.Name ?? "",
|
||||||
|
headerTransparent: true,
|
||||||
|
headerStyle: { backgroundColor: "transparent" },
|
||||||
|
headerShadowVisible: false,
|
||||||
|
});
|
||||||
}, [artist?.Name, navigation]);
|
}, [artist?.Name, navigation]);
|
||||||
|
|
||||||
const imageUrl = useMemo(
|
const imageUrl = useMemo(
|
||||||
@@ -138,7 +143,10 @@ export default function ArtistDetailScreen() {
|
|||||||
paddingBottom: insets.bottom + 100,
|
paddingBottom: insets.bottom + 100,
|
||||||
}}
|
}}
|
||||||
ListHeaderComponent={
|
ListHeaderComponent={
|
||||||
<View className='items-center px-4 pt-4 pb-6'>
|
<View
|
||||||
|
className='items-center px-4 pb-6 bg-black'
|
||||||
|
style={{ paddingTop: insets.top + 50 }}
|
||||||
|
>
|
||||||
{/* Artist image */}
|
{/* Artist image */}
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -54,7 +54,12 @@ export default function PlaylistDetailScreen() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({ title: playlist?.Name ?? "" });
|
navigation.setOptions({
|
||||||
|
title: playlist?.Name ?? "",
|
||||||
|
headerTransparent: true,
|
||||||
|
headerStyle: { backgroundColor: "transparent" },
|
||||||
|
headerShadowVisible: false,
|
||||||
|
});
|
||||||
}, [playlist?.Name, navigation]);
|
}, [playlist?.Name, navigation]);
|
||||||
|
|
||||||
const imageUrl = useMemo(
|
const imageUrl = useMemo(
|
||||||
@@ -111,7 +116,10 @@ export default function PlaylistDetailScreen() {
|
|||||||
paddingBottom: insets.bottom + 100,
|
paddingBottom: insets.bottom + 100,
|
||||||
}}
|
}}
|
||||||
ListHeaderComponent={
|
ListHeaderComponent={
|
||||||
<View className='items-center px-4 pt-4 pb-6'>
|
<View
|
||||||
|
className='items-center px-4 pb-6 bg-black'
|
||||||
|
style={{ paddingTop: insets.top + 50 }}
|
||||||
|
>
|
||||||
{/* Playlist artwork */}
|
{/* Playlist artwork */}
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -29,7 +29,13 @@ const Layout = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack.Screen options={{ title: t("music.title") }} />
|
<Stack.Screen
|
||||||
|
options={{
|
||||||
|
title: t("music.title"),
|
||||||
|
headerStyle: { backgroundColor: "black" },
|
||||||
|
headerShadowVisible: false,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Tab
|
<Tab
|
||||||
initialRouteName='suggestions'
|
initialRouteName='suggestions'
|
||||||
keyboardDismissMode='none'
|
keyboardDismissMode='none'
|
||||||
|
|||||||
@@ -95,42 +95,44 @@ export default function AlbumsScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlashList
|
<View className='flex-1 bg-black'>
|
||||||
data={albums}
|
<FlashList
|
||||||
numColumns={numColumns}
|
data={albums}
|
||||||
contentContainerStyle={{
|
numColumns={numColumns}
|
||||||
paddingBottom: insets.bottom + 100,
|
contentContainerStyle={{
|
||||||
paddingTop: 16,
|
paddingBottom: insets.bottom + 100,
|
||||||
paddingHorizontal: padding,
|
paddingTop: 16,
|
||||||
}}
|
paddingHorizontal: padding,
|
||||||
refreshControl={
|
}}
|
||||||
<RefreshControl
|
refreshControl={
|
||||||
refreshing={false}
|
<RefreshControl
|
||||||
onRefresh={refetch}
|
refreshing={false}
|
||||||
tintColor='#9334E9'
|
onRefresh={refetch}
|
||||||
/>
|
tintColor='#9334E9'
|
||||||
}
|
/>
|
||||||
onEndReached={handleEndReached}
|
}
|
||||||
onEndReachedThreshold={0.5}
|
onEndReached={handleEndReached}
|
||||||
renderItem={({ item, index }) => (
|
onEndReachedThreshold={0.5}
|
||||||
<View
|
renderItem={({ item, index }) => (
|
||||||
style={{
|
<View
|
||||||
width: itemWidth,
|
style={{
|
||||||
marginRight: index % numColumns === 0 ? gap : 0,
|
width: itemWidth,
|
||||||
marginBottom: gap,
|
marginRight: index % numColumns === 0 ? gap : 0,
|
||||||
}}
|
marginBottom: gap,
|
||||||
>
|
}}
|
||||||
<MusicAlbumCard album={item} width={itemWidth} />
|
>
|
||||||
</View>
|
<MusicAlbumCard album={item} width={itemWidth} />
|
||||||
)}
|
|
||||||
keyExtractor={(item) => item.Id!}
|
|
||||||
ListFooterComponent={
|
|
||||||
isFetchingNextPage ? (
|
|
||||||
<View className='py-4'>
|
|
||||||
<Loader />
|
|
||||||
</View>
|
</View>
|
||||||
) : null
|
)}
|
||||||
}
|
keyExtractor={(item) => item.Id!}
|
||||||
/>
|
ListFooterComponent={
|
||||||
|
isFetchingNextPage ? (
|
||||||
|
<View className='py-4'>
|
||||||
|
<Loader />
|
||||||
|
</View>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,42 +129,44 @@ export default function ArtistsScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlashList
|
<View className='flex-1 bg-black'>
|
||||||
data={artists}
|
<FlashList
|
||||||
numColumns={numColumns}
|
data={artists}
|
||||||
contentContainerStyle={{
|
numColumns={numColumns}
|
||||||
paddingBottom: insets.bottom + 100,
|
contentContainerStyle={{
|
||||||
paddingTop: 16,
|
paddingBottom: insets.bottom + 100,
|
||||||
paddingHorizontal: padding,
|
paddingTop: 16,
|
||||||
}}
|
paddingHorizontal: padding,
|
||||||
refreshControl={
|
}}
|
||||||
<RefreshControl
|
refreshControl={
|
||||||
refreshing={false}
|
<RefreshControl
|
||||||
onRefresh={refetch}
|
refreshing={false}
|
||||||
tintColor='#9334E9'
|
onRefresh={refetch}
|
||||||
/>
|
tintColor='#9334E9'
|
||||||
}
|
/>
|
||||||
onEndReached={handleEndReached}
|
}
|
||||||
onEndReachedThreshold={0.5}
|
onEndReached={handleEndReached}
|
||||||
renderItem={({ item, index }) => (
|
onEndReachedThreshold={0.5}
|
||||||
<View
|
renderItem={({ item, index }) => (
|
||||||
style={{
|
<View
|
||||||
width: itemWidth,
|
style={{
|
||||||
marginRight: index % numColumns !== numColumns - 1 ? gap : 0,
|
width: itemWidth,
|
||||||
marginBottom: gap,
|
marginRight: index % numColumns !== numColumns - 1 ? gap : 0,
|
||||||
}}
|
marginBottom: gap,
|
||||||
>
|
}}
|
||||||
<MusicArtistCard artist={item} size={itemWidth} />
|
>
|
||||||
</View>
|
<MusicArtistCard artist={item} size={itemWidth} />
|
||||||
)}
|
|
||||||
keyExtractor={(item) => item.Id!}
|
|
||||||
ListFooterComponent={
|
|
||||||
isFetchingNextPage ? (
|
|
||||||
<View className='py-4'>
|
|
||||||
<Loader />
|
|
||||||
</View>
|
</View>
|
||||||
) : null
|
)}
|
||||||
}
|
keyExtractor={(item) => item.Id!}
|
||||||
/>
|
ListFooterComponent={
|
||||||
|
isFetchingNextPage ? (
|
||||||
|
<View className='py-4'>
|
||||||
|
<Loader />
|
||||||
|
</View>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,42 +129,44 @@ export default function PlaylistsScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlashList
|
<View className='flex-1 bg-black'>
|
||||||
data={playlists}
|
<FlashList
|
||||||
numColumns={numColumns}
|
data={playlists}
|
||||||
contentContainerStyle={{
|
numColumns={numColumns}
|
||||||
paddingBottom: insets.bottom + 100,
|
contentContainerStyle={{
|
||||||
paddingTop: 16,
|
paddingBottom: insets.bottom + 100,
|
||||||
paddingHorizontal: padding,
|
paddingTop: 16,
|
||||||
}}
|
paddingHorizontal: padding,
|
||||||
refreshControl={
|
}}
|
||||||
<RefreshControl
|
refreshControl={
|
||||||
refreshing={false}
|
<RefreshControl
|
||||||
onRefresh={refetch}
|
refreshing={false}
|
||||||
tintColor='#9334E9'
|
onRefresh={refetch}
|
||||||
/>
|
tintColor='#9334E9'
|
||||||
}
|
/>
|
||||||
onEndReached={handleEndReached}
|
}
|
||||||
onEndReachedThreshold={0.5}
|
onEndReached={handleEndReached}
|
||||||
renderItem={({ item, index }) => (
|
onEndReachedThreshold={0.5}
|
||||||
<View
|
renderItem={({ item, index }) => (
|
||||||
style={{
|
<View
|
||||||
width: itemWidth,
|
style={{
|
||||||
marginRight: index % numColumns === 0 ? gap : 0,
|
width: itemWidth,
|
||||||
marginBottom: gap,
|
marginRight: index % numColumns === 0 ? gap : 0,
|
||||||
}}
|
marginBottom: gap,
|
||||||
>
|
}}
|
||||||
<MusicPlaylistCard playlist={item} width={itemWidth} />
|
>
|
||||||
</View>
|
<MusicPlaylistCard playlist={item} width={itemWidth} />
|
||||||
)}
|
|
||||||
keyExtractor={(item) => item.Id!}
|
|
||||||
ListFooterComponent={
|
|
||||||
isFetchingNextPage ? (
|
|
||||||
<View className='py-4'>
|
|
||||||
<Loader />
|
|
||||||
</View>
|
</View>
|
||||||
) : null
|
)}
|
||||||
}
|
keyExtractor={(item) => item.Id!}
|
||||||
/>
|
ListFooterComponent={
|
||||||
|
isFetchingNextPage ? (
|
||||||
|
<View className='py-4'>
|
||||||
|
<Loader />
|
||||||
|
</View>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,44 +243,46 @@ export default function SuggestionsScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlashList
|
<View className='flex-1 bg-black'>
|
||||||
data={sections}
|
<FlashList
|
||||||
contentContainerStyle={{
|
data={sections}
|
||||||
paddingBottom: insets.bottom + 100,
|
contentContainerStyle={{
|
||||||
paddingTop: 16,
|
paddingBottom: insets.bottom + 100,
|
||||||
}}
|
paddingTop: 16,
|
||||||
refreshControl={
|
}}
|
||||||
<RefreshControl
|
refreshControl={
|
||||||
refreshing={false}
|
<RefreshControl
|
||||||
onRefresh={handleRefresh}
|
refreshing={false}
|
||||||
tintColor='#9334E9'
|
onRefresh={handleRefresh}
|
||||||
/>
|
tintColor='#9334E9'
|
||||||
}
|
/>
|
||||||
renderItem={({ item: section }) => (
|
}
|
||||||
<View className='mb-6'>
|
renderItem={({ item: section }) => (
|
||||||
<Text className='text-lg font-bold px-4 mb-3'>{section.title}</Text>
|
<View className='mb-6'>
|
||||||
{section.type === "albums" ? (
|
<Text className='text-lg font-bold px-4 mb-3'>{section.title}</Text>
|
||||||
<HorizontalScroll
|
{section.type === "albums" ? (
|
||||||
data={section.data}
|
<HorizontalScroll
|
||||||
height={200}
|
data={section.data}
|
||||||
keyExtractor={(item) => item.Id!}
|
height={200}
|
||||||
renderItem={(item) => <MusicAlbumCard album={item} />}
|
keyExtractor={(item) => item.Id!}
|
||||||
/>
|
renderItem={(item) => <MusicAlbumCard album={item} />}
|
||||||
) : (
|
/>
|
||||||
<View className='px-4'>
|
) : (
|
||||||
{section.data.slice(0, 5).map((track, index, _tracks) => (
|
<View className='px-4'>
|
||||||
<MusicTrackItem
|
{section.data.slice(0, 5).map((track, index, _tracks) => (
|
||||||
key={track.Id}
|
<MusicTrackItem
|
||||||
track={track}
|
key={track.Id}
|
||||||
index={index + 1}
|
track={track}
|
||||||
queue={section.data}
|
index={index + 1}
|
||||||
/>
|
queue={section.data}
|
||||||
))}
|
/>
|
||||||
</View>
|
))}
|
||||||
)}
|
</View>
|
||||||
</View>
|
)}
|
||||||
)}
|
</View>
|
||||||
keyExtractor={(item) => item.title}
|
)}
|
||||||
/>
|
keyExtractor={(item) => item.title}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -599,6 +599,9 @@
|
|||||||
"artists": "Artists",
|
"artists": "Artists",
|
||||||
"playlists": "Playlists"
|
"playlists": "Playlists"
|
||||||
},
|
},
|
||||||
|
"filters": {
|
||||||
|
"all": "All"
|
||||||
|
},
|
||||||
"recently_added": "Recently Added",
|
"recently_added": "Recently Added",
|
||||||
"recently_played": "Recently Played",
|
"recently_played": "Recently Played",
|
||||||
"frequently_played": "Frequently Played",
|
"frequently_played": "Frequently Played",
|
||||||
|
|||||||
Reference in New Issue
Block a user