Skip to content

Commit a986f02

Browse files
committed
Add: Play similar songs for artists and albums
1 parent 6903f51 commit a986f02

File tree

5 files changed

+76
-24
lines changed

5 files changed

+76
-24
lines changed

app/components/options/OptionsAlbum.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11

2-
import React from 'react';
3-
import { Platform, Share } from 'react-native';
4-
import { useNavigation } from '@react-navigation/native';
5-
import { useTranslation } from 'react-i18next';
2+
import React from 'react'
3+
import { Platform, Share } from 'react-native'
4+
import { useNavigation } from '@react-navigation/native'
5+
import { useTranslation } from 'react-i18next'
66

7-
import { getApi } from '~/utils/api';
8-
import { ConfigContext } from '~/contexts/config';
9-
import OptionsPopup from '~/components/popup/OptionsPopup';
7+
import { getApi } from '~/utils/api'
8+
import { ConfigContext } from '~/contexts/config'
9+
import OptionsPopup from '~/components/popup/OptionsPopup'
10+
import { playSong } from '~/utils/player'
11+
import { SongDispatchContext } from '~/contexts/song'
12+
import { getApiNetworkFirst } from '~/utils/api'
1013

1114
const OptionsAlbum = ({ albums, indexOptions, setIndexOptions }) => {
12-
const { t } = useTranslation();
13-
const navigation = useNavigation();
15+
const { t } = useTranslation()
16+
const navigation = useNavigation()
1417
const config = React.useContext(ConfigContext)
1518
const refOption = React.useRef()
19+
const songDispatch = React.useContext(SongDispatchContext)
20+
21+
const playSimilarSongs = () => {
22+
getApiNetworkFirst(config, 'getSimilarSongs', `id=${albums[indexOptions].id}&count=50`)
23+
.then((json) => {
24+
if (json.similarSongs?.song) playSong(config, songDispatch, json.similarSongs.song, 0)
25+
})
26+
.catch(() => { })
27+
refOption.current.close()
28+
}
1629

1730
return (
1831
<OptionsPopup
@@ -21,6 +34,11 @@ const OptionsAlbum = ({ albums, indexOptions, setIndexOptions }) => {
2134
close={() => { setIndexOptions(-1) }}
2235
item={indexOptions >= 0 ? albums[indexOptions] : null}
2336
options={[
37+
{
38+
name: t('Play similar songs'),
39+
icon: 'play',
40+
onPress: playSimilarSongs
41+
},
2442
{
2543
name: t('Go to artist'),
2644
icon: 'user',
@@ -57,4 +75,4 @@ const OptionsAlbum = ({ albums, indexOptions, setIndexOptions }) => {
5775
)
5876
}
5977

60-
export default OptionsAlbum;
78+
export default OptionsAlbum

app/components/options/OptionsArtist.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,41 @@
1-
import React from 'react';
2-
import { useTranslation } from 'react-i18next';
1+
import React from 'react'
2+
import { useTranslation } from 'react-i18next'
33

4-
import OptionsPopup from '~/components/popup/OptionsPopup';
4+
import { ConfigContext } from '~/contexts/config'
5+
import { getApiNetworkFirst } from '~/utils/api'
6+
import { playSong } from '~/utils/player'
7+
import { SongDispatchContext } from '~/contexts/song'
8+
import OptionsPopup from '~/components/popup/OptionsPopup'
59

610
const OptionsArtist = ({ artists, indexOptions, setIndexOptions }) => {
7-
const { t } = useTranslation();
11+
const songDispatch = React.useContext(SongDispatchContext)
12+
const config = React.useContext(ConfigContext)
13+
const { t } = useTranslation()
814
const refOption = React.useRef()
915

16+
const playSimilarSongs = () => {
17+
getApiNetworkFirst(config, 'getSimilarSongs', `id=${artists[indexOptions].id}&count=50`)
18+
.then((json) => {
19+
if (json.similarSongs?.song) {
20+
playSong(config, songDispatch, json.similarSongs.song, 0)
21+
}
22+
})
23+
.catch(() => { })
24+
refOption.current.close()
25+
}
26+
1027
return (
1128
<OptionsPopup
1229
ref={refOption}
1330
visible={indexOptions >= 0}
1431
close={() => { setIndexOptions(-1) }}
1532
item={indexOptions >= 0 ? artists[indexOptions] : null}
1633
options={[
34+
{
35+
name: t('Play similar songs'),
36+
icon: 'play',
37+
onPress: playSimilarSongs
38+
},
1739
{
1840
name: t('Info'),
1941
icon: 'info',
@@ -27,4 +49,4 @@ const OptionsArtist = ({ artists, indexOptions, setIndexOptions }) => {
2749
)
2850
}
2951

30-
export default OptionsArtist;
52+
export default OptionsArtist

app/components/player/FullScreenHorizontalPlayer.js

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ import FavoritedButton from '~/components/button/FavoritedButton'
1111
import IconButton from '~/components/button/IconButton'
1212
import ImageError from '~/components/ImageError'
1313
import Lyric from '~/components/player/Lyric'
14+
import mainStyles from '~/styles/main'
15+
import OptionsQueue from '~/components/options/OptionsQueue'
16+
import PlayButton from '~/components/button/PlayButton'
1417
import Player from '~/utils/player'
1518
import size from '~/styles/size';
1619
import SlideBar from '~/components/button/SlideBar'
1720
import SlideControl from '~/components/button/SlideControl'
18-
import mainStyles from '~/styles/main'
19-
import PlayButton from '~/components/button/PlayButton'
2021

2122
const preview = {
2223
COVER: 0,
@@ -65,6 +66,7 @@ const TimeBar = () => {
6566
}
6667
const FullScreenHorizontalPlayer = ({ setFullScreen }) => {
6768
const [isPreview, setIsPreview] = React.useState(preview.COVER)
69+
const [indexOptions, setIndexOptions] = React.useState(-1)
6870
const config = React.useContext(ConfigContext)
6971
const insets = useSafeAreaInsets()
7072
const song = React.useContext(SongContext)
@@ -148,6 +150,12 @@ const FullScreenHorizontalPlayer = ({ setFullScreen }) => {
148150
{
149151
isPreview == preview.QUEUE &&
150152
<View style={{ flex: 1, maxWidth: '50%', justifyContent: 'flex-end' }}>
153+
<OptionsQueue
154+
queue={song.queue}
155+
indexOptions={indexOptions}
156+
setIndexOptions={setIndexOptions}
157+
closePlayer={() => setFullScreen(false)}
158+
/>
151159
<FlatList
152160
ref={scroll}
153161
onLayout={() => scroll.current.scrollToIndex({ index: song.index, animated: false, viewOffset: 0, viewPosition: 0.5 })}
@@ -160,15 +168,19 @@ const FullScreenHorizontalPlayer = ({ setFullScreen }) => {
160168
keyExtractor={(_, index) => index}
161169
renderItem={({ item, index }) => (
162170
<Pressable
171+
key={item.id}
163172
style={({ pressed }) => ([mainStyles.opacity({ pressed }), {
164173
flexDirection: 'row',
165174
alignItems: 'center',
166175
marginBottom: 10,
167176
}])}
168-
key={item.id}
169-
onPress={() => {
170-
Player.setIndex(config, songDispatch, song.queue, index)
171-
}}>
177+
onPress={() => Player.setIndex(config, songDispatch, song.queue, index)}
178+
onLongPress={() => setIndexOptions(index)}
179+
onContextMenu={(ev) => {
180+
ev.preventDefault()
181+
return setIndexOptions(index)
182+
}}
183+
>
172184
<View style={{ flex: 1, flexDirection: 'column' }}>
173185
<Text numberOfLines={1} style={{ color: song.index === index ? theme.primaryTouch : color.primary, fontSize: size.text.medium, marginBottom: 2, textAlign: 'right' }}>
174186
{item.title}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "castafiore",
3-
"version": "2025.08.05",
3+
"version": "2025.08.20",
44
"main": "index.js",
55
"homepage": ".",
66
"scripts": {

0 commit comments

Comments
 (0)