mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Playback track search retry-able now
Search page not rendering fix
This commit is contained in:
parent
e2bba4ac94
commit
c51a9a4c28
@ -67,7 +67,7 @@ class PlayerView extends HookConsumerWidget {
|
||||
),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15),
|
||||
child: Container(
|
||||
child: Material(
|
||||
color: paletteColor.color.withOpacity(.5),
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
|
@ -37,8 +37,8 @@ class Search extends HookConsumerWidget {
|
||||
}
|
||||
final searchSnapshot = ref.watch(searchQuery(searchTerm));
|
||||
|
||||
return SafeArea(
|
||||
child: Expanded(
|
||||
return Expanded(
|
||||
child: SafeArea(
|
||||
child: Container(
|
||||
color: Theme.of(context).backgroundColor,
|
||||
child: Column(
|
||||
|
@ -177,151 +177,155 @@ class TrackTile extends HookConsumerWidget {
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(isActive ? 10 : 0),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
width: 25,
|
||||
child: Text(
|
||||
(track.key + 1).toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
if (thumbnailUrl != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: breakpoint.isMoreThan(Breakpoints.md) ? 8.0 : 0,
|
||||
vertical: 8.0,
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 20,
|
||||
width: 25,
|
||||
child: Text(
|
||||
(track.key + 1).toString(),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||
child: CachedNetworkImage(
|
||||
placeholder: (context, url) {
|
||||
return Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
color: Theme.of(context).primaryColor,
|
||||
);
|
||||
},
|
||||
imageUrl: thumbnailUrl!,
|
||||
maxHeightDiskCache: 40,
|
||||
maxWidthDiskCache: 40,
|
||||
),
|
||||
if (thumbnailUrl != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: breakpoint.isMoreThan(Breakpoints.md) ? 8.0 : 0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(5)),
|
||||
child: CachedNetworkImage(
|
||||
placeholder: (context, url) {
|
||||
return Container(
|
||||
height: 40,
|
||||
width: 40,
|
||||
color: Theme.of(context).primaryColor,
|
||||
);
|
||||
},
|
||||
imageUrl: thumbnailUrl!,
|
||||
maxHeightDiskCache: 40,
|
||||
maxWidthDiskCache: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
playback.track?.id != null &&
|
||||
playback.track?.id == track.value.id
|
||||
? Icons.pause_circle_rounded
|
||||
: Icons.play_circle_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
onPressed: () => onTrackPlayButtonPressed?.call(
|
||||
track.value,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
playback.track?.id != null && playback.track?.id == track.value.id
|
||||
? Icons.pause_circle_rounded
|
||||
: Icons.play_circle_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
onPressed: () => onTrackPlayButtonPressed?.call(
|
||||
track.value,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
track.value.name ?? "",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: breakpoint.isSm ? 14 : 17,
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
track.value.name ?? "",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: breakpoint.isSm ? 14 : 17,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
artistsToClickableArtists(track.value.artists ?? [],
|
||||
textStyle: TextStyle(
|
||||
fontSize:
|
||||
breakpoint.isLessThan(Breakpoints.lg) ? 12 : 14)),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (breakpoint.isMoreThan(Breakpoints.md) && showAlbum)
|
||||
Expanded(
|
||||
child: LinkText(
|
||||
track.value.album!.name!,
|
||||
"/album/${track.value.album?.id}",
|
||||
extra: track.value.album,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
artistsToClickableArtists(track.value.artists ?? [],
|
||||
textStyle: TextStyle(
|
||||
fontSize:
|
||||
breakpoint.isLessThan(Breakpoints.lg) ? 12 : 14)),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (breakpoint.isMoreThan(Breakpoints.md) && showAlbum)
|
||||
Expanded(
|
||||
child: LinkText(
|
||||
track.value.album!.name!,
|
||||
"/album/${track.value.album?.id}",
|
||||
extra: track.value.album,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (!breakpoint.isSm) ...[
|
||||
if (!breakpoint.isSm) ...[
|
||||
const SizedBox(width: 10),
|
||||
Text(duration),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
Text(duration),
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.more_horiz_rounded),
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
if (auth.isLoggedIn)
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.add_box_rounded),
|
||||
SizedBox(width: 10),
|
||||
Text("Add to Playlist"),
|
||||
],
|
||||
),
|
||||
value: "add-playlist",
|
||||
),
|
||||
if (userPlaylist && auth.isLoggedIn)
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.remove_circle_outline_rounded),
|
||||
SizedBox(width: 10),
|
||||
Text("Remove from Playlist"),
|
||||
],
|
||||
),
|
||||
value: "remove-playlist",
|
||||
),
|
||||
if (auth.isLoggedIn)
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(isSaved
|
||||
? Icons.favorite_rounded
|
||||
: Icons.favorite_border_rounded),
|
||||
const SizedBox(width: 10),
|
||||
const Text("Favorite")
|
||||
],
|
||||
),
|
||||
value: "favorite",
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.share_rounded),
|
||||
SizedBox(width: 10),
|
||||
Text("Share")
|
||||
],
|
||||
),
|
||||
value: "share",
|
||||
)
|
||||
];
|
||||
},
|
||||
onSelected: (value) {
|
||||
switch (value) {
|
||||
case "favorite":
|
||||
actionFavorite(isSaved);
|
||||
break;
|
||||
case "add-playlist":
|
||||
actionAddToPlaylist();
|
||||
break;
|
||||
case "remove-playlist":
|
||||
actionRemoveFromPlaylist();
|
||||
break;
|
||||
case "share":
|
||||
actionShare(track.value);
|
||||
break;
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
PopupMenuButton(
|
||||
icon: const Icon(Icons.more_horiz_rounded),
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
if (auth.isLoggedIn)
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.add_box_rounded),
|
||||
SizedBox(width: 10),
|
||||
Text("Add to Playlist"),
|
||||
],
|
||||
),
|
||||
value: "add-playlist",
|
||||
),
|
||||
if (userPlaylist && auth.isLoggedIn)
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.remove_circle_outline_rounded),
|
||||
SizedBox(width: 10),
|
||||
Text("Remove from Playlist"),
|
||||
],
|
||||
),
|
||||
value: "remove-playlist",
|
||||
),
|
||||
if (auth.isLoggedIn)
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(isSaved
|
||||
? Icons.favorite_rounded
|
||||
: Icons.favorite_border_rounded),
|
||||
const SizedBox(width: 10),
|
||||
const Text("Favorite")
|
||||
],
|
||||
),
|
||||
value: "favorite",
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: const [
|
||||
Icon(Icons.share_rounded),
|
||||
SizedBox(width: 10),
|
||||
Text("Share")
|
||||
],
|
||||
),
|
||||
value: "share",
|
||||
)
|
||||
];
|
||||
},
|
||||
onSelected: (value) {
|
||||
switch (value) {
|
||||
case "favorite":
|
||||
actionFavorite(isSaved);
|
||||
break;
|
||||
case "add-playlist":
|
||||
actionAddToPlaylist();
|
||||
break;
|
||||
case "remove-playlist":
|
||||
actionRemoveFromPlaylist();
|
||||
break;
|
||||
case "share":
|
||||
actionShare(track.value);
|
||||
break;
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:async/async.dart';
|
||||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:audioplayers/audioplayers.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@ -227,6 +228,27 @@ class Playback extends PersistedChangeNotifier {
|
||||
player.dispose();
|
||||
}
|
||||
|
||||
Future<T> retryingOperation<T>(
|
||||
Future<T> Function() inner, {
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
T result;
|
||||
try {
|
||||
final operation = CancelableOperation.fromFuture(inner());
|
||||
result = await operation.value;
|
||||
await Future.delayed(timeout ?? const Duration(seconds: 5), () async {
|
||||
if (!operation.isCompleted) {
|
||||
operation.cancel();
|
||||
result = await inner();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
} catch (e) {
|
||||
result = await inner();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// playlist & track list methods
|
||||
Future<SpotubeTrack> toSpotubeTrack(Track track) async {
|
||||
final format = preferences.ytSearchFormat;
|
||||
@ -260,7 +282,8 @@ class Playback extends PersistedChangeNotifier {
|
||||
);
|
||||
ytVideo = VideoFromCacheTrackExtension.fromCacheTrack(cachedTrack);
|
||||
} else {
|
||||
VideoSearchList videos = await youtube.search.search(queryString);
|
||||
VideoSearchList videos =
|
||||
await retryingOperation(() => youtube.search.search(queryString));
|
||||
if (matchAlgorithm != SpotubeTrackMatchAlgorithm.youtube) {
|
||||
List<Map> ratedRankedVideos = videos
|
||||
.map((video) {
|
||||
@ -310,7 +333,9 @@ class Playback extends PersistedChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
final trackManifest = await youtube.videos.streams.getManifest(ytVideo.id);
|
||||
StreamManifest trackManifest = await retryingOperation(
|
||||
() => youtube.videos.streams.getManifest(ytVideo.id),
|
||||
);
|
||||
|
||||
_logger.v(
|
||||
"[YouTube Matched Track] ${ytVideo.title} | ${ytVideo.author} - ${ytVideo.url}",
|
||||
|
@ -37,7 +37,7 @@ packages:
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
async:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
|
@ -64,6 +64,7 @@ dependencies:
|
||||
dbus: ^0.7.3
|
||||
audioplayers: ^1.0.1
|
||||
resizable_widget: ^1.0.5
|
||||
async: ^2.8.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user