diff --git a/lib/pages/desktop_login/desktop_login.dart b/lib/pages/desktop_login/desktop_login.dart index 9c061091..21249649 100644 --- a/lib/pages/desktop_login/desktop_login.dart +++ b/lib/pages/desktop_login/desktop_login.dart @@ -73,4 +73,4 @@ class DesktopLoginPage extends HookConsumerWidget { ), ); } -} +} \ No newline at end of file diff --git a/lib/pages/mobile_login/mobile_login.dart b/lib/pages/mobile_login/mobile_login.dart index 0a1ff8b3..65c0fb73 100644 --- a/lib/pages/mobile_login/mobile_login.dart +++ b/lib/pages/mobile_login/mobile_login.dart @@ -1,3 +1,4 @@ +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:go_router/go_router.dart'; @@ -6,6 +7,9 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/utils/platform.dart'; +const _userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"; + class WebViewLogin extends HookConsumerWidget { const WebViewLogin({super.key}); @@ -14,7 +18,7 @@ class WebViewLogin extends HookConsumerWidget { final authenticationNotifier = ref.watch(authenticationProvider.notifier); if (kIsDesktop) { - const Scaffold( + return const Scaffold( body: Center( child: Text('This feature is not available on desktop'), ), @@ -24,9 +28,16 @@ class WebViewLogin extends HookConsumerWidget { return Scaffold( body: SafeArea( child: InAppWebView( + master + initialOptions: InAppWebViewGroupOptions( + crossPlatform: InAppWebViewOptions( + userAgent: _userAgent, + ), + initialSettings: InAppWebViewSettings( userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 afari/537.36", + master ), initialUrlRequest: URLRequest( url: WebUri("https://accounts.spotify.com/"), @@ -49,8 +60,19 @@ class WebViewLogin extends HookConsumerWidget { if (exp.hasMatch(url)) { final cookies = await CookieManager.instance().getCookies(url: action); - final cookieHeader = - "sp_dc=${cookies.firstWhere((element) => element.name == "sp_dc").value}"; + final spDcCookie = cookies.firstWhereOrNull((element) => element.name == "sp_dc"); + + if (spDcCookie != null) { + final cookieHeader = "sp_dc=${spDcCookie.value}"; + +master + authenticationNotifier.setCredentials( + await AuthenticationCredentials.fromCookie(cookieHeader), + ); + if (mounted()) { + // ignore: use_build_context_synchronously + GoRouter.of(context).pushReplacementNamed("/"); + } authenticationNotifier.setCredentials( await AuthenticationCredentials.fromCookie(cookieHeader), @@ -58,6 +80,7 @@ class WebViewLogin extends HookConsumerWidget { if (context.mounted) { // ignore: use_build_context_synchronously GoRouter.of(context).go("/"); + master } } }, @@ -65,4 +88,4 @@ class WebViewLogin extends HookConsumerWidget { ), ); } -} +} \ No newline at end of file diff --git a/lib/pages/search/search.dart b/lib/pages/search/search.dart index e9ada236..d33a891f 100644 --- a/lib/pages/search/search.dart +++ b/lib/pages/search/search.dart @@ -96,6 +96,24 @@ class SearchPage extends HookConsumerWidget { vertical: 10, ), color: theme.scaffoldBackgroundColor, +master + child: TextField( + autofocus: queries + .none((s) => s.hasPageData && !s.hasPageError) && + !kIsMobile, + decoration: InputDecoration( + prefixIcon: const Icon(SpotubeIcons.search), + hintText: "${context.l10n.search}...", + ), + onChanged: (value) async { + ref.read(searchTermStateProvider.notifier).state = + value; + // Fl-Query is too fast, so we need to delay the search + // to prevent spamming the API :) + Timer(const Duration(milliseconds: 50), () { + onSearch(); + }); + child: SearchAnchor( searchController: controller, viewBuilder: (_) => HookBuilder(builder: (context) { @@ -176,6 +194,7 @@ class SearchPage extends HookConsumerWidget { onTap: controller.openView, onChanged: (_) => controller.openView(), ); +master }, ), ), diff --git a/lib/provider/authentication_provider.dart b/lib/provider/authentication_provider.dart index c94f4f3e..4e513484 100644 --- a/lib/provider/authentication_provider.dart +++ b/lib/provider/authentication_provider.dart @@ -183,4 +183,4 @@ class AuthenticationNotifier final authenticationProvider = StateNotifierProvider( (ref) => AuthenticationNotifier(), -); +); \ No newline at end of file diff --git a/lib/themes/theme.dart b/lib/themes/theme.dart index 51e98269..2d0a457b 100644 --- a/lib/themes/theme.dart +++ b/lib/themes/theme.dart @@ -8,6 +8,10 @@ ThemeData theme(Color seed, Brightness brightness, bool isAmoled) { surface: isAmoled ? Colors.black : null, brightness: brightness, ); + + const borderRadius = BorderRadius.all(Radius.circular(15)); + const roundedRectangleBorder = RoundedRectangleBorder(borderRadius: borderRadius); + return ThemeData( useMaterial3: true, colorScheme: scheme, @@ -16,9 +20,9 @@ ThemeData theme(Color seed, Brightness brightness, bool isAmoled) { iconColor: scheme.onSurface, ), appBarTheme: const AppBarTheme(surfaceTintColor: Colors.transparent), - inputDecorationTheme: InputDecorationTheme( + inputDecorationTheme: const InputDecorationTheme( border: OutlineInputBorder( - borderRadius: BorderRadius.circular(15), + borderRadius: borderRadius, ), ), iconTheme: IconThemeData(size: 16, color: scheme.onSurface), @@ -36,17 +40,17 @@ ThemeData theme(Color seed, Brightness brightness, bool isAmoled) { dividerColor: Colors.transparent, indicator: BoxDecoration( color: scheme.secondaryContainer, - borderRadius: BorderRadius.circular(15), + borderRadius: borderRadius, ), ), popupMenuTheme: PopupMenuThemeData( - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), + shape: roundedRectangleBorder, color: scheme.surface, elevation: 4, ), snackBarTheme: SnackBarThemeData( behavior: SnackBarBehavior.floating, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)), + shape: roundedRectangleBorder, backgroundColor: scheme.onSurface, contentTextStyle: TextStyle(color: scheme.surface), ), @@ -63,11 +67,7 @@ ThemeData theme(Color seed, Brightness brightness, bool isAmoled) { ), ), elevation: const MaterialStatePropertyAll(0), - shape: MaterialStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), + shape: MaterialStatePropertyAll(roundedRectangleBorder), ), scrollbarTheme: const ScrollbarThemeData( thickness: MaterialStatePropertyAll(14), @@ -76,4 +76,4 @@ ThemeData theme(Color seed, Brightness brightness, bool isAmoled) { shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), ), ); -} +} \ No newline at end of file