Merge remote-tracking branch 'origin/main' into feat/adc/search-view-v2

This commit is contained in:
Clément Le Bihan
2023-12-04 23:48:14 +01:00
127 changed files with 12720 additions and 1629 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ const SongCardInfo = (props: SongCardInfoProps) => {
fontWeight: 'normal',
}}
>
{props.song.artistId}
{props.song.artist?.name}
</Text>
</View>
<Ionicons
-12
View File
@@ -1,12 +0,0 @@
import React from 'react';
export type NaviTab = {
id: string;
label: string;
icon?: React.ReactNode;
onPress?: () => void;
onLongPress?: () => void;
isActive?: boolean;
isCollapsed?: boolean;
iconName?: string;
};
@@ -1,86 +0,0 @@
import { View } from 'react-native';
import { Pressable, Text } from 'native-base';
import React from 'react';
type TabNavigationButtonProps = {
icon?: React.ReactNode;
label: string;
onPress: () => void;
onLongPress: () => void;
isActive: boolean;
isCollapsed: boolean;
};
const TabNavigationButton = (props: TabNavigationButtonProps) => {
return (
<Pressable
onPress={props.onPress}
onLongPress={props.onLongPress}
style={{
width: '100%',
}}
>
{({ isPressed, isHovered }) => {
let boxShadow: string | undefined = undefined;
if (isHovered) {
boxShadow = '0px 0px 16px 0px rgba(0, 0, 0, 0.25)';
} else if (props.isActive) {
boxShadow = '0px 0px 8px 0px rgba(0, 0, 0, 0.25)';
}
return (
<View
style={{
display: 'flex',
flexDirection: 'row',
alignSelf: 'stretch',
alignItems: 'center',
justifyContent: 'flex-start',
padding: 10,
borderRadius: 8,
flexGrow: 0,
// @ts-expect-error boxShadow isn't yet supported by react native
boxShadow: boxShadow,
backdropFilter: 'blur(2px)',
backgroundColor: (() => {
if (isPressed) {
return 'rgba(0, 0, 0, 0.1)';
} else if (isHovered) {
return 'rgba(231, 231, 232, 0.2)';
} else if (props.isActive) {
return 'rgba(16, 16, 20, 0.5)';
} else {
return 'transparent';
}
})(),
}}
>
{props.icon && (
<View
style={{
marginRight: props.isCollapsed ? undefined : 10,
}}
>
{props.icon}
</View>
)}
{!props.isCollapsed && (
<Text numberOfLines={1} selectable={false}>
{props.label}
</Text>
)}
</View>
);
}}
</Pressable>
);
};
TabNavigationButton.defaultProps = {
icon: undefined,
onPress: () => {},
onLongPress: () => {},
isActive: false,
isCollapsed: false,
};
export default TabNavigationButton;
@@ -1,179 +0,0 @@
import { View, Image } from 'react-native';
import { Divider, Text, Center, ScrollView } from 'native-base';
import TabNavigationButton from './TabNavigationButton';
import TabNavigationList from './TabNavigationList';
import { useAssets } from 'expo-asset';
import useColorScheme from '../../hooks/colorScheme';
import { useQuery, useQueries } from '../../Queries';
import { NaviTab } from './TabNavigation';
import API from '../../API';
import Song from '../../models/Song';
type TabNavigationDesktopProps = {
tabs: NaviTab[];
isCollapsed: boolean;
setIsCollapsed: (isCollapsed: boolean) => void;
activeTabID: string;
setActiveTabID: (id: string) => void;
children?: React.ReactNode;
};
const TabNavigationDesktop = (props: TabNavigationDesktopProps) => {
const colorScheme = useColorScheme();
const [icon] = useAssets(
colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png')
);
const playHistoryQuery = useQuery(API.getUserPlayHistory);
const songHistory = useQueries(
playHistoryQuery.data?.map(({ songID }) => API.getSong(songID)) ?? []
);
// settings is displayed separately (with logout)
const buttons = props.tabs.filter((tab) => tab.id !== 'settings');
return (
<View
style={{
display: 'flex',
flexDirection: 'row',
width: '100%',
height: '100%',
}}
>
<View>
<Center>
<View
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
flexShrink: 0,
padding: 10,
}}
>
<Image
source={{ uri: icon?.at(0)?.uri }}
style={{
aspectRatio: 1,
width: 40,
height: 'auto',
marginRight: 10,
}}
/>
<Text fontSize={'2xl'} selectable={false}>
Chromacase
</Text>
</View>
</Center>
<View
style={{
display: 'flex',
width: 300,
height: 'auto',
padding: 32,
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'flex-start',
flexGrow: 1,
}}
>
<TabNavigationList
style={{
flexShrink: 0,
gap: 20,
}}
>
{buttons.map((button, index) => (
<TabNavigationButton
key={'tab-navigation-button-' + index}
icon={button.icon}
label={button.label}
isActive={button.id == props.activeTabID}
onPress={button.onPress}
onLongPress={button.onLongPress}
isCollapsed={props.isCollapsed}
/>
))}
</TabNavigationList>
<TabNavigationList>
<Divider />
<TabNavigationList>
<Text
bold
style={{
paddingHorizontal: 16,
paddingVertical: 10,
fontSize: 20,
}}
>
Recently played
</Text>
{songHistory.length === 0 && (
<Text
style={{
paddingHorizontal: 16,
paddingVertical: 10,
}}
>
No songs played yet
</Text>
)}
{songHistory
.map((h) => h.data)
.filter((data): data is Song => data !== undefined)
.filter(
(song, i, array) =>
array.map((s) => s.id).findIndex((id) => id == song.id) == i
)
.slice(0, 4)
.map((histoItem, index) => (
<View
key={'tab-navigation-other-' + index}
style={{
paddingHorizontal: 16,
paddingVertical: 10,
}}
>
<Text numberOfLines={1}>{histoItem.name}</Text>
</View>
))}
</TabNavigationList>
<Divider />
<TabNavigationList
style={{
gap: 20,
}}
>
{([props.tabs.find((t) => t.id === 'settings')] as NaviTab[]).map(
(button, index) => (
<TabNavigationButton
key={'tab-navigation-setting-button-' + index}
icon={button.icon}
label={button.label}
isActive={button.id == props.activeTabID}
onPress={button.onPress}
onLongPress={button.onLongPress}
isCollapsed={props.isCollapsed}
/>
)
)}
</TabNavigationList>
</TabNavigationList>
</View>
</View>
<ScrollView
// @ts-expect-error Raw CSS
style={{
height: '100%',
width: 'calc(100% - 300px)',
}}
>
{props.children}
</ScrollView>
</View>
);
};
export default TabNavigationDesktop;
-28
View File
@@ -1,28 +0,0 @@
import React from 'react';
import { View, StyleProp, ViewStyle } from 'react-native';
type TabNavigationListProps = {
children: React.ReactNode;
style?: StyleProp<ViewStyle>;
};
const TabNavigationList = (props: TabNavigationListProps) => {
return (
<View
style={[
{
display: 'flex',
alignItems: 'flex-start',
alignSelf: 'stretch',
flexDirection: 'column',
gap: 8,
},
props.style,
]}
>
{props.children}
</View>
);
};
export default TabNavigationList;
@@ -1,71 +0,0 @@
import { View } from 'react-native';
import { Center, ScrollView } from 'native-base';
import TabNavigationButton from './TabNavigationButton';
import { NaviTab } from './TabNavigation';
type TabNavigationPhoneProps = {
tabs: NaviTab[];
activeTabID: string;
setActiveTabID: (id: string) => void;
children?: React.ReactNode;
};
const TabNavigationPhone = (props: TabNavigationPhoneProps) => {
return (
<View
style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column-reverse',
}}
>
<View
style={{
padding: 16,
height: 90,
width: '100%',
}}
>
<Center>
<View
style={{
display: 'flex',
padding: 8,
justifyContent: 'space-evenly',
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch',
borderRadius: 8,
backgroundColor: 'rgba(16, 16, 20, 0.5)',
}}
>
{props.tabs.map((tab) => (
<View key={'navigation-button-phone-' + tab.label}>
<TabNavigationButton
icon={tab.icon}
label={tab.label}
onPress={tab.onPress}
onLongPress={tab.onLongPress}
isActive={tab.id === props.activeTabID}
isCollapsed={tab.id != props.activeTabID}
/>
</View>
))}
</View>
</Center>
</View>
<ScrollView
// @ts-expect-error Raw CSS
style={{
width: '100%',
height: 'calc(100% - 90px)',
}}
>
{props.children}
</ScrollView>
</View>
);
};
export default TabNavigationPhone;