mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
refactor: use metadata plugin authentication instead
This commit is contained in:
parent
41cc79b5e6
commit
aa65bf291d
@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/collections/routes.gr.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||
|
||||
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
||||
@ -28,9 +28,10 @@ class AppRouter extends RootStackRouter {
|
||||
guards: [
|
||||
AutoRouteGuardCallback(
|
||||
(resolver, router) async {
|
||||
final auth = await ref.read(authenticationProvider.future);
|
||||
final authenticated = await ref
|
||||
.read(metadataPluginAuthenticatedProvider.future);
|
||||
|
||||
if (auth == null && !KVStoreService.doneGettingStarted) {
|
||||
if (!authenticated && !KVStoreService.doneGettingStarted) {
|
||||
resolver.redirect(const GettingStartedRoute());
|
||||
} else {
|
||||
resolver.next(true);
|
||||
@ -209,11 +210,6 @@ class AppRouter extends RootStackRouter {
|
||||
page: GettingStartedRoute.page,
|
||||
// parentNavigatorKey: rootNavigatorKey,
|
||||
),
|
||||
AutoRoute(
|
||||
path: "/login",
|
||||
page: WebViewLoginRoute.page,
|
||||
// parentNavigatorKey: rootNavigatorKey,
|
||||
),
|
||||
AutoRoute(
|
||||
path: "/lastfm-login",
|
||||
page: LastFMLoginRoute.page,
|
||||
|
@ -8,10 +8,10 @@
|
||||
// coverage:ignore-file
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:auto_route/auto_route.dart' as _i40;
|
||||
import 'package:flutter/material.dart' as _i41;
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart' as _i43;
|
||||
import 'package:spotube/models/metadata/metadata.dart' as _i42;
|
||||
import 'package:auto_route/auto_route.dart' as _i39;
|
||||
import 'package:flutter/material.dart' as _i40;
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart' as _i42;
|
||||
import 'package:spotube/models/metadata/metadata.dart' as _i41;
|
||||
import 'package:spotube/pages/album/album.dart' as _i2;
|
||||
import 'package:spotube/pages/artist/artist.dart' as _i3;
|
||||
import 'package:spotube/pages/connect/connect.dart' as _i6;
|
||||
@ -31,7 +31,6 @@ import 'package:spotube/pages/library/user_local_tracks/user_local_tracks.dart'
|
||||
import 'package:spotube/pages/library/user_playlists.dart' as _i38;
|
||||
import 'package:spotube/pages/lyrics/lyrics.dart' as _i15;
|
||||
import 'package:spotube/pages/lyrics/mini_lyrics.dart' as _i16;
|
||||
import 'package:spotube/pages/mobile_login/mobile_login.dart' as _i39;
|
||||
import 'package:spotube/pages/player/lyrics.dart' as _i17;
|
||||
import 'package:spotube/pages/player/queue.dart' as _i18;
|
||||
import 'package:spotube/pages/player/sources.dart' as _i19;
|
||||
@ -56,8 +55,8 @@ import 'package:spotube/pages/track/track.dart' as _i33;
|
||||
|
||||
/// generated route for
|
||||
/// [_i1.AboutSpotubePage]
|
||||
class AboutSpotubeRoute extends _i40.PageRouteInfo<void> {
|
||||
const AboutSpotubeRoute({List<_i40.PageRouteInfo>? children})
|
||||
class AboutSpotubeRoute extends _i39.PageRouteInfo<void> {
|
||||
const AboutSpotubeRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
AboutSpotubeRoute.name,
|
||||
initialChildren: children,
|
||||
@ -65,7 +64,7 @@ class AboutSpotubeRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'AboutSpotubeRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i1.AboutSpotubePage();
|
||||
@ -75,12 +74,12 @@ class AboutSpotubeRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i2.AlbumPage]
|
||||
class AlbumRoute extends _i40.PageRouteInfo<AlbumRouteArgs> {
|
||||
class AlbumRoute extends _i39.PageRouteInfo<AlbumRouteArgs> {
|
||||
AlbumRoute({
|
||||
_i41.Key? key,
|
||||
_i40.Key? key,
|
||||
required String id,
|
||||
required _i42.SpotubeSimpleAlbumObject album,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
required _i41.SpotubeSimpleAlbumObject album,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
AlbumRoute.name,
|
||||
args: AlbumRouteArgs(
|
||||
@ -94,7 +93,7 @@ class AlbumRoute extends _i40.PageRouteInfo<AlbumRouteArgs> {
|
||||
|
||||
static const String name = 'AlbumRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final args = data.argsAs<AlbumRouteArgs>();
|
||||
@ -114,11 +113,11 @@ class AlbumRouteArgs {
|
||||
required this.album,
|
||||
});
|
||||
|
||||
final _i41.Key? key;
|
||||
final _i40.Key? key;
|
||||
|
||||
final String id;
|
||||
|
||||
final _i42.SpotubeSimpleAlbumObject album;
|
||||
final _i41.SpotubeSimpleAlbumObject album;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -128,11 +127,11 @@ class AlbumRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i3.ArtistPage]
|
||||
class ArtistRoute extends _i40.PageRouteInfo<ArtistRouteArgs> {
|
||||
class ArtistRoute extends _i39.PageRouteInfo<ArtistRouteArgs> {
|
||||
ArtistRoute({
|
||||
required String artistId,
|
||||
_i41.Key? key,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
_i40.Key? key,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
ArtistRoute.name,
|
||||
args: ArtistRouteArgs(
|
||||
@ -145,7 +144,7 @@ class ArtistRoute extends _i40.PageRouteInfo<ArtistRouteArgs> {
|
||||
|
||||
static const String name = 'ArtistRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final pathParams = data.inheritedPathParams;
|
||||
@ -167,7 +166,7 @@ class ArtistRouteArgs {
|
||||
|
||||
final String artistId;
|
||||
|
||||
final _i41.Key? key;
|
||||
final _i40.Key? key;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -177,8 +176,8 @@ class ArtistRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i4.BlackListPage]
|
||||
class BlackListRoute extends _i40.PageRouteInfo<void> {
|
||||
const BlackListRoute({List<_i40.PageRouteInfo>? children})
|
||||
class BlackListRoute extends _i39.PageRouteInfo<void> {
|
||||
const BlackListRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
BlackListRoute.name,
|
||||
initialChildren: children,
|
||||
@ -186,7 +185,7 @@ class BlackListRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'BlackListRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i4.BlackListPage();
|
||||
@ -196,8 +195,8 @@ class BlackListRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i5.ConnectControlPage]
|
||||
class ConnectControlRoute extends _i40.PageRouteInfo<void> {
|
||||
const ConnectControlRoute({List<_i40.PageRouteInfo>? children})
|
||||
class ConnectControlRoute extends _i39.PageRouteInfo<void> {
|
||||
const ConnectControlRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
ConnectControlRoute.name,
|
||||
initialChildren: children,
|
||||
@ -205,7 +204,7 @@ class ConnectControlRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'ConnectControlRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i5.ConnectControlPage();
|
||||
@ -215,8 +214,8 @@ class ConnectControlRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i6.ConnectPage]
|
||||
class ConnectRoute extends _i40.PageRouteInfo<void> {
|
||||
const ConnectRoute({List<_i40.PageRouteInfo>? children})
|
||||
class ConnectRoute extends _i39.PageRouteInfo<void> {
|
||||
const ConnectRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
ConnectRoute.name,
|
||||
initialChildren: children,
|
||||
@ -224,7 +223,7 @@ class ConnectRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'ConnectRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i6.ConnectPage();
|
||||
@ -234,8 +233,8 @@ class ConnectRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i7.GettingStartedPage]
|
||||
class GettingStartedRoute extends _i40.PageRouteInfo<void> {
|
||||
const GettingStartedRoute({List<_i40.PageRouteInfo>? children})
|
||||
class GettingStartedRoute extends _i39.PageRouteInfo<void> {
|
||||
const GettingStartedRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
GettingStartedRoute.name,
|
||||
initialChildren: children,
|
||||
@ -243,7 +242,7 @@ class GettingStartedRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'GettingStartedRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i7.GettingStartedPage();
|
||||
@ -254,12 +253,12 @@ class GettingStartedRoute extends _i40.PageRouteInfo<void> {
|
||||
/// generated route for
|
||||
/// [_i8.HomeBrowseSectionItemsPage]
|
||||
class HomeBrowseSectionItemsRoute
|
||||
extends _i40.PageRouteInfo<HomeBrowseSectionItemsRouteArgs> {
|
||||
extends _i39.PageRouteInfo<HomeBrowseSectionItemsRouteArgs> {
|
||||
HomeBrowseSectionItemsRoute({
|
||||
_i43.Key? key,
|
||||
_i42.Key? key,
|
||||
required String sectionId,
|
||||
required _i42.SpotubeBrowseSectionObject<Object> section,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
required _i41.SpotubeBrowseSectionObject<Object> section,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
HomeBrowseSectionItemsRoute.name,
|
||||
args: HomeBrowseSectionItemsRouteArgs(
|
||||
@ -273,7 +272,7 @@ class HomeBrowseSectionItemsRoute
|
||||
|
||||
static const String name = 'HomeBrowseSectionItemsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final args = data.argsAs<HomeBrowseSectionItemsRouteArgs>();
|
||||
@ -293,11 +292,11 @@ class HomeBrowseSectionItemsRouteArgs {
|
||||
required this.section,
|
||||
});
|
||||
|
||||
final _i43.Key? key;
|
||||
final _i42.Key? key;
|
||||
|
||||
final String sectionId;
|
||||
|
||||
final _i42.SpotubeBrowseSectionObject<Object> section;
|
||||
final _i41.SpotubeBrowseSectionObject<Object> section;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -307,8 +306,8 @@ class HomeBrowseSectionItemsRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i9.HomePage]
|
||||
class HomeRoute extends _i40.PageRouteInfo<void> {
|
||||
const HomeRoute({List<_i40.PageRouteInfo>? children})
|
||||
class HomeRoute extends _i39.PageRouteInfo<void> {
|
||||
const HomeRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
HomeRoute.name,
|
||||
initialChildren: children,
|
||||
@ -316,7 +315,7 @@ class HomeRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'HomeRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i9.HomePage();
|
||||
@ -326,8 +325,8 @@ class HomeRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i10.LastFMLoginPage]
|
||||
class LastFMLoginRoute extends _i40.PageRouteInfo<void> {
|
||||
const LastFMLoginRoute({List<_i40.PageRouteInfo>? children})
|
||||
class LastFMLoginRoute extends _i39.PageRouteInfo<void> {
|
||||
const LastFMLoginRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
LastFMLoginRoute.name,
|
||||
initialChildren: children,
|
||||
@ -335,7 +334,7 @@ class LastFMLoginRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'LastFMLoginRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i10.LastFMLoginPage();
|
||||
@ -345,8 +344,8 @@ class LastFMLoginRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i11.LibraryPage]
|
||||
class LibraryRoute extends _i40.PageRouteInfo<void> {
|
||||
const LibraryRoute({List<_i40.PageRouteInfo>? children})
|
||||
class LibraryRoute extends _i39.PageRouteInfo<void> {
|
||||
const LibraryRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
LibraryRoute.name,
|
||||
initialChildren: children,
|
||||
@ -354,7 +353,7 @@ class LibraryRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'LibraryRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i11.LibraryPage();
|
||||
@ -364,11 +363,11 @@ class LibraryRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i12.LikedPlaylistPage]
|
||||
class LikedPlaylistRoute extends _i40.PageRouteInfo<LikedPlaylistRouteArgs> {
|
||||
class LikedPlaylistRoute extends _i39.PageRouteInfo<LikedPlaylistRouteArgs> {
|
||||
LikedPlaylistRoute({
|
||||
_i41.Key? key,
|
||||
required _i42.SpotubeSimplePlaylistObject playlist,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
_i40.Key? key,
|
||||
required _i41.SpotubeSimplePlaylistObject playlist,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
LikedPlaylistRoute.name,
|
||||
args: LikedPlaylistRouteArgs(
|
||||
@ -380,7 +379,7 @@ class LikedPlaylistRoute extends _i40.PageRouteInfo<LikedPlaylistRouteArgs> {
|
||||
|
||||
static const String name = 'LikedPlaylistRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final args = data.argsAs<LikedPlaylistRouteArgs>();
|
||||
@ -398,9 +397,9 @@ class LikedPlaylistRouteArgs {
|
||||
required this.playlist,
|
||||
});
|
||||
|
||||
final _i41.Key? key;
|
||||
final _i40.Key? key;
|
||||
|
||||
final _i42.SpotubeSimplePlaylistObject playlist;
|
||||
final _i41.SpotubeSimplePlaylistObject playlist;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -410,13 +409,13 @@ class LikedPlaylistRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i13.LocalLibraryPage]
|
||||
class LocalLibraryRoute extends _i40.PageRouteInfo<LocalLibraryRouteArgs> {
|
||||
class LocalLibraryRoute extends _i39.PageRouteInfo<LocalLibraryRouteArgs> {
|
||||
LocalLibraryRoute({
|
||||
required String location,
|
||||
_i41.Key? key,
|
||||
_i40.Key? key,
|
||||
bool isDownloads = false,
|
||||
bool isCache = false,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
LocalLibraryRoute.name,
|
||||
args: LocalLibraryRouteArgs(
|
||||
@ -430,7 +429,7 @@ class LocalLibraryRoute extends _i40.PageRouteInfo<LocalLibraryRouteArgs> {
|
||||
|
||||
static const String name = 'LocalLibraryRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final args = data.argsAs<LocalLibraryRouteArgs>();
|
||||
@ -454,7 +453,7 @@ class LocalLibraryRouteArgs {
|
||||
|
||||
final String location;
|
||||
|
||||
final _i41.Key? key;
|
||||
final _i40.Key? key;
|
||||
|
||||
final bool isDownloads;
|
||||
|
||||
@ -468,8 +467,8 @@ class LocalLibraryRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i14.LogsPage]
|
||||
class LogsRoute extends _i40.PageRouteInfo<void> {
|
||||
const LogsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class LogsRoute extends _i39.PageRouteInfo<void> {
|
||||
const LogsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
LogsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -477,7 +476,7 @@ class LogsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'LogsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i14.LogsPage();
|
||||
@ -487,8 +486,8 @@ class LogsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i15.LyricsPage]
|
||||
class LyricsRoute extends _i40.PageRouteInfo<void> {
|
||||
const LyricsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class LyricsRoute extends _i39.PageRouteInfo<void> {
|
||||
const LyricsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
LyricsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -496,7 +495,7 @@ class LyricsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'LyricsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i15.LyricsPage();
|
||||
@ -506,11 +505,11 @@ class LyricsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i16.MiniLyricsPage]
|
||||
class MiniLyricsRoute extends _i40.PageRouteInfo<MiniLyricsRouteArgs> {
|
||||
class MiniLyricsRoute extends _i39.PageRouteInfo<MiniLyricsRouteArgs> {
|
||||
MiniLyricsRoute({
|
||||
_i43.Key? key,
|
||||
required _i43.Size prevSize,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
_i42.Key? key,
|
||||
required _i42.Size prevSize,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
MiniLyricsRoute.name,
|
||||
args: MiniLyricsRouteArgs(
|
||||
@ -522,7 +521,7 @@ class MiniLyricsRoute extends _i40.PageRouteInfo<MiniLyricsRouteArgs> {
|
||||
|
||||
static const String name = 'MiniLyricsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final args = data.argsAs<MiniLyricsRouteArgs>();
|
||||
@ -540,9 +539,9 @@ class MiniLyricsRouteArgs {
|
||||
required this.prevSize,
|
||||
});
|
||||
|
||||
final _i43.Key? key;
|
||||
final _i42.Key? key;
|
||||
|
||||
final _i43.Size prevSize;
|
||||
final _i42.Size prevSize;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -552,8 +551,8 @@ class MiniLyricsRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i17.PlayerLyricsPage]
|
||||
class PlayerLyricsRoute extends _i40.PageRouteInfo<void> {
|
||||
const PlayerLyricsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class PlayerLyricsRoute extends _i39.PageRouteInfo<void> {
|
||||
const PlayerLyricsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
PlayerLyricsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -561,7 +560,7 @@ class PlayerLyricsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'PlayerLyricsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i17.PlayerLyricsPage();
|
||||
@ -571,8 +570,8 @@ class PlayerLyricsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i18.PlayerQueuePage]
|
||||
class PlayerQueueRoute extends _i40.PageRouteInfo<void> {
|
||||
const PlayerQueueRoute({List<_i40.PageRouteInfo>? children})
|
||||
class PlayerQueueRoute extends _i39.PageRouteInfo<void> {
|
||||
const PlayerQueueRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
PlayerQueueRoute.name,
|
||||
initialChildren: children,
|
||||
@ -580,7 +579,7 @@ class PlayerQueueRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'PlayerQueueRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i18.PlayerQueuePage();
|
||||
@ -590,8 +589,8 @@ class PlayerQueueRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i19.PlayerTrackSourcesPage]
|
||||
class PlayerTrackSourcesRoute extends _i40.PageRouteInfo<void> {
|
||||
const PlayerTrackSourcesRoute({List<_i40.PageRouteInfo>? children})
|
||||
class PlayerTrackSourcesRoute extends _i39.PageRouteInfo<void> {
|
||||
const PlayerTrackSourcesRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
PlayerTrackSourcesRoute.name,
|
||||
initialChildren: children,
|
||||
@ -599,7 +598,7 @@ class PlayerTrackSourcesRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'PlayerTrackSourcesRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i19.PlayerTrackSourcesPage();
|
||||
@ -609,12 +608,12 @@ class PlayerTrackSourcesRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i20.PlaylistPage]
|
||||
class PlaylistRoute extends _i40.PageRouteInfo<PlaylistRouteArgs> {
|
||||
class PlaylistRoute extends _i39.PageRouteInfo<PlaylistRouteArgs> {
|
||||
PlaylistRoute({
|
||||
_i41.Key? key,
|
||||
_i40.Key? key,
|
||||
required String id,
|
||||
required _i42.SpotubeSimplePlaylistObject playlist,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
required _i41.SpotubeSimplePlaylistObject playlist,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
PlaylistRoute.name,
|
||||
args: PlaylistRouteArgs(
|
||||
@ -628,7 +627,7 @@ class PlaylistRoute extends _i40.PageRouteInfo<PlaylistRouteArgs> {
|
||||
|
||||
static const String name = 'PlaylistRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final args = data.argsAs<PlaylistRouteArgs>();
|
||||
@ -648,11 +647,11 @@ class PlaylistRouteArgs {
|
||||
required this.playlist,
|
||||
});
|
||||
|
||||
final _i41.Key? key;
|
||||
final _i40.Key? key;
|
||||
|
||||
final String id;
|
||||
|
||||
final _i42.SpotubeSimplePlaylistObject playlist;
|
||||
final _i41.SpotubeSimplePlaylistObject playlist;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -662,8 +661,8 @@ class PlaylistRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i21.ProfilePage]
|
||||
class ProfileRoute extends _i40.PageRouteInfo<void> {
|
||||
const ProfileRoute({List<_i40.PageRouteInfo>? children})
|
||||
class ProfileRoute extends _i39.PageRouteInfo<void> {
|
||||
const ProfileRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
ProfileRoute.name,
|
||||
initialChildren: children,
|
||||
@ -671,7 +670,7 @@ class ProfileRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'ProfileRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i21.ProfilePage();
|
||||
@ -681,8 +680,8 @@ class ProfileRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i22.RootAppPage]
|
||||
class RootAppRoute extends _i40.PageRouteInfo<void> {
|
||||
const RootAppRoute({List<_i40.PageRouteInfo>? children})
|
||||
class RootAppRoute extends _i39.PageRouteInfo<void> {
|
||||
const RootAppRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
RootAppRoute.name,
|
||||
initialChildren: children,
|
||||
@ -690,7 +689,7 @@ class RootAppRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'RootAppRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i22.RootAppPage();
|
||||
@ -700,8 +699,8 @@ class RootAppRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i23.SearchPage]
|
||||
class SearchRoute extends _i40.PageRouteInfo<void> {
|
||||
const SearchRoute({List<_i40.PageRouteInfo>? children})
|
||||
class SearchRoute extends _i39.PageRouteInfo<void> {
|
||||
const SearchRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
SearchRoute.name,
|
||||
initialChildren: children,
|
||||
@ -709,7 +708,7 @@ class SearchRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'SearchRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i23.SearchPage();
|
||||
@ -719,8 +718,8 @@ class SearchRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i24.SettingsMetadataProviderPage]
|
||||
class SettingsMetadataProviderRoute extends _i40.PageRouteInfo<void> {
|
||||
const SettingsMetadataProviderRoute({List<_i40.PageRouteInfo>? children})
|
||||
class SettingsMetadataProviderRoute extends _i39.PageRouteInfo<void> {
|
||||
const SettingsMetadataProviderRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
SettingsMetadataProviderRoute.name,
|
||||
initialChildren: children,
|
||||
@ -728,7 +727,7 @@ class SettingsMetadataProviderRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'SettingsMetadataProviderRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i24.SettingsMetadataProviderPage();
|
||||
@ -738,8 +737,8 @@ class SettingsMetadataProviderRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i25.SettingsPage]
|
||||
class SettingsRoute extends _i40.PageRouteInfo<void> {
|
||||
const SettingsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class SettingsRoute extends _i39.PageRouteInfo<void> {
|
||||
const SettingsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
SettingsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -747,7 +746,7 @@ class SettingsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'SettingsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i25.SettingsPage();
|
||||
@ -757,8 +756,8 @@ class SettingsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i26.StatsAlbumsPage]
|
||||
class StatsAlbumsRoute extends _i40.PageRouteInfo<void> {
|
||||
const StatsAlbumsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class StatsAlbumsRoute extends _i39.PageRouteInfo<void> {
|
||||
const StatsAlbumsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
StatsAlbumsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -766,7 +765,7 @@ class StatsAlbumsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'StatsAlbumsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i26.StatsAlbumsPage();
|
||||
@ -776,8 +775,8 @@ class StatsAlbumsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i27.StatsArtistsPage]
|
||||
class StatsArtistsRoute extends _i40.PageRouteInfo<void> {
|
||||
const StatsArtistsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class StatsArtistsRoute extends _i39.PageRouteInfo<void> {
|
||||
const StatsArtistsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
StatsArtistsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -785,7 +784,7 @@ class StatsArtistsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'StatsArtistsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i27.StatsArtistsPage();
|
||||
@ -795,8 +794,8 @@ class StatsArtistsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i28.StatsMinutesPage]
|
||||
class StatsMinutesRoute extends _i40.PageRouteInfo<void> {
|
||||
const StatsMinutesRoute({List<_i40.PageRouteInfo>? children})
|
||||
class StatsMinutesRoute extends _i39.PageRouteInfo<void> {
|
||||
const StatsMinutesRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
StatsMinutesRoute.name,
|
||||
initialChildren: children,
|
||||
@ -804,7 +803,7 @@ class StatsMinutesRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'StatsMinutesRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i28.StatsMinutesPage();
|
||||
@ -814,8 +813,8 @@ class StatsMinutesRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i29.StatsPage]
|
||||
class StatsRoute extends _i40.PageRouteInfo<void> {
|
||||
const StatsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class StatsRoute extends _i39.PageRouteInfo<void> {
|
||||
const StatsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
StatsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -823,7 +822,7 @@ class StatsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'StatsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i29.StatsPage();
|
||||
@ -833,8 +832,8 @@ class StatsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i30.StatsPlaylistsPage]
|
||||
class StatsPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
||||
const StatsPlaylistsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class StatsPlaylistsRoute extends _i39.PageRouteInfo<void> {
|
||||
const StatsPlaylistsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
StatsPlaylistsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -842,7 +841,7 @@ class StatsPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'StatsPlaylistsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i30.StatsPlaylistsPage();
|
||||
@ -852,8 +851,8 @@ class StatsPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i31.StatsStreamFeesPage]
|
||||
class StatsStreamFeesRoute extends _i40.PageRouteInfo<void> {
|
||||
const StatsStreamFeesRoute({List<_i40.PageRouteInfo>? children})
|
||||
class StatsStreamFeesRoute extends _i39.PageRouteInfo<void> {
|
||||
const StatsStreamFeesRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
StatsStreamFeesRoute.name,
|
||||
initialChildren: children,
|
||||
@ -861,7 +860,7 @@ class StatsStreamFeesRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'StatsStreamFeesRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i31.StatsStreamFeesPage();
|
||||
@ -871,8 +870,8 @@ class StatsStreamFeesRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i32.StatsStreamsPage]
|
||||
class StatsStreamsRoute extends _i40.PageRouteInfo<void> {
|
||||
const StatsStreamsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class StatsStreamsRoute extends _i39.PageRouteInfo<void> {
|
||||
const StatsStreamsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
StatsStreamsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -880,7 +879,7 @@ class StatsStreamsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'StatsStreamsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i32.StatsStreamsPage();
|
||||
@ -890,11 +889,11 @@ class StatsStreamsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i33.TrackPage]
|
||||
class TrackRoute extends _i40.PageRouteInfo<TrackRouteArgs> {
|
||||
class TrackRoute extends _i39.PageRouteInfo<TrackRouteArgs> {
|
||||
TrackRoute({
|
||||
_i43.Key? key,
|
||||
_i42.Key? key,
|
||||
required String trackId,
|
||||
List<_i40.PageRouteInfo>? children,
|
||||
List<_i39.PageRouteInfo>? children,
|
||||
}) : super(
|
||||
TrackRoute.name,
|
||||
args: TrackRouteArgs(
|
||||
@ -907,7 +906,7 @@ class TrackRoute extends _i40.PageRouteInfo<TrackRouteArgs> {
|
||||
|
||||
static const String name = 'TrackRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
final pathParams = data.inheritedPathParams;
|
||||
@ -927,7 +926,7 @@ class TrackRouteArgs {
|
||||
required this.trackId,
|
||||
});
|
||||
|
||||
final _i43.Key? key;
|
||||
final _i42.Key? key;
|
||||
|
||||
final String trackId;
|
||||
|
||||
@ -939,8 +938,8 @@ class TrackRouteArgs {
|
||||
|
||||
/// generated route for
|
||||
/// [_i34.UserAlbumsPage]
|
||||
class UserAlbumsRoute extends _i40.PageRouteInfo<void> {
|
||||
const UserAlbumsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class UserAlbumsRoute extends _i39.PageRouteInfo<void> {
|
||||
const UserAlbumsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
UserAlbumsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -948,7 +947,7 @@ class UserAlbumsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'UserAlbumsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i34.UserAlbumsPage();
|
||||
@ -958,8 +957,8 @@ class UserAlbumsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i35.UserArtistsPage]
|
||||
class UserArtistsRoute extends _i40.PageRouteInfo<void> {
|
||||
const UserArtistsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class UserArtistsRoute extends _i39.PageRouteInfo<void> {
|
||||
const UserArtistsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
UserArtistsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -967,7 +966,7 @@ class UserArtistsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'UserArtistsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i35.UserArtistsPage();
|
||||
@ -977,8 +976,8 @@ class UserArtistsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i36.UserDownloadsPage]
|
||||
class UserDownloadsRoute extends _i40.PageRouteInfo<void> {
|
||||
const UserDownloadsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class UserDownloadsRoute extends _i39.PageRouteInfo<void> {
|
||||
const UserDownloadsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
UserDownloadsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -986,7 +985,7 @@ class UserDownloadsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'UserDownloadsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i36.UserDownloadsPage();
|
||||
@ -996,8 +995,8 @@ class UserDownloadsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i37.UserLocalLibraryPage]
|
||||
class UserLocalLibraryRoute extends _i40.PageRouteInfo<void> {
|
||||
const UserLocalLibraryRoute({List<_i40.PageRouteInfo>? children})
|
||||
class UserLocalLibraryRoute extends _i39.PageRouteInfo<void> {
|
||||
const UserLocalLibraryRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
UserLocalLibraryRoute.name,
|
||||
initialChildren: children,
|
||||
@ -1005,7 +1004,7 @@ class UserLocalLibraryRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'UserLocalLibraryRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i37.UserLocalLibraryPage();
|
||||
@ -1015,8 +1014,8 @@ class UserLocalLibraryRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
/// generated route for
|
||||
/// [_i38.UserPlaylistsPage]
|
||||
class UserPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
||||
const UserPlaylistsRoute({List<_i40.PageRouteInfo>? children})
|
||||
class UserPlaylistsRoute extends _i39.PageRouteInfo<void> {
|
||||
const UserPlaylistsRoute({List<_i39.PageRouteInfo>? children})
|
||||
: super(
|
||||
UserPlaylistsRoute.name,
|
||||
initialChildren: children,
|
||||
@ -1024,29 +1023,10 @@ class UserPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
||||
|
||||
static const String name = 'UserPlaylistsRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
static _i39.PageInfo page = _i39.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i38.UserPlaylistsPage();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// generated route for
|
||||
/// [_i39.WebViewLoginPage]
|
||||
class WebViewLoginRoute extends _i40.PageRouteInfo<void> {
|
||||
const WebViewLoginRoute({List<_i40.PageRouteInfo>? children})
|
||||
: super(
|
||||
WebViewLoginRoute.name,
|
||||
initialChildren: children,
|
||||
);
|
||||
|
||||
static const String name = 'WebViewLoginRoute';
|
||||
|
||||
static _i40.PageInfo page = _i40.PageInfo(
|
||||
name,
|
||||
builder: (data) {
|
||||
return const _i39.WebViewLoginPage();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
|
||||
import 'package:spotube/collections/routes.gr.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/utils/platform.dart';
|
||||
|
||||
class AnonymousFallback extends ConsumerWidget {
|
||||
@ -18,13 +18,13 @@ class AnonymousFallback extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final isLoggedIn = ref.watch(authenticationProvider);
|
||||
final isLoggedIn = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
|
||||
if (isLoggedIn.isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (isLoggedIn.asData?.value != null && child != null) return child!;
|
||||
if (isLoggedIn.asData?.value == true && child != null) return child!;
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
@ -4,7 +4,7 @@ import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:spotube/components/heart_button/use_track_toggle_like.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/library/tracks.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/user.dart';
|
||||
|
||||
@ -29,9 +29,9 @@ class HeartButton extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
|
||||
if (auth.asData?.value == null) return const SizedBox.shrink();
|
||||
if (authenticated.asData?.value != true) return const SizedBox.shrink();
|
||||
|
||||
return Tooltip(
|
||||
tooltip: TooltipContainer(child: Text(tooltip ?? "")).call,
|
||||
|
@ -226,6 +226,7 @@ class TrackPresentationTopSection extends HookConsumerWidget {
|
||||
.imageProvider(
|
||||
options.ownerImage!,
|
||||
),
|
||||
size: 20 * scale,
|
||||
)
|
||||
: null,
|
||||
child: Text(
|
||||
|
@ -22,11 +22,11 @@ import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/models/database/database.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/blacklist_provider.dart';
|
||||
import 'package:spotube/provider/download_manager_provider.dart';
|
||||
import 'package:spotube/provider/local_tracks/local_tracks_provider.dart';
|
||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/library/playlists.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/tracks/playlist.dart';
|
||||
@ -181,7 +181,7 @@ class TrackOptions extends HookConsumerWidget {
|
||||
|
||||
final playlist = ref.watch(audioPlayerProvider);
|
||||
final playback = ref.watch(audioPlayerProvider.notifier);
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
ref.watch(downloadManagerProvider);
|
||||
final downloadManager = ref.watch(downloadManagerProvider.notifier);
|
||||
final blacklist = ref.watch(blacklistProvider);
|
||||
@ -430,7 +430,7 @@ class TrackOptions extends HookConsumerWidget {
|
||||
: context.l10n.save_as_favorite,
|
||||
),
|
||||
),
|
||||
if (auth.asData?.value != null && !isLocalTrack) ...[
|
||||
if (authenticated.asData?.value == true && !isLocalTrack) ...[
|
||||
AdaptiveMenuButton(
|
||||
value: TrackOptionValue.startRadio,
|
||||
leading: const Icon(SpotubeIcons.radio),
|
||||
@ -442,7 +442,9 @@ class TrackOptions extends HookConsumerWidget {
|
||||
child: Text(context.l10n.add_to_playlist),
|
||||
),
|
||||
],
|
||||
if (userPlaylist && auth.asData?.value != null && !isLocalTrack)
|
||||
if (userPlaylist &&
|
||||
authenticated.asData?.value == true &&
|
||||
!isLocalTrack)
|
||||
AdaptiveMenuButton(
|
||||
value: TrackOptionValue.removeFromPlaylist,
|
||||
leading: const Icon(SpotubeIcons.removeFilled),
|
||||
|
@ -2,7 +2,6 @@ import 'package:spotube/provider/metadata_plugin/tracks/playlist.dart';
|
||||
import 'package:spotube/services/logger/logger.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||
|
@ -3,8 +3,8 @@ import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:spotube/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/album/releases.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
|
||||
class HomeNewReleasesSection extends HookConsumerWidget {
|
||||
@ -12,13 +12,13 @@ class HomeNewReleasesSection extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
|
||||
final newReleases = ref.watch(metadataPluginAlbumReleasesProvider);
|
||||
final newReleasesNotifier =
|
||||
ref.read(metadataPluginAlbumReleasesProvider.notifier);
|
||||
|
||||
if (auth.asData?.value == null ||
|
||||
if (authenticated.asData?.value != true ||
|
||||
newReleases.isLoading ||
|
||||
newReleases.asData?.value.items.isEmpty == true) {
|
||||
return const SizedBox.shrink();
|
||||
|
@ -20,8 +20,8 @@ import 'package:spotube/components/image/universal_image.dart';
|
||||
import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/modules/root/spotube_navigation_bar.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/server/active_track_sources.dart';
|
||||
import 'package:spotube/provider/volume_provider.dart';
|
||||
import 'package:spotube/services/sourced_track/sources/youtube.dart';
|
||||
@ -41,7 +41,7 @@ class PlayerView extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final theme = Theme.of(context);
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
final sourcedCurrentTrack = ref.watch(activeTrackSourcesProvider);
|
||||
final currentActiveTrack =
|
||||
ref.watch(audioPlayerProvider.select((s) => s.activeTrack));
|
||||
@ -242,8 +242,9 @@ class PlayerView extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
if (auth.asData?.value != null) const SizedBox(width: 10),
|
||||
if (auth.asData?.value != null)
|
||||
if (authenticated.asData?.value == true)
|
||||
const SizedBox(width: 10),
|
||||
if (authenticated.asData?.value == true)
|
||||
Expanded(
|
||||
child: OutlineButton(
|
||||
leading: const Icon(SpotubeIcons.music),
|
||||
|
@ -16,8 +16,9 @@ import 'package:spotube/components/heart_button/heart_button.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/extensions/duration.dart';
|
||||
import 'package:spotube/provider/download_manager_provider.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||
import 'package:spotube/provider/local_tracks/local_tracks_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/sleep_timer_provider.dart';
|
||||
|
||||
class PlayerActions extends HookConsumerWidget {
|
||||
@ -49,17 +50,17 @@ class PlayerActions extends HookConsumerWidget {
|
||||
downloader,
|
||||
]);
|
||||
|
||||
final localTracks = [] /* ref.watch(localTracksProvider).value */;
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final localTracks = ref.watch(localTracksProvider).value;
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
final sleepTimer = ref.watch(sleepTimerProvider);
|
||||
final sleepTimerNotifier = ref.watch(sleepTimerProvider.notifier);
|
||||
|
||||
final isDownloaded = useMemoized(() {
|
||||
return localTracks.any(
|
||||
return localTracks?.values.expand((e) => e).any(
|
||||
(element) =>
|
||||
element.name == playlist.activeTrack?.name &&
|
||||
element.album?.name == playlist.activeTrack?.album.name &&
|
||||
element.artists?.asString() ==
|
||||
element.album.name == playlist.activeTrack?.album.name &&
|
||||
element.artists.asString() ==
|
||||
playlist.activeTrack?.artists.asString(),
|
||||
) ==
|
||||
true;
|
||||
@ -175,7 +176,7 @@ class PlayerActions extends HookConsumerWidget {
|
||||
),
|
||||
if (playlist.activeTrack != null &&
|
||||
!isLocalTrack &&
|
||||
auth.asData?.value != null)
|
||||
authenticated.asData?.value == true)
|
||||
TrackHeartButton(track: playlist.activeTrack!),
|
||||
AdaptivePopSheetList<Duration>(
|
||||
tooltip: context.l10n.sleep_timer,
|
||||
|
@ -10,8 +10,8 @@ import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/modules/connect/connect_device.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/download_manager_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/user.dart';
|
||||
|
||||
class SidebarFooter extends HookConsumerWidget implements NavigationBarItem {
|
||||
@ -33,7 +33,7 @@ class SidebarFooter extends HookConsumerWidget implements NavigationBarItem {
|
||||
placeholder: ImagePlaceholder.artist,
|
||||
);
|
||||
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
|
||||
if (mediaQuery.mdAndDown) {
|
||||
return Column(
|
||||
@ -91,7 +91,7 @@ class SidebarFooter extends HookConsumerWidget implements NavigationBarItem {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (auth.asData?.value != null && data == null)
|
||||
if (authenticated.asData?.value == true && data == null)
|
||||
const CircularProgressIndicator()
|
||||
else if (data != null)
|
||||
Flexible(
|
||||
|
@ -47,7 +47,7 @@ class AlbumPage extends HookConsumerWidget {
|
||||
title: album.name,
|
||||
description:
|
||||
"${context.l10n.released} • ${album.releaseDate} • ${album.artists.first.name}",
|
||||
tracks: [],
|
||||
tracks: tracks.asData?.value.items ?? [],
|
||||
pagination: PaginationProps(
|
||||
hasNextPage: tracks.asData?.value.hasMore ?? false,
|
||||
isLoading: tracks.isLoading || tracks.isLoadingNextPage,
|
||||
|
@ -10,9 +10,9 @@ import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/models/database/database.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/blacklist_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/artist/artist.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/library/artists.dart';
|
||||
import 'package:spotube/utils/primitive_utils.dart';
|
||||
|
||||
@ -28,7 +28,7 @@ class ArtistPageHeader extends HookConsumerWidget {
|
||||
final theme = Theme.of(context);
|
||||
final ThemeData(:typography) = theme;
|
||||
|
||||
final auth = ref.watch(authenticationProvider);
|
||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||
ref.watch(blacklistProvider);
|
||||
final blacklistNotifier = ref.watch(blacklistProvider.notifier);
|
||||
final isBlackListed = blacklistNotifier.containsArtist(artist.id);
|
||||
@ -41,7 +41,7 @@ class ArtistPageHeader extends HookConsumerWidget {
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (auth.asData?.value != null)
|
||||
if (authenticated.asData?.value == true)
|
||||
Consumer(
|
||||
builder: (context, ref, _) {
|
||||
final isFollowingQuery = ref.watch(
|
||||
|
@ -6,7 +6,6 @@ import 'package:spotube/collections/routes.gr.dart';
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/modules/getting_started/blur_card.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/pages/mobile_login/hooks/login_callback.dart';
|
||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
@ -15,8 +14,6 @@ class GettingStartedScreenSupportSection extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final onLogin = useLoginCallback(ref);
|
||||
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
@ -117,31 +114,6 @@ class GettingStartedScreenSupportSection extends HookConsumerWidget {
|
||||
},
|
||||
child: Text(context.l10n.browse_anonymously),
|
||||
),
|
||||
const Gap(16),
|
||||
Button.primary(
|
||||
leading: const Icon(SpotubeIcons.spotify),
|
||||
style: ButtonVariance.primary.copyWith(
|
||||
decoration: (context, states, value) {
|
||||
if (states.isNotEmpty) {
|
||||
return ButtonVariance.primary
|
||||
.decoration(context, states);
|
||||
}
|
||||
|
||||
return BoxDecoration(
|
||||
color: const Color(0xff1db954),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
);
|
||||
},
|
||||
),
|
||||
onPressed: () async {
|
||||
await KVStoreService.setDoneGettingStarted(true);
|
||||
await onLogin();
|
||||
},
|
||||
child: Text(
|
||||
context.l10n.connect_with_spotify,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -14,7 +14,6 @@ import 'package:spotube/modules/album/album_card.dart';
|
||||
import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart';
|
||||
import 'package:spotube/components/fallbacks/anonymous_fallback.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/library/albums.dart';
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
|
@ -40,7 +40,7 @@ class UserPlaylistsPage extends HookConsumerWidget {
|
||||
() => me.asData?.value == null
|
||||
? null
|
||||
: SpotubeSimplePlaylistObject(
|
||||
id: "liked-tracks",
|
||||
id: "user-liked-tracks",
|
||||
name: context.l10n.liked_tracks,
|
||||
description: context.l10n.liked_tracks_description,
|
||||
externalUri: "",
|
||||
|
@ -1,81 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart' hide join;
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:spotube/collections/routes.gr.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';
|
||||
|
||||
Future<void> Function() useLoginCallback(WidgetRef ref) {
|
||||
final context = useContext();
|
||||
final theme = Theme.of(context);
|
||||
final authNotifier = ref.read(authenticationProvider.notifier);
|
||||
|
||||
return useCallback(() async {
|
||||
if (kIsMobile || kIsMacOS) {
|
||||
context.navigateTo(const WebViewLoginRoute());
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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.navigateTo(const HomeRoute());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
} on PlatformException catch (_) {
|
||||
if (!await WebviewWindow.isWebviewAvailable()) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const NoWebviewRuntimeDialog();
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [authNotifier, theme, context.navigateTo]);
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/collections/routes.gr.dart';
|
||||
import 'package:spotube/components/button/back_button.dart';
|
||||
import 'package:spotube/components/titlebar/titlebar.dart';
|
||||
|
||||
import 'package:spotube/provider/authentication/authentication.dart';
|
||||
import 'package:spotube/utils/platform.dart';
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
|
||||
@RoutePage()
|
||||
class WebViewLoginPage extends HookConsumerWidget {
|
||||
static const name = "login";
|
||||
const WebViewLoginPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final authenticationNotifier = ref.watch(authenticationProvider.notifier);
|
||||
|
||||
if (kIsDesktop) {
|
||||
const Scaffold(
|
||||
child: Center(
|
||||
child: Text('This feature is not available on desktop'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return SafeArea(
|
||||
bottom: false,
|
||||
child: Scaffold(
|
||||
headers: const [
|
||||
TitleBar(
|
||||
leading: [BackButton(color: Colors.white)],
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
],
|
||||
floatingHeader: true,
|
||||
child: InAppWebView(
|
||||
initialSettings: InAppWebViewSettings(
|
||||
userAgent:
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 safari/537.36",
|
||||
),
|
||||
initialUrlRequest: URLRequest(
|
||||
url: WebUri("https://accounts.spotify.com/"),
|
||||
),
|
||||
onPermissionRequest: (controller, permissionRequest) async {
|
||||
return PermissionResponse(
|
||||
resources: permissionRequest.resources,
|
||||
action: PermissionResponseAction.GRANT,
|
||||
);
|
||||
},
|
||||
onLoadStop: (controller, action) async {
|
||||
if (action == null) return;
|
||||
String url = action.toString();
|
||||
if (url.endsWith("/")) {
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
|
||||
final exp = RegExp(r"https:\/\/accounts.spotify.com\/.+\/status");
|
||||
|
||||
if (exp.hasMatch(url)) {
|
||||
final cookies =
|
||||
await CookieManager.instance().getCookies(url: action);
|
||||
final cookieHeader =
|
||||
"sp_dc=${cookies.firstWhere((element) => element.name == "sp_dc").value}";
|
||||
|
||||
await authenticationNotifier.login(cookieHeader);
|
||||
if (context.mounted) {
|
||||
// ignore: use_build_context_synchronously
|
||||
context.navigateTo(const HomeRoute());
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
import 'package:shadcn_flutter/shadcn_flutter.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),
|
||||
),
|
||||
Button.primary(
|
||||
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) {
|
||||
showToast(
|
||||
context: context,
|
||||
builder: (context, overlay) {
|
||||
return const SurfaceCard(
|
||||
child: Basic(
|
||||
title: 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',
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ import 'package:spotube/hooks/controllers/use_shadcn_text_editing_controller.dar
|
||||
import 'package:spotube/pages/search/sections/albums.dart';
|
||||
import 'package:spotube/pages/search/sections/artists.dart';
|
||||
import 'package:spotube/pages/search/sections/playlists.dart';
|
||||
import 'package:spotube/pages/search/sections/tracks.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||
@ -227,7 +228,7 @@ class SearchPage extends HookConsumerWidget {
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
// SearchTracksSection(),
|
||||
SearchTracksSection(),
|
||||
SearchPlaylistsSection(),
|
||||
Gap(20),
|
||||
SearchArtistsSection(),
|
||||
|
@ -1,309 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:desktop_webview_window/desktop_webview_window.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio_http2_adapter/dio_http2_adapter.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart'
|
||||
hide X509Certificate;
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/collections/routes.dart';
|
||||
import 'package:spotube/components/dialogs/prompt_dialog.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/models/database/database.dart';
|
||||
import 'package:spotube/provider/database/database.dart';
|
||||
import 'package:spotube/services/logger/logger.dart';
|
||||
import 'package:spotube/utils/platform.dart';
|
||||
import 'package:otp_util/otp_util.dart';
|
||||
// ignore: implementation_imports
|
||||
import 'package:otp_util/src/utils/generic_util.dart';
|
||||
import 'package:spotube/utils/service_utils.dart';
|
||||
|
||||
extension ExpirationAuthenticationTableData on AuthenticationTableData {
|
||||
bool get isExpired => DateTime.now().isAfter(expiration);
|
||||
|
||||
String? getCookie(String key) => cookie.value
|
||||
.split("; ")
|
||||
.firstWhereOrNull((c) => c.trim().startsWith("$key="))
|
||||
?.trim()
|
||||
.split("=")
|
||||
.last
|
||||
.replaceAll(";", "");
|
||||
}
|
||||
|
||||
class AuthenticationNotifier extends AsyncNotifier<AuthenticationTableData?> {
|
||||
static final Dio dio = () {
|
||||
final dio = Dio()
|
||||
..httpClientAdapter = Http2Adapter(
|
||||
ConnectionManager(
|
||||
idleTimeout: const Duration(seconds: 10),
|
||||
onClientCreate: (uri, clientSettings) {
|
||||
clientSettings.onBadCertificate = (X509Certificate cert) {
|
||||
return uri.host.endsWith("spotify.com");
|
||||
};
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return dio;
|
||||
}();
|
||||
|
||||
@override
|
||||
build() async {
|
||||
final database = ref.watch(databaseProvider);
|
||||
|
||||
final data = await (database.select(database.authenticationTable)
|
||||
..where((s) => s.id.equals(0)))
|
||||
.getSingleOrNull();
|
||||
|
||||
Timer? refreshTimer;
|
||||
|
||||
listenSelf((prevData, newData) async {
|
||||
if (newData.asData?.value == null) return;
|
||||
|
||||
if (newData.asData!.value!.isExpired) {
|
||||
await refreshCredentials();
|
||||
}
|
||||
|
||||
// set the refresh timer
|
||||
refreshTimer?.cancel();
|
||||
refreshTimer = Timer(
|
||||
newData.asData!.value!.expiration.difference(DateTime.now()),
|
||||
() => refreshCredentials(),
|
||||
);
|
||||
});
|
||||
|
||||
final subscription =
|
||||
database.select(database.authenticationTable).watch().listen(
|
||||
(event) {
|
||||
state = AsyncData(event.isEmpty ? null : event.first);
|
||||
},
|
||||
);
|
||||
|
||||
ref.onDispose(() {
|
||||
subscription.cancel();
|
||||
refreshTimer?.cancel();
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<void> refreshCredentials() async {
|
||||
final database = ref.read(databaseProvider);
|
||||
final refreshedCredentials =
|
||||
await credentialsFromCookie(state.asData!.value!.cookie.value);
|
||||
|
||||
await database
|
||||
.update(database.authenticationTable)
|
||||
.replace(refreshedCredentials);
|
||||
}
|
||||
|
||||
Future<void> login(String cookie) async {
|
||||
final database = ref.read(databaseProvider);
|
||||
final refreshedCredentials = await credentialsFromCookie(cookie);
|
||||
|
||||
await database
|
||||
.into(database.authenticationTable)
|
||||
.insert(refreshedCredentials, mode: InsertMode.replace);
|
||||
}
|
||||
|
||||
String base32FromBytes(Uint8List e, String secretSauce) {
|
||||
var t = 0;
|
||||
var n = 0;
|
||||
var r = "";
|
||||
for (int i = 0; i < e.length; i++) {
|
||||
n = n << 8 | e[i];
|
||||
t += 8;
|
||||
while (t >= 5) {
|
||||
r += secretSauce[n >>> t - 5 & 31];
|
||||
t -= 5;
|
||||
}
|
||||
}
|
||||
if (t > 0) {
|
||||
r += secretSauce[n << 5 - t & 31];
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
Uint8List cleanBuffer(String e) {
|
||||
e = e.replaceAll(" ", "");
|
||||
final t = List.filled(e.length ~/ 2, 0);
|
||||
final n = Uint8List.fromList(t);
|
||||
for (int r = 0; r < e.length; r += 2) {
|
||||
n[r ~/ 2] = int.parse(e.substring(r, r + 2), radix: 16);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
Future<String> generateTotp() async {
|
||||
const secretSauce = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
final secretCipherBytes = const [
|
||||
12,
|
||||
56,
|
||||
76,
|
||||
33,
|
||||
88,
|
||||
44,
|
||||
88,
|
||||
33,
|
||||
78,
|
||||
78,
|
||||
11,
|
||||
66,
|
||||
22,
|
||||
22,
|
||||
55,
|
||||
69,
|
||||
54
|
||||
].mapIndexed((t, e) => e ^ t % 33 + 9).toList();
|
||||
|
||||
final secretBytes = cleanBuffer(
|
||||
utf8
|
||||
.encode(secretCipherBytes.join(""))
|
||||
.map((e) => e.toRadixString(16))
|
||||
.join(),
|
||||
);
|
||||
|
||||
final secret = base32FromBytes(secretBytes, secretSauce);
|
||||
|
||||
final res = await dio.get(
|
||||
"https://open.spotify.com/server-time",
|
||||
options: Options(
|
||||
headers: {
|
||||
"Host": "open.spotify.com",
|
||||
"User-Agent": ServiceUtils.randomUserAgent(
|
||||
kIsDesktop ? UserAgentDevice.desktop : UserAgentDevice.mobile,
|
||||
),
|
||||
"accept": "*/*",
|
||||
},
|
||||
),
|
||||
);
|
||||
final serverTimeSeconds = res.data["serverTime"] as int;
|
||||
|
||||
final totp = TOTP(
|
||||
secret: secret,
|
||||
algorithm: OTPAlgorithm.SHA1,
|
||||
digits: 6,
|
||||
interval: 30,
|
||||
);
|
||||
|
||||
return totp.generateOTP(
|
||||
input: Util.timeFormat(
|
||||
time: DateTime.fromMillisecondsSinceEpoch(serverTimeSeconds * 1000),
|
||||
interval: 30,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<Response> getToken({
|
||||
required String totp,
|
||||
required int timestamp,
|
||||
String mode = "transport",
|
||||
String? spDc,
|
||||
}) async {
|
||||
assert(mode == "transport" || mode == "init");
|
||||
|
||||
final accessTokenUrl = Uri.parse(
|
||||
"https://open.spotify.com/get_access_token?reason=$mode&productType=web-player"
|
||||
"&totp=$totp&totpVer=5&ts=$timestamp",
|
||||
);
|
||||
|
||||
final res = await dio.getUri(
|
||||
accessTokenUrl,
|
||||
options: Options(
|
||||
headers: {
|
||||
"Cookie": spDc ?? "",
|
||||
"User-Agent": ServiceUtils.randomUserAgent(
|
||||
kIsDesktop ? UserAgentDevice.desktop : UserAgentDevice.mobile,
|
||||
),
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<AuthenticationTableCompanion> credentialsFromCookie(
|
||||
String cookie,
|
||||
) async {
|
||||
try {
|
||||
final spDc = cookie
|
||||
.split("; ")
|
||||
.firstWhereOrNull((c) => c.trim().startsWith("sp_dc="))
|
||||
?.trim();
|
||||
|
||||
final totp = await generateTotp();
|
||||
|
||||
final timestamp = (DateTime.now().millisecondsSinceEpoch / 1000).floor();
|
||||
|
||||
var res = await getToken(
|
||||
totp: totp,
|
||||
timestamp: timestamp,
|
||||
spDc: spDc,
|
||||
mode: "transport",
|
||||
);
|
||||
|
||||
if ((res.data["accessToken"]?.length ?? 0) != 374) {
|
||||
res = await getToken(
|
||||
totp: totp,
|
||||
timestamp: timestamp,
|
||||
spDc: spDc,
|
||||
mode: "init",
|
||||
);
|
||||
}
|
||||
|
||||
final body = res.data as Map<String, dynamic>;
|
||||
|
||||
if (body["accessToken"] == null) {
|
||||
AppLogger.reportError(
|
||||
"The access token is only ${body["accessToken"]?.length} characters long instead of 374\n"
|
||||
"Your authentication probably doesn't work",
|
||||
StackTrace.current,
|
||||
);
|
||||
}
|
||||
|
||||
return AuthenticationTableCompanion.insert(
|
||||
id: const Value(0),
|
||||
cookie: DecryptedText("${res.headers["set-cookie"]?.join(";")}; $spDc"),
|
||||
accessToken: DecryptedText(body['accessToken']),
|
||||
expiration: DateTime.fromMillisecondsSinceEpoch(
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
state = const AsyncData(null);
|
||||
final database = ref.read(databaseProvider);
|
||||
await (database.delete(database.authenticationTable)
|
||||
..where((s) => s.id.equals(0)))
|
||||
.go();
|
||||
if (kIsMobile) {
|
||||
WebStorageManager.instance().deleteAllData();
|
||||
CookieManager.instance().deleteAllCookies();
|
||||
}
|
||||
if (kIsDesktop) {
|
||||
await WebviewWindow.clearAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final authenticationProvider =
|
||||
AsyncNotifierProvider<AuthenticationNotifier, AuthenticationTableData?>(
|
||||
() => AuthenticationNotifier(),
|
||||
);
|
@ -1,7 +1,6 @@
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotube/models/metadata/metadata.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/user.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||
import 'package:spotube/provider/metadata_plugin/utils/paginated.dart';
|
||||
|
||||
@ -11,17 +10,7 @@ class MetadataPluginSavedTracksNotifier
|
||||
|
||||
@override
|
||||
fetch(offset, limit) async {
|
||||
final user = await ref.read(metadataPluginUserProvider.future);
|
||||
|
||||
if (user == null) {
|
||||
throw Exception(
|
||||
'User not found \n'
|
||||
'You need to be logged in to access saved tracks.',
|
||||
);
|
||||
}
|
||||
|
||||
final tracks = await (await metadataPlugin).album.tracks(
|
||||
user.id,
|
||||
final tracks = await (await metadataPlugin).user.savedTracks(
|
||||
offset: offset,
|
||||
limit: limit,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user