Skip to content

Commit

Permalink
fix: alternative searched sources doesn't play #1059
Browse files Browse the repository at this point in the history
  • Loading branch information
KRTirtho committed Jan 22, 2024
1 parent 59e0e6b commit a8e9b82
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 21 deletions.
Binary file added assets/jiosaavn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions lib/collections/assets.gen.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/collections/spotube_icons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,5 @@ abstract class SpotubeIcons {
static const normalize = FeatherIcons.barChart2;
static const wikipedia = SimpleIcons.wikipedia;
static const discord = SimpleIcons.discord;
static const youtube = SimpleIcons.youtube;
}
54 changes: 48 additions & 6 deletions lib/components/player/sibling_tracks_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart' hide Offset;
import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/collections/spotube_icons.dart';

import 'package:spotube/components/shared/image/universal_image.dart';
Expand All @@ -19,10 +20,28 @@ import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
import 'package:spotube/services/sourced_track/models/source_info.dart';
import 'package:spotube/services/sourced_track/models/video_info.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart';
import 'package:spotube/services/sourced_track/sources/jiosaavn.dart';
import 'package:spotube/services/sourced_track/sources/piped.dart';
import 'package:spotube/services/sourced_track/sources/youtube.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:spotube/utils/type_conversion_utils.dart';

final sourceInfoToIconMap = {
YoutubeSourceInfo: const Icon(SpotubeIcons.youtube, color: Color(0xFFFF0000)),
JioSaavnSourceInfo: Container(
height: 30,
width: 30,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(90),
image: DecorationImage(
image: Assets.jiosaavn.provider(),
fit: BoxFit.cover,
),
),
),
PipedSourceInfo: const Icon(SpotubeIcons.piped),
};

class SiblingTracksSheet extends HookConsumerWidget {
final bool floating;
const SiblingTracksSheet({
Expand Down Expand Up @@ -64,17 +83,34 @@ class SiblingTracksSheet extends HookConsumerWidget {
return <SourceInfo>[];
}

final results = await youtubeClient.search.search(searchTerm.trim());
final resultsYt = await youtubeClient.search.search(searchTerm.trim());
final resultsJioSaavn =
await jiosaavnClient.search.songs(searchTerm.trim());

return await Future.wait(
results.map(YoutubeVideoInfo.fromVideo).mapIndexed((i, video) async {
final searchResults = await Future.wait([
...resultsJioSaavn.results.mapIndexed((i, song) async {
final siblingType = JioSaavnSourcedTrack.toSiblingType(song);
return siblingType.info;
}),
...resultsYt
.map(YoutubeVideoInfo.fromVideo)
.mapIndexed((i, video) async {
final siblingType = await YoutubeSourcedTrack.toSiblingType(i, video);
return siblingType.info;
}),
);
]);
final activeSourceInfo =
(playlist.activeTrack! as SourcedTrack).sourceInfo;
return searchResults
..removeWhere((element) => element.id == activeSourceInfo.id)
..insert(
0,
activeSourceInfo,
);
}, [
searchTerm,
searchMode.value,
playlist.activeTrack,
]);

final siblings = useMemoized(
Expand Down Expand Up @@ -104,6 +140,7 @@ class SiblingTracksSheet extends HookConsumerWidget {

final itemBuilder = useCallback(
(SourceInfo sourceInfo) {
final icon = sourceInfoToIconMap[sourceInfo.runtimeType];
return ListTile(
title: Text(sourceInfo.title),
leading: Padding(
Expand All @@ -118,7 +155,12 @@ class SiblingTracksSheet extends HookConsumerWidget {
borderRadius: BorderRadius.circular(5),
),
trailing: Text(sourceInfo.duration.toHumanReadableString()),
subtitle: Text(sourceInfo.artist),
subtitle: Row(
children: [
if (icon != null) icon,
Text(" • ${sourceInfo.artist}"),
],
),
enabled: playlist.isFetching != true,
selected: playlist.isFetching != true &&
sourceInfo.id ==
Expand All @@ -137,7 +179,7 @@ class SiblingTracksSheet extends HookConsumerWidget {
[playlist.isFetching, playlist.activeTrack, siblings],
);

var mediaQuery = MediaQuery.of(context);
final mediaQuery = MediaQuery.of(context);
return SafeArea(
child: ClipRRect(
borderRadius: borderRadius,
Expand Down
2 changes: 1 addition & 1 deletion lib/services/sourced_track/enums.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ enum SourceQualities {
low,
}

typedef SiblingType = ({SourceInfo info, SourceMap? source});
typedef SiblingType<T extends SourceInfo> = ({T info, SourceMap? source});
25 changes: 21 additions & 4 deletions lib/services/sourced_track/sources/jiosaavn.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ import 'package:spotube/extensions/string.dart';

final jiosaavnClient = JioSaavnClient();

class JioSaavnSourceInfo extends SourceInfo {
JioSaavnSourceInfo({
required super.id,
required super.title,
required super.artist,
required super.thumbnail,
required super.pageUrl,
required super.duration,
required super.artistUrl,
required super.album,
});
}

class JioSaavnSourcedTrack extends SourcedTrack {
JioSaavnSourcedTrack({
required super.ref,
Expand Down Expand Up @@ -70,7 +83,7 @@ class JioSaavnSourcedTrack extends SourcedTrack {

static SiblingType toSiblingType(SongResponse result) {
final SiblingType sibling = (
info: SourceInfo(
info: JioSaavnSourceInfo(
artist: [
result.primaryArtists,
if (result.featuredArtists.isNotEmpty) ", ",
Expand Down Expand Up @@ -155,12 +168,16 @@ class JioSaavnSourcedTrack extends SourcedTrack {

@override
Future<JioSaavnSourcedTrack?> swapWithSibling(SourceInfo sibling) async {
if (sibling.id == sourceInfo.id ||
siblings.none((s) => s.id == sibling.id)) {
if (sibling.id == sourceInfo.id) {
return null;
}

final newSourceInfo = siblings.firstWhere((s) => s.id == sibling.id);
// a sibling source that was fetched from the search results
final isStepSibling = siblings.none((s) => s.id == sibling.id);

final newSourceInfo = isStepSibling
? sibling
: siblings.firstWhere((s) => s.id == sibling.id);
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
..insert(0, sourceInfo);

Expand Down
27 changes: 22 additions & 5 deletions lib/services/sourced_track/sources/piped.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@ final pipedProvider = Provider<PipedClient>(
},
);

class PipedSourceInfo extends SourceInfo {
PipedSourceInfo({
required super.id,
required super.title,
required super.artist,
required super.thumbnail,
required super.pageUrl,
required super.duration,
required super.artistUrl,
required super.album,
});
}

class PipedSourcedTrack extends SourcedTrack {
PipedSourcedTrack({
required super.ref,
Expand Down Expand Up @@ -71,7 +84,7 @@ class PipedSourcedTrack extends SourcedTrack {
ref: ref,
siblings: [],
source: toSourceMap(manifest),
sourceInfo: SourceInfo(
sourceInfo: PipedSourceInfo(
id: manifest.id,
artist: manifest.uploader,
artistUrl: manifest.uploaderUrl,
Expand Down Expand Up @@ -122,7 +135,7 @@ class PipedSourcedTrack extends SourcedTrack {
}

final SiblingType sibling = (
info: SourceInfo(
info: PipedSourceInfo(
id: item.id,
artist: item.channelName,
artistUrl: "https://www.youtube.com/${item.channelId}",
Expand Down Expand Up @@ -233,12 +246,16 @@ class PipedSourcedTrack extends SourcedTrack {

@override
Future<SourcedTrack?> swapWithSibling(SourceInfo sibling) async {
if (sibling.id == sourceInfo.id ||
siblings.none((s) => s.id == sibling.id)) {
if (sibling.id == sourceInfo.id) {
return null;
}

final newSourceInfo = siblings.firstWhere((s) => s.id == sibling.id);
// a sibling source that was fetched from the search results
final isStepSibling = siblings.none((s) => s.id == sibling.id);

final newSourceInfo = isStepSibling
? sibling
: siblings.firstWhere((s) => s.id == sibling.id);
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
..insert(0, sourceInfo);

Expand Down
27 changes: 22 additions & 5 deletions lib/services/sourced_track/sources/youtube.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@ final officialMusicRegex = RegExp(
caseSensitive: false,
);

class YoutubeSourceInfo extends SourceInfo {
YoutubeSourceInfo({
required super.id,
required super.title,
required super.artist,
required super.thumbnail,
required super.pageUrl,
required super.duration,
required super.artistUrl,
required super.album,
});
}

class YoutubeSourcedTrack extends SourcedTrack {
YoutubeSourcedTrack({
required super.source,
Expand Down Expand Up @@ -64,7 +77,7 @@ class YoutubeSourcedTrack extends SourcedTrack {
ref: ref,
siblings: [],
source: toSourceMap(manifest),
sourceInfo: SourceInfo(
sourceInfo: YoutubeSourceInfo(
id: item.id.value,
artist: item.author,
artistUrl: "https://www.youtube.com/channel/${item.channelId}",
Expand Down Expand Up @@ -117,7 +130,7 @@ class YoutubeSourcedTrack extends SourcedTrack {
}

final SiblingType sibling = (
info: SourceInfo(
info: YoutubeSourceInfo(
id: item.id,
artist: item.channelName,
artistUrl: "https://www.youtube.com/channel/${item.channelId}",
Expand Down Expand Up @@ -217,12 +230,16 @@ class YoutubeSourcedTrack extends SourcedTrack {

@override
Future<YoutubeSourcedTrack?> swapWithSibling(SourceInfo sibling) async {
if (sibling.id == sourceInfo.id ||
siblings.none((s) => s.id == sibling.id)) {
if (sibling.id == sourceInfo.id) {
return null;
}

final newSourceInfo = siblings.firstWhere((s) => s.id == sibling.id);
// a sibling source that was fetched from the search results
final isStepSibling = siblings.none((s) => s.id == sibling.id);

final newSourceInfo = isStepSibling
? sibling
: siblings.firstWhere((s) => s.id == sibling.id);
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
..insert(0, sourceInfo);

Expand Down

0 comments on commit a8e9b82

Please sign in to comment.