Add iOS Dark Mode
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { StackParams } from '../types';
|
||||
import { Text, ScrollView, Dimensions, Button, RefreshControl } from 'react-native';
|
||||
import { Text, ScrollView, Dimensions, Button, RefreshControl, StyleSheet } from 'react-native';
|
||||
import { useGetImage } from 'utility/JellyfinApi';
|
||||
import styled, { css } from 'styled-components/native';
|
||||
import { useRoute, RouteProp } from '@react-navigation/native';
|
||||
@@ -14,11 +14,32 @@ import usePlayAlbum from 'utility/usePlayAlbum';
|
||||
import usePlayTrack from 'utility/usePlayTrack';
|
||||
import TouchableHandler from 'components/TouchableHandler';
|
||||
import useCurrentTrack from 'utility/useCurrentTrack';
|
||||
import { colors } from 'components/Colors';
|
||||
|
||||
type Route = RouteProp<StackParams, 'Album'>;
|
||||
|
||||
const Screen = Dimensions.get('screen');
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
name: {
|
||||
...colors.text,
|
||||
fontSize: 36,
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
artist: {
|
||||
...colors.text,
|
||||
fontSize: 24,
|
||||
opacity: 0.5,
|
||||
marginBottom: 24
|
||||
},
|
||||
index: {
|
||||
...colors.text,
|
||||
width: 20,
|
||||
opacity: 0.5,
|
||||
marginRight: 5
|
||||
}
|
||||
});
|
||||
|
||||
const AlbumImage = styled(FastImage)`
|
||||
border-radius: 10px;
|
||||
width: ${Screen.width * 0.6}px;
|
||||
@@ -29,7 +50,6 @@ const AlbumImage = styled(FastImage)`
|
||||
const TrackContainer = styled.View<{isPlaying: boolean}>`
|
||||
padding: 15px;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #eee;
|
||||
flex-direction: row;
|
||||
|
||||
${props => props.isPlaying && css`
|
||||
@@ -71,23 +91,22 @@ const Album: React.FC = () => {
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
style={{ backgroundColor: '#f6f6f6' }}
|
||||
contentContainerStyle={{ padding: 20, paddingBottom: 50 }}
|
||||
refreshControl={
|
||||
<RefreshControl refreshing={isLoading} onRefresh={refresh} />
|
||||
}
|
||||
>
|
||||
<AlbumImage source={{ uri: getImage(album?.Id) }} />
|
||||
<Text style={{ fontSize: 36, fontWeight: 'bold' }} >{album?.Name}</Text>
|
||||
<Text style={{ fontSize: 24, opacity: 0.5, marginBottom: 24 }}>{album?.AlbumArtist}</Text>
|
||||
<AlbumImage source={{ uri: getImage(album?.Id) }} style={colors.imageBackground} />
|
||||
<Text style={styles.name} >{album?.Name}</Text>
|
||||
<Text style={styles.artist}>{album?.AlbumArtist}</Text>
|
||||
<Button title="Play Album" onPress={selectAlbum} color={THEME_COLOR} />
|
||||
{album?.Tracks?.length ? album.Tracks.map((trackId) =>
|
||||
<TouchableHandler key={trackId} id={trackId} onPress={selectTrack}>
|
||||
<TrackContainer isPlaying={currentTrack?.id.startsWith(trackId) || false}>
|
||||
<Text style={{ width: 20, opacity: 0.5, marginRight: 5 }}>
|
||||
<TrackContainer isPlaying={currentTrack?.id.startsWith(trackId) || false} style={colors.border}>
|
||||
<Text style={styles.index}>
|
||||
{tracks[trackId]?.IndexNumber}
|
||||
</Text>
|
||||
<Text>{tracks[trackId]?.Name}</Text>
|
||||
<Text style={colors.text}>{tracks[trackId]?.Name}</Text>
|
||||
</TrackContainer>
|
||||
</TouchableHandler>
|
||||
) : undefined}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { selectAlbumsByAlphabet, SectionedId } from 'store/music/selectors';
|
||||
import AlphabetScroller from 'components/AlphabetScroller';
|
||||
import { EntityId } from '@reduxjs/toolkit';
|
||||
import styled from 'styled-components/native';
|
||||
import { colors } from 'components/Colors';
|
||||
|
||||
interface VirtualizedItemInfo {
|
||||
section: SectionedId,
|
||||
@@ -39,8 +40,6 @@ function generateSection({ section }: { section: SectionedId }) {
|
||||
}
|
||||
|
||||
const SectionContainer = styled.View`
|
||||
background-color: #f6f6f6;
|
||||
border-bottom-color: #eee;
|
||||
border-bottom-width: 1px;
|
||||
height: 50px;
|
||||
justify-content: center;
|
||||
@@ -56,8 +55,8 @@ class SectionHeading extends PureComponent<{ label: string }> {
|
||||
const { label } = this.props;
|
||||
|
||||
return (
|
||||
<SectionContainer>
|
||||
<SectionText>{label}</SectionText>
|
||||
<SectionContainer style={colors.view}>
|
||||
<SectionText style={colors.text}>{label}</SectionText>
|
||||
</SectionContainer>
|
||||
);
|
||||
}
|
||||
@@ -82,9 +81,9 @@ class GeneratedAlbumItem extends PureComponent<GeneratedAlbumItemProps> {
|
||||
return (
|
||||
<TouchableHandler id={id as string} onPress={onPress}>
|
||||
<AlbumItem>
|
||||
<AlbumImage source={{ uri: imageUrl }} />
|
||||
<Text numberOfLines={1}>{name}</Text>
|
||||
<HalfOpacity numberOfLines={1}>{artist}</HalfOpacity>
|
||||
<AlbumImage source={{ uri: imageUrl }} style={colors.imageBackground} />
|
||||
<Text numberOfLines={1} style={colors.text}>{name}</Text>
|
||||
<HalfOpacity style={colors.text} numberOfLines={1}>{artist}</HalfOpacity>
|
||||
</AlbumItem>
|
||||
</TouchableHandler>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useGetImage } from 'utility/JellyfinApi';
|
||||
import { Album, NavigationProp } from '../types';
|
||||
import { Text, SafeAreaView, FlatList } from 'react-native';
|
||||
import { Text, SafeAreaView, FlatList, StyleSheet } from 'react-native';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { useTypedSelector } from 'store';
|
||||
@@ -12,6 +12,14 @@ import AlbumImage, { AlbumItem } from './components/AlbumImage';
|
||||
import { useRecentAlbums } from 'store/music/selectors';
|
||||
import { Header } from 'components/Typography';
|
||||
import ListButton from 'components/ListButton';
|
||||
import { colors } from 'components/Colors';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
artist: {
|
||||
...colors.text,
|
||||
opacity: 0.5,
|
||||
}
|
||||
});
|
||||
|
||||
const NavigationHeader: React.FC = () => {
|
||||
const navigation = useNavigation();
|
||||
@@ -22,7 +30,7 @@ const NavigationHeader: React.FC = () => {
|
||||
<ListContainer>
|
||||
<ListButton onPress={handleAllAlbumsClick}>All Albums</ListButton>
|
||||
<ListButton onPress={handleSearchClick}>Search</ListButton>
|
||||
<Header>Recent Albums</Header>
|
||||
<Header style={colors.text}>Recent Albums</Header>
|
||||
</ListContainer>
|
||||
);
|
||||
};
|
||||
@@ -58,9 +66,9 @@ const RecentAlbums: React.FC = () => {
|
||||
renderItem={({ item }) => (
|
||||
<TouchableHandler id={item} onPress={selectAlbum}>
|
||||
<AlbumItem>
|
||||
<AlbumImage source={{ uri: getImage(item) }} />
|
||||
<Text numberOfLines={1}>{albums[item]?.Name}</Text>
|
||||
<Text numberOfLines={1} style={{ opacity: 0.5 }}>{albums[item]?.AlbumArtist}</Text>
|
||||
<AlbumImage source={{ uri: getImage(item) }} style={colors.imageBackground} />
|
||||
<Text style={colors.text} numberOfLines={1}>{albums[item]?.Name}</Text>
|
||||
<Text style={styles.artist} numberOfLines={1}>{albums[item]?.AlbumArtist}</Text>
|
||||
</AlbumItem>
|
||||
</TouchableHandler>
|
||||
)}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useNavigation } from '@react-navigation/native';
|
||||
import { useGetImage } from 'utility/JellyfinApi';
|
||||
import { NavigationProp } from '../types';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { colors } from 'components/Colors';
|
||||
|
||||
const Container = styled.View`
|
||||
padding: 0 20px;
|
||||
@@ -20,7 +21,6 @@ const AlbumImage = styled(FastImage)`
|
||||
border-radius: 4px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
background-color: #fefefe;
|
||||
margin-right: 10px;
|
||||
`;
|
||||
|
||||
@@ -33,7 +33,6 @@ const HalfOpacity = styled.Text`
|
||||
const SearchResult = styled.View`
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border-bottom-color: #ddd;
|
||||
border-bottom-width: 1px;
|
||||
margin-left: 15px;
|
||||
padding-right: 15px;
|
||||
@@ -51,7 +50,7 @@ export default function Search() {
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
const albums = useTypedSelector(state => state.music.albums.entities);
|
||||
const [results, setResults] = useState<Fuse.FuseResult<Album>[]>([]);
|
||||
let fuse = useRef<Fuse<Album, typeof fuseOptions>>();
|
||||
const fuse = useRef<Fuse<Album, typeof fuseOptions>>();
|
||||
|
||||
// Prepare helpers
|
||||
const navigation = useNavigation<NavigationProp>();
|
||||
@@ -89,7 +88,7 @@ export default function Search() {
|
||||
|
||||
const HeaderComponent = React.useMemo(() => (
|
||||
<Container>
|
||||
<Input value={searchTerm} onChangeText={setSearchTerm} placeholder="Search..." />
|
||||
<Input value={searchTerm} onChangeText={setSearchTerm} style={colors.input} placeholder="Search..." />
|
||||
{(searchTerm.length && !results.length) ? <Text>No results...</Text> : null}
|
||||
</Container>
|
||||
), [searchTerm, results, setSearchTerm]);
|
||||
@@ -105,13 +104,13 @@ export default function Search() {
|
||||
data={results}
|
||||
renderItem={({ item: { item: album } }) =>(
|
||||
<TouchableHandler id={album.Id} onPress={selectAlbum}>
|
||||
<SearchResult>
|
||||
<SearchResult style={colors.border}>
|
||||
<AlbumImage source={{ uri: getImage(album.Id) }} />
|
||||
<View>
|
||||
<Text numberOfLines={1} ellipsizeMode="tail">
|
||||
<Text numberOfLines={1} ellipsizeMode="tail" style={colors.text}>
|
||||
{album.Name} - {album.AlbumArtist}
|
||||
</Text>
|
||||
<HalfOpacity>Album</HalfOpacity>
|
||||
<HalfOpacity style={colors.text}>Album</HalfOpacity>
|
||||
</View>
|
||||
</SearchResult>
|
||||
</TouchableHandler>
|
||||
|
||||
@@ -14,7 +14,6 @@ const AlbumImage = styled(FastImage)`
|
||||
border-radius: 10px;
|
||||
width: ${Screen.width / 2 - 40}px;
|
||||
height: ${Screen.width / 2 - 40}px;
|
||||
background-color: #fefefe;
|
||||
margin-bottom: 5px;
|
||||
`;
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import styled from 'styled-components/native';
|
||||
|
||||
const ListContainer = styled.View`
|
||||
padding: 10px;
|
||||
background-color: #f6f6f6;
|
||||
`;
|
||||
|
||||
export default ListContainer;
|
||||
Reference in New Issue
Block a user