moooore styling

started albums
these commits are messy
This commit is contained in:
austinried
2021-06-19 17:19:49 +09:00
parent f19cbabac4
commit c9b096d347
29 changed files with 312 additions and 55 deletions

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { Image, ImageSourcePropType } from 'react-native';
import { primary } from '../styles/colors';
export type FocusableIconProps = {
focused: boolean,
@@ -11,12 +12,16 @@ export type FocusableIconProps = {
const FocusableIcon: React.FC<FocusableIconProps> = (props) => {
props.focusedSource = props.focusedSource || props.source;
props.width = props.width || 32;
props.height = props.height || 32;
props.width = props.width || 26;
props.height = props.height || 26;
return (
<Image
style={{ height: props.height, width: props.width }}
style={{
height: props.height,
width: props.width,
tintColor: props.focused ? primary.focused : primary.blurred,
}}
source={props.focused ? props.focusedSource : props.source}
/>
);

View File

@@ -1,63 +1,144 @@
import React from 'react';
import { Text, View, Image } from 'react-native';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import React, { ReactComponentElement } from 'react';
import { Text, View, Image, FlatList } from 'react-native';
import { createMaterialTopTabNavigator, MaterialTopTabBarProps } from '@react-navigation/material-top-tabs';
import { NavigationContainer } from '@react-navigation/native';
import { Artist } from '../models/music';
import { useRecoilValue } from 'recoil';
import { artistsState } from '../state/artists';
import LinearGradient from 'react-native-linear-gradient';
import { primary } from '../styles/colors';
import text from '../styles/text';
const SectionHeader: React.FC<{ title: string }> = ({ title }) => {
const TabView: React.FC<{}> = ({ children }) => (
<LinearGradient
colors={['#383838', '#000000']}
// colors={['#395266', '#06172d']}
// start={{x: 0.0, y: 0.25}} end={{x: 0.5, y: 1.0}}
locations={[0.05,0.75]}
style={{
flex: 1,
}}
>
{children}
</LinearGradient>
);
const Albums = () => (
<TabView>
</TabView>
);
const Playlists = () => (
<TabView>
</TabView>
);
const ArtistItem: React.FC<{ item: Artist } > = ({ item }) => (
<View style={{
flexDirection: 'row',
alignItems: 'center',
// height: 56,
marginVertical: 6,
marginLeft: 6,
}}>
<Image
source={item.coverArt ? { uri: 'https://reactnative.dev/img/tiny_logo.png' } : require('../../res/mic_on-fill.png')}
style={{
width: 56,
height: 56,
// tintColor: 'white',
}}
/>
<Text style={{
...text.regular,
marginLeft: 12,
}}>{item.name}</Text>
</View>
);
const Artists = () => {
const artists = useRecoilValue(artistsState);
const renderItem: React.FC<{ item: Artist }> = ({ item }) => (
<ArtistItem item={item} />
);
return (
<TabView>
<FlatList
data={artists}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</TabView>
);
}
const TabBar: React.FC<MaterialTopTabBarProps> = ({ state, descriptors }) => {
return (
<View style={{
height: 60,
height: 48,
backgroundColor: '#383838',
flexDirection: 'row',
justifyContent: 'space-between',
// backgroundColor: 'green',
alignItems: 'center',
paddingLeft: 15,
paddingRight: 15,
justifyContent: 'space-around',
}}>
<Text style={{
color: 'white',
fontSize: 22,
fontFamily: 'Lato-Black',
}}>{title}</Text>
<Image
style={{
width: 32,
height: 32,
tintColor: 'white',
}}
source={require('../../res/chevron_right-fill.png')}
/>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const fontFamily = isFocused ? 'Ubuntu-Regular' : 'Ubuntu-Light';
const color = isFocused ? primary.focused : primary.blurred;
const borderBottomColor = isFocused ? primary.focused : '#383838';
return (
<View style={{
borderBottomColor,
borderBottomWidth: 2,
borderBottomLeftRadius: 2,
borderBottomEndRadius: 2,
paddingBottom: 5,
width: 100,
justifyContent: 'center',
flexDirection: 'row',
}}>
<Text style={{
...text.header,
fontFamily, color
}}>{label}</Text>
</View>
);
})}
</View>
);
}
const Tab = createMaterialTopTabNavigator();
const Albums = () => (
<SectionHeader title='Albums' />
);
const Artists = () => (
<SectionHeader title='Artists' />
);
const Playlists = () => (
<SectionHeader title='Playlists' />
);
const Library = () => (
<Tab.Navigator>
<Tab.Screen
name='Albums'
component={Albums}
/>
<Tab.Screen
name='Artists'
component={Artists}
/>
<Tab.Screen
name='Playlists'
component={Playlists}
/>
</Tab.Navigator>
<View style={{
flex: 1,
}}>
<Tab.Navigator tabBar={TabBar}>
<Tab.Screen
name='Albums'
component={Albums}
/>
<Tab.Screen
name='Artists'
component={Artists}
/>
<Tab.Screen
name='Playlists'
component={Playlists}
/>
</Tab.Navigator>
</View>
);
export default Library;

View File

@@ -10,7 +10,15 @@ const Tab = createBottomTabNavigator();
const TabNavigator = () => {
return (
<Tab.Navigator>
<Tab.Navigator
tabBarOptions={{
style: {
backgroundColor: '#383838',
borderTopColor: '#383838',
height: 44,
},
}}
>
<Tab.Screen
name='Home'
component={ArtistsList}

View File

@@ -1,4 +1,10 @@
export interface Artist {
id: string;
name: string;
coverArt?: string;
}
export interface Album {
id: string;
name: string;
}

41
src/state/albums.ts Normal file
View File

@@ -0,0 +1,41 @@
import { atom, DefaultValue, selector, useRecoilValue, useSetRecoilState } from 'recoil';
import { SubsonicApiClient } from '../subsonic/api';
import { activeServer } from './settings'
import { Artist } from '../models/music';
import { musicDb } from '../clients';
export const albumsState = atom<Artist[]>({
key: 'albumsState',
default: selector({
key: 'albumsState/default',
get: () => musicDb.getAlbums(),
}),
effects_UNSTABLE: [
({ onSet }) => {
onSet((newValue) => {
if (!(newValue instanceof DefaultValue)) {
musicDb.updateAlbums(newValue);
}
});
}
],
});
// export const useUpdateAlbums = () => {
// const setAlbums = useSetRecoilState(albumsState);
// const server = useRecoilValue(activeServer);
// return async () => {
// if (!server) {
// return;
// }
// const client = new SubsonicApiClient(server.address, server.username, server.token, server.salt);
// const response = await client.getAlbums();
// setAlbums(response.data.albums.map(i => ({
// id: i.id,
// name: i.name,
// })));
// };
// };

View File

@@ -33,9 +33,10 @@ export const useUpdateArtists = () => {
const client = new SubsonicApiClient(server.address, server.username, server.token, server.salt);
const response = await client.getArtists();
setArtists(response.data.artists.map(i => ({
id: i.id,
name: i.name,
setArtists(response.data.artists.map(x => ({
id: x.id,
name: x.name,
coverArt: x.coverArt,
})));
};
};

View File

@@ -1,4 +1,4 @@
import { Artist } from '../models/music';
import { Album, Artist } from '../models/music';
import { DbStorage } from './db';
export class MusicDb extends DbStorage {
@@ -10,6 +10,14 @@ export class MusicDb extends DbStorage {
await this.initDb(tx => {
tx.executeSql(`
CREATE TABLE artists (
id TEXT PRIMARY KEY NOT NULL,
name TEXT NOT NULL,
starred INTEGER NOT NULL,
coverArt TEXT
);
`);
tx.executeSql(`
CREATE TABLE albums (
id TEXT PRIMARY KEY NOT NULL,
name TEXT NOT NULL,
starred INTEGER NOT NULL
@@ -24,6 +32,7 @@ export class MusicDb extends DbStorage {
`))[0].rows.raw().map(x => ({
id: x.id,
name: x.name,
coverArt: x.coverArt || undefined,
}));
}
@@ -34,7 +43,30 @@ export class MusicDb extends DbStorage {
`);
for (const a of artists) {
tx.executeSql(`
INSERT INTO artists (id, name, starred)
INSERT INTO artists (id, name, starred, coverArt)
VALUES (?, ?, ?, ?);
`, [a.id, a.name, false, a.coverArt || null]);
}
});
}
async getAlbums(): Promise<Album[]> {
return (await this.executeSql(`
SELECT * FROM albums;
`))[0].rows.raw().map(x => ({
id: x.id,
name: x.name,
}));
}
async updateAlbums(albums: Album[]): Promise<void> {
await this.transaction((tx) => {
tx.executeSql(`
DELETE FROM albums
`);
for (const a of albums) {
tx.executeSql(`
INSERT INTO albums (id, name, starred)
VALUES (?, ?, ?);
`, [a.id, a.name, false]);
}

6
src/styles/colors.ts Normal file
View File

@@ -0,0 +1,6 @@
import { StyleSheet } from "react-native";
export const primary = {
focused: '#fff',
blurred: '#bababa',
}

21
src/styles/text.ts Normal file
View File

@@ -0,0 +1,21 @@
import { StyleSheet, TextStyle } from "react-native";
const regular: TextStyle = {
fontFamily: 'Ubuntu-Light',
fontSize: 18,
color: '#fff',
};
const header: TextStyle = {
...regular,
fontSize: 22,
};
export type TextStyles = {
[key: string]: TextStyle,
}
export default {
regular,
header,
};