mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55: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:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/collections/routes.gr.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';
|
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||||
|
|
||||||
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
||||||
@ -28,9 +28,10 @@ class AppRouter extends RootStackRouter {
|
|||||||
guards: [
|
guards: [
|
||||||
AutoRouteGuardCallback(
|
AutoRouteGuardCallback(
|
||||||
(resolver, router) async {
|
(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());
|
resolver.redirect(const GettingStartedRoute());
|
||||||
} else {
|
} else {
|
||||||
resolver.next(true);
|
resolver.next(true);
|
||||||
@ -209,11 +210,6 @@ class AppRouter extends RootStackRouter {
|
|||||||
page: GettingStartedRoute.page,
|
page: GettingStartedRoute.page,
|
||||||
// parentNavigatorKey: rootNavigatorKey,
|
// parentNavigatorKey: rootNavigatorKey,
|
||||||
),
|
),
|
||||||
AutoRoute(
|
|
||||||
path: "/login",
|
|
||||||
page: WebViewLoginRoute.page,
|
|
||||||
// parentNavigatorKey: rootNavigatorKey,
|
|
||||||
),
|
|
||||||
AutoRoute(
|
AutoRoute(
|
||||||
path: "/lastfm-login",
|
path: "/lastfm-login",
|
||||||
page: LastFMLoginRoute.page,
|
page: LastFMLoginRoute.page,
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
|
|
||||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
import 'package:auto_route/auto_route.dart' as _i40;
|
import 'package:auto_route/auto_route.dart' as _i39;
|
||||||
import 'package:flutter/material.dart' as _i41;
|
import 'package:flutter/material.dart' as _i40;
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart' as _i43;
|
import 'package:shadcn_flutter/shadcn_flutter.dart' as _i42;
|
||||||
import 'package:spotube/models/metadata/metadata.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/album/album.dart' as _i2;
|
||||||
import 'package:spotube/pages/artist/artist.dart' as _i3;
|
import 'package:spotube/pages/artist/artist.dart' as _i3;
|
||||||
import 'package:spotube/pages/connect/connect.dart' as _i6;
|
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/library/user_playlists.dart' as _i38;
|
||||||
import 'package:spotube/pages/lyrics/lyrics.dart' as _i15;
|
import 'package:spotube/pages/lyrics/lyrics.dart' as _i15;
|
||||||
import 'package:spotube/pages/lyrics/mini_lyrics.dart' as _i16;
|
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/lyrics.dart' as _i17;
|
||||||
import 'package:spotube/pages/player/queue.dart' as _i18;
|
import 'package:spotube/pages/player/queue.dart' as _i18;
|
||||||
import 'package:spotube/pages/player/sources.dart' as _i19;
|
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
|
/// generated route for
|
||||||
/// [_i1.AboutSpotubePage]
|
/// [_i1.AboutSpotubePage]
|
||||||
class AboutSpotubeRoute extends _i40.PageRouteInfo<void> {
|
class AboutSpotubeRoute extends _i39.PageRouteInfo<void> {
|
||||||
const AboutSpotubeRoute({List<_i40.PageRouteInfo>? children})
|
const AboutSpotubeRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
AboutSpotubeRoute.name,
|
AboutSpotubeRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -65,7 +64,7 @@ class AboutSpotubeRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'AboutSpotubeRoute';
|
static const String name = 'AboutSpotubeRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i1.AboutSpotubePage();
|
return const _i1.AboutSpotubePage();
|
||||||
@ -75,12 +74,12 @@ class AboutSpotubeRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i2.AlbumPage]
|
/// [_i2.AlbumPage]
|
||||||
class AlbumRoute extends _i40.PageRouteInfo<AlbumRouteArgs> {
|
class AlbumRoute extends _i39.PageRouteInfo<AlbumRouteArgs> {
|
||||||
AlbumRoute({
|
AlbumRoute({
|
||||||
_i41.Key? key,
|
_i40.Key? key,
|
||||||
required String id,
|
required String id,
|
||||||
required _i42.SpotubeSimpleAlbumObject album,
|
required _i41.SpotubeSimpleAlbumObject album,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
AlbumRoute.name,
|
AlbumRoute.name,
|
||||||
args: AlbumRouteArgs(
|
args: AlbumRouteArgs(
|
||||||
@ -94,7 +93,7 @@ class AlbumRoute extends _i40.PageRouteInfo<AlbumRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'AlbumRoute';
|
static const String name = 'AlbumRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<AlbumRouteArgs>();
|
final args = data.argsAs<AlbumRouteArgs>();
|
||||||
@ -114,11 +113,11 @@ class AlbumRouteArgs {
|
|||||||
required this.album,
|
required this.album,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i41.Key? key;
|
final _i40.Key? key;
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
final _i42.SpotubeSimpleAlbumObject album;
|
final _i41.SpotubeSimpleAlbumObject album;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -128,11 +127,11 @@ class AlbumRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i3.ArtistPage]
|
/// [_i3.ArtistPage]
|
||||||
class ArtistRoute extends _i40.PageRouteInfo<ArtistRouteArgs> {
|
class ArtistRoute extends _i39.PageRouteInfo<ArtistRouteArgs> {
|
||||||
ArtistRoute({
|
ArtistRoute({
|
||||||
required String artistId,
|
required String artistId,
|
||||||
_i41.Key? key,
|
_i40.Key? key,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
ArtistRoute.name,
|
ArtistRoute.name,
|
||||||
args: ArtistRouteArgs(
|
args: ArtistRouteArgs(
|
||||||
@ -145,7 +144,7 @@ class ArtistRoute extends _i40.PageRouteInfo<ArtistRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'ArtistRoute';
|
static const String name = 'ArtistRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
@ -167,7 +166,7 @@ class ArtistRouteArgs {
|
|||||||
|
|
||||||
final String artistId;
|
final String artistId;
|
||||||
|
|
||||||
final _i41.Key? key;
|
final _i40.Key? key;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -177,8 +176,8 @@ class ArtistRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i4.BlackListPage]
|
/// [_i4.BlackListPage]
|
||||||
class BlackListRoute extends _i40.PageRouteInfo<void> {
|
class BlackListRoute extends _i39.PageRouteInfo<void> {
|
||||||
const BlackListRoute({List<_i40.PageRouteInfo>? children})
|
const BlackListRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
BlackListRoute.name,
|
BlackListRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -186,7 +185,7 @@ class BlackListRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'BlackListRoute';
|
static const String name = 'BlackListRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i4.BlackListPage();
|
return const _i4.BlackListPage();
|
||||||
@ -196,8 +195,8 @@ class BlackListRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i5.ConnectControlPage]
|
/// [_i5.ConnectControlPage]
|
||||||
class ConnectControlRoute extends _i40.PageRouteInfo<void> {
|
class ConnectControlRoute extends _i39.PageRouteInfo<void> {
|
||||||
const ConnectControlRoute({List<_i40.PageRouteInfo>? children})
|
const ConnectControlRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
ConnectControlRoute.name,
|
ConnectControlRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -205,7 +204,7 @@ class ConnectControlRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'ConnectControlRoute';
|
static const String name = 'ConnectControlRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i5.ConnectControlPage();
|
return const _i5.ConnectControlPage();
|
||||||
@ -215,8 +214,8 @@ class ConnectControlRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i6.ConnectPage]
|
/// [_i6.ConnectPage]
|
||||||
class ConnectRoute extends _i40.PageRouteInfo<void> {
|
class ConnectRoute extends _i39.PageRouteInfo<void> {
|
||||||
const ConnectRoute({List<_i40.PageRouteInfo>? children})
|
const ConnectRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
ConnectRoute.name,
|
ConnectRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -224,7 +223,7 @@ class ConnectRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'ConnectRoute';
|
static const String name = 'ConnectRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i6.ConnectPage();
|
return const _i6.ConnectPage();
|
||||||
@ -234,8 +233,8 @@ class ConnectRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i7.GettingStartedPage]
|
/// [_i7.GettingStartedPage]
|
||||||
class GettingStartedRoute extends _i40.PageRouteInfo<void> {
|
class GettingStartedRoute extends _i39.PageRouteInfo<void> {
|
||||||
const GettingStartedRoute({List<_i40.PageRouteInfo>? children})
|
const GettingStartedRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
GettingStartedRoute.name,
|
GettingStartedRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -243,7 +242,7 @@ class GettingStartedRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'GettingStartedRoute';
|
static const String name = 'GettingStartedRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i7.GettingStartedPage();
|
return const _i7.GettingStartedPage();
|
||||||
@ -254,12 +253,12 @@ class GettingStartedRoute extends _i40.PageRouteInfo<void> {
|
|||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i8.HomeBrowseSectionItemsPage]
|
/// [_i8.HomeBrowseSectionItemsPage]
|
||||||
class HomeBrowseSectionItemsRoute
|
class HomeBrowseSectionItemsRoute
|
||||||
extends _i40.PageRouteInfo<HomeBrowseSectionItemsRouteArgs> {
|
extends _i39.PageRouteInfo<HomeBrowseSectionItemsRouteArgs> {
|
||||||
HomeBrowseSectionItemsRoute({
|
HomeBrowseSectionItemsRoute({
|
||||||
_i43.Key? key,
|
_i42.Key? key,
|
||||||
required String sectionId,
|
required String sectionId,
|
||||||
required _i42.SpotubeBrowseSectionObject<Object> section,
|
required _i41.SpotubeBrowseSectionObject<Object> section,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
HomeBrowseSectionItemsRoute.name,
|
HomeBrowseSectionItemsRoute.name,
|
||||||
args: HomeBrowseSectionItemsRouteArgs(
|
args: HomeBrowseSectionItemsRouteArgs(
|
||||||
@ -273,7 +272,7 @@ class HomeBrowseSectionItemsRoute
|
|||||||
|
|
||||||
static const String name = 'HomeBrowseSectionItemsRoute';
|
static const String name = 'HomeBrowseSectionItemsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<HomeBrowseSectionItemsRouteArgs>();
|
final args = data.argsAs<HomeBrowseSectionItemsRouteArgs>();
|
||||||
@ -293,11 +292,11 @@ class HomeBrowseSectionItemsRouteArgs {
|
|||||||
required this.section,
|
required this.section,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i43.Key? key;
|
final _i42.Key? key;
|
||||||
|
|
||||||
final String sectionId;
|
final String sectionId;
|
||||||
|
|
||||||
final _i42.SpotubeBrowseSectionObject<Object> section;
|
final _i41.SpotubeBrowseSectionObject<Object> section;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -307,8 +306,8 @@ class HomeBrowseSectionItemsRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i9.HomePage]
|
/// [_i9.HomePage]
|
||||||
class HomeRoute extends _i40.PageRouteInfo<void> {
|
class HomeRoute extends _i39.PageRouteInfo<void> {
|
||||||
const HomeRoute({List<_i40.PageRouteInfo>? children})
|
const HomeRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
HomeRoute.name,
|
HomeRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -316,7 +315,7 @@ class HomeRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'HomeRoute';
|
static const String name = 'HomeRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i9.HomePage();
|
return const _i9.HomePage();
|
||||||
@ -326,8 +325,8 @@ class HomeRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i10.LastFMLoginPage]
|
/// [_i10.LastFMLoginPage]
|
||||||
class LastFMLoginRoute extends _i40.PageRouteInfo<void> {
|
class LastFMLoginRoute extends _i39.PageRouteInfo<void> {
|
||||||
const LastFMLoginRoute({List<_i40.PageRouteInfo>? children})
|
const LastFMLoginRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
LastFMLoginRoute.name,
|
LastFMLoginRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -335,7 +334,7 @@ class LastFMLoginRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'LastFMLoginRoute';
|
static const String name = 'LastFMLoginRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i10.LastFMLoginPage();
|
return const _i10.LastFMLoginPage();
|
||||||
@ -345,8 +344,8 @@ class LastFMLoginRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i11.LibraryPage]
|
/// [_i11.LibraryPage]
|
||||||
class LibraryRoute extends _i40.PageRouteInfo<void> {
|
class LibraryRoute extends _i39.PageRouteInfo<void> {
|
||||||
const LibraryRoute({List<_i40.PageRouteInfo>? children})
|
const LibraryRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
LibraryRoute.name,
|
LibraryRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -354,7 +353,7 @@ class LibraryRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'LibraryRoute';
|
static const String name = 'LibraryRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i11.LibraryPage();
|
return const _i11.LibraryPage();
|
||||||
@ -364,11 +363,11 @@ class LibraryRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i12.LikedPlaylistPage]
|
/// [_i12.LikedPlaylistPage]
|
||||||
class LikedPlaylistRoute extends _i40.PageRouteInfo<LikedPlaylistRouteArgs> {
|
class LikedPlaylistRoute extends _i39.PageRouteInfo<LikedPlaylistRouteArgs> {
|
||||||
LikedPlaylistRoute({
|
LikedPlaylistRoute({
|
||||||
_i41.Key? key,
|
_i40.Key? key,
|
||||||
required _i42.SpotubeSimplePlaylistObject playlist,
|
required _i41.SpotubeSimplePlaylistObject playlist,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
LikedPlaylistRoute.name,
|
LikedPlaylistRoute.name,
|
||||||
args: LikedPlaylistRouteArgs(
|
args: LikedPlaylistRouteArgs(
|
||||||
@ -380,7 +379,7 @@ class LikedPlaylistRoute extends _i40.PageRouteInfo<LikedPlaylistRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'LikedPlaylistRoute';
|
static const String name = 'LikedPlaylistRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<LikedPlaylistRouteArgs>();
|
final args = data.argsAs<LikedPlaylistRouteArgs>();
|
||||||
@ -398,9 +397,9 @@ class LikedPlaylistRouteArgs {
|
|||||||
required this.playlist,
|
required this.playlist,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i41.Key? key;
|
final _i40.Key? key;
|
||||||
|
|
||||||
final _i42.SpotubeSimplePlaylistObject playlist;
|
final _i41.SpotubeSimplePlaylistObject playlist;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -410,13 +409,13 @@ class LikedPlaylistRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i13.LocalLibraryPage]
|
/// [_i13.LocalLibraryPage]
|
||||||
class LocalLibraryRoute extends _i40.PageRouteInfo<LocalLibraryRouteArgs> {
|
class LocalLibraryRoute extends _i39.PageRouteInfo<LocalLibraryRouteArgs> {
|
||||||
LocalLibraryRoute({
|
LocalLibraryRoute({
|
||||||
required String location,
|
required String location,
|
||||||
_i41.Key? key,
|
_i40.Key? key,
|
||||||
bool isDownloads = false,
|
bool isDownloads = false,
|
||||||
bool isCache = false,
|
bool isCache = false,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
LocalLibraryRoute.name,
|
LocalLibraryRoute.name,
|
||||||
args: LocalLibraryRouteArgs(
|
args: LocalLibraryRouteArgs(
|
||||||
@ -430,7 +429,7 @@ class LocalLibraryRoute extends _i40.PageRouteInfo<LocalLibraryRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'LocalLibraryRoute';
|
static const String name = 'LocalLibraryRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<LocalLibraryRouteArgs>();
|
final args = data.argsAs<LocalLibraryRouteArgs>();
|
||||||
@ -454,7 +453,7 @@ class LocalLibraryRouteArgs {
|
|||||||
|
|
||||||
final String location;
|
final String location;
|
||||||
|
|
||||||
final _i41.Key? key;
|
final _i40.Key? key;
|
||||||
|
|
||||||
final bool isDownloads;
|
final bool isDownloads;
|
||||||
|
|
||||||
@ -468,8 +467,8 @@ class LocalLibraryRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i14.LogsPage]
|
/// [_i14.LogsPage]
|
||||||
class LogsRoute extends _i40.PageRouteInfo<void> {
|
class LogsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const LogsRoute({List<_i40.PageRouteInfo>? children})
|
const LogsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
LogsRoute.name,
|
LogsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -477,7 +476,7 @@ class LogsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'LogsRoute';
|
static const String name = 'LogsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i14.LogsPage();
|
return const _i14.LogsPage();
|
||||||
@ -487,8 +486,8 @@ class LogsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i15.LyricsPage]
|
/// [_i15.LyricsPage]
|
||||||
class LyricsRoute extends _i40.PageRouteInfo<void> {
|
class LyricsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const LyricsRoute({List<_i40.PageRouteInfo>? children})
|
const LyricsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
LyricsRoute.name,
|
LyricsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -496,7 +495,7 @@ class LyricsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'LyricsRoute';
|
static const String name = 'LyricsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i15.LyricsPage();
|
return const _i15.LyricsPage();
|
||||||
@ -506,11 +505,11 @@ class LyricsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i16.MiniLyricsPage]
|
/// [_i16.MiniLyricsPage]
|
||||||
class MiniLyricsRoute extends _i40.PageRouteInfo<MiniLyricsRouteArgs> {
|
class MiniLyricsRoute extends _i39.PageRouteInfo<MiniLyricsRouteArgs> {
|
||||||
MiniLyricsRoute({
|
MiniLyricsRoute({
|
||||||
_i43.Key? key,
|
_i42.Key? key,
|
||||||
required _i43.Size prevSize,
|
required _i42.Size prevSize,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
MiniLyricsRoute.name,
|
MiniLyricsRoute.name,
|
||||||
args: MiniLyricsRouteArgs(
|
args: MiniLyricsRouteArgs(
|
||||||
@ -522,7 +521,7 @@ class MiniLyricsRoute extends _i40.PageRouteInfo<MiniLyricsRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'MiniLyricsRoute';
|
static const String name = 'MiniLyricsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<MiniLyricsRouteArgs>();
|
final args = data.argsAs<MiniLyricsRouteArgs>();
|
||||||
@ -540,9 +539,9 @@ class MiniLyricsRouteArgs {
|
|||||||
required this.prevSize,
|
required this.prevSize,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i43.Key? key;
|
final _i42.Key? key;
|
||||||
|
|
||||||
final _i43.Size prevSize;
|
final _i42.Size prevSize;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -552,8 +551,8 @@ class MiniLyricsRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i17.PlayerLyricsPage]
|
/// [_i17.PlayerLyricsPage]
|
||||||
class PlayerLyricsRoute extends _i40.PageRouteInfo<void> {
|
class PlayerLyricsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const PlayerLyricsRoute({List<_i40.PageRouteInfo>? children})
|
const PlayerLyricsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
PlayerLyricsRoute.name,
|
PlayerLyricsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -561,7 +560,7 @@ class PlayerLyricsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'PlayerLyricsRoute';
|
static const String name = 'PlayerLyricsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i17.PlayerLyricsPage();
|
return const _i17.PlayerLyricsPage();
|
||||||
@ -571,8 +570,8 @@ class PlayerLyricsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i18.PlayerQueuePage]
|
/// [_i18.PlayerQueuePage]
|
||||||
class PlayerQueueRoute extends _i40.PageRouteInfo<void> {
|
class PlayerQueueRoute extends _i39.PageRouteInfo<void> {
|
||||||
const PlayerQueueRoute({List<_i40.PageRouteInfo>? children})
|
const PlayerQueueRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
PlayerQueueRoute.name,
|
PlayerQueueRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -580,7 +579,7 @@ class PlayerQueueRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'PlayerQueueRoute';
|
static const String name = 'PlayerQueueRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i18.PlayerQueuePage();
|
return const _i18.PlayerQueuePage();
|
||||||
@ -590,8 +589,8 @@ class PlayerQueueRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i19.PlayerTrackSourcesPage]
|
/// [_i19.PlayerTrackSourcesPage]
|
||||||
class PlayerTrackSourcesRoute extends _i40.PageRouteInfo<void> {
|
class PlayerTrackSourcesRoute extends _i39.PageRouteInfo<void> {
|
||||||
const PlayerTrackSourcesRoute({List<_i40.PageRouteInfo>? children})
|
const PlayerTrackSourcesRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
PlayerTrackSourcesRoute.name,
|
PlayerTrackSourcesRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -599,7 +598,7 @@ class PlayerTrackSourcesRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'PlayerTrackSourcesRoute';
|
static const String name = 'PlayerTrackSourcesRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i19.PlayerTrackSourcesPage();
|
return const _i19.PlayerTrackSourcesPage();
|
||||||
@ -609,12 +608,12 @@ class PlayerTrackSourcesRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i20.PlaylistPage]
|
/// [_i20.PlaylistPage]
|
||||||
class PlaylistRoute extends _i40.PageRouteInfo<PlaylistRouteArgs> {
|
class PlaylistRoute extends _i39.PageRouteInfo<PlaylistRouteArgs> {
|
||||||
PlaylistRoute({
|
PlaylistRoute({
|
||||||
_i41.Key? key,
|
_i40.Key? key,
|
||||||
required String id,
|
required String id,
|
||||||
required _i42.SpotubeSimplePlaylistObject playlist,
|
required _i41.SpotubeSimplePlaylistObject playlist,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
PlaylistRoute.name,
|
PlaylistRoute.name,
|
||||||
args: PlaylistRouteArgs(
|
args: PlaylistRouteArgs(
|
||||||
@ -628,7 +627,7 @@ class PlaylistRoute extends _i40.PageRouteInfo<PlaylistRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'PlaylistRoute';
|
static const String name = 'PlaylistRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<PlaylistRouteArgs>();
|
final args = data.argsAs<PlaylistRouteArgs>();
|
||||||
@ -648,11 +647,11 @@ class PlaylistRouteArgs {
|
|||||||
required this.playlist,
|
required this.playlist,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i41.Key? key;
|
final _i40.Key? key;
|
||||||
|
|
||||||
final String id;
|
final String id;
|
||||||
|
|
||||||
final _i42.SpotubeSimplePlaylistObject playlist;
|
final _i41.SpotubeSimplePlaylistObject playlist;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
@ -662,8 +661,8 @@ class PlaylistRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i21.ProfilePage]
|
/// [_i21.ProfilePage]
|
||||||
class ProfileRoute extends _i40.PageRouteInfo<void> {
|
class ProfileRoute extends _i39.PageRouteInfo<void> {
|
||||||
const ProfileRoute({List<_i40.PageRouteInfo>? children})
|
const ProfileRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
ProfileRoute.name,
|
ProfileRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -671,7 +670,7 @@ class ProfileRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'ProfileRoute';
|
static const String name = 'ProfileRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i21.ProfilePage();
|
return const _i21.ProfilePage();
|
||||||
@ -681,8 +680,8 @@ class ProfileRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i22.RootAppPage]
|
/// [_i22.RootAppPage]
|
||||||
class RootAppRoute extends _i40.PageRouteInfo<void> {
|
class RootAppRoute extends _i39.PageRouteInfo<void> {
|
||||||
const RootAppRoute({List<_i40.PageRouteInfo>? children})
|
const RootAppRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
RootAppRoute.name,
|
RootAppRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -690,7 +689,7 @@ class RootAppRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'RootAppRoute';
|
static const String name = 'RootAppRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i22.RootAppPage();
|
return const _i22.RootAppPage();
|
||||||
@ -700,8 +699,8 @@ class RootAppRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i23.SearchPage]
|
/// [_i23.SearchPage]
|
||||||
class SearchRoute extends _i40.PageRouteInfo<void> {
|
class SearchRoute extends _i39.PageRouteInfo<void> {
|
||||||
const SearchRoute({List<_i40.PageRouteInfo>? children})
|
const SearchRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
SearchRoute.name,
|
SearchRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -709,7 +708,7 @@ class SearchRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'SearchRoute';
|
static const String name = 'SearchRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i23.SearchPage();
|
return const _i23.SearchPage();
|
||||||
@ -719,8 +718,8 @@ class SearchRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i24.SettingsMetadataProviderPage]
|
/// [_i24.SettingsMetadataProviderPage]
|
||||||
class SettingsMetadataProviderRoute extends _i40.PageRouteInfo<void> {
|
class SettingsMetadataProviderRoute extends _i39.PageRouteInfo<void> {
|
||||||
const SettingsMetadataProviderRoute({List<_i40.PageRouteInfo>? children})
|
const SettingsMetadataProviderRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
SettingsMetadataProviderRoute.name,
|
SettingsMetadataProviderRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -728,7 +727,7 @@ class SettingsMetadataProviderRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'SettingsMetadataProviderRoute';
|
static const String name = 'SettingsMetadataProviderRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i24.SettingsMetadataProviderPage();
|
return const _i24.SettingsMetadataProviderPage();
|
||||||
@ -738,8 +737,8 @@ class SettingsMetadataProviderRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i25.SettingsPage]
|
/// [_i25.SettingsPage]
|
||||||
class SettingsRoute extends _i40.PageRouteInfo<void> {
|
class SettingsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const SettingsRoute({List<_i40.PageRouteInfo>? children})
|
const SettingsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
SettingsRoute.name,
|
SettingsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -747,7 +746,7 @@ class SettingsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'SettingsRoute';
|
static const String name = 'SettingsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i25.SettingsPage();
|
return const _i25.SettingsPage();
|
||||||
@ -757,8 +756,8 @@ class SettingsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i26.StatsAlbumsPage]
|
/// [_i26.StatsAlbumsPage]
|
||||||
class StatsAlbumsRoute extends _i40.PageRouteInfo<void> {
|
class StatsAlbumsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const StatsAlbumsRoute({List<_i40.PageRouteInfo>? children})
|
const StatsAlbumsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
StatsAlbumsRoute.name,
|
StatsAlbumsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -766,7 +765,7 @@ class StatsAlbumsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'StatsAlbumsRoute';
|
static const String name = 'StatsAlbumsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i26.StatsAlbumsPage();
|
return const _i26.StatsAlbumsPage();
|
||||||
@ -776,8 +775,8 @@ class StatsAlbumsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i27.StatsArtistsPage]
|
/// [_i27.StatsArtistsPage]
|
||||||
class StatsArtistsRoute extends _i40.PageRouteInfo<void> {
|
class StatsArtistsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const StatsArtistsRoute({List<_i40.PageRouteInfo>? children})
|
const StatsArtistsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
StatsArtistsRoute.name,
|
StatsArtistsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -785,7 +784,7 @@ class StatsArtistsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'StatsArtistsRoute';
|
static const String name = 'StatsArtistsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i27.StatsArtistsPage();
|
return const _i27.StatsArtistsPage();
|
||||||
@ -795,8 +794,8 @@ class StatsArtistsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i28.StatsMinutesPage]
|
/// [_i28.StatsMinutesPage]
|
||||||
class StatsMinutesRoute extends _i40.PageRouteInfo<void> {
|
class StatsMinutesRoute extends _i39.PageRouteInfo<void> {
|
||||||
const StatsMinutesRoute({List<_i40.PageRouteInfo>? children})
|
const StatsMinutesRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
StatsMinutesRoute.name,
|
StatsMinutesRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -804,7 +803,7 @@ class StatsMinutesRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'StatsMinutesRoute';
|
static const String name = 'StatsMinutesRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i28.StatsMinutesPage();
|
return const _i28.StatsMinutesPage();
|
||||||
@ -814,8 +813,8 @@ class StatsMinutesRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i29.StatsPage]
|
/// [_i29.StatsPage]
|
||||||
class StatsRoute extends _i40.PageRouteInfo<void> {
|
class StatsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const StatsRoute({List<_i40.PageRouteInfo>? children})
|
const StatsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
StatsRoute.name,
|
StatsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -823,7 +822,7 @@ class StatsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'StatsRoute';
|
static const String name = 'StatsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i29.StatsPage();
|
return const _i29.StatsPage();
|
||||||
@ -833,8 +832,8 @@ class StatsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i30.StatsPlaylistsPage]
|
/// [_i30.StatsPlaylistsPage]
|
||||||
class StatsPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
class StatsPlaylistsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const StatsPlaylistsRoute({List<_i40.PageRouteInfo>? children})
|
const StatsPlaylistsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
StatsPlaylistsRoute.name,
|
StatsPlaylistsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -842,7 +841,7 @@ class StatsPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'StatsPlaylistsRoute';
|
static const String name = 'StatsPlaylistsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i30.StatsPlaylistsPage();
|
return const _i30.StatsPlaylistsPage();
|
||||||
@ -852,8 +851,8 @@ class StatsPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i31.StatsStreamFeesPage]
|
/// [_i31.StatsStreamFeesPage]
|
||||||
class StatsStreamFeesRoute extends _i40.PageRouteInfo<void> {
|
class StatsStreamFeesRoute extends _i39.PageRouteInfo<void> {
|
||||||
const StatsStreamFeesRoute({List<_i40.PageRouteInfo>? children})
|
const StatsStreamFeesRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
StatsStreamFeesRoute.name,
|
StatsStreamFeesRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -861,7 +860,7 @@ class StatsStreamFeesRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'StatsStreamFeesRoute';
|
static const String name = 'StatsStreamFeesRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i31.StatsStreamFeesPage();
|
return const _i31.StatsStreamFeesPage();
|
||||||
@ -871,8 +870,8 @@ class StatsStreamFeesRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i32.StatsStreamsPage]
|
/// [_i32.StatsStreamsPage]
|
||||||
class StatsStreamsRoute extends _i40.PageRouteInfo<void> {
|
class StatsStreamsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const StatsStreamsRoute({List<_i40.PageRouteInfo>? children})
|
const StatsStreamsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
StatsStreamsRoute.name,
|
StatsStreamsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -880,7 +879,7 @@ class StatsStreamsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'StatsStreamsRoute';
|
static const String name = 'StatsStreamsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i32.StatsStreamsPage();
|
return const _i32.StatsStreamsPage();
|
||||||
@ -890,11 +889,11 @@ class StatsStreamsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i33.TrackPage]
|
/// [_i33.TrackPage]
|
||||||
class TrackRoute extends _i40.PageRouteInfo<TrackRouteArgs> {
|
class TrackRoute extends _i39.PageRouteInfo<TrackRouteArgs> {
|
||||||
TrackRoute({
|
TrackRoute({
|
||||||
_i43.Key? key,
|
_i42.Key? key,
|
||||||
required String trackId,
|
required String trackId,
|
||||||
List<_i40.PageRouteInfo>? children,
|
List<_i39.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
TrackRoute.name,
|
TrackRoute.name,
|
||||||
args: TrackRouteArgs(
|
args: TrackRouteArgs(
|
||||||
@ -907,7 +906,7 @@ class TrackRoute extends _i40.PageRouteInfo<TrackRouteArgs> {
|
|||||||
|
|
||||||
static const String name = 'TrackRoute';
|
static const String name = 'TrackRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
@ -927,7 +926,7 @@ class TrackRouteArgs {
|
|||||||
required this.trackId,
|
required this.trackId,
|
||||||
});
|
});
|
||||||
|
|
||||||
final _i43.Key? key;
|
final _i42.Key? key;
|
||||||
|
|
||||||
final String trackId;
|
final String trackId;
|
||||||
|
|
||||||
@ -939,8 +938,8 @@ class TrackRouteArgs {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i34.UserAlbumsPage]
|
/// [_i34.UserAlbumsPage]
|
||||||
class UserAlbumsRoute extends _i40.PageRouteInfo<void> {
|
class UserAlbumsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const UserAlbumsRoute({List<_i40.PageRouteInfo>? children})
|
const UserAlbumsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
UserAlbumsRoute.name,
|
UserAlbumsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -948,7 +947,7 @@ class UserAlbumsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'UserAlbumsRoute';
|
static const String name = 'UserAlbumsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i34.UserAlbumsPage();
|
return const _i34.UserAlbumsPage();
|
||||||
@ -958,8 +957,8 @@ class UserAlbumsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i35.UserArtistsPage]
|
/// [_i35.UserArtistsPage]
|
||||||
class UserArtistsRoute extends _i40.PageRouteInfo<void> {
|
class UserArtistsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const UserArtistsRoute({List<_i40.PageRouteInfo>? children})
|
const UserArtistsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
UserArtistsRoute.name,
|
UserArtistsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -967,7 +966,7 @@ class UserArtistsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'UserArtistsRoute';
|
static const String name = 'UserArtistsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i35.UserArtistsPage();
|
return const _i35.UserArtistsPage();
|
||||||
@ -977,8 +976,8 @@ class UserArtistsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i36.UserDownloadsPage]
|
/// [_i36.UserDownloadsPage]
|
||||||
class UserDownloadsRoute extends _i40.PageRouteInfo<void> {
|
class UserDownloadsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const UserDownloadsRoute({List<_i40.PageRouteInfo>? children})
|
const UserDownloadsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
UserDownloadsRoute.name,
|
UserDownloadsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -986,7 +985,7 @@ class UserDownloadsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'UserDownloadsRoute';
|
static const String name = 'UserDownloadsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i36.UserDownloadsPage();
|
return const _i36.UserDownloadsPage();
|
||||||
@ -996,8 +995,8 @@ class UserDownloadsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i37.UserLocalLibraryPage]
|
/// [_i37.UserLocalLibraryPage]
|
||||||
class UserLocalLibraryRoute extends _i40.PageRouteInfo<void> {
|
class UserLocalLibraryRoute extends _i39.PageRouteInfo<void> {
|
||||||
const UserLocalLibraryRoute({List<_i40.PageRouteInfo>? children})
|
const UserLocalLibraryRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
UserLocalLibraryRoute.name,
|
UserLocalLibraryRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -1005,7 +1004,7 @@ class UserLocalLibraryRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'UserLocalLibraryRoute';
|
static const String name = 'UserLocalLibraryRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i37.UserLocalLibraryPage();
|
return const _i37.UserLocalLibraryPage();
|
||||||
@ -1015,8 +1014,8 @@ class UserLocalLibraryRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [_i38.UserPlaylistsPage]
|
/// [_i38.UserPlaylistsPage]
|
||||||
class UserPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
class UserPlaylistsRoute extends _i39.PageRouteInfo<void> {
|
||||||
const UserPlaylistsRoute({List<_i40.PageRouteInfo>? children})
|
const UserPlaylistsRoute({List<_i39.PageRouteInfo>? children})
|
||||||
: super(
|
: super(
|
||||||
UserPlaylistsRoute.name,
|
UserPlaylistsRoute.name,
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
@ -1024,29 +1023,10 @@ class UserPlaylistsRoute extends _i40.PageRouteInfo<void> {
|
|||||||
|
|
||||||
static const String name = 'UserPlaylistsRoute';
|
static const String name = 'UserPlaylistsRoute';
|
||||||
|
|
||||||
static _i40.PageInfo page = _i40.PageInfo(
|
static _i39.PageInfo page = _i39.PageInfo(
|
||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
return const _i38.UserPlaylistsPage();
|
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:shadcn_flutter/shadcn_flutter_extension.dart';
|
||||||
import 'package:spotube/collections/routes.gr.dart';
|
import 'package:spotube/collections/routes.gr.dart';
|
||||||
import 'package:spotube/extensions/context.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';
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class AnonymousFallback extends ConsumerWidget {
|
class AnonymousFallback extends ConsumerWidget {
|
||||||
@ -18,13 +18,13 @@ class AnonymousFallback extends ConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final isLoggedIn = ref.watch(authenticationProvider);
|
final isLoggedIn = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
|
|
||||||
if (isLoggedIn.isLoading) {
|
if (isLoggedIn.isLoading) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
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(
|
return Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
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/components/heart_button/use_track_toggle_like.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.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/library/tracks.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/user.dart';
|
import 'package:spotube/provider/metadata_plugin/user.dart';
|
||||||
|
|
||||||
@ -29,9 +29,9 @@ class HeartButton extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
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(
|
return Tooltip(
|
||||||
tooltip: TooltipContainer(child: Text(tooltip ?? "")).call,
|
tooltip: TooltipContainer(child: Text(tooltip ?? "")).call,
|
||||||
|
@ -226,6 +226,7 @@ class TrackPresentationTopSection extends HookConsumerWidget {
|
|||||||
.imageProvider(
|
.imageProvider(
|
||||||
options.ownerImage!,
|
options.ownerImage!,
|
||||||
),
|
),
|
||||||
|
size: 20 * scale,
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
child: Text(
|
child: Text(
|
||||||
|
@ -22,11 +22,11 @@ import 'package:spotube/extensions/constrains.dart';
|
|||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/models/database/database.dart';
|
import 'package:spotube/models/database/database.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.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/blacklist_provider.dart';
|
||||||
import 'package:spotube/provider/download_manager_provider.dart';
|
import 'package:spotube/provider/download_manager_provider.dart';
|
||||||
import 'package:spotube/provider/local_tracks/local_tracks_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/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/library/playlists.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/tracks/playlist.dart';
|
import 'package:spotube/provider/metadata_plugin/tracks/playlist.dart';
|
||||||
@ -181,7 +181,7 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
|
|
||||||
final playlist = ref.watch(audioPlayerProvider);
|
final playlist = ref.watch(audioPlayerProvider);
|
||||||
final playback = ref.watch(audioPlayerProvider.notifier);
|
final playback = ref.watch(audioPlayerProvider.notifier);
|
||||||
final auth = ref.watch(authenticationProvider);
|
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
ref.watch(downloadManagerProvider);
|
ref.watch(downloadManagerProvider);
|
||||||
final downloadManager = ref.watch(downloadManagerProvider.notifier);
|
final downloadManager = ref.watch(downloadManagerProvider.notifier);
|
||||||
final blacklist = ref.watch(blacklistProvider);
|
final blacklist = ref.watch(blacklistProvider);
|
||||||
@ -430,7 +430,7 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
: context.l10n.save_as_favorite,
|
: context.l10n.save_as_favorite,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (auth.asData?.value != null && !isLocalTrack) ...[
|
if (authenticated.asData?.value == true && !isLocalTrack) ...[
|
||||||
AdaptiveMenuButton(
|
AdaptiveMenuButton(
|
||||||
value: TrackOptionValue.startRadio,
|
value: TrackOptionValue.startRadio,
|
||||||
leading: const Icon(SpotubeIcons.radio),
|
leading: const Icon(SpotubeIcons.radio),
|
||||||
@ -442,7 +442,9 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
child: Text(context.l10n.add_to_playlist),
|
child: Text(context.l10n.add_to_playlist),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
if (userPlaylist && auth.asData?.value != null && !isLocalTrack)
|
if (userPlaylist &&
|
||||||
|
authenticated.asData?.value == true &&
|
||||||
|
!isLocalTrack)
|
||||||
AdaptiveMenuButton(
|
AdaptiveMenuButton(
|
||||||
value: TrackOptionValue.removeFromPlaylist,
|
value: TrackOptionValue.removeFromPlaylist,
|
||||||
leading: const Icon(SpotubeIcons.removeFilled),
|
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:spotube/services/logger/logger.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.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/audio_player/audio_player.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
import 'package:spotube/services/audio_player/audio_player.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/components/horizontal_playbutton_card_view/horizontal_playbutton_card_view.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.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/album/releases.dart';
|
||||||
|
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
import 'package:spotube/provider/metadata_plugin/utils/common.dart';
|
||||||
|
|
||||||
class HomeNewReleasesSection extends HookConsumerWidget {
|
class HomeNewReleasesSection extends HookConsumerWidget {
|
||||||
@ -12,13 +12,13 @@ class HomeNewReleasesSection extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final auth = ref.watch(authenticationProvider);
|
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
|
|
||||||
final newReleases = ref.watch(metadataPluginAlbumReleasesProvider);
|
final newReleases = ref.watch(metadataPluginAlbumReleasesProvider);
|
||||||
final newReleasesNotifier =
|
final newReleasesNotifier =
|
||||||
ref.read(metadataPluginAlbumReleasesProvider.notifier);
|
ref.read(metadataPluginAlbumReleasesProvider.notifier);
|
||||||
|
|
||||||
if (auth.asData?.value == null ||
|
if (authenticated.asData?.value != true ||
|
||||||
newReleases.isLoading ||
|
newReleases.isLoading ||
|
||||||
newReleases.asData?.value.items.isEmpty == true) {
|
newReleases.asData?.value.items.isEmpty == true) {
|
||||||
return const SizedBox.shrink();
|
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/constrains.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/modules/root/spotube_navigation_bar.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/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/server/active_track_sources.dart';
|
||||||
import 'package:spotube/provider/volume_provider.dart';
|
import 'package:spotube/provider/volume_provider.dart';
|
||||||
import 'package:spotube/services/sourced_track/sources/youtube.dart';
|
import 'package:spotube/services/sourced_track/sources/youtube.dart';
|
||||||
@ -41,7 +41,7 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final auth = ref.watch(authenticationProvider);
|
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
final sourcedCurrentTrack = ref.watch(activeTrackSourcesProvider);
|
final sourcedCurrentTrack = ref.watch(activeTrackSourcesProvider);
|
||||||
final currentActiveTrack =
|
final currentActiveTrack =
|
||||||
ref.watch(audioPlayerProvider.select((s) => s.activeTrack));
|
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 (authenticated.asData?.value == true)
|
||||||
if (auth.asData?.value != null)
|
const SizedBox(width: 10),
|
||||||
|
if (authenticated.asData?.value == true)
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlineButton(
|
child: OutlineButton(
|
||||||
leading: const Icon(SpotubeIcons.music),
|
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/context.dart';
|
||||||
import 'package:spotube/extensions/duration.dart';
|
import 'package:spotube/extensions/duration.dart';
|
||||||
import 'package:spotube/provider/download_manager_provider.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/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';
|
import 'package:spotube/provider/sleep_timer_provider.dart';
|
||||||
|
|
||||||
class PlayerActions extends HookConsumerWidget {
|
class PlayerActions extends HookConsumerWidget {
|
||||||
@ -49,17 +50,17 @@ class PlayerActions extends HookConsumerWidget {
|
|||||||
downloader,
|
downloader,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
final localTracks = [] /* ref.watch(localTracksProvider).value */;
|
final localTracks = ref.watch(localTracksProvider).value;
|
||||||
final auth = ref.watch(authenticationProvider);
|
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
final sleepTimer = ref.watch(sleepTimerProvider);
|
final sleepTimer = ref.watch(sleepTimerProvider);
|
||||||
final sleepTimerNotifier = ref.watch(sleepTimerProvider.notifier);
|
final sleepTimerNotifier = ref.watch(sleepTimerProvider.notifier);
|
||||||
|
|
||||||
final isDownloaded = useMemoized(() {
|
final isDownloaded = useMemoized(() {
|
||||||
return localTracks.any(
|
return localTracks?.values.expand((e) => e).any(
|
||||||
(element) =>
|
(element) =>
|
||||||
element.name == playlist.activeTrack?.name &&
|
element.name == playlist.activeTrack?.name &&
|
||||||
element.album?.name == playlist.activeTrack?.album.name &&
|
element.album.name == playlist.activeTrack?.album.name &&
|
||||||
element.artists?.asString() ==
|
element.artists.asString() ==
|
||||||
playlist.activeTrack?.artists.asString(),
|
playlist.activeTrack?.artists.asString(),
|
||||||
) ==
|
) ==
|
||||||
true;
|
true;
|
||||||
@ -175,7 +176,7 @@ class PlayerActions extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
if (playlist.activeTrack != null &&
|
if (playlist.activeTrack != null &&
|
||||||
!isLocalTrack &&
|
!isLocalTrack &&
|
||||||
auth.asData?.value != null)
|
authenticated.asData?.value == true)
|
||||||
TrackHeartButton(track: playlist.activeTrack!),
|
TrackHeartButton(track: playlist.activeTrack!),
|
||||||
AdaptivePopSheetList<Duration>(
|
AdaptivePopSheetList<Duration>(
|
||||||
tooltip: context.l10n.sleep_timer,
|
tooltip: context.l10n.sleep_timer,
|
||||||
|
@ -10,8 +10,8 @@ import 'package:spotube/extensions/constrains.dart';
|
|||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.dart';
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
import 'package:spotube/modules/connect/connect_device.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/download_manager_provider.dart';
|
||||||
|
import 'package:spotube/provider/metadata_plugin/auth.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/user.dart';
|
import 'package:spotube/provider/metadata_plugin/user.dart';
|
||||||
|
|
||||||
class SidebarFooter extends HookConsumerWidget implements NavigationBarItem {
|
class SidebarFooter extends HookConsumerWidget implements NavigationBarItem {
|
||||||
@ -33,7 +33,7 @@ class SidebarFooter extends HookConsumerWidget implements NavigationBarItem {
|
|||||||
placeholder: ImagePlaceholder.artist,
|
placeholder: ImagePlaceholder.artist,
|
||||||
);
|
);
|
||||||
|
|
||||||
final auth = ref.watch(authenticationProvider);
|
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
|
|
||||||
if (mediaQuery.mdAndDown) {
|
if (mediaQuery.mdAndDown) {
|
||||||
return Column(
|
return Column(
|
||||||
@ -91,7 +91,7 @@ class SidebarFooter extends HookConsumerWidget implements NavigationBarItem {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
if (auth.asData?.value != null && data == null)
|
if (authenticated.asData?.value == true && data == null)
|
||||||
const CircularProgressIndicator()
|
const CircularProgressIndicator()
|
||||||
else if (data != null)
|
else if (data != null)
|
||||||
Flexible(
|
Flexible(
|
||||||
|
@ -47,7 +47,7 @@ class AlbumPage extends HookConsumerWidget {
|
|||||||
title: album.name,
|
title: album.name,
|
||||||
description:
|
description:
|
||||||
"${context.l10n.released} • ${album.releaseDate} • ${album.artists.first.name}",
|
"${context.l10n.released} • ${album.releaseDate} • ${album.artists.first.name}",
|
||||||
tracks: [],
|
tracks: tracks.asData?.value.items ?? [],
|
||||||
pagination: PaginationProps(
|
pagination: PaginationProps(
|
||||||
hasNextPage: tracks.asData?.value.hasMore ?? false,
|
hasNextPage: tracks.asData?.value.hasMore ?? false,
|
||||||
isLoading: tracks.isLoading || tracks.isLoadingNextPage,
|
isLoading: tracks.isLoading || tracks.isLoadingNextPage,
|
||||||
|
@ -10,9 +10,9 @@ import 'package:spotube/extensions/constrains.dart';
|
|||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/models/database/database.dart';
|
import 'package:spotube/models/database/database.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.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/blacklist_provider.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/artist/artist.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/provider/metadata_plugin/library/artists.dart';
|
||||||
import 'package:spotube/utils/primitive_utils.dart';
|
import 'package:spotube/utils/primitive_utils.dart';
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ class ArtistPageHeader extends HookConsumerWidget {
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final ThemeData(:typography) = theme;
|
final ThemeData(:typography) = theme;
|
||||||
|
|
||||||
final auth = ref.watch(authenticationProvider);
|
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
||||||
ref.watch(blacklistProvider);
|
ref.watch(blacklistProvider);
|
||||||
final blacklistNotifier = ref.watch(blacklistProvider.notifier);
|
final blacklistNotifier = ref.watch(blacklistProvider.notifier);
|
||||||
final isBlackListed = blacklistNotifier.containsArtist(artist.id);
|
final isBlackListed = blacklistNotifier.containsArtist(artist.id);
|
||||||
@ -41,7 +41,7 @@ class ArtistPageHeader extends HookConsumerWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if (auth.asData?.value != null)
|
if (authenticated.asData?.value == true)
|
||||||
Consumer(
|
Consumer(
|
||||||
builder: (context, ref, _) {
|
builder: (context, ref, _) {
|
||||||
final isFollowingQuery = ref.watch(
|
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/collections/spotube_icons.dart';
|
||||||
import 'package:spotube/modules/getting_started/blur_card.dart';
|
import 'package:spotube/modules/getting_started/blur_card.dart';
|
||||||
import 'package:spotube/extensions/context.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:spotube/services/kv_store/kv_store.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
@ -15,8 +14,6 @@ class GettingStartedScreenSupportSection extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final onLogin = useLoginCallback(ref);
|
|
||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@ -117,31 +114,6 @@ class GettingStartedScreenSupportSection extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
child: Text(context.l10n.browse_anonymously),
|
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/inter_scrollbar/inter_scrollbar.dart';
|
||||||
import 'package:spotube/components/fallbacks/anonymous_fallback.dart';
|
import 'package:spotube/components/fallbacks/anonymous_fallback.dart';
|
||||||
import 'package:spotube/extensions/context.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/auth.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/library/albums.dart';
|
import 'package:spotube/provider/metadata_plugin/library/albums.dart';
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
@ -40,7 +40,7 @@ class UserPlaylistsPage extends HookConsumerWidget {
|
|||||||
() => me.asData?.value == null
|
() => me.asData?.value == null
|
||||||
? null
|
? null
|
||||||
: SpotubeSimplePlaylistObject(
|
: SpotubeSimplePlaylistObject(
|
||||||
id: "liked-tracks",
|
id: "user-liked-tracks",
|
||||||
name: context.l10n.liked_tracks,
|
name: context.l10n.liked_tracks,
|
||||||
description: context.l10n.liked_tracks_description,
|
description: context.l10n.liked_tracks_description,
|
||||||
externalUri: "",
|
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/albums.dart';
|
||||||
import 'package:spotube/pages/search/sections/artists.dart';
|
import 'package:spotube/pages/search/sections/artists.dart';
|
||||||
import 'package:spotube/pages/search/sections/playlists.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/auth.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
import 'package:spotube/provider/metadata_plugin/search/all.dart';
|
||||||
import 'package:spotube/services/kv_store/kv_store.dart';
|
import 'package:spotube/services/kv_store/kv_store.dart';
|
||||||
@ -227,7 +228,7 @@ class SearchPage extends HookConsumerWidget {
|
|||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// SearchTracksSection(),
|
SearchTracksSection(),
|
||||||
SearchPlaylistsSection(),
|
SearchPlaylistsSection(),
|
||||||
Gap(20),
|
Gap(20),
|
||||||
SearchArtistsSection(),
|
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:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:spotube/models/metadata/metadata.dart';
|
import 'package:spotube/models/metadata/metadata.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/metadata_plugin_provider.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/common.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/utils/paginated.dart';
|
import 'package:spotube/provider/metadata_plugin/utils/paginated.dart';
|
||||||
|
|
||||||
@ -11,17 +10,7 @@ class MetadataPluginSavedTracksNotifier
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
fetch(offset, limit) async {
|
fetch(offset, limit) async {
|
||||||
final user = await ref.read(metadataPluginUserProvider.future);
|
final tracks = await (await metadataPlugin).user.savedTracks(
|
||||||
|
|
||||||
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,
|
|
||||||
offset: offset,
|
offset: offset,
|
||||||
limit: limit,
|
limit: limit,
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user