mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
feat: show error dialog on failed to login
This commit is contained in:
parent
15d466a045
commit
101c32523d
@ -20,6 +20,8 @@ class TokenLoginForm extends HookConsumerWidget {
|
|||||||
final keyCodeController = useTextEditingController();
|
final keyCodeController = useTextEditingController();
|
||||||
final mounted = useIsMounted();
|
final mounted = useIsMounted();
|
||||||
|
|
||||||
|
final isLoading = useState(false);
|
||||||
|
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxWidth: 400,
|
maxWidth: 400,
|
||||||
@ -45,7 +47,11 @@ class TokenLoginForm extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: () async {
|
onPressed: isLoading.value
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
if (keyCodeController.text.isEmpty ||
|
if (keyCodeController.text.isEmpty ||
|
||||||
directCodeController.text.isEmpty) {
|
directCodeController.text.isEmpty) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
@ -60,11 +66,15 @@ class TokenLoginForm extends HookConsumerWidget {
|
|||||||
"sp_dc=${directCodeController.text}; sp_key=${keyCodeController.text}";
|
"sp_dc=${directCodeController.text}; sp_key=${keyCodeController.text}";
|
||||||
|
|
||||||
authenticationNotifier.setCredentials(
|
authenticationNotifier.setCredentials(
|
||||||
await AuthenticationCredentials.fromCookie(cookieHeader),
|
await AuthenticationCredentials.fromCookie(
|
||||||
|
cookieHeader),
|
||||||
);
|
);
|
||||||
if (mounted()) {
|
if (mounted()) {
|
||||||
onDone?.call();
|
onDone?.call();
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: Text(context.l10n.submit),
|
child: Text(context.l10n.submit),
|
||||||
)
|
)
|
||||||
|
@ -4,6 +4,9 @@ import 'dart:convert';
|
|||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:http/http.dart';
|
import 'package:http/http.dart';
|
||||||
|
import 'package:spotube/collections/routes.dart';
|
||||||
|
import 'package:spotube/components/shared/dialogs/prompt_dialog.dart';
|
||||||
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/utils/persisted_state_notifier.dart';
|
import 'package:spotube/utils/persisted_state_notifier.dart';
|
||||||
import 'package:spotube/utils/platform.dart';
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
@ -21,7 +24,8 @@ class AuthenticationCredentials {
|
|||||||
});
|
});
|
||||||
|
|
||||||
static Future<AuthenticationCredentials> fromCookie(String cookie) async {
|
static Future<AuthenticationCredentials> fromCookie(String cookie) async {
|
||||||
final Map body = await get(
|
try {
|
||||||
|
final res = await get(
|
||||||
Uri.parse(
|
Uri.parse(
|
||||||
"https://open.spotify.com/get_access_token?reason=transport&productType=web_player",
|
"https://open.spotify.com/get_access_token?reason=transport&productType=web_player",
|
||||||
),
|
),
|
||||||
@ -30,7 +34,14 @@ class AuthenticationCredentials {
|
|||||||
"User-Agent":
|
"User-Agent":
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
|
||||||
},
|
},
|
||||||
).then((res) => jsonDecode(res.body));
|
);
|
||||||
|
final body = jsonDecode(res.body);
|
||||||
|
|
||||||
|
if (res.statusCode >= 400) {
|
||||||
|
throw Exception(
|
||||||
|
"Failed to get access token: ${body['error'] ?? res.reasonPhrase}",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return AuthenticationCredentials(
|
return AuthenticationCredentials(
|
||||||
cookie: cookie,
|
cookie: cookie,
|
||||||
@ -39,6 +50,18 @@ class AuthenticationCredentials {
|
|||||||
body['accessTokenExpirationTimestampMs'],
|
body['accessTokenExpirationTimestampMs'],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} catch (e) {
|
||||||
|
if (rootNavigatorKey?.currentContext != null) {
|
||||||
|
showPromptDialog(
|
||||||
|
context: rootNavigatorKey!.currentContext!,
|
||||||
|
title: rootNavigatorKey!.currentContext!.l10n
|
||||||
|
.error("Authentication Failure"),
|
||||||
|
message: e.toString(),
|
||||||
|
cancelText: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
factory AuthenticationCredentials.fromJson(Map<String, dynamic> json) {
|
factory AuthenticationCredentials.fromJson(Map<String, dynamic> json) {
|
||||||
|
Loading…
Reference in New Issue
Block a user