Skip to content

Commit a8e9b82

Browse files
committed
fix: alternative searched sources doesn't play #1059
1 parent 59e0e6b commit a8e9b82

File tree

8 files changed

+117
-21
lines changed

8 files changed

+117
-21
lines changed

assets/jiosaavn.png

13.7 KB
Loading

lib/collections/assets.gen.dart

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/collections/spotube_icons.dart

+1
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,5 @@ abstract class SpotubeIcons {
109109
static const normalize = FeatherIcons.barChart2;
110110
static const wikipedia = SimpleIcons.wikipedia;
111111
static const discord = SimpleIcons.discord;
112+
static const youtube = SimpleIcons.youtube;
112113
}

lib/components/player/sibling_tracks_sheet.dart

+48-6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
55
import 'package:flutter_hooks/flutter_hooks.dart';
66
import 'package:hooks_riverpod/hooks_riverpod.dart';
77
import 'package:spotify/spotify.dart' hide Offset;
8+
import 'package:spotube/collections/assets.gen.dart';
89
import 'package:spotube/collections/spotube_icons.dart';
910

1011
import 'package:spotube/components/shared/image/universal_image.dart';
@@ -19,10 +20,28 @@ import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
1920
import 'package:spotube/services/sourced_track/models/source_info.dart';
2021
import 'package:spotube/services/sourced_track/models/video_info.dart';
2122
import 'package:spotube/services/sourced_track/sourced_track.dart';
23+
import 'package:spotube/services/sourced_track/sources/jiosaavn.dart';
24+
import 'package:spotube/services/sourced_track/sources/piped.dart';
2225
import 'package:spotube/services/sourced_track/sources/youtube.dart';
2326
import 'package:spotube/utils/service_utils.dart';
2427
import 'package:spotube/utils/type_conversion_utils.dart';
2528

29+
final sourceInfoToIconMap = {
30+
YoutubeSourceInfo: const Icon(SpotubeIcons.youtube, color: Color(0xFFFF0000)),
31+
JioSaavnSourceInfo: Container(
32+
height: 30,
33+
width: 30,
34+
decoration: BoxDecoration(
35+
borderRadius: BorderRadius.circular(90),
36+
image: DecorationImage(
37+
image: Assets.jiosaavn.provider(),
38+
fit: BoxFit.cover,
39+
),
40+
),
41+
),
42+
PipedSourceInfo: const Icon(SpotubeIcons.piped),
43+
};
44+
2645
class SiblingTracksSheet extends HookConsumerWidget {
2746
final bool floating;
2847
const SiblingTracksSheet({
@@ -64,17 +83,34 @@ class SiblingTracksSheet extends HookConsumerWidget {
6483
return <SourceInfo>[];
6584
}
6685

67-
final results = await youtubeClient.search.search(searchTerm.trim());
86+
final resultsYt = await youtubeClient.search.search(searchTerm.trim());
87+
final resultsJioSaavn =
88+
await jiosaavnClient.search.songs(searchTerm.trim());
6889

69-
return await Future.wait(
70-
results.map(YoutubeVideoInfo.fromVideo).mapIndexed((i, video) async {
90+
final searchResults = await Future.wait([
91+
...resultsJioSaavn.results.mapIndexed((i, song) async {
92+
final siblingType = JioSaavnSourcedTrack.toSiblingType(song);
93+
return siblingType.info;
94+
}),
95+
...resultsYt
96+
.map(YoutubeVideoInfo.fromVideo)
97+
.mapIndexed((i, video) async {
7198
final siblingType = await YoutubeSourcedTrack.toSiblingType(i, video);
7299
return siblingType.info;
73100
}),
74-
);
101+
]);
102+
final activeSourceInfo =
103+
(playlist.activeTrack! as SourcedTrack).sourceInfo;
104+
return searchResults
105+
..removeWhere((element) => element.id == activeSourceInfo.id)
106+
..insert(
107+
0,
108+
activeSourceInfo,
109+
);
75110
}, [
76111
searchTerm,
77112
searchMode.value,
113+
playlist.activeTrack,
78114
]);
79115

80116
final siblings = useMemoized(
@@ -104,6 +140,7 @@ class SiblingTracksSheet extends HookConsumerWidget {
104140

105141
final itemBuilder = useCallback(
106142
(SourceInfo sourceInfo) {
143+
final icon = sourceInfoToIconMap[sourceInfo.runtimeType];
107144
return ListTile(
108145
title: Text(sourceInfo.title),
109146
leading: Padding(
@@ -118,7 +155,12 @@ class SiblingTracksSheet extends HookConsumerWidget {
118155
borderRadius: BorderRadius.circular(5),
119156
),
120157
trailing: Text(sourceInfo.duration.toHumanReadableString()),
121-
subtitle: Text(sourceInfo.artist),
158+
subtitle: Row(
159+
children: [
160+
if (icon != null) icon,
161+
Text(" • ${sourceInfo.artist}"),
162+
],
163+
),
122164
enabled: playlist.isFetching != true,
123165
selected: playlist.isFetching != true &&
124166
sourceInfo.id ==
@@ -137,7 +179,7 @@ class SiblingTracksSheet extends HookConsumerWidget {
137179
[playlist.isFetching, playlist.activeTrack, siblings],
138180
);
139181

140-
var mediaQuery = MediaQuery.of(context);
182+
final mediaQuery = MediaQuery.of(context);
141183
return SafeArea(
142184
child: ClipRRect(
143185
borderRadius: borderRadius,

lib/services/sourced_track/enums.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ enum SourceQualities {
1515
low,
1616
}
1717

18-
typedef SiblingType = ({SourceInfo info, SourceMap? source});
18+
typedef SiblingType<T extends SourceInfo> = ({T info, SourceMap? source});

lib/services/sourced_track/sources/jiosaavn.dart

+21-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ import 'package:spotube/extensions/string.dart';
1212

1313
final jiosaavnClient = JioSaavnClient();
1414

15+
class JioSaavnSourceInfo extends SourceInfo {
16+
JioSaavnSourceInfo({
17+
required super.id,
18+
required super.title,
19+
required super.artist,
20+
required super.thumbnail,
21+
required super.pageUrl,
22+
required super.duration,
23+
required super.artistUrl,
24+
required super.album,
25+
});
26+
}
27+
1528
class JioSaavnSourcedTrack extends SourcedTrack {
1629
JioSaavnSourcedTrack({
1730
required super.ref,
@@ -70,7 +83,7 @@ class JioSaavnSourcedTrack extends SourcedTrack {
7083

7184
static SiblingType toSiblingType(SongResponse result) {
7285
final SiblingType sibling = (
73-
info: SourceInfo(
86+
info: JioSaavnSourceInfo(
7487
artist: [
7588
result.primaryArtists,
7689
if (result.featuredArtists.isNotEmpty) ", ",
@@ -155,12 +168,16 @@ class JioSaavnSourcedTrack extends SourcedTrack {
155168

156169
@override
157170
Future<JioSaavnSourcedTrack?> swapWithSibling(SourceInfo sibling) async {
158-
if (sibling.id == sourceInfo.id ||
159-
siblings.none((s) => s.id == sibling.id)) {
171+
if (sibling.id == sourceInfo.id) {
160172
return null;
161173
}
162174

163-
final newSourceInfo = siblings.firstWhere((s) => s.id == sibling.id);
175+
// a sibling source that was fetched from the search results
176+
final isStepSibling = siblings.none((s) => s.id == sibling.id);
177+
178+
final newSourceInfo = isStepSibling
179+
? sibling
180+
: siblings.firstWhere((s) => s.id == sibling.id);
164181
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
165182
..insert(0, sourceInfo);
166183

lib/services/sourced_track/sources/piped.dart

+22-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ final pipedProvider = Provider<PipedClient>(
2222
},
2323
);
2424

25+
class PipedSourceInfo extends SourceInfo {
26+
PipedSourceInfo({
27+
required super.id,
28+
required super.title,
29+
required super.artist,
30+
required super.thumbnail,
31+
required super.pageUrl,
32+
required super.duration,
33+
required super.artistUrl,
34+
required super.album,
35+
});
36+
}
37+
2538
class PipedSourcedTrack extends SourcedTrack {
2639
PipedSourcedTrack({
2740
required super.ref,
@@ -71,7 +84,7 @@ class PipedSourcedTrack extends SourcedTrack {
7184
ref: ref,
7285
siblings: [],
7386
source: toSourceMap(manifest),
74-
sourceInfo: SourceInfo(
87+
sourceInfo: PipedSourceInfo(
7588
id: manifest.id,
7689
artist: manifest.uploader,
7790
artistUrl: manifest.uploaderUrl,
@@ -122,7 +135,7 @@ class PipedSourcedTrack extends SourcedTrack {
122135
}
123136

124137
final SiblingType sibling = (
125-
info: SourceInfo(
138+
info: PipedSourceInfo(
126139
id: item.id,
127140
artist: item.channelName,
128141
artistUrl: "https://www.youtube.com/${item.channelId}",
@@ -233,12 +246,16 @@ class PipedSourcedTrack extends SourcedTrack {
233246

234247
@override
235248
Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async {
236-
if (sibling.id == sourceInfo.id ||
237-
siblings.none((s) => s.id == sibling.id)) {
249+
if (sibling.id == sourceInfo.id) {
238250
return null;
239251
}
240252

241-
final newSourceInfo = siblings.firstWhere((s) => s.id == sibling.id);
253+
// a sibling source that was fetched from the search results
254+
final isStepSibling = siblings.none((s) => s.id == sibling.id);
255+
256+
final newSourceInfo = isStepSibling
257+
? sibling
258+
: siblings.firstWhere((s) => s.id == sibling.id);
242259
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
243260
..insert(0, sourceInfo);
244261

lib/services/sourced_track/sources/youtube.dart

+22-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ final officialMusicRegex = RegExp(
1717
caseSensitive: false,
1818
);
1919

20+
class YoutubeSourceInfo extends SourceInfo {
21+
YoutubeSourceInfo({
22+
required super.id,
23+
required super.title,
24+
required super.artist,
25+
required super.thumbnail,
26+
required super.pageUrl,
27+
required super.duration,
28+
required super.artistUrl,
29+
required super.album,
30+
});
31+
}
32+
2033
class YoutubeSourcedTrack extends SourcedTrack {
2134
YoutubeSourcedTrack({
2235
required super.source,
@@ -64,7 +77,7 @@ class YoutubeSourcedTrack extends SourcedTrack {
6477
ref: ref,
6578
siblings: [],
6679
source: toSourceMap(manifest),
67-
sourceInfo: SourceInfo(
80+
sourceInfo: YoutubeSourceInfo(
6881
id: item.id.value,
6982
artist: item.author,
7083
artistUrl: "https://www.youtube.com/channel/${item.channelId}",
@@ -117,7 +130,7 @@ class YoutubeSourcedTrack extends SourcedTrack {
117130
}
118131

119132
final SiblingType sibling = (
120-
info: SourceInfo(
133+
info: YoutubeSourceInfo(
121134
id: item.id,
122135
artist: item.channelName,
123136
artistUrl: "https://www.youtube.com/channel/${item.channelId}",
@@ -217,12 +230,16 @@ class YoutubeSourcedTrack extends SourcedTrack {
217230

218231
@override
219232
Future<YoutubeSourcedTrack?> swapWithSibling(SourceInfo sibling) async {
220-
if (sibling.id == sourceInfo.id ||
221-
siblings.none((s) => s.id == sibling.id)) {
233+
if (sibling.id == sourceInfo.id) {
222234
return null;
223235
}
224236

225-
final newSourceInfo = siblings.firstWhere((s) => s.id == sibling.id);
237+
// a sibling source that was fetched from the search results
238+
final isStepSibling = siblings.none((s) => s.id == sibling.id);
239+
240+
final newSourceInfo = isStepSibling
241+
? sibling
242+
: siblings.firstWhere((s) => s.id == sibling.id);
226243
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
227244
..insert(0, sourceInfo);
228245

0 commit comments

Comments
 (0)