feat: show error dialog on piped API 500 error

This commit is contained in:
Kingkor Roy Tirtho 2023-08-15 13:00:38 +06:00
parent c94e5ba430
commit c69f81ec6f
5 changed files with 143 additions and 29 deletions

View File

@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/provider/user_preferences_provider.dart';
class PipedDownDialog extends HookConsumerWidget {
const PipedDownDialog({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, ref) {
final pipedInstance =
ref.watch(userPreferencesProvider.select((s) => s.pipedInstance));
final ThemeData(:colorScheme) = Theme.of(context);
return AlertDialog(
insetPadding: const EdgeInsets.all(6),
contentPadding: const EdgeInsets.all(6),
icon: Icon(
SpotubeIcons.error,
color: colorScheme.error,
),
title: Text(
context.l10n.piped_api_down,
style: TextStyle(color: colorScheme.error),
),
content: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child:
Text(context.l10n.piped_down_error_instructions(pipedInstance)),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(context.l10n.ok),
),
FilledButton(
onPressed: () => Navigator.pop(context),
child: Text(context.l10n.settings),
),
],
);
}
}

View File

@ -254,5 +254,7 @@
"ok": "Ok", "ok": "Ok",
"failed_to_encrypt": "Failed to encrypt", "failed_to_encrypt": "Failed to encrypt",
"encryption_failed_warning": "Spotube uses encryption to securely store your data. But failed to do so. So it'll fallback to insecure storage\nIf you're using linux, please make sure you've any secret-service (gnome-keyring, kde-wallet, keepassxc etc) installed", "encryption_failed_warning": "Spotube uses encryption to securely store your data. But failed to do so. So it'll fallback to insecure storage\nIf you're using linux, please make sure you've any secret-service (gnome-keyring, kde-wallet, keepassxc etc) installed",
"querying_info": "Querying info..." "querying_info": "Querying info...",
"piped_api_down": "Piped API is down",
"piped_down_error_instructions": "The Piped instance {pipedInstance} is currently down\n\nEither change the instance or change the 'API type' to official YouTube API\n\nMake sure to restart the app after change"
} }

View File

@ -66,19 +66,17 @@ class SpotubeTrack extends Track {
await client.search("$title - ${artists.join(", ")}").then( await client.search("$title - ${artists.join(", ")}").then(
(res) { (res) {
final siblings = res final siblings = res
.sorted((a, b) => a.views.compareTo(b.views))
.where((item) { .where((item) {
return artists.any( return artists.any(
(artist) => (artist) =>
client.preferences.searchMode == SearchMode.youtube ||
artist.toLowerCase() == item.channelName.toLowerCase(), artist.toLowerCase() == item.channelName.toLowerCase(),
); );
}) })
.take(10) .take(10)
.toList(); .toList();
if (siblings.isEmpty) {
return res.take(10).toList();
}
return siblings; return siblings;
}, },
); );

View File

@ -1,5 +1,8 @@
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:piped_client/piped_client.dart'; import 'package:piped_client/piped_client.dart';
import 'package:spotube/collections/routes.dart';
import 'package:spotube/components/shared/dialogs/piped_down_dialog.dart';
import 'package:spotube/models/matched_track.dart'; import 'package:spotube/models/matched_track.dart';
import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/utils/primitive_utils.dart'; import 'package:spotube/utils/primitive_utils.dart';
@ -133,6 +136,18 @@ class YoutubeEndpoints {
} }
} }
Future<void> showPipedErrorDialog(Exception e) async {
if (e is DioException && (e.response?.statusCode ?? 0) >= 500) {
final context = rootNavigatorKey?.currentContext;
if (context != null) {
await showDialog(
context: context,
builder: (context) => const PipedDownDialog(),
);
}
}
}
Future<List<YoutubeVideoInfo>> search(String query) async { Future<List<YoutubeVideoInfo>> search(String query) async {
if (youtube != null) { if (youtube != null) {
final res = await youtube!.search( final res = await youtube!.search(
@ -142,6 +157,7 @@ class YoutubeEndpoints {
return res.map(YoutubeVideoInfo.fromVideo).toList(); return res.map(YoutubeVideoInfo.fromVideo).toList();
} else { } else {
try {
final res = await piped!.search( final res = await piped!.search(
query, query,
switch (preferences.searchMode) { switch (preferences.searchMode) {
@ -158,6 +174,10 @@ class YoutubeEndpoints {
), ),
) )
.toList(); .toList();
} on Exception catch (e) {
await showPipedErrorDialog(e);
rethrow;
}
} }
} }
@ -193,7 +213,9 @@ class YoutubeEndpoints {
} }
Future<(YoutubeVideoInfo info, String streamingUrl)> video( Future<(YoutubeVideoInfo info, String streamingUrl)> video(
String id, SearchMode searchMode) async { String id,
SearchMode searchMode,
) async {
if (youtube != null) { if (youtube != null) {
final res = await youtube!.videos.get(id); final res = await youtube!.videos.get(id);
return ( return (
@ -201,11 +223,16 @@ class YoutubeEndpoints {
await streamingUrl(id), await streamingUrl(id),
); );
} else { } else {
try {
final res = await piped!.streams(id); final res = await piped!.streams(id);
return ( return (
YoutubeVideoInfo.fromStreamResponse(res, searchMode), YoutubeVideoInfo.fromStreamResponse(res, searchMode),
_pipedStreamResponseToStreamUrl(res), _pipedStreamResponseToStreamUrl(res),
); );
} on Exception catch (e) {
await showPipedErrorDialog(e);
rethrow;
}
} }
} }
} }

View File

@ -1 +1,42 @@
{} {
"bn": [
"piped_api_down",
"piped_down_error_instructions"
],
"ca": [
"querying_info",
"piped_api_down",
"piped_down_error_instructions"
],
"de": [
"piped_api_down",
"piped_down_error_instructions"
],
"es": [
"piped_api_down",
"piped_down_error_instructions"
],
"fr": [
"piped_api_down",
"piped_down_error_instructions"
],
"hi": [
"piped_api_down",
"piped_down_error_instructions"
],
"ja": [
"piped_api_down",
"piped_down_error_instructions"
],
"zh": [
"piped_api_down",
"piped_down_error_instructions"
]
}