From 33ecbe066c1f6f425935a841f3c31ac1b2bb1c16 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Sun, 15 Sep 2024 10:31:20 +0600 Subject: [PATCH] feat(desktop): show error dialog if webview is not found on login #1871 --- lib/l10n/app_en.arb | 5 +- .../mobile_login/hooks/login_callback.dart | 87 ++++++---- .../no_webview_runtime_dialog.dart | 50 ++++++ untranslated_messages.json | 158 +++++++++++++++++- 4 files changed, 262 insertions(+), 38 deletions(-) create mode 100644 lib/pages/mobile_login/no_webview_runtime_dialog.dart diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 06a90d79..c63f8543 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -384,5 +384,8 @@ "summary_got_your_love": "Got your love", "summary_playlists": "playlists", "summary_were_on_repeat": "Were on repeat", - "total_money": "Total {money}" + "total_money": "Total {money}", + "webview_not_found": "Webview not found", + "webview_not_found_description": "No webview runtime is installed in your device.\nIf it's installed make sure it's in the Environment PATH\n\nAfter installing, restart the app", + "unsupported_platform": "Unsupported platform" } \ No newline at end of file diff --git a/lib/pages/mobile_login/hooks/login_callback.dart b/lib/pages/mobile_login/hooks/login_callback.dart index 815e81d0..1648da19 100644 --- a/lib/pages/mobile_login/hooks/login_callback.dart +++ b/lib/pages/mobile_login/hooks/login_callback.dart @@ -2,12 +2,14 @@ import 'dart:io'; import 'package:desktop_webview_window/desktop_webview_window.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:spotube/pages/mobile_login/mobile_login.dart'; +import 'package:spotube/pages/mobile_login/no_webview_runtime_dialog.dart'; import 'package:spotube/provider/authentication/authentication.dart'; import 'package:spotube/utils/platform.dart'; @@ -22,43 +24,56 @@ Future Function() useLoginCallback(WidgetRef ref) { return; } - final exp = RegExp(r"https:\/\/accounts.spotify.com\/.+\/status"); - final applicationSupportDir = await getApplicationSupportDirectory(); - final userDataFolder = - Directory(join(applicationSupportDir.path, "webview_window_Webview2")); + try { + final exp = RegExp(r"https:\/\/accounts.spotify.com\/.+\/status"); + final applicationSupportDir = await getApplicationSupportDirectory(); + final userDataFolder = Directory( + join(applicationSupportDir.path, "webview_window_Webview2")); - if (!await userDataFolder.exists()) { - await userDataFolder.create(); + if (!await userDataFolder.exists()) { + await userDataFolder.create(); + } + + final webview = await WebviewWindow.create( + configuration: CreateConfiguration( + title: "Spotify Login", + titleBarTopPadding: kIsMacOS ? 20 : 0, + windowHeight: 720, + windowWidth: 1280, + userDataFolderWindows: userDataFolder.path, + ), + ); + webview + ..setBrightness(theme.colorScheme.brightness) + ..launch("https://accounts.spotify.com/") + ..setOnUrlRequestCallback((url) { + if (exp.hasMatch(url)) { + webview.getAllCookies().then((cookies) async { + final cookieHeader = + "sp_dc=${cookies.firstWhere((element) => element.name.contains("sp_dc")).value.replaceAll("\u0000", "")}"; + + await authNotifier.login(cookieHeader); + + webview.close(); + if (context.mounted) { + context.go("/"); + } + }); + } + + return true; + }); + } on PlatformException catch (_) { + if (!await WebviewWindow.isWebviewAvailable()) { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + showDialog( + context: context, + builder: (context) { + return const NoWebviewRuntimeDialog(); + }, + ); + }); + } } - - final webview = await WebviewWindow.create( - configuration: CreateConfiguration( - title: "Spotify Login", - titleBarTopPadding: kIsMacOS ? 20 : 0, - windowHeight: 720, - windowWidth: 1280, - userDataFolderWindows: userDataFolder.path, - ), - ); - webview - ..setBrightness(theme.colorScheme.brightness) - ..launch("https://accounts.spotify.com/") - ..setOnUrlRequestCallback((url) { - if (exp.hasMatch(url)) { - webview.getAllCookies().then((cookies) async { - final cookieHeader = - "sp_dc=${cookies.firstWhere((element) => element.name.contains("sp_dc")).value.replaceAll("\u0000", "")}"; - - await authNotifier.login(cookieHeader); - - webview.close(); - if (context.mounted) { - context.go("/"); - } - }); - } - - return true; - }); }, [authNotifier, theme, context.go, context.pushNamed]); } diff --git a/lib/pages/mobile_login/no_webview_runtime_dialog.dart b/lib/pages/mobile_login/no_webview_runtime_dialog.dart new file mode 100644 index 00000000..a6cc5ffb --- /dev/null +++ b/lib/pages/mobile_login/no_webview_runtime_dialog.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:spotube/extensions/context.dart'; +import 'package:url_launcher/url_launcher_string.dart'; + +class NoWebviewRuntimeDialog extends StatelessWidget { + const NoWebviewRuntimeDialog({super.key}); + + @override + Widget build(BuildContext context) { + final ThemeData(:platform) = Theme.of(context); + + return AlertDialog( + title: Text(context.l10n.webview_not_found), + content: Text(context.l10n.webview_not_found_description), + actions: [ + TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(context.l10n.cancel), + ), + FilledButton( + onPressed: () async { + final url = switch (platform) { + TargetPlatform.windows => + 'https://developer.microsoft.com/en-us/microsoft-edge/webview2', + TargetPlatform.macOS => 'https://www.apple.com/safari/', + TargetPlatform.linux => + 'https://webkitgtk.org/reference/webkit2gtk/stable/', + _ => "", + }; + if (url.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Unsupported platform')), + ); + } + + await launchUrlString(url); + }, + child: Text(switch (platform) { + TargetPlatform.windows => 'Download Edge WebView2', + TargetPlatform.macOS => 'Download Safari', + TargetPlatform.linux => 'Download Webkit2Gtk', + _ => 'Download Webview', + }), + ), + ], + ); + } +} diff --git a/untranslated_messages.json b/untranslated_messages.json index 9e26dfee..01124edd 100644 --- a/untranslated_messages.json +++ b/untranslated_messages.json @@ -1 +1,157 @@ -{} \ No newline at end of file +{ + "ar": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "bn": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "ca": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "cs": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "de": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "es": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "eu": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "fa": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "fi": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "fr": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "hi": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "id": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "it": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "ja": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "ka": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "ko": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "ne": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "nl": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "pl": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "pt": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "ru": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "th": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "tr": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "uk": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "vi": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ], + + "zh": [ + "webview_not_found", + "webview_not_found_description", + "unsupported_platform" + ] +}