mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 00:59:28 +01:00
gradient working better now/in album view
title bar now also uses gradient color
This commit is contained in:
parent
0a31597111
commit
a151fe299e
@ -1,13 +1,11 @@
|
||||
import { useAtomValue } from 'jotai/utils';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { StyleSheet, Text, View, StatusBar, useWindowDimensions } from 'react-native';
|
||||
import React from 'react';
|
||||
import { StatusBar, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { currentQueueNameAtom, currentTrackAtom } from '../state/trackplayer';
|
||||
import colors from '../styles/colors';
|
||||
import text from '../styles/text';
|
||||
import CoverArt from './common/CoverArt';
|
||||
import GradientBackground from './common/GradientBackground';
|
||||
import ImageColors from 'react-native-image-colors';
|
||||
import ImageGradientBackground from './common/ImageGradientBackground';
|
||||
|
||||
const NowPlayingHeader = () => {
|
||||
const queueName = useAtomValue(currentQueueNameAtom);
|
||||
@ -106,61 +104,8 @@ const infoStyles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
interface AndroidImageColors {
|
||||
dominant?: string;
|
||||
average?: string;
|
||||
vibrant?: string;
|
||||
darkVibrant?: string;
|
||||
lightVibrant?: string;
|
||||
darkMuted?: string;
|
||||
lightMuted?: string;
|
||||
muted?: string;
|
||||
platform: 'android';
|
||||
}
|
||||
|
||||
interface IOSImageColors {
|
||||
background: string;
|
||||
primary: string;
|
||||
secondary: string;
|
||||
detail: string;
|
||||
quality: Config['quality'];
|
||||
platform: 'ios';
|
||||
}
|
||||
|
||||
interface Config {
|
||||
fallback?: string;
|
||||
pixelSpacing?: number;
|
||||
quality?: 'lowest' | 'low' | 'high' | 'highest';
|
||||
cache?: boolean;
|
||||
key?: string;
|
||||
}
|
||||
|
||||
declare type ImageColorsResult = AndroidImageColors | IOSImageColors;
|
||||
|
||||
const NowPlayingLayout = () => {
|
||||
const track = useAtomValue(currentTrackAtom);
|
||||
const [imageColors, setImageColors] = useState<ImageColorsResult | undefined>(undefined);
|
||||
const ica = imageColors as AndroidImageColors;
|
||||
|
||||
useEffect(() => {
|
||||
async function getColors() {
|
||||
if (track?.artwork === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cachedResult = ImageColors.cache.getItem(track.artwork as string);
|
||||
if (cachedResult) {
|
||||
setImageColors(cachedResult);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await ImageColors.getColors(track.artwork as string, {
|
||||
cache: true,
|
||||
});
|
||||
setImageColors(result);
|
||||
}
|
||||
getColors();
|
||||
}, [track]);
|
||||
|
||||
return (
|
||||
<View
|
||||
@ -168,10 +113,7 @@ const NowPlayingLayout = () => {
|
||||
flex: 1,
|
||||
paddingTop: StatusBar.currentHeight,
|
||||
}}>
|
||||
<GradientBackground
|
||||
colors={[ica ? (ica.muted as string) : colors.gradient.high, colors.gradient.low]}
|
||||
locations={[0.1, 1.0]}
|
||||
/>
|
||||
<ImageGradientBackground imageUri={track?.artwork as string} />
|
||||
<NowPlayingHeader />
|
||||
<SongCoverArt />
|
||||
<SongInfo />
|
||||
|
||||
@ -18,7 +18,7 @@ import text from '../../styles/text';
|
||||
import AlbumArt from './AlbumArt';
|
||||
import Button from './Button';
|
||||
import GradientBackground from './GradientBackground';
|
||||
import GradientScrollView from './GradientScrollView';
|
||||
import ImageGradientScrollView from './ImageGradientScrollView';
|
||||
|
||||
const SongItem: React.FC<{
|
||||
id: string;
|
||||
@ -102,7 +102,8 @@ const AlbumDetails: React.FC<{
|
||||
}
|
||||
|
||||
return (
|
||||
<GradientScrollView
|
||||
<ImageGradientScrollView
|
||||
imageUri={album.coverArtUri}
|
||||
style={{
|
||||
flex: 1,
|
||||
}}
|
||||
@ -166,7 +167,7 @@ const AlbumDetails: React.FC<{
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</GradientScrollView>
|
||||
</ImageGradientScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
65
src/components/common/ImageGradientBackground.tsx
Normal file
65
src/components/common/ImageGradientBackground.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { ViewStyle } from 'react-native';
|
||||
import ImageColors from 'react-native-image-colors';
|
||||
import { AndroidImageColors } from 'react-native-image-colors/lib/typescript/types';
|
||||
import colors from '../../styles/colors';
|
||||
import GradientBackground from './GradientBackground';
|
||||
|
||||
const ImageGradientBackground: React.FC<{
|
||||
height?: number | string;
|
||||
width?: number | string;
|
||||
position?: 'relative' | 'absolute';
|
||||
style?: ViewStyle;
|
||||
imageUri?: string;
|
||||
}> = ({ height, width, position, style, imageUri, children }) => {
|
||||
const [highColor, setHighColor] = useState<string>(colors.gradient.high);
|
||||
const navigation = useNavigation();
|
||||
|
||||
useEffect(() => {
|
||||
async function getColors() {
|
||||
if (imageUri === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let res: AndroidImageColors;
|
||||
const cachedResult = ImageColors.cache.getItem(imageUri);
|
||||
if (cachedResult) {
|
||||
res = cachedResult as AndroidImageColors;
|
||||
} else {
|
||||
res = (await ImageColors.getColors(imageUri, {
|
||||
cache: true,
|
||||
})) as AndroidImageColors;
|
||||
}
|
||||
|
||||
if (res.muted && res.muted !== '#000000') {
|
||||
setHighColor(res.muted);
|
||||
} else if (res.darkMuted && res.darkMuted !== '#000000') {
|
||||
setHighColor(res.darkMuted);
|
||||
}
|
||||
}
|
||||
getColors();
|
||||
}, [imageUri]);
|
||||
|
||||
useEffect(() => {
|
||||
navigation.setOptions({
|
||||
headerStyle: {
|
||||
backgroundColor: highColor,
|
||||
},
|
||||
});
|
||||
}, [navigation, highColor]);
|
||||
|
||||
return (
|
||||
<GradientBackground
|
||||
height={height}
|
||||
width={width}
|
||||
position={position}
|
||||
style={style}
|
||||
colors={[highColor, colors.gradient.low]}
|
||||
locations={[0.1, 1.0]}>
|
||||
{children}
|
||||
</GradientBackground>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageGradientBackground;
|
||||
30
src/components/common/ImageGradientScrollView.tsx
Normal file
30
src/components/common/ImageGradientScrollView.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import React, { useState } from 'react';
|
||||
import { LayoutRectangle, ScrollView, ScrollViewProps } from 'react-native';
|
||||
import colors from '../../styles/colors';
|
||||
import ImageGradientBackground from './ImageGradientBackground';
|
||||
|
||||
const ImageGradientScrollView: React.FC<ScrollViewProps & { imageUri?: string }> = props => {
|
||||
const [layout, setLayout] = useState<LayoutRectangle | undefined>(undefined);
|
||||
|
||||
props.style = props.style || {};
|
||||
if (typeof props.style === 'object' && props.style !== null) {
|
||||
props.style = {
|
||||
...props.style,
|
||||
backgroundColor: colors.gradient.low,
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
overScrollMode="never"
|
||||
{...props}
|
||||
onLayout={event => {
|
||||
setLayout(event.nativeEvent.layout);
|
||||
}}>
|
||||
<ImageGradientBackground height={layout?.height} imageUri={props.imageUri} />
|
||||
{props.children}
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageGradientScrollView;
|
||||
Loading…
x
Reference in New Issue
Block a user