@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import styled from 'styled-components/native';
|
||||
import { ALPHABET_LETTERS, THEME_COLOR } from '@/CONSTANTS';
|
||||
import { ALPHABET_LETTERS } from '@/CONSTANTS';
|
||||
import { View, LayoutChangeEvent } from 'react-native';
|
||||
import {
|
||||
PanGestureHandler,
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
TapGestureHandler,
|
||||
TapGestureHandlerGestureEvent
|
||||
} from 'react-native-gesture-handler';
|
||||
import useDefaultStyles from './Colors';
|
||||
|
||||
// interface LetterContainerProps {
|
||||
// onPress: (letter: string) => void;
|
||||
@@ -29,7 +30,6 @@ const Letter = styled.Text`
|
||||
text-align: center;
|
||||
padding: 1px 0;
|
||||
font-size: 12px;
|
||||
color: ${THEME_COLOR};
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
@@ -41,6 +41,7 @@ interface Props {
|
||||
* screen with all letters of the Alphabet.
|
||||
*/
|
||||
const AlphabetScroller: React.FC<Props> = ({ onSelect }) => {
|
||||
const styles = useDefaultStyles();
|
||||
const [ height, setHeight ] = useState(0);
|
||||
const [ index, setIndex ] = useState<number>();
|
||||
|
||||
@@ -69,7 +70,9 @@ const AlphabetScroller: React.FC<Props> = ({ onSelect }) => {
|
||||
key={l}
|
||||
onLayout={i === 0 ? handleLayout : undefined}
|
||||
>
|
||||
<Letter>{l}</Letter>
|
||||
<Letter style={styles.themeColor}>
|
||||
{l}
|
||||
</Letter>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { SvgProps } from 'react-native-svg';
|
||||
import {
|
||||
PressableProps, ViewProps, View,
|
||||
} from 'react-native';
|
||||
import { THEME_COLOR } from '@/CONSTANTS';
|
||||
import styled, { css } from 'styled-components/native';
|
||||
import useDefaultStyles from './Colors';
|
||||
|
||||
@@ -35,7 +34,6 @@ const BaseButton = styled.Pressable<{ size: ButtonSize }>`
|
||||
`;
|
||||
|
||||
const ButtonText = styled.Text<{ active?: boolean, size: ButtonSize }>`
|
||||
color: ${THEME_COLOR};
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
flex-shrink: 1;
|
||||
@@ -72,16 +70,17 @@ const Button = React.forwardRef<View, ButtonProps>(function Button(props, ref) {
|
||||
<Icon
|
||||
width={14}
|
||||
height={14}
|
||||
fill={THEME_COLOR}
|
||||
style={{
|
||||
marginRight: title ? 8 : 0,
|
||||
}}
|
||||
fill={defaultStyles.themeColor.color}
|
||||
style={[
|
||||
{ marginRight: title ? 8 : 0 }
|
||||
]}
|
||||
/>
|
||||
}
|
||||
{title ? (
|
||||
<ButtonText
|
||||
active={isPressed}
|
||||
size={size}
|
||||
style={defaultStyles.themeColor}
|
||||
numberOfLines={1}
|
||||
>
|
||||
{title}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { BlurView, BlurViewProps } from '@react-native-community/blur';
|
||||
import { THEME_COLOR } from '@/CONSTANTS';
|
||||
import React, { PropsWithChildren } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { ColorSchemeName, Platform, StyleSheet, View, useColorScheme } from 'react-native';
|
||||
import { useTypedSelector } from '@/store';
|
||||
import { ColorScheme } from '@/store/settings/types';
|
||||
import { useAccessibilitySetting } from 'react-native-accessibility-settings';
|
||||
|
||||
const majorPlatformVersion = typeof Platform.Version === 'string' ? parseInt(Platform.Version, 10) : Platform.Version;
|
||||
|
||||
@@ -12,7 +12,7 @@ const majorPlatformVersion = typeof Platform.Version === 'string' ? parseInt(Pla
|
||||
* Function for generating both the dark and light stylesheets, so that they
|
||||
* don't have to be generate on every individual component render
|
||||
*/
|
||||
function generateStyles(scheme: ColorSchemeName) {
|
||||
function generateStyles(scheme: ColorSchemeName, highContrast: boolean) {
|
||||
return StyleSheet.create({
|
||||
text: {
|
||||
color: scheme === 'dark' ? '#fff' : '#000',
|
||||
@@ -20,12 +20,15 @@ function generateStyles(scheme: ColorSchemeName) {
|
||||
fontFamily: 'Inter',
|
||||
},
|
||||
textHalfOpacity: {
|
||||
color: scheme === 'dark' ? '#ffffff88' : '#00000088',
|
||||
color: highContrast
|
||||
? (scheme === 'dark' ? '#ffffffbb' : '#000000bb')
|
||||
: (scheme === 'dark' ? '#ffffff88' : '#00000088'),
|
||||
fontSize: 14,
|
||||
// fontFamily: 'Inter',
|
||||
},
|
||||
textQuarterOpacity: {
|
||||
color: scheme === 'dark' ? '#ffffff44' : '#00000044',
|
||||
color: highContrast
|
||||
? (scheme === 'dark' ? '#ffffff88' : '#00000088')
|
||||
: (scheme === 'dark' ? '#ffffff44' : '#00000044'),
|
||||
fontSize: 14,
|
||||
},
|
||||
view: {
|
||||
@@ -35,7 +38,9 @@ function generateStyles(scheme: ColorSchemeName) {
|
||||
borderColor: scheme === 'dark' ? '#262626' : '#ddd',
|
||||
},
|
||||
activeBackground: {
|
||||
backgroundColor: `${THEME_COLOR}${scheme === 'dark' ? '26' : '16'}`,
|
||||
backgroundColor: highContrast
|
||||
? `#8b513c${scheme === 'dark' ? '26' : '10'}`
|
||||
: `#FF3C00${scheme === 'dark' ? '26' : '16'}`,
|
||||
},
|
||||
imageBackground: {
|
||||
backgroundColor: scheme === 'dark' ? '#191919' : '#eee',
|
||||
@@ -49,7 +54,9 @@ function generateStyles(scheme: ColorSchemeName) {
|
||||
backgroundColor: scheme === 'dark' ? '#000' : '#fff',
|
||||
},
|
||||
button: {
|
||||
backgroundColor: scheme === 'dark' ? '#ffffff09' : '#00000009',
|
||||
backgroundColor: highContrast
|
||||
? (scheme === 'dark' ? '#ffffff0f' : '#0000000f')
|
||||
: (scheme === 'dark' ? '#ffffff09' : '#00000009'),
|
||||
},
|
||||
input: {
|
||||
backgroundColor: scheme === 'dark' ? '#191919' : '#f3f3f3',
|
||||
@@ -67,13 +74,35 @@ function generateStyles(scheme: ColorSchemeName) {
|
||||
filter: {
|
||||
backgroundColor: scheme === 'dark' ? '#191919' : '#f3f3f3',
|
||||
},
|
||||
themeColor: {
|
||||
color: highContrast
|
||||
? scheme === 'dark' ? '#FF7A1C' : '#c93400'
|
||||
: '#FF3C00',
|
||||
},
|
||||
themeColorHalfOpacity: {
|
||||
color: highContrast
|
||||
? scheme === 'dark' ? '#FF7A1Cbb' : '#c93400bb'
|
||||
: '#FF3C0088',
|
||||
},
|
||||
themeColorQuarterOpacity: {
|
||||
color: highContrast
|
||||
? scheme === 'dark' ? '#FF7A1C88' : '#c9340088'
|
||||
: '#FF3C0044',
|
||||
},
|
||||
themeBackground: {
|
||||
backgroundColor: highContrast
|
||||
? scheme === 'dark' ? '#FF7A1C' : '#c93400'
|
||||
: '#FF3C00',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Prerender both stylesheets
|
||||
export const themes: Record<'dark' | 'light', ReturnType<typeof generateStyles>> = {
|
||||
'dark': generateStyles('dark'),
|
||||
'light': generateStyles('light'),
|
||||
export const themes: Record<'dark' | 'light' | 'dark-highcontrast' | 'light-highcontrast', ReturnType<typeof generateStyles>> = {
|
||||
'dark': generateStyles('dark', false),
|
||||
'light': generateStyles('light', false),
|
||||
'dark-highcontrast': generateStyles('dark', true),
|
||||
'light-highcontrast': generateStyles('light', true),
|
||||
};
|
||||
|
||||
// Create context for supplying the theming information
|
||||
@@ -84,9 +113,12 @@ export const ColorSchemeContext = React.createContext(themes.dark);
|
||||
*/
|
||||
export function ColorSchemeProvider({ children }: PropsWithChildren<{}>) {
|
||||
const systemScheme = useColorScheme();
|
||||
const highContrast = useAccessibilitySetting('darkerSystemColors');
|
||||
const userScheme = useTypedSelector((state) => state.settings.colorScheme);
|
||||
const scheme = userScheme === ColorScheme.System ? systemScheme : userScheme;
|
||||
const theme = themes[scheme || 'light'];
|
||||
const theme = highContrast
|
||||
? themes[`${scheme || 'light'}-highcontrast`]
|
||||
: themes[scheme || 'light'];
|
||||
|
||||
return (
|
||||
<ColorSchemeContext.Provider value={theme}>
|
||||
|
||||
@@ -6,13 +6,14 @@ import CloudExclamationMarkIcon from '@/assets/icons/cloud-exclamation-mark.svg'
|
||||
import InternalDriveIcon from '@/assets/icons/internal-drive.svg';
|
||||
import useDefaultStyles from './Colors';
|
||||
import Svg, { Circle, CircleProps } from 'react-native-svg';
|
||||
import { Animated, Easing } from 'react-native';
|
||||
import { Animated, Easing, ViewProps } from 'react-native';
|
||||
import styled from 'styled-components/native';
|
||||
|
||||
interface DownloadIconProps {
|
||||
trackId: string;
|
||||
size?: number;
|
||||
fill?: string;
|
||||
style?: ViewProps['style'];
|
||||
}
|
||||
|
||||
const DownloadContainer = styled.View`
|
||||
@@ -26,7 +27,7 @@ const IconOverlay = styled.View`
|
||||
transform: scale(0.5);
|
||||
`;
|
||||
|
||||
function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
|
||||
function DownloadIcon({ trackId, size = 16, fill, style }: DownloadIconProps) {
|
||||
// determine styles
|
||||
const defaultStyles = useDefaultStyles();
|
||||
const iconFill = fill || defaultStyles.textQuarterOpacity.color;
|
||||
@@ -66,19 +67,19 @@ function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
|
||||
|
||||
if (!entity && !isQueued) {
|
||||
return (
|
||||
<CloudIcon width={size} height={size} fill={iconFill} />
|
||||
<CloudIcon width={size} height={size} fill={iconFill} style={style} />
|
||||
);
|
||||
}
|
||||
|
||||
if (entity?.isComplete) {
|
||||
return (
|
||||
<InternalDriveIcon width={size} height={size} fill={iconFill} />
|
||||
<InternalDriveIcon width={size} height={size} fill={iconFill} style={style} />
|
||||
);
|
||||
}
|
||||
|
||||
if (entity?.isFailed) {
|
||||
return (
|
||||
<CloudExclamationMarkIcon width={size} height={size} fill={iconFill} />
|
||||
<CloudExclamationMarkIcon width={size} height={size} fill={iconFill} style={style} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -100,7 +101,7 @@ function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
|
||||
/>
|
||||
</Svg>
|
||||
<IconOverlay>
|
||||
<CloudDownArrow width={size} height={size} fill={iconFill} />
|
||||
<CloudDownArrow width={size} height={size} fill={iconFill} style={style} />
|
||||
</IconOverlay>
|
||||
</DownloadContainer>
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ import React, { useCallback, useState } from 'react';
|
||||
import { TouchableOpacityProps } from 'react-native';
|
||||
import ChevronRight from '@/assets/icons/chevron-right.svg';
|
||||
import styled from 'styled-components/native';
|
||||
import { THEME_COLOR } from '@/CONSTANTS';
|
||||
import useDefaultStyles from './Colors';
|
||||
|
||||
const BUTTON_SIZE = 14;
|
||||
@@ -17,7 +16,6 @@ const Container = styled.Pressable<{ active?: boolean }>`
|
||||
`;
|
||||
|
||||
const Label = styled.Text<{ active?: boolean }>`
|
||||
color: ${THEME_COLOR};
|
||||
font-size: 16px;
|
||||
`;
|
||||
|
||||
@@ -37,8 +35,14 @@ const ListButton: React.FC<TouchableOpacityProps> = ({ children, ...props }) =>
|
||||
isPressed ? defaultStyles.activeBackground : undefined
|
||||
]}
|
||||
>
|
||||
<Label>{children}</Label>
|
||||
<ChevronRight width={BUTTON_SIZE} height={BUTTON_SIZE} fill={THEME_COLOR} />
|
||||
<Label style={defaultStyles.themeColor}>
|
||||
{children}
|
||||
</Label>
|
||||
<ChevronRight
|
||||
width={BUTTON_SIZE}
|
||||
height={BUTTON_SIZE}
|
||||
fill={defaultStyles.themeColor.color}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { THEME_COLOR } from '@/CONSTANTS';
|
||||
import styled from 'styled-components/native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
|
||||
@@ -51,7 +50,6 @@ const ProgressTrack = styled(Animated.View)<ProgressTrackProps>`
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: ${(props) => props.stroke ? props.stroke + 'px' : '100%'};
|
||||
background-color: ${THEME_COLOR};
|
||||
opacity: ${(props) => props.opacity || 1};
|
||||
border-radius: 99px;
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user