Skip to content

Commit

Permalink
Merge pull request #5 from sawyerf/sound
Browse files Browse the repository at this point in the history
Compatibility with android
  • Loading branch information
sawyerf authored Dec 25, 2024
2 parents c5ce8d3 + cf83ae8 commit 9ed087b
Show file tree
Hide file tree
Showing 62 changed files with 964 additions and 693 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ yarn-error.*

# typescript
*.tsbuildinfo

*.aab
*.apk
26 changes: 17 additions & 9 deletions App.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import React from 'react';
import { StatusBar } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { NavigationContainer } from '@react-navigation/native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import React from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';

import TabBar from '~/components/TabBar';
import TabBar from '~/components/bar/TabBar';
import { HomeStack, SearchStack, PlaylistsStack, SettingsStack } from '~/screens/Stacks';

import { ThemeContext, getTheme } from '~/contexts/theme';
import { ConfigContext, SetConfigContext, getConfig } from '~/contexts/config';
import { getSettings, SettingsContext, SetSettingsContext } from '~/contexts/settings';
import { initPlayer, initService } from '~/utils/player';
import { SongContext, defaultSong, songReducer } from '~/contexts/song';
import * as serviceWorkerRegistration from '~/services/serviceWorkerRegistration';
import { initPlayer, unloadSong } from '~/utils/player';
import { ThemeContext, getTheme } from '~/contexts/theme';

const Tab = createBottomTabNavigator();

Expand All @@ -32,7 +31,7 @@ const App = () => {
const [theme, setTheme] = React.useState(getTheme())

React.useEffect(() => {
if (!song.sound) initPlayer(dispatch)
if (!song.isInit) initPlayer(dispatch)
getConfig()
.then((config) => {
setConfig(config)
Expand All @@ -43,6 +42,10 @@ const App = () => {
})
}, [])

React.useEffect(() => {
if (window) window.config = config
}, [config])

React.useEffect(() => {
setTheme(getTheme(settings))
}, [settings.theme])
Expand Down Expand Up @@ -70,6 +73,11 @@ const App = () => {
}
}}
>
<StatusBar
backgroundColor={'rgba(0, 0, 0, 0)'}
translucent={true}
barStyle={'light-content'}
/>
<Tab.Navigator
tabBar={(props) => <TabBar {...props} />}
screenOptions={{
Expand Down Expand Up @@ -99,6 +107,6 @@ const App = () => {
);
}

serviceWorkerRegistration.register();
initService()

export default App;
19 changes: 15 additions & 4 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Castafiore",
"slug": "Castafiore",
"description": "Mobile app for navidrome",
"version": "2024.12.06",
"version": "2024.12.25",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
Expand All @@ -19,16 +19,27 @@
}
},
"android": {
"package": "com.sawyerf.castafiore",
"adaptiveIcon": {
"foregroundImage": "./assets/icon.png",
"backgroundColor": "#ffffff"
"foregroundImage": "./assets/foreground-icon.png",
"backgroundColor": "#660000"
},
"splash": {
"image": "./assets/foreground-icon.png",
"resizeMode": "contain",
"backgroundColor": "#660000"
}
},
"web": {
"shortName": "Castafiore",
"startUrl": "./index.html",
"backgroundColor": "#121212",
"theme_color": "#121212"
},
"extra": {
"eas": {
"projectId": "98d27f72-714e-415c-99f9-30f3f78d68e2"
}
}
}
}
}
3 changes: 1 addition & 2 deletions app/components/Header.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react'
import { View, Text, TextInput } from 'react-native'
import { View, Text } from 'react-native'
import { useNavigation } from '@react-navigation/native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import IconButton from '~/components/button/IconButton'
import presStyles from '~/styles/pres'
import { ThemeContext } from '~/contexts/theme'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Text, View, TouchableOpacity, Image } from 'react-native';
import { Text, View, TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { ConfigContext } from '~/contexts/config';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const SideBar = ({ state, descriptors, navigation }) => {
disabled={(!config.query && route.name !== 'Settings')}
>
<Icon name={options.icon} size={26} color={getColor()} style={{ marginRight: 10 }} />
<Text style={{ color: getColor(), textAlign: 'left', fontSize: 20, fontWeight: '550' }}>
<Text style={{ color: getColor(), textAlign: 'left', fontSize: 20, fontWeight: '600' }}>
{options.title}
</Text>
</TouchableOpacity>
Expand Down
4 changes: 2 additions & 2 deletions app/components/TabBar.js → app/components/bar/TabBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { ConfigContext } from '~/contexts/config';
import { SettingsContext } from '~/contexts/settings';

import Player from '~/components/player/Player';
import BottomBar from '~/components/Bar/BottomBar';
import SideBar from '~/components/Bar/SideBar';
import BottomBar from '~/components/bar/BottomBar';
import SideBar from '~/components/bar/SideBar';

const TabBar = ({ state, descriptors, navigation }) => {
const config = React.useContext(ConfigContext)
Expand Down
2 changes: 1 addition & 1 deletion app/components/button/BackButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const BackButton = () => {
}} onPress={() => navigation.goBack()}
icon="chevron-left"
size={23}
color={theme.primaryTouch}
color={theme.primaryLight}
/>
);
}
Expand Down
2 changes: 1 addition & 1 deletion app/components/button/RandomButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const RandomButton = ({ songList, size = 23 }) => {

const shuffleSong = () => {
if (songList?.length) {
playSong(config, song, songDispatch, shuffle(songList), 0)
playSong(config, songDispatch, shuffle(songList), 0)
}
}

Expand Down
5 changes: 3 additions & 2 deletions app/components/button/SlideBar.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { View, Pressable } from 'react-native'
import { View, Pressable, Platform } from 'react-native'

import { ThemeContext } from '~/contexts/theme'

Expand Down Expand Up @@ -45,7 +45,8 @@ const styles = {
height: sizeBitogno,
borderRadius: sizeBitogno / 2,
backgroundColor: theme.primaryTouch,
left: `calc(${vol * 100}% - ${sizeBitogno / 2}px)`, top: 7
left: Platform.OS === 'web' ? `calc(${vol * 100}% - ${sizeBitogno / 2}px)` : vol * 99 + '%', // TODO: fix calc native
top: 7
})
}

Expand Down
2 changes: 1 addition & 1 deletion app/components/lists/CustomScroll.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { View, Text, Image, ScrollView } from 'react-native';
import { View, ScrollView } from 'react-native';
import IconButton from '~/components/button/IconButton';
import { ThemeContext } from '~/contexts/theme';
import { SettingsContext } from '~/contexts/settings';
Expand Down
3 changes: 1 addition & 2 deletions app/components/lists/HorizontalAlbums.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Text, Image, ScrollView, TouchableOpacity } from 'react-native';
import { Text, Image, TouchableOpacity } from 'react-native';
import { useNavigation } from '@react-navigation/native';

import { ThemeContext } from '~/contexts/theme';
Expand Down Expand Up @@ -54,7 +54,6 @@ const HorizontalAlbums = ({ config, albums }) => {

const styles = {
album: {
// marginEnd: 20,
width: 160,
height: 210,
alignItems: 'center',
Expand Down
2 changes: 1 addition & 1 deletion app/components/lists/HorizontalArtists.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Text, Image, ScrollView, TouchableOpacity } from 'react-native';
import { Text, Image, TouchableOpacity } from 'react-native';
import { useNavigation } from '@react-navigation/native';

import { ThemeContext } from '~/contexts/theme';
Expand Down
2 changes: 1 addition & 1 deletion app/components/lists/HorizontalGenres.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Text, Image, ScrollView, TouchableOpacity } from 'react-native';
import { Text, TouchableOpacity } from 'react-native';
import { useNavigation } from '@react-navigation/native';

import { ThemeContext } from '~/contexts/theme';
Expand Down
9 changes: 1 addition & 8 deletions app/components/lists/HorizontalLBStat.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
import React from 'react';
import { Text, View } from 'react-native';

import { getCachedAndApi } from '~/utils/api';
import { ThemeContext } from '~/contexts/theme';
import { SettingsContext } from '~/contexts/settings';
import HorizontalAlbums from './HorizontalAlbums';
import HorizontalArtists from './HorizontalArtists';
import HorizontalGenres from './HorizontalGenres';
import mainStyles from '~/styles/main';
import RadioList from './RadioList';
import CustomScroll from '~/components/lists/CustomScroll';


const HorizontalLBStat = ({ config, stats }) => {
const HorizontalLBStat = ({ stats }) => {
const theme = React.useContext(ThemeContext)
const settings = React.useContext(SettingsContext)
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
const [maxCount, setMaxCount] = React.useState(0)

Expand Down
6 changes: 2 additions & 4 deletions app/components/lists/RadioList.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { ScrollView, View, Text, Image, TouchableOpacity, Linking } from 'react-native'
import { View, Text, TouchableOpacity, Linking } from 'react-native'
import Icon from 'react-native-vector-icons/FontAwesome';
import { useNavigation } from '@react-navigation/native';

Expand All @@ -18,7 +18,7 @@ const RadioList = ({ config, radios }) => {
const theme = React.useContext(ThemeContext)

const playRadio = (index) => {
playSong(config, song, songDispatch, radios.map(radio => ({
playSong(config, songDispatch, radios.map(radio => ({
id: radio.streamUrl,
title: radio.name,
artist: radio.homePageUrl ? radio.homePageUrl : 'Radio',
Expand Down Expand Up @@ -172,8 +172,6 @@ const styles = {
cardRadio: theme => ({
height: 60,
minWidth: 200,
// marginEnd: 10,
// marginBottom: 10,
padding: 10,
paddingEnd: 20,
backgroundColor: theme.secondaryDark,
Expand Down
8 changes: 4 additions & 4 deletions app/components/lists/SongsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const SongsList = ({ config, songs, isIndex = false, listToPlay = null, isMargin
onLongPress={() => setIndexOptions(index)}
onContextMenu={() => setIndexOptions(index)}
delayLongPress={200}
onPress={() => playSong(config, songCon, songDispatch, listToPlay ? listToPlay : songs, index)}>
onPress={() => playSong(config, songDispatch, listToPlay ? listToPlay : songs, index)}>
<Image
style={styles.albumCover}
source={{
Expand Down Expand Up @@ -77,9 +77,9 @@ const SongsList = ({ config, songs, isIndex = false, listToPlay = null, isMargin
.then((json) => {
if (!json.similarSongs?.song) {
setError('No similar songs found')
playSong(config, songCon, songDispatch, [songs[indexOptions]], 0)
playSong(config, songDispatch, [songs[indexOptions]], 0)
} else {
playSong(config, songCon, songDispatch, json.similarSongs?.song, 0)
playSong(config, songDispatch, json.similarSongs?.song, 0)
}
})
.catch((error) => { })
Expand All @@ -93,7 +93,7 @@ const SongsList = ({ config, songs, isIndex = false, listToPlay = null, isMargin
if (songCon.queue) {
songDispatch({ type: 'addQueue', queue: [songs[indexOptions]] })
} else {
playSong(config, songCon, songDispatch, [songs[indexOptions]], 0)
playSong(config, songDispatch, [songs[indexOptions]], 0)
}
setIndexOptions(-1)
}
Expand Down
28 changes: 16 additions & 12 deletions app/components/player/BoxDesktopPlayer.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import React from 'react';
import { Text, View, Platform } from 'react-native';
import { Text, View } from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';

import { ConfigContext } from '~/contexts/config';
import { SongContext } from '~/contexts/song';
import { ThemeContext } from '~/contexts/theme';
import { nextSong, pauseSong, resumeSong, previousSong, setPosition, secondToTime, setVolume } from '~/utils/player';
import { nextSong, pauseSong, resumeSong, previousSong, setPosition, secondToTime, setVolume, getVolume, updateVolume, setRepeat } from '~/utils/player';
import { urlCover } from '~/utils/api';
import mainStyles from '~/styles/main';
import IconButton from '~/components/button/IconButton';
import ImageError from '~/components/ImageError';
import SlideBar from '~/components/button/SlideBar';

const BoxDesktopPlayer = ({ fullscreen, time }) => {
const [song, songDispatch] = React.useContext(SongContext)
const [volume, setVol] = React.useState(getVolume())
const config = React.useContext(ConfigContext)
const theme = React.useContext(ThemeContext)

React.useEffect(() => {
return updateVolume(setVol)
}, [])

return (
<View
style={{
Expand All @@ -34,7 +38,7 @@ const BoxDesktopPlayer = ({ fullscreen, time }) => {
borderTopColor: theme.tertiaryDark,
}}>
<View style={{ flexDirection: 'row', flex: 1 }}>
<View style={{ ...styles.boxPlayerImage, flex: Platform.OS === 'android' ? 0 : 'initial' }}>
<View style={styles.boxPlayerImage}>
<ImageError
source={{ uri: urlCover(config, song?.songInfo?.albumId, 100), }}
style={styles.boxPlayerImage}
Expand All @@ -56,7 +60,7 @@ const BoxDesktopPlayer = ({ fullscreen, time }) => {
size={19}
color={song.actionEndOfSong == 'repeat' ? theme.primaryTouch : theme.secondaryLight}
onPress={() => {
songDispatch({ type: 'setActionEndOfSong', action: song.actionEndOfSong === 'repeat' ? 'next' : 'repeat' })
setRepeat(songDispatch, song.actionEndOfSong === 'repeat' ? 'next' : 'repeat')
}}
/>
<IconButton
Expand All @@ -69,7 +73,7 @@ const BoxDesktopPlayer = ({ fullscreen, time }) => {
icon={song.isPlaying ? 'pause' : 'play'}
size={19}
color={theme.primaryLight}
onPress={() => song.isPlaying ? pauseSong(song.sound) : resumeSong(song.sound)}
onPress={() => song.isPlaying ? pauseSong() : resumeSong()}
/>
<IconButton
icon="step-forward"
Expand All @@ -87,7 +91,7 @@ const BoxDesktopPlayer = ({ fullscreen, time }) => {
<Text style={{ color: theme.primaryLight, fontSize: 13 }}>{secondToTime(time.position)}</Text>
<SlideBar
progress={time.position / time.duration}
onPress={(progress) => setPosition(song.sound, progress * time.duration)}
onPress={(progress) => setPosition(progress * time.duration)}
stylePress={{ flex: 1, height: 6 }}
styleBar={{ width: '100%', height: '100%', borderRadius: 3, backgroundColor: theme.primaryLight, overflow: 'hidden' }}
styleProgress={{ backgroundColor: theme.primaryTouch }}
Expand All @@ -97,25 +101,25 @@ const BoxDesktopPlayer = ({ fullscreen, time }) => {
</View>
<View style={{ flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-end', marginEnd: 20, gap: 5 }} >
{
song?.sound?.volume ?
volume ?
<IconButton
icon="volume-up"
size={17}
color={theme.primaryLight}
style={{ width: 27 }}
onPress={() => song.sound.volume = 0}
onPress={() => setVolume(0)}
/>
: <IconButton
icon="volume-off"
size={17}
style={{ width: 27 }}
color={theme.primaryLight}
onPress={() => song.sound.volume = 1}
onPress={() => setVolume(1)}
/>
}
<SlideBar
progress={song.sound.volume}
onPress={(progress) => setVolume(song.sound ,progress)}
progress={volume}
onPress={(progress) => setVolume(progress)}
stylePress={{ maxWidth: 100, height: 25, paddingVertical: 10, width: '100%' }}
styleBar={{ width: '100%', height: '100%', borderRadius: 3, backgroundColor: theme.primaryLight, overflow: 'hidden' }}
styleProgress={{ backgroundColor: theme.primaryTouch }}
Expand Down
Loading

0 comments on commit 9ed087b

Please sign in to comment.