Compare commits
1 Commits
87178c6cd2
...
03dfad2969
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03dfad2969 |
|
Before Width: | Height: | Size: 3.6 KiB |
@ -39,11 +39,6 @@ class InstallDependenciesCommand extends Command {
|
|||||||
|
|
||||||
switch (argResults!.option("platform")) {
|
switch (argResults!.option("platform")) {
|
||||||
case "windows":
|
case "windows":
|
||||||
await shell.run(
|
|
||||||
"""
|
|
||||||
choco install innosetup -y
|
|
||||||
""",
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "linux":
|
case "linux":
|
||||||
await shell.run(
|
await shell.run(
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
// dart format width=80
|
|
||||||
|
|
||||||
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
/// *****************************************************
|
/// *****************************************************
|
||||||
/// FlutterGen
|
/// FlutterGen
|
||||||
@ -7,7 +5,7 @@
|
|||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: deprecated_member_use,directives_ordering,implicit_dynamic_list_literal,unnecessary_import
|
// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use
|
||||||
|
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
@ -69,10 +67,6 @@ class $AssetsImagesGen {
|
|||||||
class $AssetsImagesLogosGen {
|
class $AssetsImagesLogosGen {
|
||||||
const $AssetsImagesLogosGen();
|
const $AssetsImagesLogosGen();
|
||||||
|
|
||||||
/// File path: assets/images/logos/dab-music.png
|
|
||||||
AssetGenImage get dabMusic =>
|
|
||||||
const AssetGenImage('assets/images/logos/dab-music.png');
|
|
||||||
|
|
||||||
/// File path: assets/images/logos/invidious.jpg
|
/// File path: assets/images/logos/invidious.jpg
|
||||||
AssetGenImage get invidious =>
|
AssetGenImage get invidious =>
|
||||||
const AssetGenImage('assets/images/logos/invidious.jpg');
|
const AssetGenImage('assets/images/logos/invidious.jpg');
|
||||||
@ -86,12 +80,11 @@ class $AssetsImagesLogosGen {
|
|||||||
const AssetGenImage('assets/images/logos/songlink-transparent.png');
|
const AssetGenImage('assets/images/logos/songlink-transparent.png');
|
||||||
|
|
||||||
/// List of all assets
|
/// List of all assets
|
||||||
List<AssetGenImage> get values =>
|
List<AssetGenImage> get values => [invidious, jiosaavn, songlinkTransparent];
|
||||||
[dabMusic, invidious, jiosaavn, songlinkTransparent];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Assets {
|
class Assets {
|
||||||
const Assets._();
|
Assets._();
|
||||||
|
|
||||||
static const String license = 'LICENSE';
|
static const String license = 'LICENSE';
|
||||||
static const $AssetsBrandingGen branding = $AssetsBrandingGen();
|
static const $AssetsBrandingGen branding = $AssetsBrandingGen();
|
||||||
@ -106,14 +99,12 @@ class AssetGenImage {
|
|||||||
this._assetName, {
|
this._assetName, {
|
||||||
this.size,
|
this.size,
|
||||||
this.flavors = const {},
|
this.flavors = const {},
|
||||||
this.animation,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final String _assetName;
|
final String _assetName;
|
||||||
|
|
||||||
final Size? size;
|
final Size? size;
|
||||||
final Set<String> flavors;
|
final Set<String> flavors;
|
||||||
final AssetGenImageAnimation? animation;
|
|
||||||
|
|
||||||
Image image({
|
Image image({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -136,7 +127,7 @@ class AssetGenImage {
|
|||||||
bool gaplessPlayback = true,
|
bool gaplessPlayback = true,
|
||||||
bool isAntiAlias = false,
|
bool isAntiAlias = false,
|
||||||
String? package,
|
String? package,
|
||||||
FilterQuality filterQuality = FilterQuality.medium,
|
FilterQuality filterQuality = FilterQuality.low,
|
||||||
int? cacheWidth,
|
int? cacheWidth,
|
||||||
int? cacheHeight,
|
int? cacheHeight,
|
||||||
}) {
|
}) {
|
||||||
@ -183,15 +174,3 @@ class AssetGenImage {
|
|||||||
|
|
||||||
String get keyName => _assetName;
|
String get keyName => _assetName;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetGenImageAnimation {
|
|
||||||
const AssetGenImageAnimation({
|
|
||||||
required this.isAnimation,
|
|
||||||
required this.duration,
|
|
||||||
required this.frames,
|
|
||||||
});
|
|
||||||
|
|
||||||
final bool isAnimation;
|
|
||||||
final Duration duration;
|
|
||||||
final int frames;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// dart format width=80
|
|
||||||
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
/// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
/// *****************************************************
|
/// *****************************************************
|
||||||
/// FlutterGen
|
/// FlutterGen
|
||||||
@ -6,7 +5,7 @@
|
|||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: deprecated_member_use,directives_ordering,implicit_dynamic_list_literal,unnecessary_import
|
// ignore_for_file: directives_ordering,unnecessary_import,implicit_dynamic_list_literal,deprecated_member_use
|
||||||
|
|
||||||
class FontFamily {
|
class FontFamily {
|
||||||
FontFamily._();
|
FontFamily._();
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
// dart format width=80
|
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
@ -60,7 +59,10 @@ import 'package:spotube/pages/track/track.dart' as _i35;
|
|||||||
/// [_i1.AboutSpotubePage]
|
/// [_i1.AboutSpotubePage]
|
||||||
class AboutSpotubeRoute extends _i41.PageRouteInfo<void> {
|
class AboutSpotubeRoute extends _i41.PageRouteInfo<void> {
|
||||||
const AboutSpotubeRoute({List<_i41.PageRouteInfo>? children})
|
const AboutSpotubeRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(AboutSpotubeRoute.name, initialChildren: children);
|
: super(
|
||||||
|
AboutSpotubeRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'AboutSpotubeRoute';
|
static const String name = 'AboutSpotubeRoute';
|
||||||
|
|
||||||
@ -81,11 +83,15 @@ class AlbumRoute extends _i41.PageRouteInfo<AlbumRouteArgs> {
|
|||||||
required _i43.SpotubeSimpleAlbumObject album,
|
required _i43.SpotubeSimpleAlbumObject album,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
AlbumRoute.name,
|
AlbumRoute.name,
|
||||||
args: AlbumRouteArgs(key: key, id: id, album: album),
|
args: AlbumRouteArgs(
|
||||||
rawPathParams: {'id': id},
|
key: key,
|
||||||
initialChildren: children,
|
id: id,
|
||||||
);
|
album: album,
|
||||||
|
),
|
||||||
|
rawPathParams: {'id': id},
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'AlbumRoute';
|
static const String name = 'AlbumRoute';
|
||||||
|
|
||||||
@ -93,13 +99,21 @@ class AlbumRoute extends _i41.PageRouteInfo<AlbumRouteArgs> {
|
|||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<AlbumRouteArgs>();
|
final args = data.argsAs<AlbumRouteArgs>();
|
||||||
return _i2.AlbumPage(key: args.key, id: args.id, album: args.album);
|
return _i2.AlbumPage(
|
||||||
|
key: args.key,
|
||||||
|
id: args.id,
|
||||||
|
album: args.album,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class AlbumRouteArgs {
|
class AlbumRouteArgs {
|
||||||
const AlbumRouteArgs({this.key, required this.id, required this.album});
|
const AlbumRouteArgs({
|
||||||
|
this.key,
|
||||||
|
required this.id,
|
||||||
|
required this.album,
|
||||||
|
});
|
||||||
|
|
||||||
final _i42.Key? key;
|
final _i42.Key? key;
|
||||||
|
|
||||||
@ -121,11 +135,14 @@ class ArtistRoute extends _i41.PageRouteInfo<ArtistRouteArgs> {
|
|||||||
_i42.Key? key,
|
_i42.Key? key,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
ArtistRoute.name,
|
ArtistRoute.name,
|
||||||
args: ArtistRouteArgs(artistId: artistId, key: key),
|
args: ArtistRouteArgs(
|
||||||
rawPathParams: {'id': artistId},
|
artistId: artistId,
|
||||||
initialChildren: children,
|
key: key,
|
||||||
);
|
),
|
||||||
|
rawPathParams: {'id': artistId},
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'ArtistRoute';
|
static const String name = 'ArtistRoute';
|
||||||
|
|
||||||
@ -134,15 +151,20 @@ class ArtistRoute extends _i41.PageRouteInfo<ArtistRouteArgs> {
|
|||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<ArtistRouteArgs>(
|
final args = data.argsAs<ArtistRouteArgs>(
|
||||||
orElse: () => ArtistRouteArgs(artistId: pathParams.getString('id')),
|
orElse: () => ArtistRouteArgs(artistId: pathParams.getString('id')));
|
||||||
|
return _i3.ArtistPage(
|
||||||
|
args.artistId,
|
||||||
|
key: args.key,
|
||||||
);
|
);
|
||||||
return _i3.ArtistPage(args.artistId, key: args.key);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArtistRouteArgs {
|
class ArtistRouteArgs {
|
||||||
const ArtistRouteArgs({required this.artistId, this.key});
|
const ArtistRouteArgs({
|
||||||
|
required this.artistId,
|
||||||
|
this.key,
|
||||||
|
});
|
||||||
|
|
||||||
final String artistId;
|
final String artistId;
|
||||||
|
|
||||||
@ -158,7 +180,10 @@ class ArtistRouteArgs {
|
|||||||
/// [_i4.BlackListPage]
|
/// [_i4.BlackListPage]
|
||||||
class BlackListRoute extends _i41.PageRouteInfo<void> {
|
class BlackListRoute extends _i41.PageRouteInfo<void> {
|
||||||
const BlackListRoute({List<_i41.PageRouteInfo>? children})
|
const BlackListRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(BlackListRoute.name, initialChildren: children);
|
: super(
|
||||||
|
BlackListRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'BlackListRoute';
|
static const String name = 'BlackListRoute';
|
||||||
|
|
||||||
@ -174,7 +199,10 @@ class BlackListRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i5.ConnectControlPage]
|
/// [_i5.ConnectControlPage]
|
||||||
class ConnectControlRoute extends _i41.PageRouteInfo<void> {
|
class ConnectControlRoute extends _i41.PageRouteInfo<void> {
|
||||||
const ConnectControlRoute({List<_i41.PageRouteInfo>? children})
|
const ConnectControlRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(ConnectControlRoute.name, initialChildren: children);
|
: super(
|
||||||
|
ConnectControlRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'ConnectControlRoute';
|
static const String name = 'ConnectControlRoute';
|
||||||
|
|
||||||
@ -190,7 +218,10 @@ class ConnectControlRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i6.ConnectPage]
|
/// [_i6.ConnectPage]
|
||||||
class ConnectRoute extends _i41.PageRouteInfo<void> {
|
class ConnectRoute extends _i41.PageRouteInfo<void> {
|
||||||
const ConnectRoute({List<_i41.PageRouteInfo>? children})
|
const ConnectRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(ConnectRoute.name, initialChildren: children);
|
: super(
|
||||||
|
ConnectRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'ConnectRoute';
|
static const String name = 'ConnectRoute';
|
||||||
|
|
||||||
@ -206,7 +237,10 @@ class ConnectRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i7.GettingStartedPage]
|
/// [_i7.GettingStartedPage]
|
||||||
class GettingStartedRoute extends _i41.PageRouteInfo<void> {
|
class GettingStartedRoute extends _i41.PageRouteInfo<void> {
|
||||||
const GettingStartedRoute({List<_i41.PageRouteInfo>? children})
|
const GettingStartedRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(GettingStartedRoute.name, initialChildren: children);
|
: super(
|
||||||
|
GettingStartedRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'GettingStartedRoute';
|
static const String name = 'GettingStartedRoute';
|
||||||
|
|
||||||
@ -228,15 +262,15 @@ class HomeBrowseSectionItemsRoute
|
|||||||
required _i43.SpotubeBrowseSectionObject<Object> section,
|
required _i43.SpotubeBrowseSectionObject<Object> section,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
HomeBrowseSectionItemsRoute.name,
|
HomeBrowseSectionItemsRoute.name,
|
||||||
args: HomeBrowseSectionItemsRouteArgs(
|
args: HomeBrowseSectionItemsRouteArgs(
|
||||||
key: key,
|
key: key,
|
||||||
sectionId: sectionId,
|
sectionId: sectionId,
|
||||||
section: section,
|
section: section,
|
||||||
),
|
),
|
||||||
rawPathParams: {'sectionId': sectionId},
|
rawPathParams: {'sectionId': sectionId},
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
);
|
);
|
||||||
|
|
||||||
static const String name = 'HomeBrowseSectionItemsRoute';
|
static const String name = 'HomeBrowseSectionItemsRoute';
|
||||||
|
|
||||||
@ -276,7 +310,10 @@ class HomeBrowseSectionItemsRouteArgs {
|
|||||||
/// [_i9.HomePage]
|
/// [_i9.HomePage]
|
||||||
class HomeRoute extends _i41.PageRouteInfo<void> {
|
class HomeRoute extends _i41.PageRouteInfo<void> {
|
||||||
const HomeRoute({List<_i41.PageRouteInfo>? children})
|
const HomeRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(HomeRoute.name, initialChildren: children);
|
: super(
|
||||||
|
HomeRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'HomeRoute';
|
static const String name = 'HomeRoute';
|
||||||
|
|
||||||
@ -292,7 +329,10 @@ class HomeRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i10.LastFMLoginPage]
|
/// [_i10.LastFMLoginPage]
|
||||||
class LastFMLoginRoute extends _i41.PageRouteInfo<void> {
|
class LastFMLoginRoute extends _i41.PageRouteInfo<void> {
|
||||||
const LastFMLoginRoute({List<_i41.PageRouteInfo>? children})
|
const LastFMLoginRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(LastFMLoginRoute.name, initialChildren: children);
|
: super(
|
||||||
|
LastFMLoginRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'LastFMLoginRoute';
|
static const String name = 'LastFMLoginRoute';
|
||||||
|
|
||||||
@ -308,7 +348,10 @@ class LastFMLoginRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i11.LibraryPage]
|
/// [_i11.LibraryPage]
|
||||||
class LibraryRoute extends _i41.PageRouteInfo<void> {
|
class LibraryRoute extends _i41.PageRouteInfo<void> {
|
||||||
const LibraryRoute({List<_i41.PageRouteInfo>? children})
|
const LibraryRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(LibraryRoute.name, initialChildren: children);
|
: super(
|
||||||
|
LibraryRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'LibraryRoute';
|
static const String name = 'LibraryRoute';
|
||||||
|
|
||||||
@ -328,10 +371,13 @@ class LikedPlaylistRoute extends _i41.PageRouteInfo<LikedPlaylistRouteArgs> {
|
|||||||
required _i43.SpotubeSimplePlaylistObject playlist,
|
required _i43.SpotubeSimplePlaylistObject playlist,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
LikedPlaylistRoute.name,
|
LikedPlaylistRoute.name,
|
||||||
args: LikedPlaylistRouteArgs(key: key, playlist: playlist),
|
args: LikedPlaylistRouteArgs(
|
||||||
initialChildren: children,
|
key: key,
|
||||||
);
|
playlist: playlist,
|
||||||
|
),
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'LikedPlaylistRoute';
|
static const String name = 'LikedPlaylistRoute';
|
||||||
|
|
||||||
@ -339,13 +385,19 @@ class LikedPlaylistRoute extends _i41.PageRouteInfo<LikedPlaylistRouteArgs> {
|
|||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<LikedPlaylistRouteArgs>();
|
final args = data.argsAs<LikedPlaylistRouteArgs>();
|
||||||
return _i12.LikedPlaylistPage(key: args.key, playlist: args.playlist);
|
return _i12.LikedPlaylistPage(
|
||||||
|
key: args.key,
|
||||||
|
playlist: args.playlist,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LikedPlaylistRouteArgs {
|
class LikedPlaylistRouteArgs {
|
||||||
const LikedPlaylistRouteArgs({this.key, required this.playlist});
|
const LikedPlaylistRouteArgs({
|
||||||
|
this.key,
|
||||||
|
required this.playlist,
|
||||||
|
});
|
||||||
|
|
||||||
final _i42.Key? key;
|
final _i42.Key? key;
|
||||||
|
|
||||||
@ -367,15 +419,15 @@ class LocalLibraryRoute extends _i41.PageRouteInfo<LocalLibraryRouteArgs> {
|
|||||||
bool isCache = false,
|
bool isCache = false,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
LocalLibraryRoute.name,
|
LocalLibraryRoute.name,
|
||||||
args: LocalLibraryRouteArgs(
|
args: LocalLibraryRouteArgs(
|
||||||
location: location,
|
location: location,
|
||||||
key: key,
|
key: key,
|
||||||
isDownloads: isDownloads,
|
isDownloads: isDownloads,
|
||||||
isCache: isCache,
|
isCache: isCache,
|
||||||
),
|
),
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
);
|
);
|
||||||
|
|
||||||
static const String name = 'LocalLibraryRoute';
|
static const String name = 'LocalLibraryRoute';
|
||||||
|
|
||||||
@ -419,7 +471,10 @@ class LocalLibraryRouteArgs {
|
|||||||
/// [_i14.LogsPage]
|
/// [_i14.LogsPage]
|
||||||
class LogsRoute extends _i41.PageRouteInfo<void> {
|
class LogsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const LogsRoute({List<_i41.PageRouteInfo>? children})
|
const LogsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(LogsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
LogsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'LogsRoute';
|
static const String name = 'LogsRoute';
|
||||||
|
|
||||||
@ -435,7 +490,10 @@ class LogsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i15.LyricsPage]
|
/// [_i15.LyricsPage]
|
||||||
class LyricsRoute extends _i41.PageRouteInfo<void> {
|
class LyricsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const LyricsRoute({List<_i41.PageRouteInfo>? children})
|
const LyricsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(LyricsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
LyricsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'LyricsRoute';
|
static const String name = 'LyricsRoute';
|
||||||
|
|
||||||
@ -455,10 +513,13 @@ class MiniLyricsRoute extends _i41.PageRouteInfo<MiniLyricsRouteArgs> {
|
|||||||
required _i44.Size prevSize,
|
required _i44.Size prevSize,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
MiniLyricsRoute.name,
|
MiniLyricsRoute.name,
|
||||||
args: MiniLyricsRouteArgs(key: key, prevSize: prevSize),
|
args: MiniLyricsRouteArgs(
|
||||||
initialChildren: children,
|
key: key,
|
||||||
);
|
prevSize: prevSize,
|
||||||
|
),
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'MiniLyricsRoute';
|
static const String name = 'MiniLyricsRoute';
|
||||||
|
|
||||||
@ -466,13 +527,19 @@ class MiniLyricsRoute extends _i41.PageRouteInfo<MiniLyricsRouteArgs> {
|
|||||||
name,
|
name,
|
||||||
builder: (data) {
|
builder: (data) {
|
||||||
final args = data.argsAs<MiniLyricsRouteArgs>();
|
final args = data.argsAs<MiniLyricsRouteArgs>();
|
||||||
return _i16.MiniLyricsPage(key: args.key, prevSize: args.prevSize);
|
return _i16.MiniLyricsPage(
|
||||||
|
key: args.key,
|
||||||
|
prevSize: args.prevSize,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MiniLyricsRouteArgs {
|
class MiniLyricsRouteArgs {
|
||||||
const MiniLyricsRouteArgs({this.key, required this.prevSize});
|
const MiniLyricsRouteArgs({
|
||||||
|
this.key,
|
||||||
|
required this.prevSize,
|
||||||
|
});
|
||||||
|
|
||||||
final _i44.Key? key;
|
final _i44.Key? key;
|
||||||
|
|
||||||
@ -488,7 +555,10 @@ class MiniLyricsRouteArgs {
|
|||||||
/// [_i17.PlayerLyricsPage]
|
/// [_i17.PlayerLyricsPage]
|
||||||
class PlayerLyricsRoute extends _i41.PageRouteInfo<void> {
|
class PlayerLyricsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const PlayerLyricsRoute({List<_i41.PageRouteInfo>? children})
|
const PlayerLyricsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(PlayerLyricsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
PlayerLyricsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'PlayerLyricsRoute';
|
static const String name = 'PlayerLyricsRoute';
|
||||||
|
|
||||||
@ -504,7 +574,10 @@ class PlayerLyricsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i18.PlayerQueuePage]
|
/// [_i18.PlayerQueuePage]
|
||||||
class PlayerQueueRoute extends _i41.PageRouteInfo<void> {
|
class PlayerQueueRoute extends _i41.PageRouteInfo<void> {
|
||||||
const PlayerQueueRoute({List<_i41.PageRouteInfo>? children})
|
const PlayerQueueRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(PlayerQueueRoute.name, initialChildren: children);
|
: super(
|
||||||
|
PlayerQueueRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'PlayerQueueRoute';
|
static const String name = 'PlayerQueueRoute';
|
||||||
|
|
||||||
@ -520,7 +593,10 @@ class PlayerQueueRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i19.PlayerTrackSourcesPage]
|
/// [_i19.PlayerTrackSourcesPage]
|
||||||
class PlayerTrackSourcesRoute extends _i41.PageRouteInfo<void> {
|
class PlayerTrackSourcesRoute extends _i41.PageRouteInfo<void> {
|
||||||
const PlayerTrackSourcesRoute({List<_i41.PageRouteInfo>? children})
|
const PlayerTrackSourcesRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(PlayerTrackSourcesRoute.name, initialChildren: children);
|
: super(
|
||||||
|
PlayerTrackSourcesRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'PlayerTrackSourcesRoute';
|
static const String name = 'PlayerTrackSourcesRoute';
|
||||||
|
|
||||||
@ -541,11 +617,15 @@ class PlaylistRoute extends _i41.PageRouteInfo<PlaylistRouteArgs> {
|
|||||||
required _i43.SpotubeSimplePlaylistObject playlist,
|
required _i43.SpotubeSimplePlaylistObject playlist,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
PlaylistRoute.name,
|
PlaylistRoute.name,
|
||||||
args: PlaylistRouteArgs(key: key, id: id, playlist: playlist),
|
args: PlaylistRouteArgs(
|
||||||
rawPathParams: {'id': id},
|
key: key,
|
||||||
initialChildren: children,
|
id: id,
|
||||||
);
|
playlist: playlist,
|
||||||
|
),
|
||||||
|
rawPathParams: {'id': id},
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'PlaylistRoute';
|
static const String name = 'PlaylistRoute';
|
||||||
|
|
||||||
@ -563,7 +643,11 @@ class PlaylistRoute extends _i41.PageRouteInfo<PlaylistRouteArgs> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class PlaylistRouteArgs {
|
class PlaylistRouteArgs {
|
||||||
const PlaylistRouteArgs({this.key, required this.id, required this.playlist});
|
const PlaylistRouteArgs({
|
||||||
|
this.key,
|
||||||
|
required this.id,
|
||||||
|
required this.playlist,
|
||||||
|
});
|
||||||
|
|
||||||
final _i42.Key? key;
|
final _i42.Key? key;
|
||||||
|
|
||||||
@ -581,7 +665,10 @@ class PlaylistRouteArgs {
|
|||||||
/// [_i21.ProfilePage]
|
/// [_i21.ProfilePage]
|
||||||
class ProfileRoute extends _i41.PageRouteInfo<void> {
|
class ProfileRoute extends _i41.PageRouteInfo<void> {
|
||||||
const ProfileRoute({List<_i41.PageRouteInfo>? children})
|
const ProfileRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(ProfileRoute.name, initialChildren: children);
|
: super(
|
||||||
|
ProfileRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'ProfileRoute';
|
static const String name = 'ProfileRoute';
|
||||||
|
|
||||||
@ -597,7 +684,10 @@ class ProfileRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i22.RootAppPage]
|
/// [_i22.RootAppPage]
|
||||||
class RootAppRoute extends _i41.PageRouteInfo<void> {
|
class RootAppRoute extends _i41.PageRouteInfo<void> {
|
||||||
const RootAppRoute({List<_i41.PageRouteInfo>? children})
|
const RootAppRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(RootAppRoute.name, initialChildren: children);
|
: super(
|
||||||
|
RootAppRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'RootAppRoute';
|
static const String name = 'RootAppRoute';
|
||||||
|
|
||||||
@ -613,7 +703,10 @@ class RootAppRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i23.SearchPage]
|
/// [_i23.SearchPage]
|
||||||
class SearchRoute extends _i41.PageRouteInfo<void> {
|
class SearchRoute extends _i41.PageRouteInfo<void> {
|
||||||
const SearchRoute({List<_i41.PageRouteInfo>? children})
|
const SearchRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(SearchRoute.name, initialChildren: children);
|
: super(
|
||||||
|
SearchRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'SearchRoute';
|
static const String name = 'SearchRoute';
|
||||||
|
|
||||||
@ -635,14 +728,14 @@ class SettingsMetadataProviderFormRoute
|
|||||||
required List<_i43.MetadataFormFieldObject> fields,
|
required List<_i43.MetadataFormFieldObject> fields,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
SettingsMetadataProviderFormRoute.name,
|
SettingsMetadataProviderFormRoute.name,
|
||||||
args: SettingsMetadataProviderFormRouteArgs(
|
args: SettingsMetadataProviderFormRouteArgs(
|
||||||
key: key,
|
key: key,
|
||||||
title: title,
|
title: title,
|
||||||
fields: fields,
|
fields: fields,
|
||||||
),
|
),
|
||||||
initialChildren: children,
|
initialChildren: children,
|
||||||
);
|
);
|
||||||
|
|
||||||
static const String name = 'SettingsMetadataProviderFormRoute';
|
static const String name = 'SettingsMetadataProviderFormRoute';
|
||||||
|
|
||||||
@ -682,7 +775,10 @@ class SettingsMetadataProviderFormRouteArgs {
|
|||||||
/// [_i25.SettingsMetadataProviderPage]
|
/// [_i25.SettingsMetadataProviderPage]
|
||||||
class SettingsMetadataProviderRoute extends _i41.PageRouteInfo<void> {
|
class SettingsMetadataProviderRoute extends _i41.PageRouteInfo<void> {
|
||||||
const SettingsMetadataProviderRoute({List<_i41.PageRouteInfo>? children})
|
const SettingsMetadataProviderRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(SettingsMetadataProviderRoute.name, initialChildren: children);
|
: super(
|
||||||
|
SettingsMetadataProviderRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'SettingsMetadataProviderRoute';
|
static const String name = 'SettingsMetadataProviderRoute';
|
||||||
|
|
||||||
@ -698,7 +794,10 @@ class SettingsMetadataProviderRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i26.SettingsPage]
|
/// [_i26.SettingsPage]
|
||||||
class SettingsRoute extends _i41.PageRouteInfo<void> {
|
class SettingsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const SettingsRoute({List<_i41.PageRouteInfo>? children})
|
const SettingsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(SettingsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
SettingsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'SettingsRoute';
|
static const String name = 'SettingsRoute';
|
||||||
|
|
||||||
@ -714,7 +813,10 @@ class SettingsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i27.SettingsScrobblingPage]
|
/// [_i27.SettingsScrobblingPage]
|
||||||
class SettingsScrobblingRoute extends _i41.PageRouteInfo<void> {
|
class SettingsScrobblingRoute extends _i41.PageRouteInfo<void> {
|
||||||
const SettingsScrobblingRoute({List<_i41.PageRouteInfo>? children})
|
const SettingsScrobblingRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(SettingsScrobblingRoute.name, initialChildren: children);
|
: super(
|
||||||
|
SettingsScrobblingRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'SettingsScrobblingRoute';
|
static const String name = 'SettingsScrobblingRoute';
|
||||||
|
|
||||||
@ -730,7 +832,10 @@ class SettingsScrobblingRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i28.StatsAlbumsPage]
|
/// [_i28.StatsAlbumsPage]
|
||||||
class StatsAlbumsRoute extends _i41.PageRouteInfo<void> {
|
class StatsAlbumsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const StatsAlbumsRoute({List<_i41.PageRouteInfo>? children})
|
const StatsAlbumsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(StatsAlbumsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
StatsAlbumsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'StatsAlbumsRoute';
|
static const String name = 'StatsAlbumsRoute';
|
||||||
|
|
||||||
@ -746,7 +851,10 @@ class StatsAlbumsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i29.StatsArtistsPage]
|
/// [_i29.StatsArtistsPage]
|
||||||
class StatsArtistsRoute extends _i41.PageRouteInfo<void> {
|
class StatsArtistsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const StatsArtistsRoute({List<_i41.PageRouteInfo>? children})
|
const StatsArtistsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(StatsArtistsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
StatsArtistsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'StatsArtistsRoute';
|
static const String name = 'StatsArtistsRoute';
|
||||||
|
|
||||||
@ -762,7 +870,10 @@ class StatsArtistsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i30.StatsMinutesPage]
|
/// [_i30.StatsMinutesPage]
|
||||||
class StatsMinutesRoute extends _i41.PageRouteInfo<void> {
|
class StatsMinutesRoute extends _i41.PageRouteInfo<void> {
|
||||||
const StatsMinutesRoute({List<_i41.PageRouteInfo>? children})
|
const StatsMinutesRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(StatsMinutesRoute.name, initialChildren: children);
|
: super(
|
||||||
|
StatsMinutesRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'StatsMinutesRoute';
|
static const String name = 'StatsMinutesRoute';
|
||||||
|
|
||||||
@ -778,7 +889,10 @@ class StatsMinutesRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i31.StatsPage]
|
/// [_i31.StatsPage]
|
||||||
class StatsRoute extends _i41.PageRouteInfo<void> {
|
class StatsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const StatsRoute({List<_i41.PageRouteInfo>? children})
|
const StatsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(StatsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
StatsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'StatsRoute';
|
static const String name = 'StatsRoute';
|
||||||
|
|
||||||
@ -794,7 +908,10 @@ class StatsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i32.StatsPlaylistsPage]
|
/// [_i32.StatsPlaylistsPage]
|
||||||
class StatsPlaylistsRoute extends _i41.PageRouteInfo<void> {
|
class StatsPlaylistsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const StatsPlaylistsRoute({List<_i41.PageRouteInfo>? children})
|
const StatsPlaylistsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(StatsPlaylistsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
StatsPlaylistsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'StatsPlaylistsRoute';
|
static const String name = 'StatsPlaylistsRoute';
|
||||||
|
|
||||||
@ -810,7 +927,10 @@ class StatsPlaylistsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i33.StatsStreamFeesPage]
|
/// [_i33.StatsStreamFeesPage]
|
||||||
class StatsStreamFeesRoute extends _i41.PageRouteInfo<void> {
|
class StatsStreamFeesRoute extends _i41.PageRouteInfo<void> {
|
||||||
const StatsStreamFeesRoute({List<_i41.PageRouteInfo>? children})
|
const StatsStreamFeesRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(StatsStreamFeesRoute.name, initialChildren: children);
|
: super(
|
||||||
|
StatsStreamFeesRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'StatsStreamFeesRoute';
|
static const String name = 'StatsStreamFeesRoute';
|
||||||
|
|
||||||
@ -826,7 +946,10 @@ class StatsStreamFeesRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i34.StatsStreamsPage]
|
/// [_i34.StatsStreamsPage]
|
||||||
class StatsStreamsRoute extends _i41.PageRouteInfo<void> {
|
class StatsStreamsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const StatsStreamsRoute({List<_i41.PageRouteInfo>? children})
|
const StatsStreamsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(StatsStreamsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
StatsStreamsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'StatsStreamsRoute';
|
static const String name = 'StatsStreamsRoute';
|
||||||
|
|
||||||
@ -846,11 +969,14 @@ class TrackRoute extends _i41.PageRouteInfo<TrackRouteArgs> {
|
|||||||
required String trackId,
|
required String trackId,
|
||||||
List<_i41.PageRouteInfo>? children,
|
List<_i41.PageRouteInfo>? children,
|
||||||
}) : super(
|
}) : super(
|
||||||
TrackRoute.name,
|
TrackRoute.name,
|
||||||
args: TrackRouteArgs(key: key, trackId: trackId),
|
args: TrackRouteArgs(
|
||||||
rawPathParams: {'id': trackId},
|
key: key,
|
||||||
initialChildren: children,
|
trackId: trackId,
|
||||||
);
|
),
|
||||||
|
rawPathParams: {'id': trackId},
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'TrackRoute';
|
static const String name = 'TrackRoute';
|
||||||
|
|
||||||
@ -859,15 +985,20 @@ class TrackRoute extends _i41.PageRouteInfo<TrackRouteArgs> {
|
|||||||
builder: (data) {
|
builder: (data) {
|
||||||
final pathParams = data.inheritedPathParams;
|
final pathParams = data.inheritedPathParams;
|
||||||
final args = data.argsAs<TrackRouteArgs>(
|
final args = data.argsAs<TrackRouteArgs>(
|
||||||
orElse: () => TrackRouteArgs(trackId: pathParams.getString('id')),
|
orElse: () => TrackRouteArgs(trackId: pathParams.getString('id')));
|
||||||
|
return _i35.TrackPage(
|
||||||
|
key: args.key,
|
||||||
|
trackId: args.trackId,
|
||||||
);
|
);
|
||||||
return _i35.TrackPage(key: args.key, trackId: args.trackId);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TrackRouteArgs {
|
class TrackRouteArgs {
|
||||||
const TrackRouteArgs({this.key, required this.trackId});
|
const TrackRouteArgs({
|
||||||
|
this.key,
|
||||||
|
required this.trackId,
|
||||||
|
});
|
||||||
|
|
||||||
final _i44.Key? key;
|
final _i44.Key? key;
|
||||||
|
|
||||||
@ -883,7 +1014,10 @@ class TrackRouteArgs {
|
|||||||
/// [_i36.UserAlbumsPage]
|
/// [_i36.UserAlbumsPage]
|
||||||
class UserAlbumsRoute extends _i41.PageRouteInfo<void> {
|
class UserAlbumsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const UserAlbumsRoute({List<_i41.PageRouteInfo>? children})
|
const UserAlbumsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(UserAlbumsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
UserAlbumsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'UserAlbumsRoute';
|
static const String name = 'UserAlbumsRoute';
|
||||||
|
|
||||||
@ -899,7 +1033,10 @@ class UserAlbumsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i37.UserArtistsPage]
|
/// [_i37.UserArtistsPage]
|
||||||
class UserArtistsRoute extends _i41.PageRouteInfo<void> {
|
class UserArtistsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const UserArtistsRoute({List<_i41.PageRouteInfo>? children})
|
const UserArtistsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(UserArtistsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
UserArtistsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'UserArtistsRoute';
|
static const String name = 'UserArtistsRoute';
|
||||||
|
|
||||||
@ -915,7 +1052,10 @@ class UserArtistsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i38.UserDownloadsPage]
|
/// [_i38.UserDownloadsPage]
|
||||||
class UserDownloadsRoute extends _i41.PageRouteInfo<void> {
|
class UserDownloadsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const UserDownloadsRoute({List<_i41.PageRouteInfo>? children})
|
const UserDownloadsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(UserDownloadsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
UserDownloadsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'UserDownloadsRoute';
|
static const String name = 'UserDownloadsRoute';
|
||||||
|
|
||||||
@ -931,7 +1071,10 @@ class UserDownloadsRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i39.UserLocalLibraryPage]
|
/// [_i39.UserLocalLibraryPage]
|
||||||
class UserLocalLibraryRoute extends _i41.PageRouteInfo<void> {
|
class UserLocalLibraryRoute extends _i41.PageRouteInfo<void> {
|
||||||
const UserLocalLibraryRoute({List<_i41.PageRouteInfo>? children})
|
const UserLocalLibraryRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(UserLocalLibraryRoute.name, initialChildren: children);
|
: super(
|
||||||
|
UserLocalLibraryRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'UserLocalLibraryRoute';
|
static const String name = 'UserLocalLibraryRoute';
|
||||||
|
|
||||||
@ -947,7 +1090,10 @@ class UserLocalLibraryRoute extends _i41.PageRouteInfo<void> {
|
|||||||
/// [_i40.UserPlaylistsPage]
|
/// [_i40.UserPlaylistsPage]
|
||||||
class UserPlaylistsRoute extends _i41.PageRouteInfo<void> {
|
class UserPlaylistsRoute extends _i41.PageRouteInfo<void> {
|
||||||
const UserPlaylistsRoute({List<_i41.PageRouteInfo>? children})
|
const UserPlaylistsRoute({List<_i41.PageRouteInfo>? children})
|
||||||
: super(UserPlaylistsRoute.name, initialChildren: children);
|
: super(
|
||||||
|
UserPlaylistsRoute.name,
|
||||||
|
initialChildren: children,
|
||||||
|
);
|
||||||
|
|
||||||
static const String name = 'UserPlaylistsRoute';
|
static const String name = 'UserPlaylistsRoute';
|
||||||
|
|
||||||
|
|||||||
@ -80,7 +80,6 @@ abstract class SpotubeIcons {
|
|||||||
static const hoverOff = Icons.back_hand_outlined;
|
static const hoverOff = Icons.back_hand_outlined;
|
||||||
static const dragHandle = Icons.drag_indicator;
|
static const dragHandle = Icons.drag_indicator;
|
||||||
static const lightning = Icons.flash_on_rounded;
|
static const lightning = Icons.flash_on_rounded;
|
||||||
static const lightningOutlined = FeatherIcons.zap;
|
|
||||||
static const colorSync = FeatherIcons.activity;
|
static const colorSync = FeatherIcons.activity;
|
||||||
static const language = FeatherIcons.globe;
|
static const language = FeatherIcons.globe;
|
||||||
static const error = FeatherIcons.alertTriangle;
|
static const error = FeatherIcons.alertTriangle;
|
||||||
|
|||||||
@ -1,69 +0,0 @@
|
|||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
|
||||||
import 'package:spotube/collections/spotube_icons.dart';
|
|
||||||
import 'package:spotube/extensions/context.dart';
|
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
|
||||||
|
|
||||||
class LinkOpenPermissionDialog extends StatelessWidget {
|
|
||||||
final String? href;
|
|
||||||
const LinkOpenPermissionDialog({super.key, this.href});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(maxWidth: 450),
|
|
||||||
child: AlertDialog(
|
|
||||||
title: Row(
|
|
||||||
spacing: 8,
|
|
||||||
children: [
|
|
||||||
const Icon(SpotubeIcons.warning),
|
|
||||||
Text(context.l10n.open_link_in_browser),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
content: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(
|
|
||||||
text:
|
|
||||||
"${context.l10n.do_you_want_to_open_the_following_link}:\n",
|
|
||||||
),
|
|
||||||
if (href != null)
|
|
||||||
TextSpan(
|
|
||||||
text: "$href\n\n",
|
|
||||||
style: const TextStyle(color: Colors.blue),
|
|
||||||
),
|
|
||||||
TextSpan(text: context.l10n.unsafe_url_warning),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
Button.ghost(
|
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
|
||||||
child: Text(context.l10n.cancel),
|
|
||||||
),
|
|
||||||
Button.ghost(
|
|
||||||
onPressed: () {
|
|
||||||
if (href != null) {
|
|
||||||
Clipboard.setData(ClipboardData(text: href!));
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop(false);
|
|
||||||
},
|
|
||||||
child: Text(context.l10n.copy_link),
|
|
||||||
),
|
|
||||||
Button.destructive(
|
|
||||||
onPressed: () {
|
|
||||||
if (href != null) {
|
|
||||||
launchUrlString(
|
|
||||||
href!,
|
|
||||||
mode: LaunchMode.externalApplication,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop(true);
|
|
||||||
},
|
|
||||||
child: Text(context.l10n.open),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +1,9 @@
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
|
import 'package:flutter_markdown_plus/flutter_markdown_plus.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
import 'package:spotube/components/dialogs/link_open_permission_dialog.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
class AppMarkdown extends StatelessWidget {
|
class AppMarkdown extends StatelessWidget {
|
||||||
@ -26,7 +28,61 @@ class AppMarkdown extends StatelessWidget {
|
|||||||
final allowOpeningLink = await showDialog<bool>(
|
final allowOpeningLink = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return LinkOpenPermissionDialog(href: href);
|
return ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 450),
|
||||||
|
child: AlertDialog(
|
||||||
|
title: Row(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
const Icon(SpotubeIcons.warning),
|
||||||
|
Text(context.l10n.open_link_in_browser),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text:
|
||||||
|
"${context.l10n.do_you_want_to_open_the_following_link}:\n",
|
||||||
|
),
|
||||||
|
if (href != null)
|
||||||
|
TextSpan(
|
||||||
|
text: "$href\n\n",
|
||||||
|
style: const TextStyle(color: Colors.blue),
|
||||||
|
),
|
||||||
|
TextSpan(text: context.l10n.unsafe_url_warning),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
Button.ghost(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
child: Text(context.l10n.cancel),
|
||||||
|
),
|
||||||
|
Button.ghost(
|
||||||
|
onPressed: () {
|
||||||
|
if (href != null) {
|
||||||
|
Clipboard.setData(ClipboardData(text: href));
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop(false);
|
||||||
|
},
|
||||||
|
child: Text(context.l10n.copy_link),
|
||||||
|
),
|
||||||
|
Button.destructive(
|
||||||
|
onPressed: () {
|
||||||
|
if (href != null) {
|
||||||
|
launchUrlString(
|
||||||
|
href,
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
child: Text(context.l10n.open),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -461,8 +461,5 @@
|
|||||||
"available_plugins": "Available plugins",
|
"available_plugins": "Available plugins",
|
||||||
"configure_your_own_metadata_plugin": "Configure your own playlist/album/artist/feed metadata provider",
|
"configure_your_own_metadata_plugin": "Configure your own playlist/album/artist/feed metadata provider",
|
||||||
"audio_scrobblers": "Audio Scrobblers",
|
"audio_scrobblers": "Audio Scrobblers",
|
||||||
"scrobbling": "Scrobbling",
|
"scrobbling": "Scrobbling"
|
||||||
"source": "Source: ",
|
|
||||||
"uncompressed": "Uncompressed",
|
|
||||||
"dab_music_source_description": "For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2930,24 +2930,6 @@ abstract class AppLocalizations {
|
|||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Scrobbling'**
|
/// **'Scrobbling'**
|
||||||
String get scrobbling;
|
String get scrobbling;
|
||||||
|
|
||||||
/// No description provided for @source.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Source: '**
|
|
||||||
String get source;
|
|
||||||
|
|
||||||
/// No description provided for @uncompressed.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Uncompressed'**
|
|
||||||
String get uncompressed;
|
|
||||||
|
|
||||||
/// No description provided for @dab_music_source_description.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.'**
|
|
||||||
String get dab_music_source_description;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate
|
class _AppLocalizationsDelegate
|
||||||
|
|||||||
@ -1537,14 +1537,4 @@ class AppLocalizationsAr extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'التتبع';
|
String get scrobbling => 'التتبع';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1538,14 +1538,4 @@ class AppLocalizationsBn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'স্ক্রোব্বলিং';
|
String get scrobbling => 'স্ক্রোব্বলিং';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1548,14 +1548,4 @@ class AppLocalizationsCa extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1538,14 +1538,4 @@ class AppLocalizationsCs extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1550,14 +1550,4 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1536,14 +1536,4 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1551,14 +1551,4 @@ class AppLocalizationsEs extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1548,14 +1548,4 @@ class AppLocalizationsEu extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1536,14 +1536,4 @@ class AppLocalizationsFa extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'اسکراببلینگ';
|
String get scrobbling => 'اسکراببلینگ';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1536,14 +1536,4 @@ class AppLocalizationsFi extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1556,14 +1556,4 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1542,14 +1542,4 @@ class AppLocalizationsHi extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'स्क्रॉबलिंग';
|
String get scrobbling => 'स्क्रॉबलिंग';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1544,14 +1544,4 @@ class AppLocalizationsId extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1543,14 +1543,4 @@ class AppLocalizationsIt extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1507,14 +1507,4 @@ class AppLocalizationsJa extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1545,14 +1545,4 @@ class AppLocalizationsKa extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'სქრობლინგი';
|
String get scrobbling => 'სქრობლინგი';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1511,14 +1511,4 @@ class AppLocalizationsKo extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => '스크로블링';
|
String get scrobbling => '스크로블링';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1548,14 +1548,4 @@ class AppLocalizationsNe extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'स्क्रब्बलिंग';
|
String get scrobbling => 'स्क्रब्बलिंग';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1542,14 +1542,4 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1544,14 +1544,4 @@ class AppLocalizationsPl extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1541,14 +1541,4 @@ class AppLocalizationsPt extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1544,14 +1544,4 @@ class AppLocalizationsRu extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Скробблинг';
|
String get scrobbling => 'Скробблинг';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1550,14 +1550,4 @@ class AppLocalizationsTa extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'ஸ்க்ரோப்ளிங்';
|
String get scrobbling => 'ஸ்க்ரோப்ளிங்';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1533,14 +1533,4 @@ class AppLocalizationsTh extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1551,14 +1551,4 @@ class AppLocalizationsTl extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1544,14 +1544,4 @@ class AppLocalizationsTr extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1540,14 +1540,4 @@ class AppLocalizationsUk extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Скроблінг';
|
String get scrobbling => 'Скроблінг';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1546,14 +1546,4 @@ class AppLocalizationsVi extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1500,16 +1500,6 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get scrobbling => 'Scrobbling';
|
String get scrobbling => 'Scrobbling';
|
||||||
|
|
||||||
@override
|
|
||||||
String get source => 'Source: ';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get uncompressed => 'Uncompressed';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get dab_music_source_description =>
|
|
||||||
'For audiophiles. Provides high-quality/lossless audio streams. Accurate ISRC based track matching.';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The translations for Chinese, as used in Taiwan (`zh_TW`).
|
/// The translations for Chinese, as used in Taiwan (`zh_TW`).
|
||||||
|
|||||||
@ -112,13 +112,8 @@ mixin _$WebSocketLoadEventData {
|
|||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) =>
|
}) =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this WebSocketLoadEventData to a JSON map.
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$WebSocketLoadEventDataCopyWith<WebSocketLoadEventData> get copyWith =>
|
$WebSocketLoadEventDataCopyWith<WebSocketLoadEventData> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -147,8 +142,6 @@ class _$WebSocketLoadEventDataCopyWithImpl<$Res,
|
|||||||
// ignore: unused_field
|
// ignore: unused_field
|
||||||
final $Res Function($Val) _then;
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -197,8 +190,6 @@ class __$$WebSocketLoadEventDataPlaylistImplCopyWithImpl<$Res>
|
|||||||
$Res Function(_$WebSocketLoadEventDataPlaylistImpl) _then)
|
$Res Function(_$WebSocketLoadEventDataPlaylistImpl) _then)
|
||||||
: super(_value, _then);
|
: super(_value, _then);
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -222,8 +213,6 @@ class __$$WebSocketLoadEventDataPlaylistImplCopyWithImpl<$Res>
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
$SpotubeSimplePlaylistObjectCopyWith<$Res>? get collection {
|
$SpotubeSimplePlaylistObjectCopyWith<$Res>? get collection {
|
||||||
@ -292,14 +281,12 @@ class _$WebSocketLoadEventDataPlaylistImpl
|
|||||||
other.initialIndex == initialIndex));
|
other.initialIndex == initialIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,
|
int get hashCode => Object.hash(runtimeType,
|
||||||
const DeepCollectionEquality().hash(_tracks), collection, initialIndex);
|
const DeepCollectionEquality().hash(_tracks), collection, initialIndex);
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
@JsonKey(ignore: true)
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$$WebSocketLoadEventDataPlaylistImplCopyWith<
|
_$$WebSocketLoadEventDataPlaylistImplCopyWith<
|
||||||
@ -433,11 +420,8 @@ abstract class WebSocketLoadEventDataPlaylist extends WebSocketLoadEventData {
|
|||||||
SpotubeSimplePlaylistObject? get collection;
|
SpotubeSimplePlaylistObject? get collection;
|
||||||
@override
|
@override
|
||||||
int? get initialIndex;
|
int? get initialIndex;
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
_$$WebSocketLoadEventDataPlaylistImplCopyWith<
|
_$$WebSocketLoadEventDataPlaylistImplCopyWith<
|
||||||
_$WebSocketLoadEventDataPlaylistImpl>
|
_$WebSocketLoadEventDataPlaylistImpl>
|
||||||
get copyWith => throw _privateConstructorUsedError;
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
@ -472,8 +456,6 @@ class __$$WebSocketLoadEventDataAlbumImplCopyWithImpl<$Res>
|
|||||||
$Res Function(_$WebSocketLoadEventDataAlbumImpl) _then)
|
$Res Function(_$WebSocketLoadEventDataAlbumImpl) _then)
|
||||||
: super(_value, _then);
|
: super(_value, _then);
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -497,8 +479,6 @@ class __$$WebSocketLoadEventDataAlbumImplCopyWithImpl<$Res>
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
$SpotubeSimpleAlbumObjectCopyWith<$Res>? get collection {
|
$SpotubeSimpleAlbumObjectCopyWith<$Res>? get collection {
|
||||||
@ -565,14 +545,12 @@ class _$WebSocketLoadEventDataAlbumImpl extends WebSocketLoadEventDataAlbum {
|
|||||||
other.initialIndex == initialIndex));
|
other.initialIndex == initialIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,
|
int get hashCode => Object.hash(runtimeType,
|
||||||
const DeepCollectionEquality().hash(_tracks), collection, initialIndex);
|
const DeepCollectionEquality().hash(_tracks), collection, initialIndex);
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
@JsonKey(ignore: true)
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$$WebSocketLoadEventDataAlbumImplCopyWith<_$WebSocketLoadEventDataAlbumImpl>
|
_$$WebSocketLoadEventDataAlbumImplCopyWith<_$WebSocketLoadEventDataAlbumImpl>
|
||||||
@ -705,11 +683,8 @@ abstract class WebSocketLoadEventDataAlbum extends WebSocketLoadEventData {
|
|||||||
SpotubeSimpleAlbumObject? get collection;
|
SpotubeSimpleAlbumObject? get collection;
|
||||||
@override
|
@override
|
||||||
int? get initialIndex;
|
int? get initialIndex;
|
||||||
|
|
||||||
/// Create a copy of WebSocketLoadEventData
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
_$$WebSocketLoadEventDataAlbumImplCopyWith<_$WebSocketLoadEventDataAlbumImpl>
|
_$$WebSocketLoadEventDataAlbumImplCopyWith<_$WebSocketLoadEventDataAlbumImpl>
|
||||||
get copyWith => throw _privateConstructorUsedError;
|
get copyWith => throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,12 +18,15 @@ class $AuthenticationTableTable extends AuthenticationTable
|
|||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultConstraints:
|
defaultConstraints:
|
||||||
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
|
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
|
||||||
|
static const VerificationMeta _cookieMeta = const VerificationMeta('cookie');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<DecryptedText, String> cookie =
|
late final GeneratedColumnWithTypeConverter<DecryptedText, String> cookie =
|
||||||
GeneratedColumn<String>('cookie', aliasedName, false,
|
GeneratedColumn<String>('cookie', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||||
.withConverter<DecryptedText>(
|
.withConverter<DecryptedText>(
|
||||||
$AuthenticationTableTable.$convertercookie);
|
$AuthenticationTableTable.$convertercookie);
|
||||||
|
static const VerificationMeta _accessTokenMeta =
|
||||||
|
const VerificationMeta('accessToken');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<DecryptedText, String>
|
late final GeneratedColumnWithTypeConverter<DecryptedText, String>
|
||||||
accessToken = GeneratedColumn<String>('access_token', aliasedName, false,
|
accessToken = GeneratedColumn<String>('access_token', aliasedName, false,
|
||||||
@ -52,6 +55,8 @@ class $AuthenticationTableTable extends AuthenticationTable
|
|||||||
if (data.containsKey('id')) {
|
if (data.containsKey('id')) {
|
||||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||||
}
|
}
|
||||||
|
context.handle(_cookieMeta, const VerificationResult.success());
|
||||||
|
context.handle(_accessTokenMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('expiration')) {
|
if (data.containsKey('expiration')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_expirationMeta,
|
_expirationMeta,
|
||||||
@ -296,6 +301,8 @@ class $BlacklistTableTable extends BlacklistTable
|
|||||||
late final GeneratedColumn<String> name = GeneratedColumn<String>(
|
late final GeneratedColumn<String> name = GeneratedColumn<String>(
|
||||||
'name', aliasedName, false,
|
'name', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
|
static const VerificationMeta _elementTypeMeta =
|
||||||
|
const VerificationMeta('elementType');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<BlacklistedType, String>
|
late final GeneratedColumnWithTypeConverter<BlacklistedType, String>
|
||||||
elementType = GeneratedColumn<String>('element_type', aliasedName, false,
|
elementType = GeneratedColumn<String>('element_type', aliasedName, false,
|
||||||
@ -329,6 +336,7 @@ class $BlacklistTableTable extends BlacklistTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_nameMeta);
|
context.missing(_nameMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_elementTypeMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('element_id')) {
|
if (data.containsKey('element_id')) {
|
||||||
context.handle(_elementIdMeta,
|
context.handle(_elementIdMeta,
|
||||||
elementId.isAcceptableOrUnknown(data['element_id']!, _elementIdMeta));
|
elementId.isAcceptableOrUnknown(data['element_id']!, _elementIdMeta));
|
||||||
@ -558,6 +566,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultConstraints:
|
defaultConstraints:
|
||||||
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
|
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
|
||||||
|
static const VerificationMeta _audioQualityMeta =
|
||||||
|
const VerificationMeta('audioQuality');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SourceQualities, String>
|
late final GeneratedColumnWithTypeConverter<SourceQualities, String>
|
||||||
audioQuality = GeneratedColumn<String>(
|
audioQuality = GeneratedColumn<String>(
|
||||||
@ -637,6 +647,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
defaultConstraints: GeneratedColumn.constraintIsAlways(
|
||||||
'CHECK ("skip_non_music" IN (0, 1))'),
|
'CHECK ("skip_non_music" IN (0, 1))'),
|
||||||
defaultValue: const Constant(false));
|
defaultValue: const Constant(false));
|
||||||
|
static const VerificationMeta _closeBehaviorMeta =
|
||||||
|
const VerificationMeta('closeBehavior');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<CloseBehavior, String>
|
late final GeneratedColumnWithTypeConverter<CloseBehavior, String>
|
||||||
closeBehavior = GeneratedColumn<String>(
|
closeBehavior = GeneratedColumn<String>(
|
||||||
@ -646,6 +658,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultValue: Constant(CloseBehavior.close.name))
|
defaultValue: Constant(CloseBehavior.close.name))
|
||||||
.withConverter<CloseBehavior>(
|
.withConverter<CloseBehavior>(
|
||||||
$PreferencesTableTable.$convertercloseBehavior);
|
$PreferencesTableTable.$convertercloseBehavior);
|
||||||
|
static const VerificationMeta _accentColorSchemeMeta =
|
||||||
|
const VerificationMeta('accentColorScheme');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SpotubeColor, String>
|
late final GeneratedColumnWithTypeConverter<SpotubeColor, String>
|
||||||
accentColorScheme = GeneratedColumn<String>(
|
accentColorScheme = GeneratedColumn<String>(
|
||||||
@ -655,6 +669,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultValue: const Constant("Slate:0xff64748b"))
|
defaultValue: const Constant("Slate:0xff64748b"))
|
||||||
.withConverter<SpotubeColor>(
|
.withConverter<SpotubeColor>(
|
||||||
$PreferencesTableTable.$converteraccentColorScheme);
|
$PreferencesTableTable.$converteraccentColorScheme);
|
||||||
|
static const VerificationMeta _layoutModeMeta =
|
||||||
|
const VerificationMeta('layoutMode');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<LayoutMode, String> layoutMode =
|
late final GeneratedColumnWithTypeConverter<LayoutMode, String> layoutMode =
|
||||||
GeneratedColumn<String>('layout_mode', aliasedName, false,
|
GeneratedColumn<String>('layout_mode', aliasedName, false,
|
||||||
@ -663,6 +679,7 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultValue: Constant(LayoutMode.adaptive.name))
|
defaultValue: Constant(LayoutMode.adaptive.name))
|
||||||
.withConverter<LayoutMode>(
|
.withConverter<LayoutMode>(
|
||||||
$PreferencesTableTable.$converterlayoutMode);
|
$PreferencesTableTable.$converterlayoutMode);
|
||||||
|
static const VerificationMeta _localeMeta = const VerificationMeta('locale');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<Locale, String> locale =
|
late final GeneratedColumnWithTypeConverter<Locale, String> locale =
|
||||||
GeneratedColumn<String>('locale', aliasedName, false,
|
GeneratedColumn<String>('locale', aliasedName, false,
|
||||||
@ -671,6 +688,7 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultValue: const Constant(
|
defaultValue: const Constant(
|
||||||
'{"languageCode":"system","countryCode":"system"}'))
|
'{"languageCode":"system","countryCode":"system"}'))
|
||||||
.withConverter<Locale>($PreferencesTableTable.$converterlocale);
|
.withConverter<Locale>($PreferencesTableTable.$converterlocale);
|
||||||
|
static const VerificationMeta _marketMeta = const VerificationMeta('market');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<Market, String> market =
|
late final GeneratedColumnWithTypeConverter<Market, String> market =
|
||||||
GeneratedColumn<String>('market', aliasedName, false,
|
GeneratedColumn<String>('market', aliasedName, false,
|
||||||
@ -678,6 +696,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: Constant(Market.US.name))
|
defaultValue: Constant(Market.US.name))
|
||||||
.withConverter<Market>($PreferencesTableTable.$convertermarket);
|
.withConverter<Market>($PreferencesTableTable.$convertermarket);
|
||||||
|
static const VerificationMeta _searchModeMeta =
|
||||||
|
const VerificationMeta('searchMode');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SearchMode, String> searchMode =
|
late final GeneratedColumnWithTypeConverter<SearchMode, String> searchMode =
|
||||||
GeneratedColumn<String>('search_mode', aliasedName, false,
|
GeneratedColumn<String>('search_mode', aliasedName, false,
|
||||||
@ -694,6 +714,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
type: DriftSqlType.string,
|
type: DriftSqlType.string,
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: const Constant(""));
|
defaultValue: const Constant(""));
|
||||||
|
static const VerificationMeta _localLibraryLocationMeta =
|
||||||
|
const VerificationMeta('localLibraryLocation');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<List<String>, String>
|
late final GeneratedColumnWithTypeConverter<List<String>, String>
|
||||||
localLibraryLocation = GeneratedColumn<String>(
|
localLibraryLocation = GeneratedColumn<String>(
|
||||||
@ -719,6 +741,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
type: DriftSqlType.string,
|
type: DriftSqlType.string,
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: const Constant("https://inv.nadeko.net"));
|
defaultValue: const Constant("https://inv.nadeko.net"));
|
||||||
|
static const VerificationMeta _themeModeMeta =
|
||||||
|
const VerificationMeta('themeMode');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<ThemeMode, String> themeMode =
|
late final GeneratedColumnWithTypeConverter<ThemeMode, String> themeMode =
|
||||||
GeneratedColumn<String>('theme_mode', aliasedName, false,
|
GeneratedColumn<String>('theme_mode', aliasedName, false,
|
||||||
@ -726,6 +750,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: Constant(ThemeMode.system.name))
|
defaultValue: Constant(ThemeMode.system.name))
|
||||||
.withConverter<ThemeMode>($PreferencesTableTable.$converterthemeMode);
|
.withConverter<ThemeMode>($PreferencesTableTable.$converterthemeMode);
|
||||||
|
static const VerificationMeta _audioSourceMeta =
|
||||||
|
const VerificationMeta('audioSource');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<AudioSource, String> audioSource =
|
late final GeneratedColumnWithTypeConverter<AudioSource, String> audioSource =
|
||||||
GeneratedColumn<String>('audio_source', aliasedName, false,
|
GeneratedColumn<String>('audio_source', aliasedName, false,
|
||||||
@ -734,6 +760,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultValue: Constant(AudioSource.youtube.name))
|
defaultValue: Constant(AudioSource.youtube.name))
|
||||||
.withConverter<AudioSource>(
|
.withConverter<AudioSource>(
|
||||||
$PreferencesTableTable.$converteraudioSource);
|
$PreferencesTableTable.$converteraudioSource);
|
||||||
|
static const VerificationMeta _youtubeClientEngineMeta =
|
||||||
|
const VerificationMeta('youtubeClientEngine');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<YoutubeClientEngine, String>
|
late final GeneratedColumnWithTypeConverter<YoutubeClientEngine, String>
|
||||||
youtubeClientEngine = GeneratedColumn<String>(
|
youtubeClientEngine = GeneratedColumn<String>(
|
||||||
@ -743,6 +771,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultValue: Constant(YoutubeClientEngine.youtubeExplode.name))
|
defaultValue: Constant(YoutubeClientEngine.youtubeExplode.name))
|
||||||
.withConverter<YoutubeClientEngine>(
|
.withConverter<YoutubeClientEngine>(
|
||||||
$PreferencesTableTable.$converteryoutubeClientEngine);
|
$PreferencesTableTable.$converteryoutubeClientEngine);
|
||||||
|
static const VerificationMeta _streamMusicCodecMeta =
|
||||||
|
const VerificationMeta('streamMusicCodec');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SourceCodecs, String>
|
late final GeneratedColumnWithTypeConverter<SourceCodecs, String>
|
||||||
streamMusicCodec = GeneratedColumn<String>(
|
streamMusicCodec = GeneratedColumn<String>(
|
||||||
@ -752,6 +782,8 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
defaultValue: Constant(SourceCodecs.weba.name))
|
defaultValue: Constant(SourceCodecs.weba.name))
|
||||||
.withConverter<SourceCodecs>(
|
.withConverter<SourceCodecs>(
|
||||||
$PreferencesTableTable.$converterstreamMusicCodec);
|
$PreferencesTableTable.$converterstreamMusicCodec);
|
||||||
|
static const VerificationMeta _downloadMusicCodecMeta =
|
||||||
|
const VerificationMeta('downloadMusicCodec');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SourceCodecs, String>
|
late final GeneratedColumnWithTypeConverter<SourceCodecs, String>
|
||||||
downloadMusicCodec = GeneratedColumn<String>(
|
downloadMusicCodec = GeneratedColumn<String>(
|
||||||
@ -855,6 +887,7 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
if (data.containsKey('id')) {
|
if (data.containsKey('id')) {
|
||||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||||
}
|
}
|
||||||
|
context.handle(_audioQualityMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('album_color_sync')) {
|
if (data.containsKey('album_color_sync')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_albumColorSyncMeta,
|
_albumColorSyncMeta,
|
||||||
@ -897,12 +930,20 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
skipNonMusic.isAcceptableOrUnknown(
|
skipNonMusic.isAcceptableOrUnknown(
|
||||||
data['skip_non_music']!, _skipNonMusicMeta));
|
data['skip_non_music']!, _skipNonMusicMeta));
|
||||||
}
|
}
|
||||||
|
context.handle(_closeBehaviorMeta, const VerificationResult.success());
|
||||||
|
context.handle(_accentColorSchemeMeta, const VerificationResult.success());
|
||||||
|
context.handle(_layoutModeMeta, const VerificationResult.success());
|
||||||
|
context.handle(_localeMeta, const VerificationResult.success());
|
||||||
|
context.handle(_marketMeta, const VerificationResult.success());
|
||||||
|
context.handle(_searchModeMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('download_location')) {
|
if (data.containsKey('download_location')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_downloadLocationMeta,
|
_downloadLocationMeta,
|
||||||
downloadLocation.isAcceptableOrUnknown(
|
downloadLocation.isAcceptableOrUnknown(
|
||||||
data['download_location']!, _downloadLocationMeta));
|
data['download_location']!, _downloadLocationMeta));
|
||||||
}
|
}
|
||||||
|
context.handle(
|
||||||
|
_localLibraryLocationMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('piped_instance')) {
|
if (data.containsKey('piped_instance')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_pipedInstanceMeta,
|
_pipedInstanceMeta,
|
||||||
@ -915,6 +956,12 @@ class $PreferencesTableTable extends PreferencesTable
|
|||||||
invidiousInstance.isAcceptableOrUnknown(
|
invidiousInstance.isAcceptableOrUnknown(
|
||||||
data['invidious_instance']!, _invidiousInstanceMeta));
|
data['invidious_instance']!, _invidiousInstanceMeta));
|
||||||
}
|
}
|
||||||
|
context.handle(_themeModeMeta, const VerificationResult.success());
|
||||||
|
context.handle(_audioSourceMeta, const VerificationResult.success());
|
||||||
|
context.handle(
|
||||||
|
_youtubeClientEngineMeta, const VerificationResult.success());
|
||||||
|
context.handle(_streamMusicCodecMeta, const VerificationResult.success());
|
||||||
|
context.handle(_downloadMusicCodecMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('discord_presence')) {
|
if (data.containsKey('discord_presence')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_discordPresenceMeta,
|
_discordPresenceMeta,
|
||||||
@ -1983,6 +2030,8 @@ class $ScrobblerTableTable extends ScrobblerTable
|
|||||||
late final GeneratedColumn<String> username = GeneratedColumn<String>(
|
late final GeneratedColumn<String> username = GeneratedColumn<String>(
|
||||||
'username', aliasedName, false,
|
'username', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
|
static const VerificationMeta _passwordHashMeta =
|
||||||
|
const VerificationMeta('passwordHash');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<DecryptedText, String>
|
late final GeneratedColumnWithTypeConverter<DecryptedText, String>
|
||||||
passwordHash = GeneratedColumn<String>(
|
passwordHash = GeneratedColumn<String>(
|
||||||
@ -2015,6 +2064,7 @@ class $ScrobblerTableTable extends ScrobblerTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_usernameMeta);
|
context.missing(_usernameMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_passwordHashMeta, const VerificationResult.success());
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2545,6 +2595,8 @@ class $SourceMatchTableTable extends SourceMatchTable
|
|||||||
late final GeneratedColumn<String> sourceId = GeneratedColumn<String>(
|
late final GeneratedColumn<String> sourceId = GeneratedColumn<String>(
|
||||||
'source_id', aliasedName, false,
|
'source_id', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
|
static const VerificationMeta _sourceTypeMeta =
|
||||||
|
const VerificationMeta('sourceType');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SourceType, String> sourceType =
|
late final GeneratedColumnWithTypeConverter<SourceType, String> sourceType =
|
||||||
GeneratedColumn<String>('source_type', aliasedName, false,
|
GeneratedColumn<String>('source_type', aliasedName, false,
|
||||||
@ -2590,6 +2642,7 @@ class $SourceMatchTableTable extends SourceMatchTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_sourceIdMeta);
|
context.missing(_sourceIdMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_sourceTypeMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('created_at')) {
|
if (data.containsKey('created_at')) {
|
||||||
context.handle(_createdAtMeta,
|
context.handle(_createdAtMeta,
|
||||||
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
||||||
@ -2848,6 +2901,8 @@ class $AudioPlayerStateTableTable extends AudioPlayerStateTable
|
|||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints:
|
defaultConstraints:
|
||||||
GeneratedColumn.constraintIsAlways('CHECK ("playing" IN (0, 1))'));
|
GeneratedColumn.constraintIsAlways('CHECK ("playing" IN (0, 1))'));
|
||||||
|
static const VerificationMeta _loopModeMeta =
|
||||||
|
const VerificationMeta('loopMode');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<PlaylistMode, String> loopMode =
|
late final GeneratedColumnWithTypeConverter<PlaylistMode, String> loopMode =
|
||||||
GeneratedColumn<String>('loop_mode', aliasedName, false,
|
GeneratedColumn<String>('loop_mode', aliasedName, false,
|
||||||
@ -2863,12 +2918,15 @@ class $AudioPlayerStateTableTable extends AudioPlayerStateTable
|
|||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
defaultConstraints:
|
defaultConstraints:
|
||||||
GeneratedColumn.constraintIsAlways('CHECK ("shuffled" IN (0, 1))'));
|
GeneratedColumn.constraintIsAlways('CHECK ("shuffled" IN (0, 1))'));
|
||||||
|
static const VerificationMeta _collectionsMeta =
|
||||||
|
const VerificationMeta('collections');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<List<String>, String>
|
late final GeneratedColumnWithTypeConverter<List<String>, String>
|
||||||
collections = GeneratedColumn<String>('collections', aliasedName, false,
|
collections = GeneratedColumn<String>('collections', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||||
.withConverter<List<String>>(
|
.withConverter<List<String>>(
|
||||||
$AudioPlayerStateTableTable.$convertercollections);
|
$AudioPlayerStateTableTable.$convertercollections);
|
||||||
|
static const VerificationMeta _tracksMeta = const VerificationMeta('tracks');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<List<SpotubeTrackObject>, String>
|
late final GeneratedColumnWithTypeConverter<List<SpotubeTrackObject>, String>
|
||||||
tracks = GeneratedColumn<String>('tracks', aliasedName, false,
|
tracks = GeneratedColumn<String>('tracks', aliasedName, false,
|
||||||
@ -2908,12 +2966,15 @@ class $AudioPlayerStateTableTable extends AudioPlayerStateTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_playingMeta);
|
context.missing(_playingMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_loopModeMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('shuffled')) {
|
if (data.containsKey('shuffled')) {
|
||||||
context.handle(_shuffledMeta,
|
context.handle(_shuffledMeta,
|
||||||
shuffled.isAcceptableOrUnknown(data['shuffled']!, _shuffledMeta));
|
shuffled.isAcceptableOrUnknown(data['shuffled']!, _shuffledMeta));
|
||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_shuffledMeta);
|
context.missing(_shuffledMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_collectionsMeta, const VerificationResult.success());
|
||||||
|
context.handle(_tracksMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('current_index')) {
|
if (data.containsKey('current_index')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_currentIndexMeta,
|
_currentIndexMeta,
|
||||||
@ -3244,6 +3305,7 @@ class $HistoryTableTable extends HistoryTable
|
|||||||
type: DriftSqlType.dateTime,
|
type: DriftSqlType.dateTime,
|
||||||
requiredDuringInsert: false,
|
requiredDuringInsert: false,
|
||||||
defaultValue: currentDateAndTime);
|
defaultValue: currentDateAndTime);
|
||||||
|
static const VerificationMeta _typeMeta = const VerificationMeta('type');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<HistoryEntryType, String> type =
|
late final GeneratedColumnWithTypeConverter<HistoryEntryType, String> type =
|
||||||
GeneratedColumn<String>('type', aliasedName, false,
|
GeneratedColumn<String>('type', aliasedName, false,
|
||||||
@ -3254,6 +3316,7 @@ class $HistoryTableTable extends HistoryTable
|
|||||||
late final GeneratedColumn<String> itemId = GeneratedColumn<String>(
|
late final GeneratedColumn<String> itemId = GeneratedColumn<String>(
|
||||||
'item_id', aliasedName, false,
|
'item_id', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
|
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<Map<String, dynamic>, String>
|
late final GeneratedColumnWithTypeConverter<Map<String, dynamic>, String>
|
||||||
data = GeneratedColumn<String>('data', aliasedName, false,
|
data = GeneratedColumn<String>('data', aliasedName, false,
|
||||||
@ -3279,12 +3342,14 @@ class $HistoryTableTable extends HistoryTable
|
|||||||
context.handle(_createdAtMeta,
|
context.handle(_createdAtMeta,
|
||||||
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
||||||
}
|
}
|
||||||
|
context.handle(_typeMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('item_id')) {
|
if (data.containsKey('item_id')) {
|
||||||
context.handle(_itemIdMeta,
|
context.handle(_itemIdMeta,
|
||||||
itemId.isAcceptableOrUnknown(data['item_id']!, _itemIdMeta));
|
itemId.isAcceptableOrUnknown(data['item_id']!, _itemIdMeta));
|
||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_itemIdMeta);
|
context.missing(_itemIdMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_dataMeta, const VerificationResult.success());
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3543,6 +3608,7 @@ class $LyricsTableTable extends LyricsTable
|
|||||||
late final GeneratedColumn<String> trackId = GeneratedColumn<String>(
|
late final GeneratedColumn<String> trackId = GeneratedColumn<String>(
|
||||||
'track_id', aliasedName, false,
|
'track_id', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
|
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<SubtitleSimple, String> data =
|
late final GeneratedColumnWithTypeConverter<SubtitleSimple, String> data =
|
||||||
GeneratedColumn<String>('data', aliasedName, false,
|
GeneratedColumn<String>('data', aliasedName, false,
|
||||||
@ -3569,6 +3635,7 @@ class $LyricsTableTable extends LyricsTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_trackIdMeta);
|
context.missing(_trackIdMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_dataMeta, const VerificationResult.success());
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3786,12 +3853,15 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
|
|||||||
late final GeneratedColumn<String> entryPoint = GeneratedColumn<String>(
|
late final GeneratedColumn<String> entryPoint = GeneratedColumn<String>(
|
||||||
'entry_point', aliasedName, false,
|
'entry_point', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||||
|
static const VerificationMeta _apisMeta = const VerificationMeta('apis');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<List<String>, String> apis =
|
late final GeneratedColumnWithTypeConverter<List<String>, String> apis =
|
||||||
GeneratedColumn<String>('apis', aliasedName, false,
|
GeneratedColumn<String>('apis', aliasedName, false,
|
||||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||||
.withConverter<List<String>>(
|
.withConverter<List<String>>(
|
||||||
$MetadataPluginsTableTable.$converterapis);
|
$MetadataPluginsTableTable.$converterapis);
|
||||||
|
static const VerificationMeta _abilitiesMeta =
|
||||||
|
const VerificationMeta('abilities');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumnWithTypeConverter<List<String>, String> abilities =
|
late final GeneratedColumnWithTypeConverter<List<String>, String> abilities =
|
||||||
GeneratedColumn<String>('abilities', aliasedName, false,
|
GeneratedColumn<String>('abilities', aliasedName, false,
|
||||||
@ -3884,6 +3954,8 @@ class $MetadataPluginsTableTable extends MetadataPluginsTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_entryPointMeta);
|
context.missing(_entryPointMeta);
|
||||||
}
|
}
|
||||||
|
context.handle(_apisMeta, const VerificationResult.success());
|
||||||
|
context.handle(_abilitiesMeta, const VerificationResult.success());
|
||||||
if (data.containsKey('selected')) {
|
if (data.containsKey('selected')) {
|
||||||
context.handle(_selectedMeta,
|
context.handle(_selectedMeta,
|
||||||
selected.isAcceptableOrUnknown(data['selected']!, _selectedMeta));
|
selected.isAcceptableOrUnknown(data['selected']!, _selectedMeta));
|
||||||
|
|||||||
@ -12,14 +12,12 @@ enum CloseBehavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum AudioSource {
|
enum AudioSource {
|
||||||
youtube("YouTube"),
|
youtube,
|
||||||
piped("Piped"),
|
piped,
|
||||||
jiosaavn("JioSaavn"),
|
jiosaavn,
|
||||||
invidious("Invidious"),
|
invidious;
|
||||||
dabMusic("DAB Music");
|
|
||||||
|
|
||||||
final String label;
|
String get label => name[0].toUpperCase() + name.substring(1);
|
||||||
const AudioSource(this.label);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum YoutubeClientEngine {
|
enum YoutubeClientEngine {
|
||||||
@ -41,6 +39,14 @@ enum YoutubeClientEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MusicCodec {
|
||||||
|
m4a._("M4a (Best for downloaded music)"),
|
||||||
|
weba._("WebA (Best for streamed music)\nDoesn't support audio metadata");
|
||||||
|
|
||||||
|
final String label;
|
||||||
|
const MusicCodec._(this.label);
|
||||||
|
}
|
||||||
|
|
||||||
enum SearchMode {
|
enum SearchMode {
|
||||||
youtube._("YouTube"),
|
youtube._("YouTube"),
|
||||||
youtubeMusic._("YouTube Music");
|
youtubeMusic._("YouTube Music");
|
||||||
|
|||||||
@ -3,8 +3,7 @@ part of '../database.dart';
|
|||||||
enum SourceType {
|
enum SourceType {
|
||||||
youtube._("YouTube"),
|
youtube._("YouTube"),
|
||||||
youtubeMusic._("YouTube Music"),
|
youtubeMusic._("YouTube Music"),
|
||||||
jiosaavn._("JioSaavn"),
|
jiosaavn._("JioSaavn");
|
||||||
dabMusic._("DAB Music");
|
|
||||||
|
|
||||||
final String label;
|
final String label;
|
||||||
|
|
||||||
|
|||||||
@ -103,7 +103,6 @@ class TrackSource with _$TrackSource {
|
|||||||
required SourceQualities quality,
|
required SourceQualities quality,
|
||||||
required SourceCodecs codec,
|
required SourceCodecs codec,
|
||||||
required String bitrate,
|
required String bitrate,
|
||||||
required String qualityLabel,
|
|
||||||
}) = _TrackSource;
|
}) = _TrackSource;
|
||||||
|
|
||||||
factory TrackSource.fromJson(Map<String, dynamic> json) =>
|
factory TrackSource.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@ -28,12 +28,8 @@ mixin _$TrackSourceQuery {
|
|||||||
String get isrc => throw _privateConstructorUsedError;
|
String get isrc => throw _privateConstructorUsedError;
|
||||||
bool get explicit => throw _privateConstructorUsedError;
|
bool get explicit => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this TrackSourceQuery to a JSON map.
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
/// Create a copy of TrackSourceQuery
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$TrackSourceQueryCopyWith<TrackSourceQuery> get copyWith =>
|
$TrackSourceQueryCopyWith<TrackSourceQuery> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -64,8 +60,6 @@ class _$TrackSourceQueryCopyWithImpl<$Res, $Val extends TrackSourceQuery>
|
|||||||
// ignore: unused_field
|
// ignore: unused_field
|
||||||
final $Res Function($Val) _then;
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
/// Create a copy of TrackSourceQuery
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -136,8 +130,6 @@ class __$$TrackSourceQueryImplCopyWithImpl<$Res>
|
|||||||
$Res Function(_$TrackSourceQueryImpl) _then)
|
$Res Function(_$TrackSourceQueryImpl) _then)
|
||||||
: super(_value, _then);
|
: super(_value, _then);
|
||||||
|
|
||||||
/// Create a copy of TrackSourceQuery
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -241,7 +233,7 @@ class _$TrackSourceQueryImpl extends _TrackSourceQuery {
|
|||||||
other.explicit == explicit));
|
other.explicit == explicit));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(
|
int get hashCode => Object.hash(
|
||||||
runtimeType,
|
runtimeType,
|
||||||
@ -253,9 +245,7 @@ class _$TrackSourceQueryImpl extends _TrackSourceQuery {
|
|||||||
isrc,
|
isrc,
|
||||||
explicit);
|
explicit);
|
||||||
|
|
||||||
/// Create a copy of TrackSourceQuery
|
@JsonKey(ignore: true)
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$$TrackSourceQueryImplCopyWith<_$TrackSourceQueryImpl> get copyWith =>
|
_$$TrackSourceQueryImplCopyWith<_$TrackSourceQueryImpl> get copyWith =>
|
||||||
@ -298,11 +288,8 @@ abstract class _TrackSourceQuery extends TrackSourceQuery {
|
|||||||
String get isrc;
|
String get isrc;
|
||||||
@override
|
@override
|
||||||
bool get explicit;
|
bool get explicit;
|
||||||
|
|
||||||
/// Create a copy of TrackSourceQuery
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
_$$TrackSourceQueryImplCopyWith<_$TrackSourceQueryImpl> get copyWith =>
|
_$$TrackSourceQueryImplCopyWith<_$TrackSourceQueryImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -320,12 +307,8 @@ mixin _$TrackSourceInfo {
|
|||||||
String get pageUrl => throw _privateConstructorUsedError;
|
String get pageUrl => throw _privateConstructorUsedError;
|
||||||
int get durationMs => throw _privateConstructorUsedError;
|
int get durationMs => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this TrackSourceInfo to a JSON map.
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
/// Create a copy of TrackSourceInfo
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$TrackSourceInfoCopyWith<TrackSourceInfo> get copyWith =>
|
$TrackSourceInfoCopyWith<TrackSourceInfo> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -355,8 +338,6 @@ class _$TrackSourceInfoCopyWithImpl<$Res, $Val extends TrackSourceInfo>
|
|||||||
// ignore: unused_field
|
// ignore: unused_field
|
||||||
final $Res Function($Val) _then;
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
/// Create a copy of TrackSourceInfo
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -421,8 +402,6 @@ class __$$TrackSourceInfoImplCopyWithImpl<$Res>
|
|||||||
_$TrackSourceInfoImpl _value, $Res Function(_$TrackSourceInfoImpl) _then)
|
_$TrackSourceInfoImpl _value, $Res Function(_$TrackSourceInfoImpl) _then)
|
||||||
: super(_value, _then);
|
: super(_value, _then);
|
||||||
|
|
||||||
/// Create a copy of TrackSourceInfo
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -509,14 +488,12 @@ class _$TrackSourceInfoImpl implements _TrackSourceInfo {
|
|||||||
other.durationMs == durationMs));
|
other.durationMs == durationMs));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(
|
int get hashCode => Object.hash(
|
||||||
runtimeType, id, title, artists, thumbnail, pageUrl, durationMs);
|
runtimeType, id, title, artists, thumbnail, pageUrl, durationMs);
|
||||||
|
|
||||||
/// Create a copy of TrackSourceInfo
|
@JsonKey(ignore: true)
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$$TrackSourceInfoImplCopyWith<_$TrackSourceInfoImpl> get copyWith =>
|
_$$TrackSourceInfoImplCopyWith<_$TrackSourceInfoImpl> get copyWith =>
|
||||||
@ -555,11 +532,8 @@ abstract class _TrackSourceInfo implements TrackSourceInfo {
|
|||||||
String get pageUrl;
|
String get pageUrl;
|
||||||
@override
|
@override
|
||||||
int get durationMs;
|
int get durationMs;
|
||||||
|
|
||||||
/// Create a copy of TrackSourceInfo
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
_$$TrackSourceInfoImplCopyWith<_$TrackSourceInfoImpl> get copyWith =>
|
_$$TrackSourceInfoImplCopyWith<_$TrackSourceInfoImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -574,14 +548,9 @@ mixin _$TrackSource {
|
|||||||
SourceQualities get quality => throw _privateConstructorUsedError;
|
SourceQualities get quality => throw _privateConstructorUsedError;
|
||||||
SourceCodecs get codec => throw _privateConstructorUsedError;
|
SourceCodecs get codec => throw _privateConstructorUsedError;
|
||||||
String get bitrate => throw _privateConstructorUsedError;
|
String get bitrate => throw _privateConstructorUsedError;
|
||||||
String get qualityLabel => throw _privateConstructorUsedError;
|
|
||||||
|
|
||||||
/// Serializes this TrackSource to a JSON map.
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
/// Create a copy of TrackSource
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$TrackSourceCopyWith<TrackSource> get copyWith =>
|
$TrackSourceCopyWith<TrackSource> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -596,8 +565,7 @@ abstract class $TrackSourceCopyWith<$Res> {
|
|||||||
{String url,
|
{String url,
|
||||||
SourceQualities quality,
|
SourceQualities quality,
|
||||||
SourceCodecs codec,
|
SourceCodecs codec,
|
||||||
String bitrate,
|
String bitrate});
|
||||||
String qualityLabel});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -610,8 +578,6 @@ class _$TrackSourceCopyWithImpl<$Res, $Val extends TrackSource>
|
|||||||
// ignore: unused_field
|
// ignore: unused_field
|
||||||
final $Res Function($Val) _then;
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
/// Create a copy of TrackSource
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -619,7 +585,6 @@ class _$TrackSourceCopyWithImpl<$Res, $Val extends TrackSource>
|
|||||||
Object? quality = null,
|
Object? quality = null,
|
||||||
Object? codec = null,
|
Object? codec = null,
|
||||||
Object? bitrate = null,
|
Object? bitrate = null,
|
||||||
Object? qualityLabel = null,
|
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
url: null == url
|
url: null == url
|
||||||
@ -638,10 +603,6 @@ class _$TrackSourceCopyWithImpl<$Res, $Val extends TrackSource>
|
|||||||
? _value.bitrate
|
? _value.bitrate
|
||||||
: bitrate // ignore: cast_nullable_to_non_nullable
|
: bitrate // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
qualityLabel: null == qualityLabel
|
|
||||||
? _value.qualityLabel
|
|
||||||
: qualityLabel // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
) as $Val);
|
) as $Val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -658,8 +619,7 @@ abstract class _$$TrackSourceImplCopyWith<$Res>
|
|||||||
{String url,
|
{String url,
|
||||||
SourceQualities quality,
|
SourceQualities quality,
|
||||||
SourceCodecs codec,
|
SourceCodecs codec,
|
||||||
String bitrate,
|
String bitrate});
|
||||||
String qualityLabel});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@ -670,8 +630,6 @@ class __$$TrackSourceImplCopyWithImpl<$Res>
|
|||||||
_$TrackSourceImpl _value, $Res Function(_$TrackSourceImpl) _then)
|
_$TrackSourceImpl _value, $Res Function(_$TrackSourceImpl) _then)
|
||||||
: super(_value, _then);
|
: super(_value, _then);
|
||||||
|
|
||||||
/// Create a copy of TrackSource
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -679,7 +637,6 @@ class __$$TrackSourceImplCopyWithImpl<$Res>
|
|||||||
Object? quality = null,
|
Object? quality = null,
|
||||||
Object? codec = null,
|
Object? codec = null,
|
||||||
Object? bitrate = null,
|
Object? bitrate = null,
|
||||||
Object? qualityLabel = null,
|
|
||||||
}) {
|
}) {
|
||||||
return _then(_$TrackSourceImpl(
|
return _then(_$TrackSourceImpl(
|
||||||
url: null == url
|
url: null == url
|
||||||
@ -698,10 +655,6 @@ class __$$TrackSourceImplCopyWithImpl<$Res>
|
|||||||
? _value.bitrate
|
? _value.bitrate
|
||||||
: bitrate // ignore: cast_nullable_to_non_nullable
|
: bitrate // ignore: cast_nullable_to_non_nullable
|
||||||
as String,
|
as String,
|
||||||
qualityLabel: null == qualityLabel
|
|
||||||
? _value.qualityLabel
|
|
||||||
: qualityLabel // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -713,8 +666,7 @@ class _$TrackSourceImpl implements _TrackSource {
|
|||||||
{required this.url,
|
{required this.url,
|
||||||
required this.quality,
|
required this.quality,
|
||||||
required this.codec,
|
required this.codec,
|
||||||
required this.bitrate,
|
required this.bitrate});
|
||||||
required this.qualityLabel});
|
|
||||||
|
|
||||||
factory _$TrackSourceImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$TrackSourceImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$TrackSourceImplFromJson(json);
|
_$$TrackSourceImplFromJson(json);
|
||||||
@ -727,12 +679,10 @@ class _$TrackSourceImpl implements _TrackSource {
|
|||||||
final SourceCodecs codec;
|
final SourceCodecs codec;
|
||||||
@override
|
@override
|
||||||
final String bitrate;
|
final String bitrate;
|
||||||
@override
|
|
||||||
final String qualityLabel;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'TrackSource(url: $url, quality: $quality, codec: $codec, bitrate: $bitrate, qualityLabel: $qualityLabel)';
|
return 'TrackSource(url: $url, quality: $quality, codec: $codec, bitrate: $bitrate)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -743,19 +693,14 @@ class _$TrackSourceImpl implements _TrackSource {
|
|||||||
(identical(other.url, url) || other.url == url) &&
|
(identical(other.url, url) || other.url == url) &&
|
||||||
(identical(other.quality, quality) || other.quality == quality) &&
|
(identical(other.quality, quality) || other.quality == quality) &&
|
||||||
(identical(other.codec, codec) || other.codec == codec) &&
|
(identical(other.codec, codec) || other.codec == codec) &&
|
||||||
(identical(other.bitrate, bitrate) || other.bitrate == bitrate) &&
|
(identical(other.bitrate, bitrate) || other.bitrate == bitrate));
|
||||||
(identical(other.qualityLabel, qualityLabel) ||
|
|
||||||
other.qualityLabel == qualityLabel));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode => Object.hash(runtimeType, url, quality, codec, bitrate);
|
||||||
Object.hash(runtimeType, url, quality, codec, bitrate, qualityLabel);
|
|
||||||
|
|
||||||
/// Create a copy of TrackSource
|
@JsonKey(ignore: true)
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$$TrackSourceImplCopyWith<_$TrackSourceImpl> get copyWith =>
|
_$$TrackSourceImplCopyWith<_$TrackSourceImpl> get copyWith =>
|
||||||
@ -774,8 +719,7 @@ abstract class _TrackSource implements TrackSource {
|
|||||||
{required final String url,
|
{required final String url,
|
||||||
required final SourceQualities quality,
|
required final SourceQualities quality,
|
||||||
required final SourceCodecs codec,
|
required final SourceCodecs codec,
|
||||||
required final String bitrate,
|
required final String bitrate}) = _$TrackSourceImpl;
|
||||||
required final String qualityLabel}) = _$TrackSourceImpl;
|
|
||||||
|
|
||||||
factory _TrackSource.fromJson(Map<String, dynamic> json) =
|
factory _TrackSource.fromJson(Map<String, dynamic> json) =
|
||||||
_$TrackSourceImpl.fromJson;
|
_$TrackSourceImpl.fromJson;
|
||||||
@ -789,12 +733,7 @@ abstract class _TrackSource implements TrackSource {
|
|||||||
@override
|
@override
|
||||||
String get bitrate;
|
String get bitrate;
|
||||||
@override
|
@override
|
||||||
String get qualityLabel;
|
@JsonKey(ignore: true)
|
||||||
|
|
||||||
/// Create a copy of TrackSource
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
_$$TrackSourceImplCopyWith<_$TrackSourceImpl> get copyWith =>
|
_$$TrackSourceImplCopyWith<_$TrackSourceImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,6 @@ const _$AudioSourceEnumMap = {
|
|||||||
AudioSource.piped: 'piped',
|
AudioSource.piped: 'piped',
|
||||||
AudioSource.jiosaavn: 'jiosaavn',
|
AudioSource.jiosaavn: 'jiosaavn',
|
||||||
AudioSource.invidious: 'invidious',
|
AudioSource.invidious: 'invidious',
|
||||||
AudioSource.dabMusic: 'dabMusic',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_$TrackSourceQueryImpl _$$TrackSourceQueryImplFromJson(Map json) =>
|
_$TrackSourceQueryImpl _$$TrackSourceQueryImplFromJson(Map json) =>
|
||||||
@ -89,7 +88,6 @@ _$TrackSourceImpl _$$TrackSourceImplFromJson(Map json) => _$TrackSourceImpl(
|
|||||||
quality: $enumDecode(_$SourceQualitiesEnumMap, json['quality']),
|
quality: $enumDecode(_$SourceQualitiesEnumMap, json['quality']),
|
||||||
codec: $enumDecode(_$SourceCodecsEnumMap, json['codec']),
|
codec: $enumDecode(_$SourceCodecsEnumMap, json['codec']),
|
||||||
bitrate: json['bitrate'] as String,
|
bitrate: json['bitrate'] as String,
|
||||||
qualityLabel: json['qualityLabel'] as String,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$TrackSourceImplToJson(_$TrackSourceImpl instance) =>
|
Map<String, dynamic> _$$TrackSourceImplToJson(_$TrackSourceImpl instance) =>
|
||||||
@ -98,11 +96,9 @@ Map<String, dynamic> _$$TrackSourceImplToJson(_$TrackSourceImpl instance) =>
|
|||||||
'quality': _$SourceQualitiesEnumMap[instance.quality]!,
|
'quality': _$SourceQualitiesEnumMap[instance.quality]!,
|
||||||
'codec': _$SourceCodecsEnumMap[instance.codec]!,
|
'codec': _$SourceCodecsEnumMap[instance.codec]!,
|
||||||
'bitrate': instance.bitrate,
|
'bitrate': instance.bitrate,
|
||||||
'qualityLabel': instance.qualityLabel,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$SourceQualitiesEnumMap = {
|
const _$SourceQualitiesEnumMap = {
|
||||||
SourceQualities.uncompressed: 'uncompressed',
|
|
||||||
SourceQualities.high: 'high',
|
SourceQualities.high: 'high',
|
||||||
SourceQualities.medium: 'medium',
|
SourceQualities.medium: 'medium',
|
||||||
SourceQualities.low: 'low',
|
SourceQualities.low: 'low',
|
||||||
@ -111,6 +107,4 @@ const _$SourceQualitiesEnumMap = {
|
|||||||
const _$SourceCodecsEnumMap = {
|
const _$SourceCodecsEnumMap = {
|
||||||
SourceCodecs.m4a: 'm4a',
|
SourceCodecs.m4a: 'm4a',
|
||||||
SourceCodecs.weba: 'weba',
|
SourceCodecs.weba: 'weba',
|
||||||
SourceCodecs.mp3: 'mp3',
|
|
||||||
SourceCodecs.flac: 'flac',
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -91,27 +91,10 @@ class MetadataInstalledPluginItem extends HookConsumerWidget {
|
|||||||
)
|
)
|
||||||
else ...[
|
else ...[
|
||||||
Text(context.l10n.author_name(plugin.author)),
|
Text(context.l10n.author_name(plugin.author)),
|
||||||
Container(
|
DestructiveBadge(
|
||||||
padding: const EdgeInsets.symmetric(
|
leading: const Icon(SpotubeIcons.warning),
|
||||||
horizontal: 6,
|
child: Text(context.l10n.third_party),
|
||||||
vertical: 2,
|
)
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.blue,
|
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
spacing: 4,
|
|
||||||
children: [
|
|
||||||
const Icon(SpotubeIcons.warning, size: 14),
|
|
||||||
Text(
|
|
||||||
context.l10n.third_party,
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
).xSmall
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
SecondaryBadge(
|
SecondaryBadge(
|
||||||
leading: const Icon(SpotubeIcons.connect),
|
leading: const Icon(SpotubeIcons.connect),
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
@ -9,7 +8,6 @@ import 'package:spotube/extensions/context.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:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
import 'package:change_case/change_case.dart';
|
|
||||||
|
|
||||||
class MetadataPluginRepositoryItem extends HookConsumerWidget {
|
class MetadataPluginRepositoryItem extends HookConsumerWidget {
|
||||||
final MetadataPluginRepository pluginRepo;
|
final MetadataPluginRepository pluginRepo;
|
||||||
@ -28,198 +26,144 @@ class MetadataPluginRepositoryItem extends HookConsumerWidget {
|
|||||||
final isInstalling = useState(false);
|
final isInstalling = useState(false);
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
child: Column(
|
child: Basic(
|
||||||
mainAxisSize: MainAxisSize.min,
|
title: Text(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
"${pluginRepo.owner == "KRTirtho" ? "" : "${pluginRepo.owner}/"}${pluginRepo.name}"),
|
||||||
spacing: 8,
|
subtitle: Column(
|
||||||
children: [
|
mainAxisSize: MainAxisSize.min,
|
||||||
Basic(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
title: Text(
|
spacing: 8,
|
||||||
pluginRepo.name.startsWith("spotube-plugin")
|
children: [
|
||||||
? pluginRepo.name
|
Text(pluginRepo.description),
|
||||||
.replaceFirst("spotube-plugin-", "")
|
Row(
|
||||||
.trim()
|
spacing: 8,
|
||||||
.toCapitalCase()
|
children: [
|
||||||
: pluginRepo.name.toCapitalCase(),
|
if (pluginRepo.owner == "KRTirtho") ...[
|
||||||
),
|
PrimaryBadge(
|
||||||
subtitle: Text(pluginRepo.description),
|
leading: Icon(SpotubeIcons.done),
|
||||||
trailing: Button.primary(
|
child: Text(context.l10n.official),
|
||||||
enabled: !isInstalling.value,
|
|
||||||
onPressed: () async {
|
|
||||||
try {
|
|
||||||
isInstalling.value = true;
|
|
||||||
final pluginConfig = await pluginsNotifier
|
|
||||||
.downloadAndCachePlugin(pluginRepo.repoUrl);
|
|
||||||
|
|
||||||
if (!context.mounted) return;
|
|
||||||
final isOfficialPlugin = pluginRepo.owner == "KRTirtho";
|
|
||||||
|
|
||||||
final isAllowed = isOfficialPlugin
|
|
||||||
? true
|
|
||||||
: await showDialog<bool>(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
final pluginAbilities = pluginConfig.apis
|
|
||||||
.map((e) =>
|
|
||||||
context.l10n.can_access_name_api(e.name))
|
|
||||||
.join("\n\n");
|
|
||||||
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text(
|
|
||||||
context.l10n.do_you_want_to_install_this_plugin,
|
|
||||||
),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(context.l10n.third_party_plugin_warning),
|
|
||||||
const Gap(8),
|
|
||||||
FutureBuilder(
|
|
||||||
future: pluginsNotifier
|
|
||||||
.getLogoPath(pluginConfig),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
return Basic(
|
|
||||||
leading: snapshot.hasData
|
|
||||||
? Image.file(
|
|
||||||
snapshot.data!,
|
|
||||||
width: 36,
|
|
||||||
height: 36,
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
height: 36,
|
|
||||||
width: 36,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: context.theme
|
|
||||||
.colorScheme.secondary,
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
SpotubeIcons.plugin),
|
|
||||||
),
|
|
||||||
title: Text(pluginConfig.name),
|
|
||||||
subtitle:
|
|
||||||
Text(pluginConfig.description),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
AppMarkdown(
|
|
||||||
data:
|
|
||||||
"**${context.l10n.author}**: ${pluginConfig.author}\n\n"
|
|
||||||
"**${context.l10n.repository}**: [${pluginConfig.repository ?? 'N/A'}](${pluginConfig.repository})\n\n\n\n"
|
|
||||||
"${context.l10n.this_plugin_can_do_following}:\n\n"
|
|
||||||
"$pluginAbilities",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
Button.secondary(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop(false);
|
|
||||||
},
|
|
||||||
child: Text(context.l10n.decline),
|
|
||||||
),
|
|
||||||
Button.primary(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop(true);
|
|
||||||
},
|
|
||||||
child: Text(context.l10n.accept),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isAllowed != true) return;
|
|
||||||
await pluginsNotifier.addPlugin(pluginConfig);
|
|
||||||
} finally {
|
|
||||||
if (context.mounted) {
|
|
||||||
isInstalling.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
leading: isInstalling.value
|
|
||||||
? SizedBox.square(
|
|
||||||
dimension: 20,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
color: context.theme.colorScheme.primaryForeground,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: const Icon(SpotubeIcons.add),
|
|
||||||
child: Text(context.l10n.install),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (pluginRepo.owner != "KRTirtho")
|
|
||||||
Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
children: [
|
|
||||||
TextSpan(text: context.l10n.source),
|
|
||||||
TextSpan(
|
|
||||||
text: pluginRepo.repoUrl.replaceAll("https://", ""),
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.blue,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
recognizer: TapGestureRecognizer()
|
|
||||||
..onTap = () async {
|
|
||||||
launchUrlString(pluginRepo.repoUrl);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
SecondaryBadge(
|
||||||
),
|
leading: host == "github.com"
|
||||||
style: context.theme.typography.xSmall,
|
? const Icon(SpotubeIcons.github)
|
||||||
),
|
: null,
|
||||||
Wrap(
|
child: Text(host),
|
||||||
spacing: 8,
|
onPressed: () {
|
||||||
runSpacing: 8,
|
launchUrlString(pluginRepo.repoUrl);
|
||||||
children: [
|
},
|
||||||
if (pluginRepo.owner == "KRTirtho")
|
|
||||||
PrimaryBadge(
|
|
||||||
leading: const Icon(SpotubeIcons.done),
|
|
||||||
child: Text(context.l10n.official),
|
|
||||||
)
|
|
||||||
else ...[
|
|
||||||
Text(
|
|
||||||
context.l10n.author_name(pluginRepo.owner),
|
|
||||||
style: context.theme.typography.xSmall,
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 6,
|
|
||||||
vertical: 2,
|
|
||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
] else ...[
|
||||||
color: Colors.blue,
|
Text(context.l10n.author_name(pluginRepo.owner)),
|
||||||
borderRadius: BorderRadius.circular(6),
|
DestructiveBadge(
|
||||||
),
|
leading: const Icon(SpotubeIcons.warning),
|
||||||
child: Row(
|
child: Text(context.l10n.third_party),
|
||||||
mainAxisSize: MainAxisSize.min,
|
)
|
||||||
spacing: 4,
|
]
|
||||||
children: [
|
|
||||||
const Icon(SpotubeIcons.warning, size: 14),
|
|
||||||
Text(
|
|
||||||
context.l10n.third_party,
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
).xSmall
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
SecondaryBadge(
|
),
|
||||||
leading: host == "github.com"
|
],
|
||||||
? const Icon(SpotubeIcons.github)
|
),
|
||||||
: null,
|
trailing: Button.primary(
|
||||||
child: Text(host),
|
enabled: !isInstalling.value,
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
launchUrlString(pluginRepo.repoUrl);
|
try {
|
||||||
},
|
isInstalling.value = true;
|
||||||
),
|
final pluginConfig = await pluginsNotifier
|
||||||
],
|
.downloadAndCachePlugin(pluginRepo.repoUrl);
|
||||||
),
|
|
||||||
],
|
if (!context.mounted) return;
|
||||||
|
final isOfficialPlugin = pluginRepo.owner == "KRTirtho";
|
||||||
|
|
||||||
|
final isAllowed = isOfficialPlugin
|
||||||
|
? true
|
||||||
|
: await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
final pluginAbilities = pluginConfig.apis
|
||||||
|
.map(
|
||||||
|
(e) => context.l10n.can_access_name_api(e.name))
|
||||||
|
.join("\n\n");
|
||||||
|
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(
|
||||||
|
context.l10n.do_you_want_to_install_this_plugin),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(context.l10n.third_party_plugin_warning),
|
||||||
|
const Gap(8),
|
||||||
|
FutureBuilder(
|
||||||
|
future:
|
||||||
|
pluginsNotifier.getLogoPath(pluginConfig),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return Basic(
|
||||||
|
leading: snapshot.hasData
|
||||||
|
? Image.file(
|
||||||
|
snapshot.data!,
|
||||||
|
width: 36,
|
||||||
|
height: 36,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
height: 36,
|
||||||
|
width: 36,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: context
|
||||||
|
.theme.colorScheme.secondary,
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
child:
|
||||||
|
const Icon(SpotubeIcons.plugin),
|
||||||
|
),
|
||||||
|
title: Text(pluginConfig.name),
|
||||||
|
subtitle: Text(pluginConfig.description),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
AppMarkdown(
|
||||||
|
data:
|
||||||
|
"**${context.l10n.author}**: ${pluginConfig.author}\n\n"
|
||||||
|
"**${context.l10n.repository}**: [${pluginConfig.repository ?? 'N/A'}](${pluginConfig.repository})\n\n\n\n"
|
||||||
|
"${context.l10n.this_plugin_can_do_following}:\n\n"
|
||||||
|
"$pluginAbilities",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
Button.secondary(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(false);
|
||||||
|
},
|
||||||
|
child: Text(context.l10n.decline),
|
||||||
|
),
|
||||||
|
Button.primary(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
child: Text(context.l10n.accept),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isAllowed != true) return;
|
||||||
|
await pluginsNotifier.addPlugin(pluginConfig);
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) {
|
||||||
|
isInstalling.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leading: isInstalling.value
|
||||||
|
? const CircularProgressIndicator()
|
||||||
|
: const Icon(SpotubeIcons.add),
|
||||||
|
child: Text(context.l10n.install),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,14 +46,6 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
final isLocalTrack = currentActiveTrack is SpotubeLocalTrackObject;
|
final isLocalTrack = currentActiveTrack is SpotubeLocalTrackObject;
|
||||||
final mediaQuery = MediaQuery.sizeOf(context);
|
final mediaQuery = MediaQuery.sizeOf(context);
|
||||||
|
|
||||||
final activeSourceCodec = useMemoized(
|
|
||||||
() {
|
|
||||||
return currentActiveTrackSource
|
|
||||||
?.getSourceOfCodec(currentActiveTrackSource.codec);
|
|
||||||
},
|
|
||||||
[currentActiveTrackSource?.sources, currentActiveTrackSource?.codec],
|
|
||||||
);
|
|
||||||
|
|
||||||
final shouldHide = useState(true);
|
final shouldHide = useState(true);
|
||||||
|
|
||||||
ref.listen(navigationPanelHeight, (_, height) {
|
ref.listen(navigationPanelHeight, (_, height) {
|
||||||
@ -275,21 +267,6 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
const Gap(25),
|
|
||||||
if (activeSourceCodec != null)
|
|
||||||
OutlineBadge(
|
|
||||||
style: const ButtonStyle.outline(
|
|
||||||
size: ButtonSize.normal,
|
|
||||||
density: ButtonDensity.dense,
|
|
||||||
shape: ButtonShape.rectangle,
|
|
||||||
).copyWith(
|
|
||||||
textStyle: (context, states, value) {
|
|
||||||
return value.copyWith(fontWeight: FontWeight.w500);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
leading: const Icon(SpotubeIcons.lightningOutlined),
|
|
||||||
child: Text(activeSourceCodec.qualityLabel),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import 'package:spotube/components/ui/button_tile.dart';
|
|||||||
import 'package:spotube/models/database/database.dart';
|
import 'package:spotube/models/database/database.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/extensions/string.dart';
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
||||||
|
|
||||||
final audioSourceToIconMap = {
|
final audioSourceToIconMap = {
|
||||||
@ -22,8 +23,6 @@ final audioSourceToIconMap = {
|
|||||||
),
|
),
|
||||||
AudioSource.jiosaavn:
|
AudioSource.jiosaavn:
|
||||||
Assets.images.logos.jiosaavn.image(width: 20, height: 20),
|
Assets.images.logos.jiosaavn.image(width: 20, height: 20),
|
||||||
AudioSource.dabMusic:
|
|
||||||
Assets.images.logos.dabMusic.image(width: 20, height: 20),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GettingStartedPagePlaybackSection extends HookConsumerWidget {
|
class GettingStartedPagePlaybackSection extends HookConsumerWidget {
|
||||||
@ -48,10 +47,8 @@ class GettingStartedPagePlaybackSection extends HookConsumerWidget {
|
|||||||
AudioSource.piped: context.l10n.piped_source_description,
|
AudioSource.piped: context.l10n.piped_source_description,
|
||||||
AudioSource.jiosaavn:
|
AudioSource.jiosaavn:
|
||||||
"${context.l10n.jiosaavn_source_description}\n"
|
"${context.l10n.jiosaavn_source_description}\n"
|
||||||
"${context.l10n.highest_quality("320kbps mp4")}",
|
"${context.l10n.highest_quality("320kbps mp")}",
|
||||||
AudioSource.invidious: context.l10n.invidious_source_description,
|
AudioSource.invidious: context.l10n.invidious_source_description,
|
||||||
AudioSource.dabMusic: "${context.l10n.dab_music_source_description}\n"
|
|
||||||
"${context.l10n.highest_quality("320kbps mp3, HI-RES 24bit 44.1kHz-96kHz flac")}",
|
|
||||||
},
|
},
|
||||||
[]);
|
[]);
|
||||||
|
|
||||||
@ -73,28 +70,43 @@ class GettingStartedPagePlaybackSection extends HookConsumerWidget {
|
|||||||
child: Text(context.l10n.select_audio_source).semiBold().large(),
|
child: Text(context.l10n.select_audio_source).semiBold().large(),
|
||||||
),
|
),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
RadioGroup<AudioSource>(
|
Select<AudioSource>(
|
||||||
value: preferences.audioSource,
|
value: preferences.audioSource,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
if (value == null) return;
|
||||||
preferencesNotifier.setAudioSource(value);
|
preferencesNotifier.setAudioSource(value);
|
||||||
},
|
},
|
||||||
child: Wrap(
|
placeholder: Text(preferences.audioSource.name.capitalize()),
|
||||||
|
itemBuilder: (context, value) => Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
runSpacing: 6,
|
|
||||||
children: [
|
children: [
|
||||||
for (final source in AudioSource.values)
|
audioSourceToIconMap[value]!,
|
||||||
RadioCard(
|
Text(value.name.capitalize()),
|
||||||
value: source,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
audioSourceToIconMap[source]!,
|
|
||||||
Text(source.label),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
popup: (context) {
|
||||||
|
return SelectPopup(
|
||||||
|
items: SelectItemBuilder(
|
||||||
|
childCount: AudioSource.values.length,
|
||||||
|
builder: (context, index) {
|
||||||
|
final source = AudioSource.values[index];
|
||||||
|
|
||||||
|
return SelectItemButton(
|
||||||
|
value: source,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
audioSourceToIconMap[source]!,
|
||||||
|
Text(source.name.capitalize()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import 'package:flutter/material.dart' show ListTile;
|
|||||||
import 'package:google_fonts/google_fonts.dart';
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:piped_client/piped_client.dart';
|
import 'package:piped_client/piped_client.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer;
|
||||||
import 'package:spotube/collections/routes.gr.dart';
|
import 'package:spotube/collections/routes.gr.dart';
|
||||||
import 'package:spotube/collections/spotube_icons.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
import 'package:spotube/models/database/database.dart';
|
import 'package:spotube/models/database/database.dart';
|
||||||
@ -44,25 +44,18 @@ class SettingsPlaybackSection extends HookConsumerWidget {
|
|||||||
title: Text(context.l10n.audio_quality),
|
title: Text(context.l10n.audio_quality),
|
||||||
value: preferences.audioQuality,
|
value: preferences.audioQuality,
|
||||||
options: [
|
options: [
|
||||||
if (preferences.audioSource == AudioSource.dabMusic)
|
|
||||||
SelectItemButton(
|
|
||||||
value: SourceQualities.uncompressed,
|
|
||||||
child: Text(context.l10n.uncompressed),
|
|
||||||
),
|
|
||||||
SelectItemButton(
|
SelectItemButton(
|
||||||
value: SourceQualities.high,
|
value: SourceQualities.high,
|
||||||
child: Text(context.l10n.high),
|
child: Text(context.l10n.high),
|
||||||
),
|
),
|
||||||
if (preferences.audioSource != AudioSource.dabMusic) ...[
|
SelectItemButton(
|
||||||
SelectItemButton(
|
value: SourceQualities.medium,
|
||||||
value: SourceQualities.medium,
|
child: Text(context.l10n.medium),
|
||||||
child: Text(context.l10n.medium),
|
),
|
||||||
),
|
SelectItemButton(
|
||||||
SelectItemButton(
|
value: SourceQualities.low,
|
||||||
value: SourceQualities.low,
|
child: Text(context.l10n.low),
|
||||||
child: Text(context.l10n.low),
|
),
|
||||||
),
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@ -403,9 +396,7 @@ class SettingsPlaybackSection extends HookConsumerWidget {
|
|||||||
onChanged: preferencesNotifier.setNormalizeAudio,
|
onChanged: preferencesNotifier.setNormalizeAudio,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (const [AudioSource.jiosaavn, AudioSource.dabMusic]
|
if (preferences.audioSource != AudioSource.jiosaavn) ...[
|
||||||
.contains(preferences.audioSource) ==
|
|
||||||
false) ...[
|
|
||||||
AdaptiveSelectTile<SourceCodecs>(
|
AdaptiveSelectTile<SourceCodecs>(
|
||||||
popupConstraints: const BoxConstraints(maxWidth: 300),
|
popupConstraints: const BoxConstraints(maxWidth: 300),
|
||||||
secondary: const Icon(SpotubeIcons.stream),
|
secondary: const Icon(SpotubeIcons.stream),
|
||||||
|
|||||||
@ -27,12 +27,8 @@ mixin _$AudioPlayerState {
|
|||||||
int get currentIndex => throw _privateConstructorUsedError;
|
int get currentIndex => throw _privateConstructorUsedError;
|
||||||
List<SpotubeTrackObject> get tracks => throw _privateConstructorUsedError;
|
List<SpotubeTrackObject> get tracks => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this AudioPlayerState to a JSON map.
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
/// Create a copy of AudioPlayerState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$AudioPlayerStateCopyWith<AudioPlayerState> get copyWith =>
|
$AudioPlayerStateCopyWith<AudioPlayerState> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -62,8 +58,6 @@ class _$AudioPlayerStateCopyWithImpl<$Res, $Val extends AudioPlayerState>
|
|||||||
// ignore: unused_field
|
// ignore: unused_field
|
||||||
final $Res Function($Val) _then;
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
/// Create a copy of AudioPlayerState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -128,8 +122,6 @@ class __$$AudioPlayerStateImplCopyWithImpl<$Res>
|
|||||||
$Res Function(_$AudioPlayerStateImpl) _then)
|
$Res Function(_$AudioPlayerStateImpl) _then)
|
||||||
: super(_value, _then);
|
: super(_value, _then);
|
||||||
|
|
||||||
/// Create a copy of AudioPlayerState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -234,7 +226,7 @@ class _$AudioPlayerStateImpl extends _AudioPlayerState {
|
|||||||
const DeepCollectionEquality().equals(other._tracks, _tracks));
|
const DeepCollectionEquality().equals(other._tracks, _tracks));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(
|
int get hashCode => Object.hash(
|
||||||
runtimeType,
|
runtimeType,
|
||||||
@ -245,9 +237,7 @@ class _$AudioPlayerStateImpl extends _AudioPlayerState {
|
|||||||
currentIndex,
|
currentIndex,
|
||||||
const DeepCollectionEquality().hash(_tracks));
|
const DeepCollectionEquality().hash(_tracks));
|
||||||
|
|
||||||
/// Create a copy of AudioPlayerState
|
@JsonKey(ignore: true)
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$$AudioPlayerStateImplCopyWith<_$AudioPlayerStateImpl> get copyWith =>
|
_$$AudioPlayerStateImplCopyWith<_$AudioPlayerStateImpl> get copyWith =>
|
||||||
@ -287,11 +277,8 @@ abstract class _AudioPlayerState extends AudioPlayerState {
|
|||||||
int get currentIndex;
|
int get currentIndex;
|
||||||
@override
|
@override
|
||||||
List<SpotubeTrackObject> get tracks;
|
List<SpotubeTrackObject> get tracks;
|
||||||
|
|
||||||
/// Create a copy of AudioPlayerState
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
_$$AudioPlayerStateImplCopyWith<_$AudioPlayerStateImpl> get copyWith =>
|
_$$AudioPlayerStateImplCopyWith<_$AudioPlayerStateImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -350,8 +350,6 @@ class MetadataPluginNotifier extends AsyncNotifier<MetadataPluginState> {
|
|||||||
abilities: plugin.abilities.map((e) => e.name).toList(),
|
abilities: plugin.abilities.map((e) => e.name).toList(),
|
||||||
pluginApiVersion: Value(plugin.pluginApiVersion),
|
pluginApiVersion: Value(plugin.pluginApiVersion),
|
||||||
repository: Value(plugin.repository),
|
repository: Value(plugin.repository),
|
||||||
// Setting the very first plugin as the default plugin
|
|
||||||
selected: Value(state.valueOrNull?.plugins.isEmpty ?? true),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -364,17 +362,6 @@ class MetadataPluginNotifier extends AsyncNotifier<MetadataPluginState> {
|
|||||||
}
|
}
|
||||||
await database.metadataPluginsTable.deleteWhere((tbl) =>
|
await database.metadataPluginsTable.deleteWhere((tbl) =>
|
||||||
tbl.name.equals(plugin.name) & tbl.author.equals(plugin.author));
|
tbl.name.equals(plugin.name) & tbl.author.equals(plugin.author));
|
||||||
|
|
||||||
// Same here, if the removed plugin is the default plugin
|
|
||||||
// set the first available plugin as the default plugin
|
|
||||||
// only when there is 1 remaining plugin
|
|
||||||
if (state.valueOrNull?.defaultPluginConfig == plugin) {
|
|
||||||
final remainingPlugins =
|
|
||||||
state.valueOrNull?.plugins.where((p) => p != plugin) ?? [];
|
|
||||||
if (remainingPlugins.length == 1) {
|
|
||||||
await setDefaultPlugin(remainingPlugins.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updatePlugin(
|
Future<void> updatePlugin(
|
||||||
|
|||||||
@ -12,7 +12,6 @@ final serverRouterProvider = Provider((ref) {
|
|||||||
|
|
||||||
router.get("/ping", (Request request) => Response.ok("pong"));
|
router.get("/ping", (Request request) => Response.ok("pong"));
|
||||||
|
|
||||||
router.head("/stream/<trackId>", playbackRoutes.headStreamTrackId);
|
|
||||||
router.get("/stream/<trackId>", playbackRoutes.getStreamTrackId);
|
router.get("/stream/<trackId>", playbackRoutes.getStreamTrackId);
|
||||||
|
|
||||||
router.get("/playback/toggle-playback", playbackRoutes.togglePlayback);
|
router.get("/playback/toggle-playback", playbackRoutes.togglePlayback);
|
||||||
|
|||||||
@ -46,95 +46,21 @@ class ServerPlaybackRoutes {
|
|||||||
|
|
||||||
ServerPlaybackRoutes(this.ref) : dio = Dio();
|
ServerPlaybackRoutes(this.ref) : dio = Dio();
|
||||||
|
|
||||||
Future<String> _getTrackCacheFilePath(SourcedTrack track) async {
|
|
||||||
return join(
|
|
||||||
await UserPreferencesNotifier.getMusicCacheDir(),
|
|
||||||
ServiceUtils.sanitizeFilename(
|
|
||||||
'${track.query.title} - ${track.query.artists.join(",")} (${track.info.id}).${track.codec.name}',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<SourcedTrack?> _getSourcedTrack(
|
|
||||||
Request request, String trackId) async {
|
|
||||||
final track =
|
|
||||||
playlist.tracks.firstWhere((element) => element.id == trackId);
|
|
||||||
|
|
||||||
final activeSourcedTrack =
|
|
||||||
await ref.read(activeTrackSourcesProvider.future);
|
|
||||||
final sourcedTrack = activeSourcedTrack?.track.id == track.id
|
|
||||||
? activeSourcedTrack?.source
|
|
||||||
: await ref.read(
|
|
||||||
trackSourcesProvider(
|
|
||||||
//! Use [Request.requestedUri] as it contains full https url.
|
|
||||||
//! [Request.url] will exclude and starts relatively. (streams/<trackId>... basically)
|
|
||||||
TrackSourceQuery.parseUri(request.requestedUri.toString()),
|
|
||||||
).future,
|
|
||||||
);
|
|
||||||
|
|
||||||
return sourcedTrack;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<dio_lib.Response> streamTrackInformation(
|
|
||||||
Request request,
|
|
||||||
SourcedTrack track,
|
|
||||||
) async {
|
|
||||||
AppLogger.log.i(
|
|
||||||
"HEAD request for track: ${track.query.title}\n"
|
|
||||||
"Headers: ${request.headers}",
|
|
||||||
);
|
|
||||||
|
|
||||||
final trackCacheFile = File(await _getTrackCacheFilePath(track));
|
|
||||||
|
|
||||||
if (await trackCacheFile.exists() && userPreferences.cacheMusic) {
|
|
||||||
final fileLength = await trackCacheFile.length();
|
|
||||||
|
|
||||||
return dio_lib.Response(
|
|
||||||
statusCode: 200,
|
|
||||||
headers: Headers.fromMap({
|
|
||||||
"content-type": ["audio/${track.codec.name}"],
|
|
||||||
"content-length": ["$fileLength"],
|
|
||||||
"accept-ranges": ["bytes"],
|
|
||||||
"content-range": ["bytes 0-$fileLength/$fileLength"],
|
|
||||||
}),
|
|
||||||
requestOptions: RequestOptions(path: request.requestedUri.toString()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String url = track.url ??
|
|
||||||
await ref
|
|
||||||
.read(trackSourcesProvider(track.query).notifier)
|
|
||||||
.swapWithNextSibling()
|
|
||||||
.then((track) => track.url!);
|
|
||||||
|
|
||||||
final options = Options(
|
|
||||||
headers: {
|
|
||||||
"user-agent": _randomUserAgent,
|
|
||||||
"Cache-Control": "max-age=3600",
|
|
||||||
"Connection": "keep-alive",
|
|
||||||
"host": Uri.parse(url).host,
|
|
||||||
},
|
|
||||||
validateStatus: (status) => status! < 400,
|
|
||||||
);
|
|
||||||
|
|
||||||
final res = await dio.head(url, options: options);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<({dio_lib.Response<Uint8List> response, Uint8List? bytes})>
|
Future<({dio_lib.Response<Uint8List> response, Uint8List? bytes})>
|
||||||
streamTrack(
|
streamTrack(
|
||||||
Request request,
|
Request request,
|
||||||
SourcedTrack track,
|
SourcedTrack track,
|
||||||
Map<String, dynamic> headers,
|
Map<String, dynamic> headers,
|
||||||
) async {
|
) async {
|
||||||
AppLogger.log.i(
|
final trackCacheFile = File(
|
||||||
"GET request for track: ${track.query.title}\n"
|
join(
|
||||||
"Headers: ${request.headers}",
|
await UserPreferencesNotifier.getMusicCacheDir(),
|
||||||
|
ServiceUtils.sanitizeFilename(
|
||||||
|
'${track.query.title} - ${track.query.artists.join(",")} (${track.info.id}).${track.codec.name}',
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final trackCacheFile = File(await _getTrackCacheFilePath(track));
|
|
||||||
|
|
||||||
if (await trackCacheFile.exists() && userPreferences.cacheMusic) {
|
if (await trackCacheFile.exists() && userPreferences.cacheMusic) {
|
||||||
final bytes = await trackCacheFile.readAsBytes();
|
final bytes = await trackCacheFile.readAsBytes();
|
||||||
final cachedFileLength = bytes.length;
|
final cachedFileLength = bytes.length;
|
||||||
@ -175,7 +101,10 @@ class ServerPlaybackRoutes {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final contentLengthRes = await Future<dio_lib.Response?>.value(
|
final contentLengthRes = await Future<dio_lib.Response?>.value(
|
||||||
dio.head(url, options: options),
|
dio.head(
|
||||||
|
url,
|
||||||
|
options: options,
|
||||||
|
),
|
||||||
).catchError((e, stack) async {
|
).catchError((e, stack) async {
|
||||||
AppLogger.reportError(e, stack);
|
AppLogger.reportError(e, stack);
|
||||||
|
|
||||||
@ -206,33 +135,25 @@ class ServerPlaybackRoutes {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers["range"] == "bytes=0-" && track.codec == SourceCodecs.flac) {
|
final contentLength = contentLengthRes?.headers.value("content-length");
|
||||||
final bufferSize =
|
|
||||||
userPreferences.audioQuality == SourceQualities.uncompressed
|
|
||||||
? 6 * 1024 * 1024 // 6MB for lossless
|
|
||||||
: 4 * 1024 * 1024; // 4MB for lossy
|
|
||||||
|
|
||||||
final endRange = min(
|
|
||||||
bufferSize,
|
|
||||||
int.parse(contentLengthRes?.headers.value("content-length") ?? "0"),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
/// Forcing partial content range as mpv sometimes greedily wants
|
||||||
|
/// everything at one go. Slows down overall streaming.
|
||||||
|
final range = RangeHeader.parse(headers["range"] ?? "");
|
||||||
|
final contentPartialLength = int.tryParse(contentLength ?? "");
|
||||||
|
if ((range.end == null) &&
|
||||||
|
contentPartialLength != null &&
|
||||||
|
range.start == 0) {
|
||||||
options = options.copyWith(
|
options = options.copyWith(
|
||||||
headers: {
|
headers: {
|
||||||
...?options.headers,
|
...?options.headers,
|
||||||
"range": "bytes=0-$endRange",
|
"range": "$range${(contentPartialLength * 0.3).ceil()}",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final res = await dio.get<Uint8List>(url, options: options);
|
final res = await dio.get<Uint8List>(url, options: options);
|
||||||
|
|
||||||
AppLogger.log.i(
|
|
||||||
"Response for track: ${track.query.title}\n"
|
|
||||||
"Status Code: ${res.statusCode}\n"
|
|
||||||
"Headers: ${res.headers.map}",
|
|
||||||
);
|
|
||||||
|
|
||||||
final bytes = res.data;
|
final bytes = res.data;
|
||||||
|
|
||||||
if (bytes == null || !userPreferences.cacheMusic) {
|
if (bytes == null || !userPreferences.cacheMusic) {
|
||||||
@ -292,42 +213,27 @@ class ServerPlaybackRoutes {
|
|||||||
return (bytes: bytes, response: res);
|
return (bytes: bytes, response: res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @head('/stream/<trackId>')
|
|
||||||
Future<Response> headStreamTrackId(Request request, String trackId) async {
|
|
||||||
try {
|
|
||||||
final sourcedTrack = await _getSourcedTrack(request, trackId);
|
|
||||||
|
|
||||||
if (sourcedTrack == null) {
|
|
||||||
return Response.notFound("Track not found in the current queue");
|
|
||||||
}
|
|
||||||
|
|
||||||
final res = await streamTrackInformation(
|
|
||||||
request,
|
|
||||||
sourcedTrack,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Response(
|
|
||||||
res.statusCode!,
|
|
||||||
headers: res.headers.map,
|
|
||||||
);
|
|
||||||
} catch (e, stack) {
|
|
||||||
AppLogger.reportError(e, stack);
|
|
||||||
return Response.internalServerError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @get('/stream/<trackId>')
|
/// @get('/stream/<trackId>')
|
||||||
Future<Response> getStreamTrackId(Request request, String trackId) async {
|
Future<Response> getStreamTrackId(Request request, String trackId) async {
|
||||||
try {
|
try {
|
||||||
final sourcedTrack = await _getSourcedTrack(request, trackId);
|
final track =
|
||||||
|
playlist.tracks.firstWhere((element) => element.id == trackId);
|
||||||
|
|
||||||
if (sourcedTrack == null) {
|
final activeSourcedTrack =
|
||||||
return Response.notFound("Track not found in the current queue");
|
await ref.read(activeTrackSourcesProvider.future);
|
||||||
}
|
final sourcedTrack = activeSourcedTrack?.track.id == track.id
|
||||||
|
? activeSourcedTrack?.source
|
||||||
|
: await ref.read(
|
||||||
|
trackSourcesProvider(
|
||||||
|
//! Use [Request.requestedUri] as it contains full https url.
|
||||||
|
//! [Request.url] will exclude and starts relatively. (streams/<trackId>... basically)
|
||||||
|
TrackSourceQuery.parseUri(request.requestedUri.toString()),
|
||||||
|
).future,
|
||||||
|
);
|
||||||
|
|
||||||
final (bytes: audioBytes, response: res) = await streamTrack(
|
final (bytes: audioBytes, response: res) = await streamTrack(
|
||||||
request,
|
request,
|
||||||
sourcedTrack,
|
sourcedTrack!,
|
||||||
request.headers,
|
request.headers,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await audioPlayer.setAudioNormalization(state.normalizeAudio);
|
await audioPlayer.setAudioNormalization(state.normalizeAudio);
|
||||||
await _updatePlayerBufferSize(event.audioQuality, state.audioQuality);
|
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
AppLogger.reportError(e, stack);
|
AppLogger.reportError(e, stack);
|
||||||
}
|
}
|
||||||
@ -80,24 +79,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets audio player's buffer size based on the selected audio quality
|
|
||||||
/// Uncompressed quality gets a larger buffer size for smoother playback
|
|
||||||
/// while other qualities use a standard buffer size.
|
|
||||||
Future<void> _updatePlayerBufferSize(
|
|
||||||
SourceQualities newQuality,
|
|
||||||
SourceQualities oldQuality,
|
|
||||||
) async {
|
|
||||||
if (newQuality == SourceQualities.uncompressed) {
|
|
||||||
audioPlayer.setDemuxerBufferSize(6 * 1024 * 1024); // 6MB
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldQuality == SourceQualities.uncompressed &&
|
|
||||||
newQuality != SourceQualities.uncompressed) {
|
|
||||||
audioPlayer.setDemuxerBufferSize(4 * 1024 * 1024); // 4MB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setData(PreferencesTableCompanion data) async {
|
Future<void> setData(PreferencesTableCompanion data) async {
|
||||||
final db = ref.read(databaseProvider);
|
final db = ref.read(databaseProvider);
|
||||||
|
|
||||||
@ -174,7 +155,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
|
|||||||
|
|
||||||
void setAudioQuality(SourceQualities quality) {
|
void setAudioQuality(SourceQualities quality) {
|
||||||
setData(PreferencesTableCompanion(audioQuality: Value(quality)));
|
setData(PreferencesTableCompanion(audioQuality: Value(quality)));
|
||||||
_updatePlayerBufferSize(quality, state.audioQuality);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDownloadLocation(String downloadDir) {
|
void setDownloadLocation(String downloadDir) {
|
||||||
@ -224,23 +204,6 @@ class UserPreferencesNotifier extends Notifier<PreferencesTableData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setAudioSource(AudioSource type) {
|
void setAudioSource(AudioSource type) {
|
||||||
switch ((type, state.audioQuality)) {
|
|
||||||
// DAB music only supports high quality/uncompressed streams
|
|
||||||
case (
|
|
||||||
AudioSource.dabMusic,
|
|
||||||
SourceQualities.low || SourceQualities.medium
|
|
||||||
):
|
|
||||||
setAudioQuality(SourceQualities.high);
|
|
||||||
break;
|
|
||||||
// If the user switches from DAB music to other sources and has
|
|
||||||
// uncompressed quality selected, downgrade to high quality
|
|
||||||
case (!= AudioSource.dabMusic, SourceQualities.uncompressed):
|
|
||||||
setAudioQuality(SourceQualities.high);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(PreferencesTableCompanion(audioSource: Value(type)));
|
setData(PreferencesTableCompanion(audioSource: Value(type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,6 @@ abstract class AudioPlayerInterface {
|
|||||||
configuration: const mk.PlayerConfiguration(
|
configuration: const mk.PlayerConfiguration(
|
||||||
title: "Spotube",
|
title: "Spotube",
|
||||||
logLevel: kDebugMode ? mk.MPVLogLevel.info : mk.MPVLogLevel.error,
|
logLevel: kDebugMode ? mk.MPVLogLevel.info : mk.MPVLogLevel.error,
|
||||||
bufferSize: 4 * 1024 * 1024, // 4MB buffer
|
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
_mkPlayer.stream.error.listen((event) {
|
_mkPlayer.stream.error.listen((event) {
|
||||||
|
|||||||
@ -131,8 +131,4 @@ class SpotubeAudioPlayer extends AudioPlayerInterface
|
|||||||
Future<void> setAudioNormalization(bool normalize) async {
|
Future<void> setAudioNormalization(bool normalize) async {
|
||||||
await _mkPlayer.setAudioNormalization(normalize);
|
await _mkPlayer.setAudioNormalization(normalize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setDemuxerBufferSize(int sizeInBytes) async {
|
|
||||||
await _mkPlayer.setDemuxerBufferSize(sizeInBytes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -133,12 +133,4 @@ class CustomPlayer extends Player {
|
|||||||
await nativePlayer.setProperty('af', '');
|
await nativePlayer.setProperty('af', '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setDemuxerBufferSize(int sizeInBytes) async {
|
|
||||||
await nativePlayer.setProperty('demuxer-max-bytes', sizeInBytes.toString());
|
|
||||||
await nativePlayer.setProperty(
|
|
||||||
'demuxer-max-back-bytes',
|
|
||||||
sizeInBytes.toString(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,12 +30,8 @@ mixin _$SongLink {
|
|||||||
String? get nativeAppUriMobile => throw _privateConstructorUsedError;
|
String? get nativeAppUriMobile => throw _privateConstructorUsedError;
|
||||||
String? get nativeAppUriDesktop => throw _privateConstructorUsedError;
|
String? get nativeAppUriDesktop => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this SongLink to a JSON map.
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(ignore: true)
|
||||||
/// Create a copy of SongLink
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$SongLinkCopyWith<SongLink> get copyWith =>
|
$SongLinkCopyWith<SongLink> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
@ -67,8 +63,6 @@ class _$SongLinkCopyWithImpl<$Res, $Val extends SongLink>
|
|||||||
// ignore: unused_field
|
// ignore: unused_field
|
||||||
final $Res Function($Val) _then;
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
/// Create a copy of SongLink
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -151,8 +145,6 @@ class __$$SongLinkImplCopyWithImpl<$Res>
|
|||||||
_$SongLinkImpl _value, $Res Function(_$SongLinkImpl) _then)
|
_$SongLinkImpl _value, $Res Function(_$SongLinkImpl) _then)
|
||||||
: super(_value, _then);
|
: super(_value, _then);
|
||||||
|
|
||||||
/// Create a copy of SongLink
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
@override
|
@override
|
||||||
$Res call({
|
$Res call({
|
||||||
@ -269,14 +261,12 @@ class _$SongLinkImpl implements _SongLink {
|
|||||||
other.nativeAppUriDesktop == nativeAppUriDesktop));
|
other.nativeAppUriDesktop == nativeAppUriDesktop));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType, displayName, linkId, platform,
|
int get hashCode => Object.hash(runtimeType, displayName, linkId, platform,
|
||||||
show, uniqueId, country, url, nativeAppUriMobile, nativeAppUriDesktop);
|
show, uniqueId, country, url, nativeAppUriMobile, nativeAppUriDesktop);
|
||||||
|
|
||||||
/// Create a copy of SongLink
|
@JsonKey(ignore: true)
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$$SongLinkImplCopyWith<_$SongLinkImpl> get copyWith =>
|
_$$SongLinkImplCopyWith<_$SongLinkImpl> get copyWith =>
|
||||||
@ -323,11 +313,8 @@ abstract class _SongLink implements SongLink {
|
|||||||
String? get nativeAppUriMobile;
|
String? get nativeAppUriMobile;
|
||||||
@override
|
@override
|
||||||
String? get nativeAppUriDesktop;
|
String? get nativeAppUriDesktop;
|
||||||
|
|
||||||
/// Create a copy of SongLink
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
@override
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(ignore: true)
|
||||||
_$$SongLinkImplCopyWith<_$SongLinkImpl> get copyWith =>
|
_$$SongLinkImplCopyWith<_$SongLinkImpl> get copyWith =>
|
||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,16 +2,13 @@ import 'package:spotube/models/playback/track_sources.dart';
|
|||||||
|
|
||||||
enum SourceCodecs {
|
enum SourceCodecs {
|
||||||
m4a._("M4a (Best for downloaded music)"),
|
m4a._("M4a (Best for downloaded music)"),
|
||||||
weba._("WebA (Best for streamed music)\nDoesn't support audio metadata"),
|
weba._("WebA (Best for streamed music)\nDoesn't support audio metadata");
|
||||||
mp3._("MP3 (Widely supported audio format)"),
|
|
||||||
flac._("FLAC (Lossless, best quality)\nLarge file size");
|
|
||||||
|
|
||||||
final String label;
|
final String label;
|
||||||
const SourceCodecs._(this.label);
|
const SourceCodecs._(this.label);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SourceQualities {
|
enum SourceQualities {
|
||||||
uncompressed(3),
|
|
||||||
high(2),
|
high(2),
|
||||||
medium(1),
|
medium(1),
|
||||||
low(0);
|
low(0);
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import 'package:spotube/models/playback/track_sources.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/sourced_track/enums.dart';
|
import 'package:spotube/services/sourced_track/enums.dart';
|
||||||
import 'package:spotube/services/sourced_track/sources/dab_music.dart';
|
|
||||||
import 'package:spotube/services/sourced_track/sources/invidious.dart';
|
import 'package:spotube/services/sourced_track/sources/invidious.dart';
|
||||||
import 'package:spotube/services/sourced_track/sources/jiosaavn.dart';
|
import 'package:spotube/services/sourced_track/sources/jiosaavn.dart';
|
||||||
import 'package:spotube/services/sourced_track/sources/piped.dart';
|
import 'package:spotube/services/sourced_track/sources/piped.dart';
|
||||||
@ -75,14 +74,6 @@ abstract class SourcedTrack extends BasicSourcedTrack {
|
|||||||
query: query,
|
query: query,
|
||||||
sources: sources,
|
sources: sources,
|
||||||
),
|
),
|
||||||
AudioSource.dabMusic => DABMusicSourcedTrack(
|
|
||||||
ref: ref,
|
|
||||||
source: source,
|
|
||||||
siblings: siblings,
|
|
||||||
info: info,
|
|
||||||
query: query,
|
|
||||||
sources: sources,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +104,6 @@ abstract class SourcedTrack extends BasicSourcedTrack {
|
|||||||
await InvidiousSourcedTrack.fetchFromTrack(query: query, ref: ref),
|
await InvidiousSourcedTrack.fetchFromTrack(query: query, ref: ref),
|
||||||
AudioSource.jiosaavn =>
|
AudioSource.jiosaavn =>
|
||||||
await JioSaavnSourcedTrack.fetchFromTrack(query: query, ref: ref),
|
await JioSaavnSourcedTrack.fetchFromTrack(query: query, ref: ref),
|
||||||
AudioSource.dabMusic =>
|
|
||||||
await DABMusicSourcedTrack.fetchFromTrack(query: query, ref: ref),
|
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (preferences.audioSource == AudioSource.youtube) {
|
if (preferences.audioSource == AudioSource.youtube) {
|
||||||
@ -140,8 +129,6 @@ abstract class SourcedTrack extends BasicSourcedTrack {
|
|||||||
JioSaavnSourcedTrack.fetchSiblings(query: query, ref: ref),
|
JioSaavnSourcedTrack.fetchSiblings(query: query, ref: ref),
|
||||||
AudioSource.invidious =>
|
AudioSource.invidious =>
|
||||||
InvidiousSourcedTrack.fetchSiblings(query: query, ref: ref),
|
InvidiousSourcedTrack.fetchSiblings(query: query, ref: ref),
|
||||||
AudioSource.dabMusic =>
|
|
||||||
DABMusicSourcedTrack.fetchSiblings(query: query, ref: ref),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +157,7 @@ abstract class SourcedTrack extends BasicSourcedTrack {
|
|||||||
///
|
///
|
||||||
/// If no sources match the codec, it will return the first or last source
|
/// If no sources match the codec, it will return the first or last source
|
||||||
/// based on the user's audio quality preference.
|
/// based on the user's audio quality preference.
|
||||||
TrackSource? getSourceOfCodec(SourceCodecs codec) {
|
String? getUrlOfCodec(SourceCodecs codec) {
|
||||||
final preferences = ref.read(userPreferencesProvider);
|
final preferences = ref.read(userPreferencesProvider);
|
||||||
|
|
||||||
final exactMatch = sources.firstWhereOrNull(
|
final exactMatch = sources.firstWhereOrNull(
|
||||||
@ -179,7 +166,7 @@ abstract class SourcedTrack extends BasicSourcedTrack {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (exactMatch != null) {
|
if (exactMatch != null) {
|
||||||
return exactMatch;
|
return exactMatch.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
final sameCodecSources = sources
|
final sameCodecSources = sources
|
||||||
@ -193,8 +180,8 @@ abstract class SourcedTrack extends BasicSourcedTrack {
|
|||||||
|
|
||||||
if (sameCodecSources.isNotEmpty) {
|
if (sameCodecSources.isNotEmpty) {
|
||||||
return preferences.audioQuality > SourceQualities.low
|
return preferences.audioQuality > SourceQualities.low
|
||||||
? sameCodecSources.first
|
? sameCodecSources.first.url
|
||||||
: sameCodecSources.last;
|
: sameCodecSources.last.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
final fallbackSource = sources.sorted((a, b) {
|
final fallbackSource = sources.sorted((a, b) {
|
||||||
@ -204,24 +191,23 @@ abstract class SourcedTrack extends BasicSourcedTrack {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return preferences.audioQuality > SourceQualities.low
|
return preferences.audioQuality > SourceQualities.low
|
||||||
? fallbackSource.firstOrNull
|
? fallbackSource.firstOrNull?.url
|
||||||
: fallbackSource.lastOrNull;
|
: fallbackSource.lastOrNull?.url;
|
||||||
}
|
|
||||||
|
|
||||||
String? getUrlOfCodec(SourceCodecs codec) {
|
|
||||||
return getSourceOfCodec(codec)?.url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceCodecs get codec {
|
SourceCodecs get codec {
|
||||||
final preferences = ref.read(userPreferencesProvider);
|
final preferences = ref.read(userPreferencesProvider);
|
||||||
|
|
||||||
return switch (preferences.audioSource) {
|
return preferences.audioSource == AudioSource.jiosaavn
|
||||||
AudioSource.dabMusic =>
|
? SourceCodecs.m4a
|
||||||
preferences.audioQuality == SourceQualities.uncompressed
|
: preferences.streamMusicCodec;
|
||||||
? SourceCodecs.flac
|
}
|
||||||
: SourceCodecs.mp3,
|
|
||||||
AudioSource.jiosaavn => SourceCodecs.m4a,
|
TrackSource get activeTrackSource {
|
||||||
_ => preferences.streamMusicCodec
|
final audioQuality = ref.read(userPreferencesProvider).audioQuality;
|
||||||
};
|
return sources.firstWhereOrNull(
|
||||||
|
(source) => source.codec == codec && source.quality == audioQuality,
|
||||||
|
) ??
|
||||||
|
sources.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,225 +0,0 @@
|
|||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
import 'package:spotube/models/database/database.dart';
|
|
||||||
import 'package:spotube/models/playback/track_sources.dart';
|
|
||||||
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
|
|
||||||
import 'package:spotube/services/logger/logger.dart';
|
|
||||||
import 'package:spotube/services/sourced_track/enums.dart';
|
|
||||||
import 'package:spotube/services/sourced_track/exceptions.dart';
|
|
||||||
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
|
||||||
import 'package:dab_music_api/dab_music_api.dart';
|
|
||||||
|
|
||||||
final dabMusicApiClient = DabMusicApiClient(
|
|
||||||
Dio(),
|
|
||||||
baseUrl: "https://dab.yeet.su/api",
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Only Music source that can't support database caching due to having no endpoint.
|
|
||||||
/// But ISRC search is 100% reliable so caching is actually not necessary.
|
|
||||||
class DABMusicSourcedTrack extends SourcedTrack {
|
|
||||||
DABMusicSourcedTrack({
|
|
||||||
required super.ref,
|
|
||||||
required super.source,
|
|
||||||
required super.siblings,
|
|
||||||
required super.info,
|
|
||||||
required super.query,
|
|
||||||
required super.sources,
|
|
||||||
});
|
|
||||||
|
|
||||||
static Future<SourcedTrack> fetchFromTrack({
|
|
||||||
required TrackSourceQuery query,
|
|
||||||
required Ref ref,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
final siblings = await fetchSiblings(ref: ref, query: query);
|
|
||||||
|
|
||||||
if (siblings.isEmpty) {
|
|
||||||
throw TrackNotFoundError(query);
|
|
||||||
}
|
|
||||||
return DABMusicSourcedTrack(
|
|
||||||
ref: ref,
|
|
||||||
siblings: siblings.map((s) => s.info).skip(1).toList(),
|
|
||||||
sources: siblings.first.source!,
|
|
||||||
info: siblings.first.info,
|
|
||||||
query: query,
|
|
||||||
source: AudioSource.dabMusic,
|
|
||||||
);
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
AppLogger.reportError(e, stackTrace);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<List<TrackSource>> fetchSources(
|
|
||||||
String id,
|
|
||||||
SourceQualities quality,
|
|
||||||
AudioQuality trackMaximumQuality,
|
|
||||||
) async {
|
|
||||||
try {
|
|
||||||
final isUncompressed = quality == SourceQualities.uncompressed;
|
|
||||||
final streamResponse = await dabMusicApiClient.music.getStream(
|
|
||||||
trackId: id,
|
|
||||||
quality: isUncompressed ? "27" : "5",
|
|
||||||
);
|
|
||||||
if (streamResponse.url == null) {
|
|
||||||
throw Exception("No stream URL found for track ID: $id");
|
|
||||||
}
|
|
||||||
|
|
||||||
// kbps = (bitDepth * sampleRate * channels) / 1000
|
|
||||||
final uncompressedBitrate = !isUncompressed
|
|
||||||
? 0
|
|
||||||
: ((trackMaximumQuality.maximumBitDepth ?? 0) *
|
|
||||||
((trackMaximumQuality.maximumSamplingRate ?? 0) * 1000) *
|
|
||||||
2) /
|
|
||||||
1000;
|
|
||||||
return [
|
|
||||||
TrackSource(
|
|
||||||
url: streamResponse.url!,
|
|
||||||
quality: isUncompressed
|
|
||||||
? SourceQualities.uncompressed
|
|
||||||
: SourceQualities.high,
|
|
||||||
bitrate:
|
|
||||||
isUncompressed ? "${uncompressedBitrate.floor()}kbps" : "320kbps",
|
|
||||||
codec: isUncompressed ? SourceCodecs.flac : SourceCodecs.mp3,
|
|
||||||
qualityLabel: isUncompressed
|
|
||||||
? "${trackMaximumQuality.maximumBitDepth}bit • ${trackMaximumQuality.maximumSamplingRate}kHz • FLAC • Stereo"
|
|
||||||
: "MP3 • 320kbps • mp3 • Stereo",
|
|
||||||
),
|
|
||||||
];
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
AppLogger.reportError(e, stackTrace);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<SiblingType> toSiblingType(
|
|
||||||
Ref ref,
|
|
||||||
int index,
|
|
||||||
Track result,
|
|
||||||
) async {
|
|
||||||
try {
|
|
||||||
List<TrackSource>? source;
|
|
||||||
if (index == 0) {
|
|
||||||
source = await fetchSources(
|
|
||||||
result.id.toString(),
|
|
||||||
ref.read(userPreferencesProvider).audioQuality,
|
|
||||||
result.audioQuality!,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final SiblingType sibling = (
|
|
||||||
info: TrackSourceInfo(
|
|
||||||
artists: result.artist!,
|
|
||||||
durationMs: Duration(seconds: result.duration!).inMilliseconds,
|
|
||||||
id: result.id.toString(),
|
|
||||||
pageUrl: "https://dab.yeet.su/music/${result.id}",
|
|
||||||
thumbnail: result.albumCover!,
|
|
||||||
title: result.title!,
|
|
||||||
),
|
|
||||||
source: source,
|
|
||||||
);
|
|
||||||
|
|
||||||
return sibling;
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
AppLogger.reportError(e, stackTrace);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<List<SiblingType>> fetchSiblings({
|
|
||||||
required TrackSourceQuery query,
|
|
||||||
required Ref ref,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
List<Track> results = [];
|
|
||||||
|
|
||||||
if (query.isrc.isNotEmpty) {
|
|
||||||
final res =
|
|
||||||
await dabMusicApiClient.music.getSearch(q: query.isrc, limit: 1);
|
|
||||||
results = res.tracks ?? <Track>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (results.isEmpty) {
|
|
||||||
final res = await dabMusicApiClient.music.getSearch(
|
|
||||||
q: SourcedTrack.getSearchTerm(query),
|
|
||||||
limit: 5,
|
|
||||||
);
|
|
||||||
results = res.tracks ?? <Track>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (results.isEmpty) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
final matchedResults =
|
|
||||||
results.mapIndexed((index, d) => toSiblingType(ref, index, d));
|
|
||||||
|
|
||||||
return Future.wait(matchedResults);
|
|
||||||
} catch (e, stackTrace) {
|
|
||||||
AppLogger.reportError(e, stackTrace);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<DABMusicSourcedTrack> copyWithSibling() async {
|
|
||||||
if (siblings.isNotEmpty) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
final fetchedSiblings = await fetchSiblings(ref: ref, query: query);
|
|
||||||
|
|
||||||
return DABMusicSourcedTrack(
|
|
||||||
ref: ref,
|
|
||||||
siblings: fetchedSiblings
|
|
||||||
.where((s) => s.info.id != info.id)
|
|
||||||
.map((s) => s.info)
|
|
||||||
.toList(),
|
|
||||||
source: source,
|
|
||||||
info: info,
|
|
||||||
query: query,
|
|
||||||
sources: sources,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<DABMusicSourcedTrack?> swapWithSibling(TrackSourceInfo sibling) async {
|
|
||||||
if (sibling.id == this.info.id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a sibling source that was fetched from the search results
|
|
||||||
final isStepSibling = siblings.none((s) => s.id == sibling.id);
|
|
||||||
|
|
||||||
final newSourceInfo = isStepSibling
|
|
||||||
? sibling
|
|
||||||
: siblings.firstWhere((s) => s.id == sibling.id);
|
|
||||||
final newSiblings = siblings.where((s) => s.id != sibling.id).toList()
|
|
||||||
..insert(0, this.info);
|
|
||||||
|
|
||||||
final source = await fetchSources(
|
|
||||||
sibling.id,
|
|
||||||
ref.read(userPreferencesProvider).audioQuality,
|
|
||||||
const AudioQuality(
|
|
||||||
isHiRes: true,
|
|
||||||
maximumBitDepth: 16,
|
|
||||||
maximumSamplingRate: 44.1,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return DABMusicSourcedTrack(
|
|
||||||
ref: ref,
|
|
||||||
siblings: newSiblings,
|
|
||||||
sources: source,
|
|
||||||
info: newSourceInfo,
|
|
||||||
query: query,
|
|
||||||
source: AudioSource.dabMusic,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<SourcedTrack> refreshStream() async {
|
|
||||||
// There's no need to refresh the stream for DABMusicSourcedTrack
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -94,7 +94,6 @@ class InvidiousSourcedTrack extends SourcedTrack {
|
|||||||
|
|
||||||
static List<TrackSource> toSources(InvidiousVideoResponse manifest) {
|
static List<TrackSource> toSources(InvidiousVideoResponse manifest) {
|
||||||
return manifest.adaptiveFormats.map((stream) {
|
return manifest.adaptiveFormats.map((stream) {
|
||||||
var isWebm = stream.type.contains("audio/webm");
|
|
||||||
return TrackSource(
|
return TrackSource(
|
||||||
url: stream.url.toString(),
|
url: stream.url.toString(),
|
||||||
quality: switch (stream.qualityLabel) {
|
quality: switch (stream.qualityLabel) {
|
||||||
@ -102,11 +101,10 @@ class InvidiousSourcedTrack extends SourcedTrack {
|
|||||||
"medium" => SourceQualities.medium,
|
"medium" => SourceQualities.medium,
|
||||||
_ => SourceQualities.low,
|
_ => SourceQualities.low,
|
||||||
},
|
},
|
||||||
codec: isWebm ? SourceCodecs.weba : SourceCodecs.m4a,
|
codec: stream.type.contains("audio/webm")
|
||||||
|
? SourceCodecs.weba
|
||||||
|
: SourceCodecs.m4a,
|
||||||
bitrate: stream.bitrate,
|
bitrate: stream.bitrate,
|
||||||
qualityLabel:
|
|
||||||
"${isWebm ? "Opus" : "AAC"} • ${stream.bitrate.replaceAll("kbps", "")}kbps "
|
|
||||||
"• ${isWebm ? "weba" : "m4a"} • Stereo",
|
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,6 @@ class JioSaavnSourcedTrack extends SourcedTrack {
|
|||||||
: SourceQualities.low,
|
: SourceQualities.low,
|
||||||
codec: SourceCodecs.m4a,
|
codec: SourceCodecs.m4a,
|
||||||
bitrate: link.quality,
|
bitrate: link.quality,
|
||||||
qualityLabel: "AAC • ${link.quality} • MP4 • Stereo",
|
|
||||||
);
|
);
|
||||||
}).toList()
|
}).toList()
|
||||||
);
|
);
|
||||||
|
|||||||
@ -98,7 +98,6 @@ class PipedSourcedTrack extends SourcedTrack {
|
|||||||
|
|
||||||
static List<TrackSource> toSources(PipedStreamResponse manifest) {
|
static List<TrackSource> toSources(PipedStreamResponse manifest) {
|
||||||
return manifest.audioStreams.map((audio) {
|
return manifest.audioStreams.map((audio) {
|
||||||
final isMp4 = audio.format == PipedAudioStreamFormat.m4a;
|
|
||||||
return TrackSource(
|
return TrackSource(
|
||||||
url: audio.url.toString(),
|
url: audio.url.toString(),
|
||||||
quality: switch (audio.quality) {
|
quality: switch (audio.quality) {
|
||||||
@ -106,11 +105,10 @@ class PipedSourcedTrack extends SourcedTrack {
|
|||||||
"medium" => SourceQualities.medium,
|
"medium" => SourceQualities.medium,
|
||||||
_ => SourceQualities.low,
|
_ => SourceQualities.low,
|
||||||
},
|
},
|
||||||
codec: isMp4 ? SourceCodecs.m4a : SourceCodecs.weba,
|
codec: audio.format == PipedAudioStreamFormat.m4a
|
||||||
|
? SourceCodecs.m4a
|
||||||
|
: SourceCodecs.weba,
|
||||||
bitrate: audio.bitrate.toString(),
|
bitrate: audio.bitrate.toString(),
|
||||||
qualityLabel:
|
|
||||||
"${isMp4 ? "AAC" : "Opus"} • ${(audio.bitrate / 1000).floor()}kbps "
|
|
||||||
"• ${isMp4 ? "m4a" : "weba"} • Stereo",
|
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,7 +98,6 @@ class YoutubeSourcedTrack extends SourcedTrack {
|
|||||||
|
|
||||||
static List<TrackSource> toTrackSources(StreamManifest manifest) {
|
static List<TrackSource> toTrackSources(StreamManifest manifest) {
|
||||||
return manifest.audioOnly.map((streamInfo) {
|
return manifest.audioOnly.map((streamInfo) {
|
||||||
var isWebm = streamInfo.codec.mimeType == "audio/webm";
|
|
||||||
return TrackSource(
|
return TrackSource(
|
||||||
url: streamInfo.url.toString(),
|
url: streamInfo.url.toString(),
|
||||||
quality: switch (streamInfo.qualityLabel) {
|
quality: switch (streamInfo.qualityLabel) {
|
||||||
@ -107,11 +106,10 @@ class YoutubeSourcedTrack extends SourcedTrack {
|
|||||||
"low" => SourceQualities.low,
|
"low" => SourceQualities.low,
|
||||||
_ => SourceQualities.high,
|
_ => SourceQualities.high,
|
||||||
},
|
},
|
||||||
codec: isWebm ? SourceCodecs.weba : SourceCodecs.m4a,
|
codec: streamInfo.codec.mimeType == "audio/webm"
|
||||||
|
? SourceCodecs.weba
|
||||||
|
: SourceCodecs.m4a,
|
||||||
bitrate: streamInfo.bitrate.bitsPerSecond.toString(),
|
bitrate: streamInfo.bitrate.bitsPerSecond.toString(),
|
||||||
qualityLabel:
|
|
||||||
"${isWebm ? "Opus" : "AAC"} • ${(streamInfo.bitrate.kiloBitsPerSecond).floor()}kbps "
|
|
||||||
"• ${isWebm ? "weba" : "m4a"} • Stereo",
|
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|||||||
19
pubspec.lock
@ -315,7 +315,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
change_case:
|
change_case:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: change_case
|
name: change_case
|
||||||
sha256: f4e08feaa845e75e4f5ad2b0e15f24813d7ea6c27e7b78252f0c17f752cf1157
|
sha256: f4e08feaa845e75e4f5ad2b0e15f24813d7ea6c27e7b78252f0c17f752cf1157
|
||||||
@ -458,15 +458,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
dab_music_api:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
path: "."
|
|
||||||
ref: main
|
|
||||||
resolved-ref: "55f96368b7465eec2e5e81774f9f2a7b18acc4ab"
|
|
||||||
url: "https://github.com/KRTirtho/dab_music_api.git"
|
|
||||||
source: git
|
|
||||||
version: "0.1.0"
|
|
||||||
dart_des:
|
dart_des:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -2055,14 +2046,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.0"
|
version: "4.1.0"
|
||||||
retrofit:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: retrofit
|
|
||||||
sha256: "699cf44ec6c7fc7d248740932eca75d334e36bdafe0a8b3e9ff93100591c8a25"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.7.2"
|
|
||||||
riverpod:
|
riverpod:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -24,10 +24,6 @@ dependencies:
|
|||||||
bonsoir: ^5.1.10
|
bonsoir: ^5.1.10
|
||||||
cached_network_image: ^3.3.1
|
cached_network_image: ^3.3.1
|
||||||
connectivity_plus: ^6.1.2
|
connectivity_plus: ^6.1.2
|
||||||
dab_music_api:
|
|
||||||
git:
|
|
||||||
url: https://github.com/KRTirtho/dab_music_api.git
|
|
||||||
ref: main
|
|
||||||
desktop_webview_window:
|
desktop_webview_window:
|
||||||
git:
|
git:
|
||||||
path: packages/desktop_webview_window
|
path: packages/desktop_webview_window
|
||||||
@ -167,7 +163,6 @@ dependencies:
|
|||||||
get_it: ^8.0.3
|
get_it: ^8.0.3
|
||||||
flutter_markdown_plus: ^1.0.3
|
flutter_markdown_plus: ^1.0.3
|
||||||
pub_semver: ^2.2.0
|
pub_semver: ^2.2.0
|
||||||
change_case: ^1.1.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.13
|
build_runner: ^2.4.13
|
||||||
|
|||||||
@ -1,176 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ar": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"bn": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"ca": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"cs": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"de": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"es": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"eu": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"fa": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"fi": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"fr": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"hi": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"id": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"it": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"ja": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"ka": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"ko": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"ne": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"nl": [
|
"nl": [
|
||||||
"audio_source",
|
"audio_source"
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"pl": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"pt": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"ru": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"ta": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"th": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"tl": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"tr": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"uk": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"vi": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"zh": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
],
|
|
||||||
|
|
||||||
"zh_TW": [
|
|
||||||
"source",
|
|
||||||
"uncompressed",
|
|
||||||
"dab_music_source_description"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
"@types/react": "^19.1.9",
|
"@types/react": "^19.1.9",
|
||||||
"@types/react-dom": "^19.1.7",
|
"@types/react-dom": "^19.1.7",
|
||||||
"astro": "^5.12.8",
|
"astro": "^5.12.8",
|
||||||
"astro-pagefind": "1.8.3",
|
"astro-pagefind": "^1.8.3",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
@ -36,4 +36,4 @@
|
|||||||
"@types/markdown-it": "^14.1.2",
|
"@types/markdown-it": "^14.1.2",
|
||||||
"@types/sanitize-html": "^2.16.0"
|
"@types/sanitize-html": "^2.16.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ importers:
|
|||||||
specifier: ^5.12.8
|
specifier: ^5.12.8
|
||||||
version: 5.12.8(@types/node@24.1.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.46.2)(typescript@5.9.2)
|
version: 5.12.8(@types/node@24.1.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.46.2)(typescript@5.9.2)
|
||||||
astro-pagefind:
|
astro-pagefind:
|
||||||
specifier: 1.8.3
|
specifier: ^1.8.3
|
||||||
version: 1.8.3(astro@5.12.8(@types/node@24.1.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.46.2)(typescript@5.9.2))
|
version: 1.8.3(astro@5.12.8(@types/node@24.1.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.46.2)(typescript@5.9.2))
|
||||||
date-fns:
|
date-fns:
|
||||||
specifier: ^4.1.0
|
specifier: ^4.1.0
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 691 B After Width: | Height: | Size: 390 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 777 B |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 89 KiB |
349
website/public/images/spotube-logo.svg
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 762 762"
|
||||||
|
version="1.1"
|
||||||
|
id="svg270"
|
||||||
|
sodipodi:docname="spotube-logo.svg"
|
||||||
|
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:export-filename="spotube-logo.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
width="762"
|
||||||
|
height="762"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:bx="https://boxy-svg.com"><sodipodi:namedview
|
||||||
|
id="namedview272"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="0.76199998"
|
||||||
|
inkscape:cx="194.22573"
|
||||||
|
inkscape:cy="314.96064"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg270"
|
||||||
|
inkscape:lockguides="false"><inkscape:page
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="762"
|
||||||
|
height="762"
|
||||||
|
id="page3136" /><inkscape:page
|
||||||
|
x="640.44641"
|
||||||
|
y="132.29141"
|
||||||
|
width="89.999939"
|
||||||
|
height="89.999985"
|
||||||
|
id="page3138" /></sodipodi:namedview><defs
|
||||||
|
id="defs220"><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient5535"><stop
|
||||||
|
style="stop-color:#00063b;stop-opacity:1;"
|
||||||
|
offset="0.25885531"
|
||||||
|
id="stop5531" /><stop
|
||||||
|
style="stop-color:#004256;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop5533" /></linearGradient><linearGradient
|
||||||
|
id="linearGradient2809"><stop
|
||||||
|
offset="0.113"
|
||||||
|
style="stop-color:#5668ea;stop-opacity:1;"
|
||||||
|
id="stop2803" /><stop
|
||||||
|
offset="0.60799998"
|
||||||
|
style="stop-color:#0093b1;stop-opacity:1;"
|
||||||
|
id="stop2805" /><stop
|
||||||
|
offset="0.94400001"
|
||||||
|
style="stop-color:#00a29f;stop-opacity:1;"
|
||||||
|
id="stop2807" /></linearGradient><linearGradient
|
||||||
|
id="linearGradient938"><stop
|
||||||
|
offset="0.113"
|
||||||
|
style="stop-color:#5869eb;stop-opacity:1;"
|
||||||
|
id="stop932" /><stop
|
||||||
|
offset="0.60799998"
|
||||||
|
style="stop-color:#0093b1;stop-opacity:1;"
|
||||||
|
id="stop934" /><stop
|
||||||
|
offset="0.94400001"
|
||||||
|
style="stop-color:#02a7a4;stop-opacity:1;"
|
||||||
|
id="stop936" /></linearGradient><radialGradient
|
||||||
|
id="gradient-2-0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
cx="251.179"
|
||||||
|
cy="248.821"
|
||||||
|
r="241.45"
|
||||||
|
gradientTransform="translate(-1.768285,0.589104)"
|
||||||
|
xlink:href="#gradient-2" /><linearGradient
|
||||||
|
id="gradient-2"><stop
|
||||||
|
offset="0.841"
|
||||||
|
style="stop-color: rgb(255, 255, 255);"
|
||||||
|
id="stop169" /><stop
|
||||||
|
offset="1"
|
||||||
|
style="stop-color: rgb(201, 201, 201);"
|
||||||
|
id="stop171" /></linearGradient><filter
|
||||||
|
id="drop-shadow-filter-0"
|
||||||
|
x="-0.050892502"
|
||||||
|
y="-0.050892502"
|
||||||
|
width="1.1017849"
|
||||||
|
height="1.1017849"
|
||||||
|
bx:preset="drop-shadow 1 0 0 10 0.42 rgba(201,201,201,1)"><feGaussianBlur
|
||||||
|
in="SourceAlpha"
|
||||||
|
stdDeviation="10"
|
||||||
|
id="feGaussianBlur174" /><feOffset
|
||||||
|
dx="0"
|
||||||
|
dy="0"
|
||||||
|
id="feOffset176" /><feComponentTransfer
|
||||||
|
result="offsetblur"
|
||||||
|
id="feComponentTransfer179"><feFuncA
|
||||||
|
id="spread-ctrl"
|
||||||
|
type="linear"
|
||||||
|
slope="0.84" /></feComponentTransfer><feFlood
|
||||||
|
flood-color="rgba(201,201,201,1)"
|
||||||
|
id="feFlood181" /><feComposite
|
||||||
|
in2="offsetblur"
|
||||||
|
operator="in"
|
||||||
|
id="feComposite183" /><feMerge
|
||||||
|
id="feMerge189"><feMergeNode
|
||||||
|
id="feMergeNode185" /><feMergeNode
|
||||||
|
in="SourceGraphic"
|
||||||
|
id="feMergeNode187" /></feMerge></filter><linearGradient
|
||||||
|
id="gradient-4-3"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="47.146"
|
||||||
|
y1="18.044001"
|
||||||
|
x2="47.146"
|
||||||
|
y2="75.353996"
|
||||||
|
xlink:href="#gradient-4" /><linearGradient
|
||||||
|
id="gradient-4"><stop
|
||||||
|
offset="0.113"
|
||||||
|
style="stop-color: rgb(83, 240, 111);"
|
||||||
|
id="stop193" /><stop
|
||||||
|
offset="0.608"
|
||||||
|
style="stop-color: rgb(0, 177, 86);"
|
||||||
|
id="stop195" /><stop
|
||||||
|
offset="0.944"
|
||||||
|
style="stop-color: rgb(2, 167, 156);"
|
||||||
|
id="stop197" /></linearGradient><filter
|
||||||
|
id="inner-shadow-filter-0"
|
||||||
|
x="-0.064836091"
|
||||||
|
y="-0.071329232"
|
||||||
|
width="1.1296722"
|
||||||
|
height="1.108079"
|
||||||
|
bx:preset="inner-shadow 1 0 0 4 0.5 rgba(0,0,0,0.7)"><feOffset
|
||||||
|
dx="0"
|
||||||
|
dy="0"
|
||||||
|
id="feOffset200" /><feGaussianBlur
|
||||||
|
stdDeviation="4"
|
||||||
|
id="feGaussianBlur202"
|
||||||
|
result="result1" /><feComposite
|
||||||
|
operator="out"
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="result1"
|
||||||
|
id="feComposite204" /><feComponentTransfer
|
||||||
|
result="choke"
|
||||||
|
id="feComponentTransfer208"><feFuncA
|
||||||
|
type="linear"
|
||||||
|
slope="1"
|
||||||
|
id="feFuncA206" /></feComponentTransfer><feFlood
|
||||||
|
flood-color="rgba(0,0,0,0.7)"
|
||||||
|
result="color"
|
||||||
|
id="feFlood210" /><feComposite
|
||||||
|
operator="in"
|
||||||
|
in="color"
|
||||||
|
in2="choke"
|
||||||
|
result="shadow"
|
||||||
|
id="feComposite212" /><feComposite
|
||||||
|
operator="over"
|
||||||
|
in="shadow"
|
||||||
|
in2="SourceGraphic"
|
||||||
|
id="feComposite214" /></filter><linearGradient
|
||||||
|
id="gradient-4-1"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="82.026001"
|
||||||
|
y1="144.832"
|
||||||
|
x2="82.026001"
|
||||||
|
y2="264.46201"
|
||||||
|
xlink:href="#linearGradient2809"
|
||||||
|
gradientTransform="translate(7.2213312)" /><linearGradient
|
||||||
|
id="gradient-4-2"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="143.69299"
|
||||||
|
y1="22.804001"
|
||||||
|
x2="143.69299"
|
||||||
|
y2="264.582"
|
||||||
|
xlink:href="#linearGradient938" /><linearGradient
|
||||||
|
id="gradient-4-0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="205.862"
|
||||||
|
y1="146.28"
|
||||||
|
x2="205.862"
|
||||||
|
y2="265.91"
|
||||||
|
xlink:href="#gradient-4"
|
||||||
|
gradientTransform="translate(-7.2213312)" /><filter
|
||||||
|
style="color-interpolation-filters:sRGB"
|
||||||
|
inkscape:label="Drop Shadow"
|
||||||
|
id="filter2000"
|
||||||
|
x="-0.3425389"
|
||||||
|
y="-0.3425389"
|
||||||
|
width="1.6850778"
|
||||||
|
height="1.6850778"><feFlood
|
||||||
|
flood-opacity="1"
|
||||||
|
flood-color="rgb(0,0,0)"
|
||||||
|
result="flood"
|
||||||
|
id="feFlood1990" /><feComposite
|
||||||
|
in="flood"
|
||||||
|
in2="SourceGraphic"
|
||||||
|
operator="out"
|
||||||
|
result="composite1"
|
||||||
|
id="feComposite1992" /><feGaussianBlur
|
||||||
|
in="composite1"
|
||||||
|
stdDeviation="29.980818"
|
||||||
|
result="blur"
|
||||||
|
id="feGaussianBlur1994" /><feOffset
|
||||||
|
dx="0"
|
||||||
|
dy="0"
|
||||||
|
result="offset"
|
||||||
|
id="feOffset1996" /><feComposite
|
||||||
|
in="offset"
|
||||||
|
in2="SourceGraphic"
|
||||||
|
operator="atop"
|
||||||
|
result="fbSourceGraphic"
|
||||||
|
id="feComposite1998" /><feColorMatrix
|
||||||
|
result="fbSourceGraphicAlpha"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||||
|
id="feColorMatrix2062" /><feFlood
|
||||||
|
id="feFlood2064"
|
||||||
|
flood-opacity="1"
|
||||||
|
flood-color="rgb(0,0,0)"
|
||||||
|
result="flood"
|
||||||
|
in="fbSourceGraphic" /><feComposite
|
||||||
|
in2="fbSourceGraphic"
|
||||||
|
id="feComposite2066"
|
||||||
|
in="flood"
|
||||||
|
operator="out"
|
||||||
|
result="composite1" /><feGaussianBlur
|
||||||
|
id="feGaussianBlur2068"
|
||||||
|
in="composite1"
|
||||||
|
stdDeviation="28.6433"
|
||||||
|
result="blur" /><feOffset
|
||||||
|
id="feOffset2070"
|
||||||
|
dx="0"
|
||||||
|
dy="0"
|
||||||
|
result="offset" /><feComposite
|
||||||
|
in2="fbSourceGraphic"
|
||||||
|
id="feComposite2072"
|
||||||
|
in="offset"
|
||||||
|
operator="atop"
|
||||||
|
result="fbSourceGraphic" /><feColorMatrix
|
||||||
|
result="fbSourceGraphicAlpha"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||||
|
id="feColorMatrix3393" /><feFlood
|
||||||
|
id="feFlood3395"
|
||||||
|
flood-opacity="0.352941"
|
||||||
|
flood-color="rgb(0,0,0)"
|
||||||
|
result="flood"
|
||||||
|
in="fbSourceGraphic" /><feComposite
|
||||||
|
in2="fbSourceGraphic"
|
||||||
|
id="feComposite3397"
|
||||||
|
in="flood"
|
||||||
|
operator="in"
|
||||||
|
result="composite1" /><feGaussianBlur
|
||||||
|
id="feGaussianBlur3399"
|
||||||
|
in="composite1"
|
||||||
|
stdDeviation="6.59891"
|
||||||
|
result="blur" /><feOffset
|
||||||
|
id="feOffset3401"
|
||||||
|
dx="0"
|
||||||
|
dy="0"
|
||||||
|
result="offset" /><feComposite
|
||||||
|
in2="offset"
|
||||||
|
id="feComposite3403"
|
||||||
|
in="fbSourceGraphic"
|
||||||
|
operator="over"
|
||||||
|
result="composite2" /></filter><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient2809"
|
||||||
|
id="linearGradient5506"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="translate(117.34662)"
|
||||||
|
x1="82.026001"
|
||||||
|
y1="144.832"
|
||||||
|
x2="82.026001"
|
||||||
|
y2="264.46201" /><radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient5535"
|
||||||
|
id="radialGradient5537"
|
||||||
|
cx="143.6935"
|
||||||
|
cy="143.69299"
|
||||||
|
fx="143.6935"
|
||||||
|
fy="143.69299"
|
||||||
|
r="152.72653"
|
||||||
|
gradientTransform="matrix(1,0,0,0.8506841,0,21.45565)"
|
||||||
|
gradientUnits="userSpaceOnUse" /></defs><circle
|
||||||
|
style="opacity:1;fill:#242832;fill-opacity:1;stroke:#000000;stroke-width:10;stroke-dasharray:none;stroke-opacity:0.961795;filter:url(#filter2000)"
|
||||||
|
id="path1157"
|
||||||
|
cx="381.48901"
|
||||||
|
cy="381.48901"
|
||||||
|
inkscape:label="path1157"
|
||||||
|
r="235.79112"
|
||||||
|
sodipodi:insensitive="true" /><g
|
||||||
|
transform="matrix(0.319972,0,0,0.323174,379.08153,437.03375)"
|
||||||
|
id="g228"><g
|
||||||
|
style="opacity:1;fill:none;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none"
|
||||||
|
transform="matrix(3.89,0,0,3.89,-175.05,-175.05)"
|
||||||
|
id="g226" /></g><g
|
||||||
|
id="g236"
|
||||||
|
style="fill:none;filter:url(#inner-shadow-filter-0)"
|
||||||
|
transform="matrix(1.107829,0,0,1.106267,221.95533,199.03714)"><path
|
||||||
|
d="m 78.642332,155.437 v 98.42 c 0,5.867 4.741,10.605 10.605,10.605 5.854,0 10.604995,-4.738 10.604995,-10.605 v -98.42 c 0,-5.856 -4.750995,-10.605 -10.604995,-10.605 -5.864,0 -10.605,4.744 -10.605,10.605 z"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:url(#gradient-4-1);stroke-width:9.80924px;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
id="path230" /><path
|
||||||
|
d="m 29.456,264.582 h 23.351 v -116.85 c 0.064,-0.56 0.166,-1.119 0.166,-1.693 0,-50.412 40.69,-91.42 90.698,-91.42 50.002,0 90.692,41.008 90.692,91.42 0,0.771 0.113,1.518 0.228,2.263 v 116.28 h 23.354 c 16.254,0 29.442,-13.64 29.442,-30.469 v -60.936 c 0,-13.878 -8.989,-25.57 -21.261,-29.249 C 264.997,76.957 210.518,22.804 143.676,22.804 76.816,22.804 22.329,76.962 21.211,143.954 8.956,147.638 0,159.32 0,173.187 v 60.926 c 0,16.819 13.187,30.469 29.456,30.469 z"
|
||||||
|
style="fill:url(#radialGradient5537);fill-opacity:1;stroke:url(#gradient-4-2);stroke-width:18.0661;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||||
|
id="path232" /><path
|
||||||
|
d="M 49.735541,279.35822 C 23.7214,267.48486 38.122112,248.62719 80.85964,237.45225 c 14.400662,-3.49216 25.08508,-5.12184 43.66659,-4.88901 11.61348,0.23282 24.62053,3.49216 24.62053,3.49216 0,-42.13877 -0.46471,-121.7601 -0.46471,-160.872338 4.6454,0 7.89719,-0.232827 14.40071,-0.232827 0,2.328107 0,4.190613 0,6.053093 0,2.095305 0,3.259358 0.46471,4.656212 4.6454,14.66709 11.14893,20.48736 43.66659,38.41381 41.34392,23.04827 53.42195,36.78411 53.42195,55.17616 -0.46471,17.22802 -30.65954,54.01213 -37.16306,52.61528 9.29075,-13.03741 22.2978,-27.00606 25.54958,-38.64661 4.18085,-14.20147 -7.43263,-34.2232 -26.01414,-44.69971 -14.86522,-8.8468 -50.17016,-16.52957 -59.92547,-16.52957 0,0 -0.46472,84.74317 -0.46472,116.87109 0,5.35464 -9.7553,14.89989 -15.32977,18.15925 -25.54958,15.36551 -75.25519,22.34984 -97.553043,12.33896 z"
|
||||||
|
id="path3079"
|
||||||
|
style="stroke-width:3.28861" /><path
|
||||||
|
d="m 188.76763,155.437 v 98.42 c 0,5.867 4.741,10.605 10.60501,10.605 5.854,0 10.605,-4.738 10.605,-10.605 v -98.42 c 0,-5.856 -4.751,-10.605 -10.605,-10.605 -5.86401,0 -10.60501,4.744 -10.60501,10.605 z"
|
||||||
|
style="fill:none;stroke:url(#linearGradient5506);stroke-width:9.80924px;stroke-linecap:round;stroke-linejoin:round"
|
||||||
|
id="path5502" /></g><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g240" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g242" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g244" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g246" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g248" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g250" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g252" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g254" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g256" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g258" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g260" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g262" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g264" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g266" /><g
|
||||||
|
transform="matrix(0.972684,0,0,0.972684,193.06382,142.14148)"
|
||||||
|
id="g268" /></svg>
|
||||||
|
After Width: | Height: | Size: 14 KiB |
@ -1,110 +1,105 @@
|
|||||||
import type { IconType } from "react-icons";
|
import type { IconType } from "react-icons";
|
||||||
import {
|
import {
|
||||||
FaAndroid,
|
FaAndroid,
|
||||||
FaApple,
|
FaApple,
|
||||||
FaDebian,
|
FaDebian,
|
||||||
FaFedora,
|
FaFedora,
|
||||||
FaOpensuse,
|
FaOpensuse,
|
||||||
FaUbuntu,
|
FaUbuntu,
|
||||||
FaWindows,
|
FaWindows,
|
||||||
FaRedhat,
|
FaRedhat,
|
||||||
} from "react-icons/fa6";
|
} from "react-icons/fa6";
|
||||||
import { LuHouse, LuNewspaper, LuDownload, LuBook } from "react-icons/lu";
|
import { LuHouse, LuNewspaper, LuDownload, LuBook } from "react-icons/lu";
|
||||||
|
|
||||||
export const routes: Record<string, [string, IconType | null]> = {
|
export const routes: Record<string, [string, IconType|null]> = {
|
||||||
"/": ["Home", LuHouse],
|
"/": ["Home", LuHouse],
|
||||||
"/blog": ["Blog", LuNewspaper],
|
"/blog": ["Blog", LuNewspaper],
|
||||||
"/docs": ["Docs", LuBook],
|
"/docs": ["Docs", LuBook],
|
||||||
"/downloads": ["Downloads", LuDownload],
|
"/downloads": ["Downloads", LuDownload],
|
||||||
"/about": ["About", null],
|
"/about": ["About", null],
|
||||||
};
|
};
|
||||||
|
|
||||||
const releasesUrl =
|
const releasesUrl =
|
||||||
"https://github.com/KRTirtho/Spotube/releases/latest/download";
|
"https://github.com/KRTirtho/Spotube/releases/latest/download";
|
||||||
|
|
||||||
export const downloadLinks: Record<string, [string, IconType[]]> = {
|
export const downloadLinks: Record<string, [string, IconType[]]> = {
|
||||||
"Android Apk": [`${releasesUrl}/Spotube-android-all-arch.apk`, [FaAndroid]],
|
"Android Apk": [`${releasesUrl}/Spotube-android-all-arch.apk`, [FaAndroid]],
|
||||||
"Windows Executable": [
|
"Windows Executable": [
|
||||||
`${releasesUrl}/Spotube-windows-x86_64-setup.exe`,
|
`${releasesUrl}/Spotube-windows-x86_64-setup.exe`,
|
||||||
[FaWindows],
|
[FaWindows],
|
||||||
],
|
],
|
||||||
"macOS Dmg": [`${releasesUrl}/Spotube-macos-universal.dmg`, [FaApple]],
|
"macOS Dmg": [`${releasesUrl}/Spotube-macos-universal.dmg`, [FaApple]],
|
||||||
"Ubuntu, Debian": [
|
"Ubuntu, Debian": [
|
||||||
`${releasesUrl}/Spotube-linux-x86_64.deb`,
|
`${releasesUrl}/Spotube-linux-x86_64.deb`,
|
||||||
[FaUbuntu, FaDebian],
|
[FaUbuntu, FaDebian],
|
||||||
],
|
],
|
||||||
"Fedora, Redhat, Opensuse": [
|
"Fedora, Redhat, Opensuse": [
|
||||||
`${releasesUrl}/Spotube-linux-x86_64.rpm`,
|
`${releasesUrl}/Spotube-linux-x86_64.rpm`,
|
||||||
[FaFedora, FaRedhat, FaOpensuse],
|
[FaFedora, FaRedhat, FaOpensuse],
|
||||||
],
|
],
|
||||||
"iPhone Ipa": [`${releasesUrl}/Spotube-iOS.ipa`, [FaApple]],
|
"iPhone Ipa": [`${releasesUrl}/Spotube-iOS.ipa`, [FaApple]],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const extendedDownloadLinks: Record<
|
export const extendedDownloadLinks: Record<
|
||||||
string,
|
string,
|
||||||
[string, IconType[], string]
|
[string, IconType[], string]
|
||||||
> = {
|
> = {
|
||||||
Android: [`${releasesUrl}/Spotube-android-all-arch.apk`, [FaAndroid], "apk"],
|
Android: [`${releasesUrl}/Spotube-android-all-arch.apk`, [FaAndroid], "apk"],
|
||||||
Windows: [
|
Windows: [
|
||||||
`${releasesUrl}/Spotube-windows-x86_64-setup.exe`,
|
`${releasesUrl}/Spotube-windows-x86_64-setup.exe`,
|
||||||
[FaWindows],
|
[FaWindows],
|
||||||
"exe",
|
"exe",
|
||||||
],
|
],
|
||||||
macOS: [`${releasesUrl}/Spotube-macos-universal.dmg`, [FaApple], "dmg"],
|
macOS: [`${releasesUrl}/Spotube-macos-universal.dmg`, [FaApple], "dmg"],
|
||||||
"Ubuntu, Debian (x64)": [
|
"Ubuntu, Debian": [
|
||||||
`${releasesUrl}/Spotube-linux-x86_64.deb`,
|
`${releasesUrl}/Spotube-linux-x86_64.deb`,
|
||||||
[FaUbuntu, FaDebian],
|
[FaUbuntu, FaDebian],
|
||||||
"deb",
|
"deb",
|
||||||
],
|
],
|
||||||
"Ubuntu, Debian (arm64)": [
|
"Fedora, Redhat, Opensuse": [
|
||||||
`${releasesUrl}/Spotube-linux-aarch64.deb`,
|
`${releasesUrl}/Spotube-linux-x86_64.rpm`,
|
||||||
[FaUbuntu, FaDebian],
|
[FaFedora, FaRedhat, FaOpensuse],
|
||||||
"deb",
|
"rpm",
|
||||||
],
|
],
|
||||||
// "Fedora, Redhat, Opensuse": [
|
iPhone: [`${releasesUrl}/Spotube-iOS.ipa`, [FaApple], "ipa"],
|
||||||
// `${releasesUrl}/Spotube-linux-x86_64.rpm`,
|
|
||||||
// [FaFedora, FaRedhat, FaOpensuse],
|
|
||||||
// "rpm",
|
|
||||||
// ],
|
|
||||||
iPhone: [`${releasesUrl}/Spotube-iOS.ipa`, [FaApple], "ipa"],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const nightlyReleaseUrl =
|
const nightlyReleaseUrl =
|
||||||
"https://github.com/KRTirtho/Spotube/releases/download/nightly";
|
"https://github.com/KRTirtho/Spotube/releases/download/nightly";
|
||||||
|
|
||||||
export const extendedNightlyDownloadLinks: Record<
|
export const extendedNightlyDownloadLinks: Record<
|
||||||
string,
|
string,
|
||||||
[string, IconType[], string]
|
[string, IconType[], string]
|
||||||
> = {
|
> = {
|
||||||
Android: [
|
Android: [
|
||||||
`${nightlyReleaseUrl}/Spotube-android-all-arch.apk`,
|
`${nightlyReleaseUrl}/Spotube-android-all-arch.apk`,
|
||||||
[FaAndroid],
|
[FaAndroid],
|
||||||
"apk",
|
"apk",
|
||||||
],
|
],
|
||||||
Windows: [
|
Windows: [
|
||||||
`${nightlyReleaseUrl}/Spotube-windows-x86_64-setup.exe`,
|
`${nightlyReleaseUrl}/Spotube-windows-x86_64-setup.exe`,
|
||||||
[FaWindows],
|
[FaWindows],
|
||||||
"exe",
|
"exe",
|
||||||
],
|
],
|
||||||
macOS: [`${nightlyReleaseUrl}/Spotube-macos-universal.dmg`, [FaApple], "dmg"],
|
macOS: [`${nightlyReleaseUrl}/Spotube-macos-universal.dmg`, [FaApple], "dmg"],
|
||||||
"Ubuntu, Debian": [
|
"Ubuntu, Debian": [
|
||||||
`${nightlyReleaseUrl}/Spotube-linux-x86_64.deb`,
|
`${nightlyReleaseUrl}/Spotube-linux-x86_64.deb`,
|
||||||
[FaUbuntu, FaDebian],
|
[FaUbuntu, FaDebian],
|
||||||
"deb",
|
"deb",
|
||||||
],
|
],
|
||||||
"Fedora, Redhat, Opensuse": [
|
"Fedora, Redhat, Opensuse": [
|
||||||
`${nightlyReleaseUrl}/Spotube-linux-x86_64.rpm`,
|
`${nightlyReleaseUrl}/Spotube-linux-x86_64.rpm`,
|
||||||
[FaFedora, FaRedhat, FaOpensuse],
|
[FaFedora, FaRedhat, FaOpensuse],
|
||||||
"rpm",
|
"rpm",
|
||||||
],
|
],
|
||||||
iPhone: [`${nightlyReleaseUrl}/Spotube-iOS.ipa`, [FaApple], "ipa"],
|
iPhone: [`${nightlyReleaseUrl}/Spotube-iOS.ipa`, [FaApple], "ipa"],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ADS_SLOTS = Object.freeze({
|
export const ADS_SLOTS = Object.freeze({
|
||||||
rootPageDisplay: 5979549631,
|
rootPageDisplay: 5979549631,
|
||||||
blogPageInFeed: 3386010031,
|
blogPageInFeed: 3386010031,
|
||||||
downloadPageDisplay: 9928443050,
|
downloadPageDisplay: 9928443050,
|
||||||
packagePageArticle: 9119323068,
|
packagePageArticle: 9119323068,
|
||||||
// This is being used for rehype-auto-ads in svelte.config.js
|
// This is being used for rehype-auto-ads in svelte.config.js
|
||||||
blogArticlePageArticle: 6788673194,
|
blogArticlePageArticle: 6788673194,
|
||||||
});
|
});
|
||||||
@ -12,7 +12,7 @@ const {
|
|||||||
adSlot,
|
adSlot,
|
||||||
adFormat,
|
adFormat,
|
||||||
fullWidthResponsive = true,
|
fullWidthResponsive = true,
|
||||||
style = "display:block",
|
style,
|
||||||
adLayout,
|
adLayout,
|
||||||
adLayoutKey,
|
adLayoutKey,
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
@ -22,7 +22,7 @@ const AD_CLIENT = "ca-pub-6419300932495863";
|
|||||||
|
|
||||||
<ins
|
<ins
|
||||||
class="adsbygoogle"
|
class="adsbygoogle"
|
||||||
style={style}
|
{style}
|
||||||
data-ad-layout={adLayout}
|
data-ad-layout={adLayout}
|
||||||
data-ad-client={AD_CLIENT}
|
data-ad-client={AD_CLIENT}
|
||||||
data-ad-slot={adSlot}
|
data-ad-slot={adSlot}
|
||||||
|
|||||||
@ -22,7 +22,34 @@ const otherDownloads: [string, string, IconType][] = [
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
<h5 class="h5">Spotube is available for every platform</h5>
|
<h5 class="h5">Spotube is available for every platform</h5>
|
||||||
<br />
|
<br />
|
||||||
<DownloadItems links={extendedDownloadLinks} />
|
<!-- WARNING! -->
|
||||||
|
<h3 class="h3 text-red-500" data-svelte-h="svelte-1l4b696">
|
||||||
|
Versions of Spotube (<=v4.0.2) are ceased to work with Spotify™ API.
|
||||||
|
<br />
|
||||||
|
So users can no longer use/download those versions.
|
||||||
|
<br />
|
||||||
|
Please wait for the next version that will remedy this issue by not using such
|
||||||
|
APIs.
|
||||||
|
</h3>
|
||||||
|
<p class="text-surface-500 mt-5" data-svelte-h="svelte-1nkw9cu">
|
||||||
|
Spotube has no affiliation with Spotify™ or any of its subsidiaries.
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<!-- <DownloadItems links={extendedDownloadLinks} /> -->
|
||||||
|
<h6 class="h6 mb-5" data-svelte-h="svelte-1ws2638">
|
||||||
|
The new Spotube v5 is still under beta. Please use the Nightly version
|
||||||
|
until stable release.
|
||||||
|
</h6>
|
||||||
|
<!-- WARNING! -->
|
||||||
|
<div class="flex">
|
||||||
|
<a href="/downloads/nightly" class="flex gap-2 btn btn-lg preset-filled">
|
||||||
|
<LuDownload />
|
||||||
|
Download Nightly
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<Ads adSlot={ADS_SLOTS.downloadPageDisplay} adFormat="auto" />
|
<Ads adSlot={ADS_SLOTS.downloadPageDisplay} adFormat="auto" />
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@ -53,11 +53,11 @@ import { ADS_SLOTS } from "~/collections/app";
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
<a
|
<a
|
||||||
href="/downloads"
|
href="/downloads/nightly"
|
||||||
class="flex gap-2 btn btn-lg preset-filled"
|
class="flex gap-2 btn btn-lg preset-filled"
|
||||||
>
|
>
|
||||||
<LuDownload />
|
<LuDownload />
|
||||||
Download
|
Download Nightly
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||