22 Commits

Author SHA1 Message Date
Bart Ribbers
60edb39455 Merge e11250182d into b0bb26f84b 2024-12-10 21:45:42 +00:00
Bart Ribbers
e11250182d chore: upgrade to Flutter 3.24.5
At the time of writing the latest Flutter version.
2024-12-10 22:45:36 +01:00
Bart Ribbers
fc0daacfc0 chore: ignore VSCode's settings.json in git
Seettings in there can be different per user and should be, it should
not be committed
2024-12-10 20:42:50 +01:00
Bart Ribbers
7e5885e5c8 chore: cleanup fvm configuration
I guess fvm changed the way it does it's configuration at some point,
but rather than having .fvm/fmv_config.json checked in .fvmrc should be
checked in. The .fvm directory is used to store files and symlinks
related to the installed Flutter version and as such should not be
commited at all.
2024-12-10 20:42:49 +01:00
austinried
b0bb26f84b Fix initial server ping/feature tests always using token auth 2023-05-18 06:42:29 +09:00
austinried
e94fcf3128 bump version 2023-05-16 18:59:16 +09:00
josé m
bd6e818f36 Translated using Weblate (Galician)
Currently translated at 100.0% (94 of 94 strings)

Co-authored-by: josé m <correoxm@disroot.org>
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/gl/
Translation: Subtracks/subtracks
2023-05-16 18:57:04 +09:00
Max Smith
96d0c35c31 Translated using Weblate (Russian)
Currently translated at 100.0% (94 of 94 strings)

Co-authored-by: Max Smith <sevinfolds@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/ru/
Translation: Subtracks/subtracks
2023-05-16 18:57:04 +09:00
Tim Schneeberger
4ef3281a0b Translated using Weblate (German)
Currently translated at 100.0% (92 of 92 strings)

Co-authored-by: Tim Schneeberger <thebone.main@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/de/
Translation: Subtracks/subtracks
2023-05-16 18:57:04 +09:00
austinried
c56e3dba0f remove todo 2023-05-16 09:34:39 +09:00
austinried
53d284ace4 redact error too
create log file if it doesn't exist first
2023-05-16 09:34:39 +09:00
austinried
c2733482e5 show snackbar error for sync
log http errors
log sync errors
2023-05-16 09:34:39 +09:00
austinried
67f0c926c4 add snackbar method for errors
test (ping) server before saving source
display error message when saving source
2023-05-16 09:34:39 +09:00
Joel Calado
889be2ff2c return null 2023-05-15 07:11:58 +09:00
Joel Calado
52b51954aa improve url validation in settings 2023-05-15 07:11:58 +09:00
austinried
1c76293559 default force plaintext password off 2023-05-14 14:35:19 +09:00
austinried
250d6793a2 wording 2023-05-14 14:29:04 +09:00
austinried
121af2bca3 audio playback error logging
subsonic error logging
source save error logging
2023-05-14 14:29:04 +09:00
austinried
e410dcb2eb log sql exceptions 2023-05-14 14:29:04 +09:00
austinried
63ff9772e5 initial console/file logging framework 2023-05-14 14:29:04 +09:00
Vojtěch Fošnár
1ae29c5ade Translated using Weblate (Czech)
Currently translated at 85.8% (79 of 92 strings)

Co-authored-by: Vojtěch Fošnár <vfosnar@fosny.eu>
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/cs/
Translation: Subtracks/subtracks
2023-05-11 10:07:23 +09:00
Joel Calado
fedd6a71bb Translated using Weblate (Portuguese)
Currently translated at 88.0% (81 of 92 strings)

Co-authored-by: Joel Calado <joelcalado@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/subtracks/subtracks/pt/
Translation: Subtracks/subtracks
2023-05-11 10:07:23 +09:00
68 changed files with 3882 additions and 2081 deletions

View File

@@ -1,4 +0,0 @@
{
"flutterSdkVersion": "3.7.11",
"flavors": {}
}

4
.fvmrc Normal file
View File

@@ -0,0 +1,4 @@
{
"flutter": "3.24.5",
"flavors": {}
}

8
.gitignore vendored
View File

@@ -16,10 +16,8 @@ migrate_working_dir/
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# VSCode related
.vscode/settings.json
# Flutter/Dart/Pub related
**/doc/api/
@@ -45,5 +43,5 @@ app.*.map.json
/.env
*.sqlite*
/.fvm/flutter_sdk
.fvm/
*.keystore

View File

@@ -22,6 +22,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -53,6 +55,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -62,32 +66,12 @@
],
"cs": [
"actionsCancel",
"actionsDelete",
"actionsDownload",
"actionsDownloadCancel",
"actionsDownloadDelete",
"actionsOk",
"controlsShuffle",
"resourcesAlbumCount",
"resourcesArtistCount",
"resourcesFilterAlbum",
"resourcesFilterArtist",
"resourcesFilterOwner",
"resourcesFilterYear",
"resourcesPlaylistCount",
"resourcesSongCount",
"resourcesSongListDeleteAllContent",
"resourcesSongListDeleteAllTitle",
"resourcesSortByAlbum",
"resourcesSortByAlbumCount",
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsLicenses",
"settingsAboutActionsProjectHomepage",
"settingsAboutActionsSupport",
"settingsAboutName",
"settingsAboutVersion",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsMusicName",
"settingsMusicOptionsScrobbleDescriptionOff",
"settingsMusicOptionsScrobbleDescriptionOn",
@@ -96,12 +80,7 @@
"settingsNetworkOptionsMinBufferTitle",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
"settingsNetworkOptionsStreamFormat",
"settingsNetworkOptionsStreamFormatServerDefault",
"settingsResetActionsClearImageCache",
"settingsResetName",
"settingsServersFieldsName"
"settingsNetworkOptionsOfflineModeOn"
],
"da": [
@@ -133,6 +112,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsMusicOptionsScrobbleDescriptionOff",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
@@ -146,29 +127,8 @@
],
"de": [
"actionsDownloadDelete",
"actionsOk",
"resourcesAlbumCount",
"resourcesArtistCount",
"resourcesFilterAlbum",
"resourcesFilterArtist",
"resourcesFilterOwner",
"resourcesFilterYear",
"resourcesPlaylistCount",
"resourcesSongCount",
"resourcesSongListDeleteAllContent",
"resourcesSongListDeleteAllTitle",
"resourcesSortByAlbum",
"resourcesSortByAlbumCount",
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
"settingsNetworkOptionsStreamFormat",
"settingsNetworkOptionsStreamFormatServerDefault",
"settingsServersFieldsName"
"settingsAboutShareLogs",
"settingsAboutChooseLog"
],
"es": [
@@ -187,6 +147,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -218,6 +180,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -249,6 +213,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -300,6 +266,8 @@
"settingsAboutActionsLicenses",
"settingsAboutActionsSupport",
"settingsAboutName",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsAboutVersion",
"settingsMusicOptionsScrobbleDescriptionOff",
"settingsMusicOptionsScrobbleDescriptionOn",
@@ -356,6 +324,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -387,6 +357,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -418,6 +390,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -427,63 +401,17 @@
],
"pt": [
"actionsCancel",
"actionsDelete",
"actionsDownload",
"actionsDownloadCancel",
"actionsDownloadDelete",
"actionsOk",
"controlsShuffle",
"resourcesAlbumCount",
"resourcesArtistCount",
"resourcesFilterAlbum",
"resourcesFilterArtist",
"resourcesFilterOwner",
"resourcesFilterYear",
"resourcesPlaylistCount",
"resourcesSongCount",
"resourcesSongListDeleteAllContent",
"resourcesSongListDeleteAllTitle",
"resourcesSortByAlbum",
"resourcesSortByAlbumCount",
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
"settingsNetworkOptionsStreamFormat",
"settingsNetworkOptionsStreamFormatServerDefault",
"settingsServersFieldsName"
],
"ru": [
"actionsCancel",
"actionsDelete",
"actionsDownload",
"actionsDownloadCancel",
"actionsDownloadDelete",
"actionsOk",
"controlsShuffle",
"resourcesAlbumCount",
"resourcesArtistCount",
"resourcesFilterAlbum",
"resourcesFilterArtist",
"resourcesFilterOwner",
"resourcesFilterYear",
"resourcesPlaylistCount",
"resourcesSongCount",
"resourcesSongListDeleteAllContent",
"resourcesSongListDeleteAllTitle",
"resourcesSortByAlbum",
"resourcesSortByAlbumCount",
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
"settingsNetworkOptionsStreamFormat",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsStreamFormatServerDefault",
"settingsServersFieldsName"
],
@@ -511,6 +439,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -542,6 +472,8 @@
"resourcesSortByTitle",
"resourcesSortByUpdated",
"settingsAboutActionsSupport",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",
@@ -556,6 +488,8 @@
"resourcesArtistCount",
"resourcesPlaylistCount",
"resourcesSongCount",
"settingsAboutShareLogs",
"settingsAboutChooseLog",
"settingsNetworkOptionsOfflineMode",
"settingsNetworkOptionsOfflineModeOff",
"settingsNetworkOptionsOfflineModeOn",

View File

@@ -1,3 +1,9 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
@@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) {
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
@@ -21,10 +22,6 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
@@ -53,7 +50,7 @@ android {
applicationId "com.subtracks2"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 19
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
@@ -81,8 +78,4 @@ android {
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
}

View File

@@ -5,4 +5,9 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- audio_service -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
</manifest>

View File

@@ -69,4 +69,5 @@
<!-- audio_service -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
</manifest>

View File

@@ -1,25 +0,0 @@
// Generated file.
//
// If you wish to remove Flutter's multidex support, delete this entire file.
//
// Modifications to this file should be done in a copy under a different name
// as this file may be regenerated.
package io.flutter.app;
import android.app.Application;
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.multidex.MultiDex;
/**
* Extension of {@link android.app.Application}, adding multidex support.
*/
public class FlutterMultiDexApplication extends Application {
@Override
@CallSuper
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}

View File

@@ -5,4 +5,9 @@
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- audio_service -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
</manifest>

View File

@@ -1,16 +1,3 @@
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
@@ -26,6 +13,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View File

@@ -1,11 +1,25 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.2.0" apply false
id "org.jetbrains.kotlin.android" version "2.0.21" apply false
}
include ":app"

View File

@@ -20,4 +20,5 @@ final lastPathProvider = NotifierProvider<LastPath, String>.internal(
);
typedef _$LastPath = Notifier<String>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -25,7 +25,7 @@ Future<T?> showContextMenu<T>({
required WidgetBuilder builder,
}) {
return showModalBottomSheet<T>(
backgroundColor: ref.read(baseThemeProvider).theme.colorScheme.background,
backgroundColor: ref.read(baseThemeProvider).theme.colorScheme.surface,
useRootNavigator: true,
isScrollControlled: true,
context: context,

View File

@@ -112,9 +112,9 @@ List<DownloadAction> useListDownloadActions({
DownloadAction cancel() {
return DownloadAction(
type: DownloadActionType.cancel,
iconBuilder: (context) => Stack(
iconBuilder: (context) => const Stack(
alignment: Alignment.center,
children: const [
children: [
Icon(Icons.cancel_rounded),
SizedBox(
height: 32,

View File

@@ -213,7 +213,7 @@ class CardClip extends StatelessWidget {
final cardShape = Theme.of(context).cardTheme.shape;
return ClipRRect(
borderRadius:
cardShape is RoundedRectangleBorder ? cardShape.borderRadius : null,
cardShape is RoundedRectangleBorder ? cardShape.borderRadius : BorderRadius.zero,
child: !square
? child
: AspectRatio(

View File

@@ -30,8 +30,6 @@ class _SystemHash {
}
}
typedef _ArtistArtCacheInfoRef = AutoDisposeProviderRef<CacheInfo>;
/// See also [_artistArtCacheInfo].
@ProviderFor(_artistArtCacheInfo)
const _artistArtCacheInfoProvider = _ArtistArtCacheInfoFamily();
@@ -81,11 +79,11 @@ class _ArtistArtCacheInfoFamily extends Family<CacheInfo> {
class _ArtistArtCacheInfoProvider extends AutoDisposeProvider<CacheInfo> {
/// See also [_artistArtCacheInfo].
_ArtistArtCacheInfoProvider({
required this.artistId,
this.thumbnail = true,
}) : super.internal(
required String artistId,
bool thumbnail = true,
}) : this._internal(
(ref) => _artistArtCacheInfo(
ref,
ref as _ArtistArtCacheInfoRef,
artistId: artistId,
thumbnail: thumbnail,
),
@@ -98,11 +96,48 @@ class _ArtistArtCacheInfoProvider extends AutoDisposeProvider<CacheInfo> {
dependencies: _ArtistArtCacheInfoFamily._dependencies,
allTransitiveDependencies:
_ArtistArtCacheInfoFamily._allTransitiveDependencies,
artistId: artistId,
thumbnail: thumbnail,
);
_ArtistArtCacheInfoProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.artistId,
required this.thumbnail,
}) : super.internal();
final String artistId;
final bool thumbnail;
@override
Override overrideWith(
CacheInfo Function(_ArtistArtCacheInfoRef provider) create,
) {
return ProviderOverride(
origin: this,
override: _ArtistArtCacheInfoProvider._internal(
(ref) => create(ref as _ArtistArtCacheInfoRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
artistId: artistId,
thumbnail: thumbnail,
),
);
}
@override
AutoDisposeProviderElement<CacheInfo> createElement() {
return _ArtistArtCacheInfoProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is _ArtistArtCacheInfoProvider &&
@@ -120,9 +155,26 @@ class _ArtistArtCacheInfoProvider extends AutoDisposeProvider<CacheInfo> {
}
}
mixin _ArtistArtCacheInfoRef on AutoDisposeProviderRef<CacheInfo> {
/// The parameter `artistId` of this provider.
String get artistId;
/// The parameter `thumbnail` of this provider.
bool get thumbnail;
}
class _ArtistArtCacheInfoProviderElement
extends AutoDisposeProviderElement<CacheInfo> with _ArtistArtCacheInfoRef {
_ArtistArtCacheInfoProviderElement(super.provider);
@override
String get artistId => (origin as _ArtistArtCacheInfoProvider).artistId;
@override
bool get thumbnail => (origin as _ArtistArtCacheInfoProvider).thumbnail;
}
String _$artistArtCachedUrlHash() =>
r'2a5e0fea614ff12a1d562faccec6cfe98394af42';
typedef _ArtistArtCachedUrlRef = AutoDisposeFutureProviderRef<String?>;
/// See also [_artistArtCachedUrl].
@ProviderFor(_artistArtCachedUrl)
@@ -173,11 +225,11 @@ class _ArtistArtCachedUrlFamily extends Family<AsyncValue<String?>> {
class _ArtistArtCachedUrlProvider extends AutoDisposeFutureProvider<String?> {
/// See also [_artistArtCachedUrl].
_ArtistArtCachedUrlProvider({
required this.artistId,
this.thumbnail = true,
}) : super.internal(
required String artistId,
bool thumbnail = true,
}) : this._internal(
(ref) => _artistArtCachedUrl(
ref,
ref as _ArtistArtCachedUrlRef,
artistId: artistId,
thumbnail: thumbnail,
),
@@ -190,11 +242,48 @@ class _ArtistArtCachedUrlProvider extends AutoDisposeFutureProvider<String?> {
dependencies: _ArtistArtCachedUrlFamily._dependencies,
allTransitiveDependencies:
_ArtistArtCachedUrlFamily._allTransitiveDependencies,
artistId: artistId,
thumbnail: thumbnail,
);
_ArtistArtCachedUrlProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.artistId,
required this.thumbnail,
}) : super.internal();
final String artistId;
final bool thumbnail;
@override
Override overrideWith(
FutureOr<String?> Function(_ArtistArtCachedUrlRef provider) create,
) {
return ProviderOverride(
origin: this,
override: _ArtistArtCachedUrlProvider._internal(
(ref) => create(ref as _ArtistArtCachedUrlRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
artistId: artistId,
thumbnail: thumbnail,
),
);
}
@override
AutoDisposeFutureProviderElement<String?> createElement() {
return _ArtistArtCachedUrlProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is _ArtistArtCachedUrlProvider &&
@@ -212,9 +301,27 @@ class _ArtistArtCachedUrlProvider extends AutoDisposeFutureProvider<String?> {
}
}
mixin _ArtistArtCachedUrlRef on AutoDisposeFutureProviderRef<String?> {
/// The parameter `artistId` of this provider.
String get artistId;
/// The parameter `thumbnail` of this provider.
bool get thumbnail;
}
class _ArtistArtCachedUrlProviderElement
extends AutoDisposeFutureProviderElement<String?>
with _ArtistArtCachedUrlRef {
_ArtistArtCachedUrlProviderElement(super.provider);
@override
String get artistId => (origin as _ArtistArtCachedUrlProvider).artistId;
@override
bool get thumbnail => (origin as _ArtistArtCachedUrlProvider).thumbnail;
}
String _$artistArtUriCacheInfoHash() =>
r'9bdc0f5654882265236ef746ea697a6d107a4b6f';
typedef _ArtistArtUriCacheInfoRef = AutoDisposeFutureProviderRef<UriCacheInfo>;
/// See also [_artistArtUriCacheInfo].
@ProviderFor(_artistArtUriCacheInfo)
@@ -266,11 +373,11 @@ class _ArtistArtUriCacheInfoProvider
extends AutoDisposeFutureProvider<UriCacheInfo> {
/// See also [_artistArtUriCacheInfo].
_ArtistArtUriCacheInfoProvider({
required this.artistId,
this.thumbnail = true,
}) : super.internal(
required String artistId,
bool thumbnail = true,
}) : this._internal(
(ref) => _artistArtUriCacheInfo(
ref,
ref as _ArtistArtUriCacheInfoRef,
artistId: artistId,
thumbnail: thumbnail,
),
@@ -283,11 +390,48 @@ class _ArtistArtUriCacheInfoProvider
dependencies: _ArtistArtUriCacheInfoFamily._dependencies,
allTransitiveDependencies:
_ArtistArtUriCacheInfoFamily._allTransitiveDependencies,
artistId: artistId,
thumbnail: thumbnail,
);
_ArtistArtUriCacheInfoProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.artistId,
required this.thumbnail,
}) : super.internal();
final String artistId;
final bool thumbnail;
@override
Override overrideWith(
FutureOr<UriCacheInfo> Function(_ArtistArtUriCacheInfoRef provider) create,
) {
return ProviderOverride(
origin: this,
override: _ArtistArtUriCacheInfoProvider._internal(
(ref) => create(ref as _ArtistArtUriCacheInfoRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
artistId: artistId,
thumbnail: thumbnail,
),
);
}
@override
AutoDisposeFutureProviderElement<UriCacheInfo> createElement() {
return _ArtistArtUriCacheInfoProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is _ArtistArtUriCacheInfoProvider &&
@@ -304,4 +448,24 @@ class _ArtistArtUriCacheInfoProvider
return _SystemHash.finish(hash);
}
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
mixin _ArtistArtUriCacheInfoRef on AutoDisposeFutureProviderRef<UriCacheInfo> {
/// The parameter `artistId` of this provider.
String get artistId;
/// The parameter `thumbnail` of this provider.
bool get thumbnail;
}
class _ArtistArtUriCacheInfoProviderElement
extends AutoDisposeFutureProviderElement<UriCacheInfo>
with _ArtistArtUriCacheInfoRef {
_ArtistArtUriCacheInfoProviderElement(super.provider);
@override
String get artistId => (origin as _ArtistArtUriCacheInfoProvider).artistId;
@override
bool get thumbnail => (origin as _ArtistArtUriCacheInfoProvider).thumbnail;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -4,6 +4,7 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
import '../services/sync_service.dart';
import 'items.dart';
import 'snackbars.dart';
class PagedListQueryView<T> extends HookConsumerWidget {
final PagingController<int, T> pagingController;
@@ -122,7 +123,14 @@ class SyncAllRefresh extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return RefreshIndicator(
onRefresh: () => ref.read(syncServiceProvider.notifier).syncAll(),
onRefresh: () async {
try {
await ref.read(syncServiceProvider.notifier).syncAll();
} catch (e) {
if (!context.mounted) return;
showErrorSnackbar(context, e.toString());
}
},
child: child,
);
}

View File

@@ -30,13 +30,13 @@ class NowPlayingBar extends HookConsumerWidget {
elevation: 3,
color: colors?.darkBackground,
// surfaceTintColor: theme?.colorScheme.background,
child: Column(
child: const Column(
children: [
SizedBox(
height: 70,
child: Row(
mainAxisSize: MainAxisSize.max,
children: const [
children: [
Padding(
padding: EdgeInsets.all(10),
child: _ArtImage(),
@@ -54,7 +54,7 @@ class NowPlayingBar extends HookConsumerWidget {
],
),
),
const _ProgressBar(),
_ProgressBar(),
],
),
),
@@ -173,7 +173,7 @@ class PlayPauseButton extends HookConsumerWidget {
width: size / 3,
child: CircularProgressIndicator(
strokeWidth: size / 16,
color: Theme.of(context).colorScheme.background,
color: Theme.of(context).colorScheme.surface,
),
),
],
@@ -195,7 +195,7 @@ class PlayPauseButton extends HookConsumerWidget {
}
},
icon: icon,
color: Theme.of(context).colorScheme.onBackground,
color: Theme.of(context).colorScheme.surface,
);
}
}

View File

@@ -111,13 +111,13 @@ class OfflineIndicator extends HookConsumerWidget {
),
child: FilledButton.tonal(
style: const ButtonStyle(
padding: MaterialStatePropertyAll<EdgeInsetsGeometry>(
padding: WidgetStatePropertyAll<EdgeInsetsGeometry>(
EdgeInsets.zero,
),
fixedSize: MaterialStatePropertyAll<Size>(
fixedSize: WidgetStatePropertyAll<Size>(
Size(42, 42),
),
minimumSize: MaterialStatePropertyAll<Size>(
minimumSize: WidgetStatePropertyAll<Size>(
Size(42, 42),
),
),

View File

@@ -53,4 +53,5 @@ final lastBottomNavStateServiceProvider =
);
typedef _$LastBottomNavStateService = AsyncNotifier<void>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -30,8 +30,6 @@ class _SystemHash {
}
}
typedef AlbumsCategoryListRef = AutoDisposeStreamProviderRef<List<Album>>;
/// See also [albumsCategoryList].
@ProviderFor(albumsCategoryList)
const albumsCategoryListProvider = AlbumsCategoryListFamily();
@@ -79,10 +77,10 @@ class AlbumsCategoryListProvider
extends AutoDisposeStreamProvider<List<Album>> {
/// See also [albumsCategoryList].
AlbumsCategoryListProvider(
this.opt,
) : super.internal(
ListQuery opt,
) : this._internal(
(ref) => albumsCategoryList(
ref,
ref as AlbumsCategoryListRef,
opt,
),
from: albumsCategoryListProvider,
@@ -94,10 +92,44 @@ class AlbumsCategoryListProvider
dependencies: AlbumsCategoryListFamily._dependencies,
allTransitiveDependencies:
AlbumsCategoryListFamily._allTransitiveDependencies,
opt: opt,
);
AlbumsCategoryListProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.opt,
}) : super.internal();
final ListQuery opt;
@override
Override overrideWith(
Stream<List<Album>> Function(AlbumsCategoryListRef provider) create,
) {
return ProviderOverride(
origin: this,
override: AlbumsCategoryListProvider._internal(
(ref) => create(ref as AlbumsCategoryListRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
opt: opt,
),
);
}
@override
AutoDisposeStreamProviderElement<List<Album>> createElement() {
return _AlbumsCategoryListProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is AlbumsCategoryListProvider && other.opt == opt;
@@ -111,4 +143,19 @@ class AlbumsCategoryListProvider
return _SystemHash.finish(hash);
}
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
mixin AlbumsCategoryListRef on AutoDisposeStreamProviderRef<List<Album>> {
/// The parameter `opt` of this provider.
ListQuery get opt;
}
class _AlbumsCategoryListProviderElement
extends AutoDisposeStreamProviderElement<List<Album>>
with AlbumsCategoryListRef {
_AlbumsCategoryListProviderElement(super.provider);
@override
ListQuery get opt => (origin as AlbumsCategoryListProvider).opt;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -60,8 +60,6 @@ class _SystemHash {
}
}
typedef LibraryListQueryRef = ProviderRef<LibraryListQuery>;
/// See also [libraryListQuery].
@ProviderFor(libraryListQuery)
const libraryListQueryProvider = LibraryListQueryFamily();
@@ -108,10 +106,10 @@ class LibraryListQueryFamily extends Family<LibraryListQuery> {
class LibraryListQueryProvider extends Provider<LibraryListQuery> {
/// See also [libraryListQuery].
LibraryListQueryProvider(
this.index,
) : super.internal(
int index,
) : this._internal(
(ref) => libraryListQuery(
ref,
ref as LibraryListQueryRef,
index,
),
from: libraryListQueryProvider,
@@ -123,10 +121,44 @@ class LibraryListQueryProvider extends Provider<LibraryListQuery> {
dependencies: LibraryListQueryFamily._dependencies,
allTransitiveDependencies:
LibraryListQueryFamily._allTransitiveDependencies,
index: index,
);
LibraryListQueryProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.index,
}) : super.internal();
final int index;
@override
Override overrideWith(
LibraryListQuery Function(LibraryListQueryRef provider) create,
) {
return ProviderOverride(
origin: this,
override: LibraryListQueryProvider._internal(
(ref) => create(ref as LibraryListQueryRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
index: index,
),
);
}
@override
ProviderElement<LibraryListQuery> createElement() {
return _LibraryListQueryProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is LibraryListQueryProvider && other.index == index;
@@ -141,6 +173,19 @@ class LibraryListQueryProvider extends Provider<LibraryListQuery> {
}
}
mixin LibraryListQueryRef on ProviderRef<LibraryListQuery> {
/// The parameter `index` of this provider.
int get index;
}
class _LibraryListQueryProviderElement extends ProviderElement<LibraryListQuery>
with LibraryListQueryRef {
_LibraryListQueryProviderElement(super.provider);
@override
int get index => (origin as LibraryListQueryProvider).index;
}
String _$lastLibraryStateServiceHash() =>
r'a49e26b5dc0fcb0f697ec2def08e7336f64c4cb3';
@@ -173,4 +218,5 @@ final libraryListsProvider =
);
typedef _$LibraryLists = Notifier<IList<LibraryListQuery>>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -29,8 +29,6 @@ class _SystemHash {
}
}
typedef SongsListRef = AutoDisposeFutureProviderRef<List<Song>>;
/// See also [songsList].
@ProviderFor(songsList)
const songsListProvider = SongsListFamily();
@@ -77,10 +75,10 @@ class SongsListFamily extends Family<AsyncValue<List<Song>>> {
class SongsListProvider extends AutoDisposeFutureProvider<List<Song>> {
/// See also [songsList].
SongsListProvider(
this.opt,
) : super.internal(
ListQuery opt,
) : this._internal(
(ref) => songsList(
ref,
ref as SongsListRef,
opt,
),
from: songsListProvider,
@@ -91,10 +89,44 @@ class SongsListProvider extends AutoDisposeFutureProvider<List<Song>> {
: _$songsListHash,
dependencies: SongsListFamily._dependencies,
allTransitiveDependencies: SongsListFamily._allTransitiveDependencies,
opt: opt,
);
SongsListProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.opt,
}) : super.internal();
final ListQuery opt;
@override
Override overrideWith(
FutureOr<List<Song>> Function(SongsListRef provider) create,
) {
return ProviderOverride(
origin: this,
override: SongsListProvider._internal(
(ref) => create(ref as SongsListRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
opt: opt,
),
);
}
@override
AutoDisposeFutureProviderElement<List<Song>> createElement() {
return _SongsListProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is SongsListProvider && other.opt == opt;
@@ -108,4 +140,18 @@ class SongsListProvider extends AutoDisposeFutureProvider<List<Song>> {
return _SystemHash.finish(hash);
}
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
mixin SongsListRef on AutoDisposeFutureProviderRef<List<Song>> {
/// The parameter `opt` of this provider.
ListQuery get opt;
}
class _SongsListProviderElement
extends AutoDisposeFutureProviderElement<List<Song>> with SongsListRef {
_SongsListProviderElement(super.provider);
@override
ListQuery get opt => (origin as SongsListProvider).opt;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -55,13 +55,13 @@ class NowPlayingPage extends HookConsumerWidget {
],
),
),
body: Stack(
body: const Stack(
children: [
const MediaItemGradient(),
MediaItemGradient(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
child: Column(
children: const [
children: [
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
@@ -229,8 +229,8 @@ class _Progress extends HookConsumerWidget {
value: changing.value ? changeValue.value : position.toDouble(),
min: 0,
max: max(duration.toDouble(), position.toDouble()),
thumbColor: colors?.theme.colorScheme.onBackground,
activeColor: colors?.theme.colorScheme.onBackground,
thumbColor: colors?.theme.colorScheme.surface,
activeColor: colors?.theme.colorScheme.surface,
inactiveColor: colors?.theme.colorScheme.surface,
onChanged: (value) {
changeValue.value = value;
@@ -354,7 +354,7 @@ class _Controls extends HookConsumerWidget {
final audio = ref.watch(audioControlProvider);
return IconTheme(
data: IconThemeData(color: base.theme.colorScheme.onBackground),
data: IconThemeData(color: base.theme.colorScheme.surface),
child: Column(
children: [
SizedBox(

View File

@@ -35,4 +35,5 @@ final searchQueryProvider =
);
typedef _$SearchQuery = AutoDisposeNotifier<String?>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -1,11 +1,16 @@
import 'dart:math';
import 'package:auto_route/auto_route.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:path/path.dart' as p;
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../log.dart';
import '../../models/support.dart';
import '../../services/settings_service.dart';
import '../../state/init.dart';
@@ -162,6 +167,54 @@ class _About extends HookConsumerWidget {
mode: LaunchMode.externalApplication,
),
),
const SizedBox(height: 12),
const _ShareLogsButton(),
],
);
}
}
class _ShareLogsButton extends StatelessWidget {
const _ShareLogsButton();
@override
Widget build(BuildContext context) {
final l = AppLocalizations.of(context);
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
OutlinedButton.icon(
icon: const Icon(Icons.share),
label: Text(l.settingsAboutShareLogs),
onPressed: () async {
final files = await logFiles();
if (files.isEmpty) return;
if (!context.mounted) return;
final value = await showDialog<String>(
context: context,
builder: (context) => MultipleChoiceDialog<String>(
title: l.settingsAboutChooseLog,
current: files.first.path,
options: files
.map((e) => MultiChoiceOption.string(
title: p.basename(e.path),
option: e.path,
))
.toIList(),
),
);
if (value == null) return;
Share.shareXFiles(
[XFile(value, mimeType: 'text/plain')],
subject: 'Logs from subtracks: ${String.fromCharCodes(
List.generate(8, (_) => Random().nextInt(26) + 65),
)}',
);
},
),
],
);
}

View File

@@ -8,9 +8,11 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../../database/database.dart';
import '../../log.dart';
import '../../models/settings.dart';
import '../../services/settings_service.dart';
import '../items.dart';
import '../snackbars.dart';
class SourcePage extends HookConsumerWidget {
final int? id;
@@ -44,7 +46,7 @@ class SourcePage extends HookConsumerWidget {
autofillHints: const [AutofillHints.url],
required: true,
validator: (value, label) {
if (Uri.tryParse(value!) == null) {
if (!value!.contains(RegExp(r'https?:\/\/'))) {
return '$label must be a valid URL';
}
return null;
@@ -64,7 +66,7 @@ class SourcePage extends HookConsumerWidget {
required: true,
);
final forcePlaintextPassword = useState(!(source?.useTokenAuth ?? false));
final forcePlaintextPassword = useState(!(source?.useTokenAuth ?? true));
final forcePlaintextSwitch = SwitchListTile(
value: forcePlaintextPassword.value,
title: Text(l.settingsServersOptionsForcePlaintextPasswordTitle),
@@ -74,8 +76,8 @@ class SourcePage extends HookConsumerWidget {
onChanged: (value) => forcePlaintextPassword.value = value,
);
return WillPopScope(
onWillPop: () async => !isSaving.value && !isDeleting.value,
return PopScope(
canPop: !isSaving.value && !isDeleting.value,
child: Scaffold(
appBar: AppBar(),
floatingActionButton: Row(
@@ -161,8 +163,10 @@ class SourcePage extends HookConsumerWidget {
),
);
}
} catch (err) {
// TOOD: toast the error or whatever
} catch (e, st) {
if (!context.mounted) return;
showErrorSnackbar(context, e.toString());
log.severe('Saving source', e, st);
error = true;
} finally {
isSaving.value = false;

14
lib/app/snackbars.dart Normal file
View File

@@ -0,0 +1,14 @@
import 'package:flutter/material.dart';
void showErrorSnackbar(BuildContext context, String message) {
final colors = Theme.of(context).colorScheme;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message, style: TextStyle(color: colors.onErrorContainer)),
backgroundColor: colors.errorContainer,
showCloseIcon: true,
closeIconColor: colors.onErrorContainer,
behavior: SnackBarBehavior.floating,
duration: const Duration(seconds: 10),
));
}

View File

@@ -20,4 +20,5 @@ final imageCacheProvider = Provider<CacheManager>.internal(
);
typedef ImageCacheRef = ProviderRef<CacheManager>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -9,11 +9,13 @@ import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../log.dart';
import '../models/music.dart';
import '../models/query.dart';
import '../models/settings.dart';
import '../models/support.dart';
import 'converters.dart';
import 'error_logging_database.dart';
part 'database.g.dart';
@@ -435,7 +437,11 @@ LazyDatabase _openConnection() {
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(p.join(dbFolder.path, 'subtracks.sqlite'));
// return NativeDatabase.createInBackground(file, logStatements: true);
return NativeDatabase.createInBackground(file);
return ErrorLoggingDatabase(
NativeDatabase.createInBackground(file),
(e, s) => log.severe('SQL error', e, s),
);
});
}

View File

@@ -53,9 +53,10 @@ class Queue extends Table with TableInfo<Queue, QueueData> {
List<GeneratedColumn> get $columns =>
[index, sourceId, id, context, contextId, currentTrack];
@override
String get aliasedName => _alias ?? 'queue';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'queue';
String get actualTableName => $name;
static const String $name = 'queue';
@override
VerificationContext validateIntegrity(Insertable<QueueData> instance,
{bool isInserting = false}) {
@@ -144,8 +145,7 @@ class QueueData extends DataClass implements Insertable<QueueData> {
map['source_id'] = Variable<int>(sourceId);
map['id'] = Variable<String>(id);
{
final converter = Queue.$convertercontext;
map['context'] = Variable<String>(converter.toSql(context));
map['context'] = Variable<String>(Queue.$convertercontext.toSql(context));
}
if (!nullToAbsent || contextId != null) {
map['context_id'] = Variable<String>(contextId);
@@ -315,8 +315,8 @@ class QueueCompanion extends UpdateCompanion<QueueData> {
map['id'] = Variable<String>(id.value);
}
if (context.present) {
final converter = Queue.$convertercontext;
map['context'] = Variable<String>(converter.toSql(context.value));
map['context'] =
Variable<String>(Queue.$convertercontext.toSql(context.value));
}
if (contextId.present) {
map['context_id'] = Variable<String>(contextId.value);
@@ -382,9 +382,10 @@ class LastAudioState extends Table
List<GeneratedColumn> get $columns =>
[id, queueMode, shuffleIndicies, repeat];
@override
String get aliasedName => _alias ?? 'last_audio_state';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'last_audio_state';
String get actualTableName => $name;
static const String $name = 'last_audio_state';
@override
VerificationContext validateIntegrity(Insertable<LastAudioStateData> instance,
{bool isInserting = false}) {
@@ -452,17 +453,16 @@ class LastAudioStateData extends DataClass
final map = <String, Expression>{};
map['id'] = Variable<int>(id);
{
final converter = LastAudioState.$converterqueueMode;
map['queue_mode'] = Variable<int>(converter.toSql(queueMode));
map['queue_mode'] =
Variable<int>(LastAudioState.$converterqueueMode.toSql(queueMode));
}
if (!nullToAbsent || shuffleIndicies != null) {
final converter = LastAudioState.$convertershuffleIndiciesn;
map['shuffle_indicies'] =
Variable<String>(converter.toSql(shuffleIndicies));
map['shuffle_indicies'] = Variable<String>(
LastAudioState.$convertershuffleIndiciesn.toSql(shuffleIndicies));
}
{
final converter = LastAudioState.$converterrepeat;
map['repeat'] = Variable<int>(converter.toSql(repeat));
map['repeat'] =
Variable<int>(LastAudioState.$converterrepeat.toSql(repeat));
}
return map;
}
@@ -592,17 +592,17 @@ class LastAudioStateCompanion extends UpdateCompanion<LastAudioStateData> {
map['id'] = Variable<int>(id.value);
}
if (queueMode.present) {
final converter = LastAudioState.$converterqueueMode;
map['queue_mode'] = Variable<int>(converter.toSql(queueMode.value));
map['queue_mode'] = Variable<int>(
LastAudioState.$converterqueueMode.toSql(queueMode.value));
}
if (shuffleIndicies.present) {
final converter = LastAudioState.$convertershuffleIndiciesn;
map['shuffle_indicies'] =
Variable<String>(converter.toSql(shuffleIndicies.value));
map['shuffle_indicies'] = Variable<String>(LastAudioState
.$convertershuffleIndiciesn
.toSql(shuffleIndicies.value));
}
if (repeat.present) {
final converter = LastAudioState.$converterrepeat;
map['repeat'] = Variable<int>(converter.toSql(repeat.value));
map['repeat'] =
Variable<int>(LastAudioState.$converterrepeat.toSql(repeat.value));
}
return map;
}
@@ -640,9 +640,10 @@ class LastBottomNavState extends Table
@override
List<GeneratedColumn> get $columns => [id, tab];
@override
String get aliasedName => _alias ?? 'last_bottom_nav_state';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'last_bottom_nav_state';
String get actualTableName => $name;
static const String $name = 'last_bottom_nav_state';
@override
VerificationContext validateIntegrity(
Insertable<LastBottomNavStateData> instance,
@@ -849,9 +850,10 @@ class LastLibraryState extends Table
List<GeneratedColumn> get $columns =>
[id, tab, albumsList, artistsList, playlistsList, songsList];
@override
String get aliasedName => _alias ?? 'last_library_state';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'last_library_state';
String get actualTableName => $name;
static const String $name = 'last_library_state';
@override
VerificationContext validateIntegrity(
Insertable<LastLibraryStateData> instance,
@@ -937,20 +939,20 @@ class LastLibraryStateData extends DataClass
map['id'] = Variable<int>(id);
map['tab'] = Variable<String>(tab);
{
final converter = LastLibraryState.$converteralbumsList;
map['albums_list'] = Variable<String>(converter.toSql(albumsList));
map['albums_list'] = Variable<String>(
LastLibraryState.$converteralbumsList.toSql(albumsList));
}
{
final converter = LastLibraryState.$converterartistsList;
map['artists_list'] = Variable<String>(converter.toSql(artistsList));
map['artists_list'] = Variable<String>(
LastLibraryState.$converterartistsList.toSql(artistsList));
}
{
final converter = LastLibraryState.$converterplaylistsList;
map['playlists_list'] = Variable<String>(converter.toSql(playlistsList));
map['playlists_list'] = Variable<String>(
LastLibraryState.$converterplaylistsList.toSql(playlistsList));
}
{
final converter = LastLibraryState.$convertersongsList;
map['songs_list'] = Variable<String>(converter.toSql(songsList));
map['songs_list'] = Variable<String>(
LastLibraryState.$convertersongsList.toSql(songsList));
}
return map;
}
@@ -1106,22 +1108,20 @@ class LastLibraryStateCompanion extends UpdateCompanion<LastLibraryStateData> {
map['tab'] = Variable<String>(tab.value);
}
if (albumsList.present) {
final converter = LastLibraryState.$converteralbumsList;
map['albums_list'] = Variable<String>(converter.toSql(albumsList.value));
map['albums_list'] = Variable<String>(
LastLibraryState.$converteralbumsList.toSql(albumsList.value));
}
if (artistsList.present) {
final converter = LastLibraryState.$converterartistsList;
map['artists_list'] =
Variable<String>(converter.toSql(artistsList.value));
map['artists_list'] = Variable<String>(
LastLibraryState.$converterartistsList.toSql(artistsList.value));
}
if (playlistsList.present) {
final converter = LastLibraryState.$converterplaylistsList;
map['playlists_list'] =
Variable<String>(converter.toSql(playlistsList.value));
map['playlists_list'] = Variable<String>(
LastLibraryState.$converterplaylistsList.toSql(playlistsList.value));
}
if (songsList.present) {
final converter = LastLibraryState.$convertersongsList;
map['songs_list'] = Variable<String>(converter.toSql(songsList.value));
map['songs_list'] = Variable<String>(
LastLibraryState.$convertersongsList.toSql(songsList.value));
}
return map;
}
@@ -1177,9 +1177,10 @@ class AppSettingsTable extends Table
List<GeneratedColumn> get $columns =>
[id, maxBitrateWifi, maxBitrateMobile, streamFormat];
@override
String get aliasedName => _alias ?? 'app_settings';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'app_settings';
String get actualTableName => $name;
static const String $name = 'app_settings';
@override
VerificationContext validateIntegrity(Insertable<AppSettings> instance,
{bool isInserting = false}) {
@@ -1359,9 +1360,10 @@ class Sources extends Table with TableInfo<Sources, Source> {
List<GeneratedColumn> get $columns =>
[id, name, address, isActive, createdAt];
@override
String get aliasedName => _alias ?? 'sources';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'sources';
String get actualTableName => $name;
static const String $name = 'sources';
@override
VerificationContext validateIntegrity(Insertable<Source> instance,
{bool isInserting = false}) {
@@ -1435,8 +1437,8 @@ class Source extends DataClass implements Insertable<Source> {
map['id'] = Variable<int>(id);
map['name'] = Variable<String>(name);
{
final converter = Sources.$converteraddress;
map['address'] = Variable<String>(converter.toSql(address));
map['address'] =
Variable<String>(Sources.$converteraddress.toSql(address));
}
if (!nullToAbsent || isActive != null) {
map['is_active'] = Variable<bool>(isActive);
@@ -1580,8 +1582,8 @@ class SourcesCompanion extends UpdateCompanion<Source> {
map['name'] = Variable<String>(name.value);
}
if (address.present) {
final converter = Sources.$converteraddress;
map['address'] = Variable<String>(converter.toSql(address.value));
map['address'] =
Variable<String>(Sources.$converteraddress.toSql(address.value));
}
if (isActive.present) {
map['is_active'] = Variable<bool>(isActive.value);
@@ -1653,9 +1655,10 @@ class SubsonicSources extends Table
List<GeneratedColumn> get $columns =>
[sourceId, features, username, password, useTokenAuth];
@override
String get aliasedName => _alias ?? 'subsonic_sources';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'subsonic_sources';
String get actualTableName => $name;
static const String $name = 'subsonic_sources';
@override
VerificationContext validateIntegrity(Insertable<SubsonicSource> instance,
{bool isInserting = false}) {
@@ -1738,8 +1741,8 @@ class SubsonicSource extends DataClass implements Insertable<SubsonicSource> {
final map = <String, Expression>{};
map['source_id'] = Variable<int>(sourceId);
{
final converter = SubsonicSources.$converterfeatures;
map['features'] = Variable<String>(converter.toSql(features));
map['features'] =
Variable<String>(SubsonicSources.$converterfeatures.toSql(features));
}
map['username'] = Variable<String>(username);
map['password'] = Variable<String>(password);
@@ -1879,8 +1882,8 @@ class SubsonicSourcesCompanion extends UpdateCompanion<SubsonicSource> {
map['source_id'] = Variable<int>(sourceId.value);
}
if (features.present) {
final converter = SubsonicSources.$converterfeatures;
map['features'] = Variable<String>(converter.toSql(features.value));
map['features'] = Variable<String>(
SubsonicSources.$converterfeatures.toSql(features.value));
}
if (username.present) {
map['username'] = Variable<String>(username.value);
@@ -1959,9 +1962,10 @@ class Artists extends Table with TableInfo<Artists, Artist> {
List<GeneratedColumn> get $columns =>
[sourceId, id, name, albumCount, starred, updated];
@override
String get aliasedName => _alias ?? 'artists';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'artists';
String get actualTableName => $name;
static const String $name = 'artists';
@override
VerificationContext validateIntegrity(Insertable<Artist> instance,
{bool isInserting = false}) {
@@ -2170,9 +2174,10 @@ class ArtistsFts extends Table
@override
List<GeneratedColumn> get $columns => [sourceId, name];
@override
String get aliasedName => _alias ?? 'artists_fts';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'artists_fts';
String get actualTableName => $name;
static const String $name = 'artists_fts';
@override
VerificationContext validateIntegrity(Insertable<ArtistsFt> instance,
{bool isInserting = false}) {
@@ -2468,9 +2473,10 @@ class Albums extends Table with TableInfo<Albums, Album> {
updated
];
@override
String get aliasedName => _alias ?? 'albums';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'albums';
String get actualTableName => $name;
static const String $name = 'albums';
@override
VerificationContext validateIntegrity(Insertable<Album> instance,
{bool isInserting = false}) {
@@ -2837,9 +2843,10 @@ class AlbumsFts extends Table
@override
List<GeneratedColumn> get $columns => [sourceId, name];
@override
String get aliasedName => _alias ?? 'albums_fts';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'albums_fts';
String get actualTableName => $name;
static const String $name = 'albums_fts';
@override
VerificationContext validateIntegrity(Insertable<AlbumsFt> instance,
{bool isInserting = false}) {
@@ -3072,9 +3079,10 @@ class Playlists extends Table with TableInfo<Playlists, Playlist> {
List<GeneratedColumn> get $columns =>
[sourceId, id, name, comment, coverArt, songCount, created, updated];
@override
String get aliasedName => _alias ?? 'playlists';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'playlists';
String get actualTableName => $name;
static const String $name = 'playlists';
@override
VerificationContext validateIntegrity(Insertable<Playlist> instance,
{bool isInserting = false}) {
@@ -3340,9 +3348,10 @@ class PlaylistSongs extends Table with TableInfo<PlaylistSongs, PlaylistSong> {
List<GeneratedColumn> get $columns =>
[sourceId, playlistId, songId, position, updated];
@override
String get aliasedName => _alias ?? 'playlist_songs';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'playlist_songs';
String get actualTableName => $name;
static const String $name = 'playlist_songs';
@override
VerificationContext validateIntegrity(Insertable<PlaylistSong> instance,
{bool isInserting = false}) {
@@ -3632,9 +3641,10 @@ class PlaylistsFts extends Table
@override
List<GeneratedColumn> get $columns => [sourceId, name];
@override
String get aliasedName => _alias ?? 'playlists_fts';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'playlists_fts';
String get actualTableName => $name;
static const String $name = 'playlists_fts';
@override
VerificationContext validateIntegrity(Insertable<PlaylistsFt> instance,
{bool isInserting = false}) {
@@ -3936,9 +3946,10 @@ class Songs extends Table with TableInfo<Songs, Song> {
updated
];
@override
String get aliasedName => _alias ?? 'songs';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'songs';
String get actualTableName => $name;
static const String $name = 'songs';
@override
VerificationContext validateIntegrity(Insertable<Song> instance,
{bool isInserting = false}) {
@@ -4236,8 +4247,8 @@ class SongsCompanion extends UpdateCompanion<Song> {
map['artist'] = Variable<String>(artist.value);
}
if (duration.present) {
final converter = Songs.$converterdurationn;
map['duration'] = Variable<int>(converter.toSql(duration.value));
map['duration'] =
Variable<int>(Songs.$converterdurationn.toSql(duration.value));
}
if (track.present) {
map['track'] = Variable<int>(track.value);
@@ -4316,9 +4327,10 @@ class SongsFts extends Table
@override
List<GeneratedColumn> get $columns => [sourceId, title];
@override
String get aliasedName => _alias ?? 'songs_fts';
String get aliasedName => _alias ?? actualTableName;
@override
String get actualTableName => 'songs_fts';
String get actualTableName => $name;
static const String $name = 'songs_fts';
@override
VerificationContext validateIntegrity(Insertable<SongsFt> instance,
{bool isInserting = false}) {
@@ -5570,4 +5582,5 @@ final databaseProvider = Provider<SubtracksDatabase>.internal(
);
typedef DatabaseRef = ProviderRef<SubtracksDatabase>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -0,0 +1,94 @@
import 'dart:async';
import 'package:drift/drift.dart';
import 'package:drift/isolate.dart';
/// https://github.com/simolus3/drift/issues/2326#issuecomment-1445138730
class ErrorLoggingDatabase implements QueryExecutor {
final QueryExecutor inner;
final void Function(Object, StackTrace) onError;
ErrorLoggingDatabase(this.inner, this.onError);
Future<T> _handleErrors<T>(Future<T> Function() body) {
return Future.sync(body)
.onError<DriftWrappedException>((error, stackTrace) {
onError(error, error.trace ?? stackTrace);
throw error;
}).onError<DriftRemoteException>((error, stackTrace) {
onError(error, error.remoteStackTrace ?? stackTrace);
throw error;
});
}
@override
TransactionExecutor beginTransaction() {
return _ErrorLoggingTransactionExecutor(inner.beginTransaction(), onError);
}
@override
Future<void> close() {
return _handleErrors(inner.close);
}
@override
SqlDialect get dialect => inner.dialect;
@override
Future<bool> ensureOpen(QueryExecutorUser user) {
return _handleErrors(() => inner.ensureOpen(user));
}
@override
Future<void> runBatched(BatchedStatements statements) {
return _handleErrors(() => inner.runBatched(statements));
}
@override
Future<void> runCustom(String statement, [List<Object?>? args]) {
return _handleErrors(() => inner.runCustom(statement, args));
}
@override
Future<int> runDelete(String statement, List<Object?> args) {
return _handleErrors(() => inner.runDelete(statement, args));
}
@override
Future<int> runInsert(String statement, List<Object?> args) {
return _handleErrors(() => inner.runInsert(statement, args));
}
@override
Future<List<Map<String, Object?>>> runSelect(
String statement, List<Object?> args) {
return _handleErrors(() => inner.runSelect(statement, args));
}
@override
Future<int> runUpdate(String statement, List<Object?> args) {
return _handleErrors(() => inner.runUpdate(statement, args));
}
}
class _ErrorLoggingTransactionExecutor extends ErrorLoggingDatabase
implements TransactionExecutor {
final TransactionExecutor transaction;
_ErrorLoggingTransactionExecutor(
this.transaction, void Function(Object, StackTrace) onError)
: super(transaction, onError);
@override
Future<void> rollback() {
return _handleErrors(transaction.rollback);
}
@override
Future<void> send() {
return _handleErrors(transaction.send);
}
@override
bool get supportsNestedTransactions => transaction.supportsNestedTransactions;
}

View File

@@ -1,7 +1,8 @@
import 'package:flutter/foundation.dart';
import 'package:http/http.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import '../log.dart';
part 'client.g.dart';
const Map<String, String> subtracksHeaders = {
@@ -14,8 +15,14 @@ class SubtracksHttpClient extends BaseClient {
@override
Future<StreamedResponse> send(BaseRequest request) {
request.headers.addAll(subtracksHeaders);
if (kDebugMode) print('${request.method} ${request.url}');
return request.send();
log.info('${request.method} ${request.url}');
try {
return request.send();
} catch (e, st) {
log.severe('HTTP client: ${request.method} ${request.url}', e, st);
rethrow;
}
}
}

View File

@@ -20,4 +20,5 @@ final httpClientProvider = Provider<BaseClient>.internal(
);
typedef HttpClientRef = ProviderRef<BaseClient>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -1,166 +1,226 @@
{
"actionsStar": "Ohodnotit",
"@actionsStar": {},
"actionsUnstar": "Zrušit hodnocení",
"@actionsUnstar": {},
"messagesNothingHere": "Zde nic není…",
"@messagesNothingHere": {},
"navigationTabsHome": "Domů",
"@navigationTabsHome": {},
"navigationTabsLibrary": "Knihovna",
"@navigationTabsLibrary": {},
"navigationTabsSearch": "Hledat",
"@navigationTabsSearch": {},
"navigationTabsSettings": "Nastavení",
"@navigationTabsSettings": {},
"resourcesAlbumActionsPlay": "Přehrát album",
"@resourcesAlbumActionsPlay": {},
"resourcesAlbumActionsView": "Zobrazit album",
"@resourcesAlbumActionsView": {},
"resourcesAlbumListsSort": "Seřadit alba",
"@resourcesAlbumListsSort": {},
"resourcesAlbumName": "{count,plural, =1{Album} few{Alba} many{Alba} other{Alba}}",
"@resourcesAlbumName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesArtistActionsView": "Zobrazit umělce",
"@resourcesArtistActionsView": {},
"resourcesArtistListsSort": "Seřadit umělce",
"@resourcesArtistListsSort": {},
"resourcesArtistName": "{count,plural, =1{Umělec} few{Umělci} many{Umělci} other{Umělci}}",
"@resourcesArtistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterGenre": "Podle žánru",
"@resourcesFilterGenre": {},
"resourcesFilterStarred": "Ohodnocené",
"@resourcesFilterStarred": {},
"resourcesPlaylistActionsPlay": "Přehrát seznam skladeb",
"@resourcesPlaylistActionsPlay": {},
"resourcesPlaylistName": "{count,plural, =1{Seznam skladeb} few{Seznamy skladeb} many{Seznamy skladeb} other{Seznamy skladeb}}",
"@resourcesPlaylistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesQueueName": "{count,plural, =1{Fronta} few{Fronty} many{Fronty} other{Fronty}}",
"@resourcesQueueName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongListsArtistTopSongs": "Top skladby",
"@resourcesSongListsArtistTopSongs": {},
"resourcesSongName": "{count,plural, =1{Skladba} few{Skladby} many{Skladby} other{Skladby}}",
"@resourcesSongName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSortByAdded": "Nedávno přidané",
"@resourcesSortByAdded": {},
"resourcesSortByArtist": "Podle umělce",
"@resourcesSortByArtist": {},
"resourcesSortByFrequentlyPlayed": "Často přehrávané",
"@resourcesSortByFrequentlyPlayed": {},
"resourcesSortByName": "Podle názvu",
"@resourcesSortByName": {},
"resourcesSortByRandom": "Náhodně",
"@resourcesSortByRandom": {},
"resourcesSortByRecentlyPlayed": "Často přehrávané",
"@resourcesSortByRecentlyPlayed": {},
"resourcesSortByYear": "Podle roku",
"@resourcesSortByYear": {},
"searchHeaderTitle": "Hledat: {query}",
"@searchHeaderTitle": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"searchInputPlaceholder": "Hledat",
"@searchInputPlaceholder": {},
"searchMoreResults": "Více…",
"@searchMoreResults": {},
"searchNowPlayingContext": "Výsledky hledání",
"@searchNowPlayingContext": {},
"settingsNetworkName": "Síť",
"@settingsNetworkName": {},
"settingsNetworkOptionsMaxBitrateMobileTitle": "Maximální datový tok (mobil)",
"@settingsNetworkOptionsMaxBitrateMobileTitle": {},
"settingsNetworkOptionsMaxBitrateWifiTitle": "Maximální datový tok (Wi-Fi)",
"@settingsNetworkOptionsMaxBitrateWifiTitle": {},
"settingsNetworkValuesKbps": "{value}kbps",
"@settingsNetworkValuesKbps": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesSeconds": "{value} sekund",
"@settingsNetworkValuesSeconds": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesUnlimitedKbps": "Neomezeno",
"@settingsNetworkValuesUnlimitedKbps": {},
"settingsServersActionsAdd": "Přidat server",
"@settingsServersActionsAdd": {},
"settingsServersActionsDelete": "Odstranit",
"@settingsServersActionsDelete": {},
"settingsServersActionsEdit": "Upravit server",
"@settingsServersActionsEdit": {},
"settingsServersActionsSave": "Uložit",
"@settingsServersActionsSave": {},
"settingsServersActionsTestConnection": "Otestovat spojení",
"@settingsServersActionsTestConnection": {},
"settingsServersFieldsAddress": "Adresa",
"@settingsServersFieldsAddress": {},
"settingsServersFieldsPassword": "Heslo",
"@settingsServersFieldsPassword": {},
"settingsServersFieldsUsername": "Uživ. jméno",
"@settingsServersFieldsUsername": {},
"settingsServersMessagesConnectionFailed": "Připojení k {address} selhalo, zkontrolujte nastavení nebo server",
"@settingsServersMessagesConnectionFailed": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersMessagesConnectionOk": "Připojení k {address} je OK!",
"@settingsServersMessagesConnectionOk": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersName": "Servery",
"@settingsServersName": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOff": "Posílat heslo jako token + salt",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOff": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOn": "Posílat heslo v prostém textu (zastaralé, ujistěte se, že je vaše připojení zabezpečené!)",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOn": {},
"settingsServersOptionsForcePlaintextPasswordTitle": "Vynutit heslo ve formátu prostého textu",
"@settingsServersOptionsForcePlaintextPasswordTitle": {}
}
"actionsStar": "Ohodnotit",
"@actionsStar": {},
"actionsUnstar": "Zrušit hodnocení",
"@actionsUnstar": {},
"messagesNothingHere": "Zde nic není…",
"@messagesNothingHere": {},
"navigationTabsHome": "Domů",
"@navigationTabsHome": {},
"navigationTabsLibrary": "Knihovna",
"@navigationTabsLibrary": {},
"navigationTabsSearch": "Hledat",
"@navigationTabsSearch": {},
"navigationTabsSettings": "Nastavení",
"@navigationTabsSettings": {},
"resourcesAlbumActionsPlay": "Přehrát album",
"@resourcesAlbumActionsPlay": {},
"resourcesAlbumActionsView": "Zobrazit album",
"@resourcesAlbumActionsView": {},
"resourcesAlbumListsSort": "Seřadit alba",
"@resourcesAlbumListsSort": {},
"resourcesAlbumName": "{count,plural, =1{Album} few{Alba} many{Alba} other{Alba}}",
"@resourcesAlbumName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesArtistActionsView": "Zobrazit umělce",
"@resourcesArtistActionsView": {},
"resourcesArtistListsSort": "Seřadit umělce",
"@resourcesArtistListsSort": {},
"resourcesArtistName": "{count,plural, =1{Umělec} few{Umělci} many{Umělci} other{Umělci}}",
"@resourcesArtistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterGenre": "Podle žánru",
"@resourcesFilterGenre": {},
"resourcesFilterStarred": "Ohodnocené",
"@resourcesFilterStarred": {},
"resourcesPlaylistActionsPlay": "Přehrát seznam skladeb",
"@resourcesPlaylistActionsPlay": {},
"resourcesPlaylistName": "{count,plural, =1{Seznam skladeb} few{Seznamy skladeb} many{Seznamy skladeb} other{Seznamy skladeb}}",
"@resourcesPlaylistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesQueueName": "{count,plural, =1{Fronta} few{Fronty} many{Fronty} other{Fronty}}",
"@resourcesQueueName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongListsArtistTopSongs": "Top skladby",
"@resourcesSongListsArtistTopSongs": {},
"resourcesSongName": "{count,plural, =1{Skladba} few{Skladby} many{Skladby} other{Skladby}}",
"@resourcesSongName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSortByAdded": "Nedávno přidané",
"@resourcesSortByAdded": {},
"resourcesSortByArtist": "Umělce",
"@resourcesSortByArtist": {},
"resourcesSortByFrequentlyPlayed": "Často přehrávané",
"@resourcesSortByFrequentlyPlayed": {},
"resourcesSortByName": "Názvu",
"@resourcesSortByName": {},
"resourcesSortByRandom": "Náhodně",
"@resourcesSortByRandom": {},
"resourcesSortByRecentlyPlayed": "Často přehrávané",
"@resourcesSortByRecentlyPlayed": {},
"resourcesSortByYear": "Roku",
"@resourcesSortByYear": {},
"searchHeaderTitle": "Hledat: {query}",
"@searchHeaderTitle": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"searchInputPlaceholder": "Hledat",
"@searchInputPlaceholder": {},
"searchMoreResults": "Více…",
"@searchMoreResults": {},
"searchNowPlayingContext": "Výsledky hledání",
"@searchNowPlayingContext": {},
"settingsNetworkName": "Síť",
"@settingsNetworkName": {},
"settingsNetworkOptionsMaxBitrateMobileTitle": "Maximální datový tok (mobil)",
"@settingsNetworkOptionsMaxBitrateMobileTitle": {},
"settingsNetworkOptionsMaxBitrateWifiTitle": "Maximální datový tok (Wi-Fi)",
"@settingsNetworkOptionsMaxBitrateWifiTitle": {},
"settingsNetworkValuesKbps": "{value}kbps",
"@settingsNetworkValuesKbps": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesSeconds": "{value} sekund",
"@settingsNetworkValuesSeconds": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesUnlimitedKbps": "Neomezeno",
"@settingsNetworkValuesUnlimitedKbps": {},
"settingsServersActionsAdd": "Přidat server",
"@settingsServersActionsAdd": {},
"settingsServersActionsDelete": "Odstranit",
"@settingsServersActionsDelete": {},
"settingsServersActionsEdit": "Upravit server",
"@settingsServersActionsEdit": {},
"settingsServersActionsSave": "Uložit",
"@settingsServersActionsSave": {},
"settingsServersActionsTestConnection": "Otestovat spojení",
"@settingsServersActionsTestConnection": {},
"settingsServersFieldsAddress": "Adresa",
"@settingsServersFieldsAddress": {},
"settingsServersFieldsPassword": "Heslo",
"@settingsServersFieldsPassword": {},
"settingsServersFieldsUsername": "Uživ. jméno",
"@settingsServersFieldsUsername": {},
"settingsServersMessagesConnectionFailed": "Připojení k {address} selhalo, zkontrolujte nastavení nebo server",
"@settingsServersMessagesConnectionFailed": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersMessagesConnectionOk": "Připojení k {address} je OK!",
"@settingsServersMessagesConnectionOk": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersName": "Servery",
"@settingsServersName": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOff": "Posílat heslo jako token + salt",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOff": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOn": "Posílat heslo v prostém textu (zastaralé, ujistěte se, že je vaše připojení zabezpečené!)",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOn": {},
"settingsServersOptionsForcePlaintextPasswordTitle": "Vynutit heslo ve formátu prostého textu",
"@settingsServersOptionsForcePlaintextPasswordTitle": {},
"actionsDownloadDelete": "Smazat stažené",
"@actionsDownloadDelete": {},
"actionsOk": "OK",
"@actionsOk": {},
"actionsCancel": "Zrušit",
"@actionsCancel": {},
"actionsDownload": "Stáhnout",
"@actionsDownload": {},
"controlsShuffle": "Náhodně",
"@controlsShuffle": {},
"resourcesFilterAlbum": "Album",
"@resourcesFilterAlbum": {},
"resourcesFilterArtist": "Umělec",
"@resourcesFilterArtist": {},
"resourcesFilterYear": "Rok",
"@resourcesFilterYear": {},
"resourcesFilterOwner": "Majitele",
"@resourcesFilterOwner": {},
"resourcesSongListDeleteAllTitle": "Smazat stažené?",
"@resourcesSongListDeleteAllTitle": {},
"resourcesSongListDeleteAllContent": "Toto odstraní všechny stažené soubory s hudbou.",
"@resourcesSongListDeleteAllContent": {},
"resourcesSortByUpdated": "Naposledy upravené",
"@resourcesSortByUpdated": {},
"resourcesSortByAlbum": "Alba",
"@resourcesSortByAlbum": {},
"resourcesSortByAlbumCount": "Počtu alb",
"@resourcesSortByAlbumCount": {},
"resourcesSortByTitle": "Názvu",
"@resourcesSortByTitle": {},
"settingsAboutActionsLicenses": "Licence",
"@settingsAboutActionsLicenses": {},
"settingsAboutActionsProjectHomepage": "Stránka projektu",
"@settingsAboutActionsProjectHomepage": {},
"settingsAboutActionsSupport": "Podpořit vývojáře 💜",
"@settingsAboutActionsSupport": {},
"settingsAboutVersion": "verze {version}",
"@settingsAboutVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"settingsNetworkOptionsStreamFormat": "Preferovaný formát pro streamování",
"@settingsNetworkOptionsStreamFormat": {},
"settingsNetworkOptionsStreamFormatServerDefault": "Použít nastavení serveru",
"@settingsNetworkOptionsStreamFormatServerDefault": {},
"settingsResetActionsClearImageCache": "Smazat mezipaměť obrázků",
"@settingsResetActionsClearImageCache": {},
"settingsResetName": "Resetovat",
"@settingsResetName": {},
"settingsServersFieldsName": "Jméno",
"@settingsServersFieldsName": {},
"settingsAboutName": "O aplikaci",
"@settingsAboutName": {},
"actionsDownloadCancel": "Zrušit stahování",
"@actionsDownloadCancel": {},
"actionsDelete": "Smazat",
"@actionsDelete": {}
}

View File

@@ -202,5 +202,75 @@
"controlsShuffle": "Zufall",
"@controlsShuffle": {},
"actionsCancel": "Abbrechen",
"@actionsCancel": {}
"@actionsCancel": {},
"actionsDownloadDelete": "Heruntergeladene Inhalte löschen",
"@actionsDownloadDelete": {},
"actionsOk": "OK",
"@actionsOk": {},
"resourcesAlbumCount": "{count,plural, =1{{count} Album} other{{count} Alben}}",
"@resourcesAlbumCount": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterAlbum": "Album",
"@resourcesFilterAlbum": {},
"resourcesArtistCount": "{count,plural, =1{{count} Künstler} other{{count} Künstler}}",
"@resourcesArtistCount": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterArtist": "Künstler",
"@resourcesFilterArtist": {},
"resourcesFilterOwner": "Besitzer",
"@resourcesFilterOwner": {},
"resourcesFilterYear": "Jahr",
"@resourcesFilterYear": {},
"resourcesPlaylistCount": "{count,plural, =1{{count} Playlist} other{{count} Playlists}}",
"@resourcesPlaylistCount": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongCount": "{count,plural, =1{{count} Song} other{{count} Songs}}",
"@resourcesSongCount": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongListDeleteAllContent": "Hierdurch werden alle heruntergeladenen Inhalte entfernt.",
"@resourcesSongListDeleteAllContent": {},
"resourcesSortByAlbum": "Album",
"@resourcesSortByAlbum": {},
"resourcesSortByAlbumCount": "Albenanzahl",
"@resourcesSortByAlbumCount": {},
"resourcesSortByTitle": "Titel",
"@resourcesSortByTitle": {},
"resourcesSortByUpdated": "Kürzlich hinzugefügt",
"@resourcesSortByUpdated": {},
"settingsAboutActionsSupport": "Den Entwickler unterstützen",
"@settingsAboutActionsSupport": {},
"settingsNetworkOptionsOfflineMode": "Offline Modus",
"@settingsNetworkOptionsOfflineMode": {},
"settingsNetworkOptionsOfflineModeOff": "Nutze das Internet um Musik zu synchronisieren.",
"@settingsNetworkOptionsOfflineModeOff": {},
"settingsNetworkOptionsOfflineModeOn": "Nutze nicht das Internet um Musik zu synchronisieren.",
"@settingsNetworkOptionsOfflineModeOn": {},
"settingsNetworkOptionsStreamFormat": "Bevorzugtes Streaming-Format",
"@settingsNetworkOptionsStreamFormat": {},
"settingsServersFieldsName": "Name",
"@settingsServersFieldsName": {},
"resourcesSongListDeleteAllTitle": "Downloads löschen?",
"@resourcesSongListDeleteAllTitle": {},
"settingsNetworkOptionsStreamFormatServerDefault": "Server-Standard verwenden",
"@settingsNetworkOptionsStreamFormatServerDefault": {}
}

View File

@@ -173,6 +173,10 @@
"@settingsAboutActionsSupport": {},
"settingsAboutName": "About",
"@settingsAboutName": {},
"settingsAboutShareLogs": "Share logs",
"@settingsAboutShareLogs": {},
"settingsAboutChooseLog": "Choose a log file",
"@settingsAboutChooseLog": {},
"settingsAboutVersion": "version {version}",
"@settingsAboutVersion": {
"placeholders": {

View File

@@ -272,5 +272,9 @@
"resourcesSortByTitle": "Título",
"@resourcesSortByTitle": {},
"resourcesSortByUpdated": "Actualizado recentemente",
"@resourcesSortByUpdated": {}
"@resourcesSortByUpdated": {},
"settingsAboutShareLogs": "Compartir rexistros",
"@settingsAboutShareLogs": {},
"settingsAboutChooseLog": "Escolle un ficheiro de rexistro",
"@settingsAboutChooseLog": {}
}

View File

@@ -1,196 +1,230 @@
{
"actionsStar": "Favorito",
"@actionsStar": {},
"actionsUnstar": "Remover favorito",
"@actionsUnstar": {},
"messagesNothingHere": "Não existe nada…",
"@messagesNothingHere": {},
"navigationTabsHome": "Início",
"@navigationTabsHome": {},
"navigationTabsLibrary": "Biblioteca",
"@navigationTabsLibrary": {},
"navigationTabsSearch": "Procurar",
"@navigationTabsSearch": {},
"navigationTabsSettings": "Definições",
"@navigationTabsSettings": {},
"resourcesAlbumActionsPlay": "Tocar Álbum",
"@resourcesAlbumActionsPlay": {},
"resourcesAlbumActionsView": "Ver Álbum",
"@resourcesAlbumActionsView": {},
"resourcesAlbumListsSort": "Ordenar Álbuns",
"@resourcesAlbumListsSort": {},
"resourcesAlbumName": "{count,plural, =1{Álbum} other{Álbuns}}",
"@resourcesAlbumName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesArtistActionsView": "Ver Artista",
"@resourcesArtistActionsView": {},
"resourcesArtistListsSort": "Ordenar Artistas",
"@resourcesArtistListsSort": {},
"resourcesArtistName": "{count,plural, =1{Artista} other{Artistas}}",
"@resourcesArtistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterGenre": "Por Género",
"@resourcesFilterGenre": {},
"resourcesFilterStarred": "Favoritos",
"@resourcesFilterStarred": {},
"resourcesPlaylistActionsPlay": "Tocar Playlist",
"@resourcesPlaylistActionsPlay": {},
"resourcesPlaylistName": "{count,plural, =1{Lista} other{Listas}}",
"@resourcesPlaylistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesQueueName": "{count,plural, =1{Fila} other{Filas}}",
"@resourcesQueueName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongListsArtistTopSongs": "Top Músicas",
"@resourcesSongListsArtistTopSongs": {},
"resourcesSongName": "{count,plural, =1{Música} other{Músicas}}",
"@resourcesSongName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSortByAdded": "Adicionado recentemente",
"@resourcesSortByAdded": {},
"resourcesSortByArtist": "Por Artista",
"@resourcesSortByArtist": {},
"resourcesSortByFrequentlyPlayed": "Mais Tocado",
"@resourcesSortByFrequentlyPlayed": {},
"resourcesSortByName": "Por Nome",
"@resourcesSortByName": {},
"resourcesSortByRandom": "Aleatório",
"@resourcesSortByRandom": {},
"resourcesSortByRecentlyPlayed": "Ouviu recentemente",
"@resourcesSortByRecentlyPlayed": {},
"resourcesSortByYear": "Por Ano",
"@resourcesSortByYear": {},
"searchHeaderTitle": "Procurar: {query}",
"@searchHeaderTitle": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"searchInputPlaceholder": "Procurar",
"@searchInputPlaceholder": {},
"searchMoreResults": "Mais…",
"@searchMoreResults": {},
"searchNowPlayingContext": "Resultados da Pesquisa",
"@searchNowPlayingContext": {},
"settingsAboutActionsLicenses": "Licenças",
"@settingsAboutActionsLicenses": {},
"settingsAboutActionsProjectHomepage": "Página do Projeto",
"@settingsAboutActionsProjectHomepage": {},
"settingsAboutName": "Acerca",
"@settingsAboutName": {},
"settingsAboutVersion": "versão {version}",
"@settingsAboutVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"settingsMusicName": "Música",
"@settingsMusicName": {},
"settingsMusicOptionsScrobbleDescriptionOff": "Não enviar histórico de reproduções por scrobble",
"@settingsMusicOptionsScrobbleDescriptionOff": {},
"settingsMusicOptionsScrobbleDescriptionOn": "Enviar histórico de reproduções por scrobble",
"@settingsMusicOptionsScrobbleDescriptionOn": {},
"settingsMusicOptionsScrobbleTitle": "Enviar reproduções por scrobble",
"@settingsMusicOptionsScrobbleTitle": {},
"settingsNetworkName": "Rede",
"@settingsNetworkName": {},
"settingsNetworkOptionsMaxBitrateMobileTitle": "Bitrate Máximo (móvel)",
"@settingsNetworkOptionsMaxBitrateMobileTitle": {},
"settingsNetworkOptionsMaxBitrateWifiTitle": "Bitrate Máximo (Wi-Fi)",
"@settingsNetworkOptionsMaxBitrateWifiTitle": {},
"settingsNetworkOptionsMaxBufferTitle": "Tempo de buffer máximo",
"@settingsNetworkOptionsMaxBufferTitle": {},
"settingsNetworkOptionsMinBufferTitle": "Tempo de buffer mínimo",
"@settingsNetworkOptionsMinBufferTitle": {},
"settingsNetworkValuesKbps": "{value}kbps",
"@settingsNetworkValuesKbps": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesSeconds": "{value} segundos",
"@settingsNetworkValuesSeconds": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesUnlimitedKbps": "Ilimitado",
"@settingsNetworkValuesUnlimitedKbps": {},
"settingsResetActionsClearImageCache": "Limpar cache de Imagens",
"@settingsResetActionsClearImageCache": {},
"settingsResetName": "Redefinir",
"@settingsResetName": {},
"settingsServersActionsAdd": "Adicionar Servidor",
"@settingsServersActionsAdd": {},
"settingsServersActionsDelete": "Apagar",
"@settingsServersActionsDelete": {},
"settingsServersActionsEdit": "Editar Servidor",
"@settingsServersActionsEdit": {},
"settingsServersActionsSave": "Guardar",
"@settingsServersActionsSave": {},
"settingsServersActionsTestConnection": "Testar Ligação",
"@settingsServersActionsTestConnection": {},
"settingsServersFieldsAddress": "Endereço",
"@settingsServersFieldsAddress": {},
"settingsServersFieldsPassword": "Senha",
"@settingsServersFieldsPassword": {},
"settingsServersFieldsUsername": "Nome de utilizador",
"@settingsServersFieldsUsername": {},
"settingsServersMessagesConnectionFailed": "Ligação a {address} falhou, verifique definições ou servidor",
"@settingsServersMessagesConnectionFailed": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersMessagesConnectionOk": "Ligação a {address} OK!",
"@settingsServersMessagesConnectionOk": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersName": "Servidores",
"@settingsServersName": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOff": "Enviar senha como token + sal",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOff": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOn": "Enviar senha em texto simples (antigo, certifique-se que a sua ligação é segura!)",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOn": {},
"settingsServersOptionsForcePlaintextPasswordTitle": "Forçar password em texto simples",
"@settingsServersOptionsForcePlaintextPasswordTitle": {}
}
"actionsStar": "Favorito",
"@actionsStar": {},
"actionsUnstar": "Remover favorito",
"@actionsUnstar": {},
"messagesNothingHere": "Não existe nada…",
"@messagesNothingHere": {},
"navigationTabsHome": "Início",
"@navigationTabsHome": {},
"navigationTabsLibrary": "Biblioteca",
"@navigationTabsLibrary": {},
"navigationTabsSearch": "Procurar",
"@navigationTabsSearch": {},
"navigationTabsSettings": "Definições",
"@navigationTabsSettings": {},
"resourcesAlbumActionsPlay": "Tocar Álbum",
"@resourcesAlbumActionsPlay": {},
"resourcesAlbumActionsView": "Ver Álbum",
"@resourcesAlbumActionsView": {},
"resourcesAlbumListsSort": "Ordenar Álbuns",
"@resourcesAlbumListsSort": {},
"resourcesAlbumName": "{count,plural, =1{Álbum} other{Álbuns}}",
"@resourcesAlbumName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesArtistActionsView": "Ver Artista",
"@resourcesArtistActionsView": {},
"resourcesArtistListsSort": "Ordenar Artistas",
"@resourcesArtistListsSort": {},
"resourcesArtistName": "{count,plural, =1{Artista} other{Artistas}}",
"@resourcesArtistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterGenre": "Por Género",
"@resourcesFilterGenre": {},
"resourcesFilterStarred": "Favoritos",
"@resourcesFilterStarred": {},
"resourcesPlaylistActionsPlay": "Tocar Playlist",
"@resourcesPlaylistActionsPlay": {},
"resourcesPlaylistName": "{count,plural, =1{Lista} other{Listas}}",
"@resourcesPlaylistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesQueueName": "{count,plural, =1{Fila} other{Filas}}",
"@resourcesQueueName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongListsArtistTopSongs": "Top Músicas",
"@resourcesSongListsArtistTopSongs": {},
"resourcesSongName": "{count,plural, =1{Música} other{Músicas}}",
"@resourcesSongName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSortByAdded": "Adicionado recentemente",
"@resourcesSortByAdded": {},
"resourcesSortByArtist": "Por Artista",
"@resourcesSortByArtist": {},
"resourcesSortByFrequentlyPlayed": "Mais Tocado",
"@resourcesSortByFrequentlyPlayed": {},
"resourcesSortByName": "Por Nome",
"@resourcesSortByName": {},
"resourcesSortByRandom": "Aleatório",
"@resourcesSortByRandom": {},
"resourcesSortByRecentlyPlayed": "Ouviu recentemente",
"@resourcesSortByRecentlyPlayed": {},
"resourcesSortByYear": "Por Ano",
"@resourcesSortByYear": {},
"searchHeaderTitle": "Procurar: {query}",
"@searchHeaderTitle": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"searchInputPlaceholder": "Procurar",
"@searchInputPlaceholder": {},
"searchMoreResults": "Mais…",
"@searchMoreResults": {},
"searchNowPlayingContext": "Resultados da Pesquisa",
"@searchNowPlayingContext": {},
"settingsAboutActionsLicenses": "Licenças",
"@settingsAboutActionsLicenses": {},
"settingsAboutActionsProjectHomepage": "Página do Projeto",
"@settingsAboutActionsProjectHomepage": {},
"settingsAboutName": "Acerca",
"@settingsAboutName": {},
"settingsAboutVersion": "versão {version}",
"@settingsAboutVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"settingsMusicName": "Música",
"@settingsMusicName": {},
"settingsMusicOptionsScrobbleDescriptionOff": "Não enviar histórico de reproduções por scrobble",
"@settingsMusicOptionsScrobbleDescriptionOff": {},
"settingsMusicOptionsScrobbleDescriptionOn": "Enviar histórico de reproduções por scrobble",
"@settingsMusicOptionsScrobbleDescriptionOn": {},
"settingsMusicOptionsScrobbleTitle": "Enviar reproduções por scrobble",
"@settingsMusicOptionsScrobbleTitle": {},
"settingsNetworkName": "Rede",
"@settingsNetworkName": {},
"settingsNetworkOptionsMaxBitrateMobileTitle": "Bitrate Máximo (móvel)",
"@settingsNetworkOptionsMaxBitrateMobileTitle": {},
"settingsNetworkOptionsMaxBitrateWifiTitle": "Bitrate Máximo (Wi-Fi)",
"@settingsNetworkOptionsMaxBitrateWifiTitle": {},
"settingsNetworkOptionsMaxBufferTitle": "Tempo de buffer máximo",
"@settingsNetworkOptionsMaxBufferTitle": {},
"settingsNetworkOptionsMinBufferTitle": "Tempo de buffer mínimo",
"@settingsNetworkOptionsMinBufferTitle": {},
"settingsNetworkValuesKbps": "{value}kbps",
"@settingsNetworkValuesKbps": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesSeconds": "{value} segundos",
"@settingsNetworkValuesSeconds": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesUnlimitedKbps": "Ilimitado",
"@settingsNetworkValuesUnlimitedKbps": {},
"settingsResetActionsClearImageCache": "Limpar cache de Imagens",
"@settingsResetActionsClearImageCache": {},
"settingsResetName": "Redefinir",
"@settingsResetName": {},
"settingsServersActionsAdd": "Adicionar Servidor",
"@settingsServersActionsAdd": {},
"settingsServersActionsDelete": "Apagar",
"@settingsServersActionsDelete": {},
"settingsServersActionsEdit": "Editar Servidor",
"@settingsServersActionsEdit": {},
"settingsServersActionsSave": "Guardar",
"@settingsServersActionsSave": {},
"settingsServersActionsTestConnection": "Testar Ligação",
"@settingsServersActionsTestConnection": {},
"settingsServersFieldsAddress": "Endereço",
"@settingsServersFieldsAddress": {},
"settingsServersFieldsPassword": "Senha",
"@settingsServersFieldsPassword": {},
"settingsServersFieldsUsername": "Nome de utilizador",
"@settingsServersFieldsUsername": {},
"settingsServersMessagesConnectionFailed": "Ligação a {address} falhou, verifique definições ou servidor",
"@settingsServersMessagesConnectionFailed": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersMessagesConnectionOk": "Ligação a {address} OK!",
"@settingsServersMessagesConnectionOk": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersName": "Servidores",
"@settingsServersName": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOff": "Enviar senha como token + sal",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOff": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOn": "Enviar senha em texto simples (antigo, certifique-se que a sua ligação é segura!)",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOn": {},
"settingsServersOptionsForcePlaintextPasswordTitle": "Forçar password em texto simples",
"@settingsServersOptionsForcePlaintextPasswordTitle": {},
"actionsCancel": "Cancelar",
"@actionsCancel": {},
"actionsDelete": "Apagar",
"@actionsDelete": {},
"actionsDownload": "Descarregar",
"@actionsDownload": {},
"actionsDownloadCancel": "Cancelar descarga",
"@actionsDownloadCancel": {},
"actionsDownloadDelete": "Apagar descarga",
"@actionsDownloadDelete": {},
"resourcesFilterAlbum": "Álbum",
"@resourcesFilterAlbum": {},
"resourcesFilterArtist": "Artista",
"@resourcesFilterArtist": {},
"resourcesFilterYear": "Ano",
"@resourcesFilterYear": {},
"resourcesSortByAlbum": "Álbum",
"@resourcesSortByAlbum": {},
"settingsAboutActionsSupport": "Apoie o programador 💜",
"@settingsAboutActionsSupport": {},
"settingsNetworkOptionsOfflineMode": "Modo offline",
"@settingsNetworkOptionsOfflineMode": {},
"settingsNetworkOptionsOfflineModeOff": "Usar a internet para sincronizar música.",
"@settingsNetworkOptionsOfflineModeOff": {},
"settingsNetworkOptionsOfflineModeOn": "Não usar a internet para sincronizar ou tocar música.",
"@settingsNetworkOptionsOfflineModeOn": {},
"settingsNetworkOptionsStreamFormat": "Formato preferido de streaming",
"@settingsNetworkOptionsStreamFormat": {},
"resourcesSortByTitle": "Título",
"@resourcesSortByTitle": {},
"actionsOk": "OK",
"@actionsOk": {},
"controlsShuffle": "Aleatório",
"@controlsShuffle": {}
}

View File

@@ -1,196 +1,280 @@
{
"actionsStar": "Избранное",
"@actionsStar": {},
"actionsUnstar": "Убрать из избранного",
"@actionsUnstar": {},
"messagesNothingHere": "Здесь ничего нет…",
"@messagesNothingHere": {},
"navigationTabsHome": "Главная",
"@navigationTabsHome": {},
"navigationTabsLibrary": "Библиотека",
"@navigationTabsLibrary": {},
"navigationTabsSearch": "Поиск",
"@navigationTabsSearch": {},
"navigationTabsSettings": "Настройки",
"@navigationTabsSettings": {},
"resourcesAlbumActionsPlay": "Воспроизвести альбом",
"@resourcesAlbumActionsPlay": {},
"resourcesAlbumActionsView": "Посмотреть альбом",
"@resourcesAlbumActionsView": {},
"resourcesAlbumListsSort": "Сортировка альбомов",
"@resourcesAlbumListsSort": {},
"resourcesAlbumName": "{count,plural, =1{Альбом} few{Альбомы} many{Альбомов} other{Альбомов}}",
"@resourcesAlbumName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesArtistActionsView": "Посмотреть исполнителя",
"@resourcesArtistActionsView": {},
"resourcesArtistListsSort": "Сортировать исполнителей",
"@resourcesArtistListsSort": {},
"resourcesArtistName": "{count,plural, =1{Исполнитель} few{Исполнители} many{Исполнителей} other{Исполнителей}}",
"@resourcesArtistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterGenre": "По жанру",
"@resourcesFilterGenre": {},
"resourcesFilterStarred": "Избранные",
"@resourcesFilterStarred": {},
"resourcesPlaylistActionsPlay": "Воспроизвести плейлист",
"@resourcesPlaylistActionsPlay": {},
"resourcesPlaylistName": "{count,plural, =1{Плейлист} few{Плейлисты} many{Плейлистов} other{Плейлистов}}",
"@resourcesPlaylistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesQueueName": "{count,plural, =1{Очередь} few{Очереди} many{Очередей} other{Очередей}}",
"@resourcesQueueName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongListsArtistTopSongs": "Лучшие треки",
"@resourcesSongListsArtistTopSongs": {},
"resourcesSongName": "{count,plural, =1{Трек} few{Трека} many{Треков} other{Треков}}",
"@resourcesSongName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSortByAdded": "Недавно добавленные",
"@resourcesSortByAdded": {},
"resourcesSortByArtist": "По исполнителю",
"@resourcesSortByArtist": {},
"resourcesSortByFrequentlyPlayed": "Часто проигрываемые",
"@resourcesSortByFrequentlyPlayed": {},
"resourcesSortByName": "По имени",
"@resourcesSortByName": {},
"resourcesSortByRandom": "Случайно",
"@resourcesSortByRandom": {},
"resourcesSortByRecentlyPlayed": "Недавно проигранные",
"@resourcesSortByRecentlyPlayed": {},
"resourcesSortByYear": "По году",
"@resourcesSortByYear": {},
"searchHeaderTitle": "Поиск: {query}",
"@searchHeaderTitle": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"searchInputPlaceholder": "Поиск",
"@searchInputPlaceholder": {},
"searchMoreResults": "Больше…",
"@searchMoreResults": {},
"searchNowPlayingContext": "Результаты поиска",
"@searchNowPlayingContext": {},
"settingsAboutActionsLicenses": "Лицензии",
"@settingsAboutActionsLicenses": {},
"settingsAboutActionsProjectHomepage": "Сайт проекта",
"@settingsAboutActionsProjectHomepage": {},
"settingsAboutName": "О Subtracks",
"@settingsAboutName": {},
"settingsAboutVersion": "версия {version}",
"@settingsAboutVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"settingsMusicName": "Музыка",
"@settingsMusicName": {},
"settingsMusicOptionsScrobbleDescriptionOff": "Не отправлять историю воспроизведений",
"@settingsMusicOptionsScrobbleDescriptionOff": {},
"settingsMusicOptionsScrobbleDescriptionOn": "Скробблинг истории воспроизведения",
"@settingsMusicOptionsScrobbleDescriptionOn": {},
"settingsMusicOptionsScrobbleTitle": "Скробблинг",
"@settingsMusicOptionsScrobbleTitle": {},
"settingsNetworkName": "Сеть",
"@settingsNetworkName": {},
"settingsNetworkOptionsMaxBitrateMobileTitle": "Максимальный битрейт (мобильный интернет)",
"@settingsNetworkOptionsMaxBitrateMobileTitle": {},
"settingsNetworkOptionsMaxBitrateWifiTitle": "Максимальный битрейт (Wi-Fi)",
"@settingsNetworkOptionsMaxBitrateWifiTitle": {},
"settingsNetworkOptionsMaxBufferTitle": "Максимальное время буферизации",
"@settingsNetworkOptionsMaxBufferTitle": {},
"settingsNetworkOptionsMinBufferTitle": "Минимальное время буферизации",
"@settingsNetworkOptionsMinBufferTitle": {},
"settingsNetworkValuesKbps": "{value} кбит/с",
"@settingsNetworkValuesKbps": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesSeconds": "{value} секунд",
"@settingsNetworkValuesSeconds": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesUnlimitedKbps": "Без ограничений",
"@settingsNetworkValuesUnlimitedKbps": {},
"settingsResetActionsClearImageCache": "Очистить кэш изображения",
"@settingsResetActionsClearImageCache": {},
"settingsResetName": "Сброс",
"@settingsResetName": {},
"settingsServersActionsAdd": "Добавить сервер",
"@settingsServersActionsAdd": {},
"settingsServersActionsDelete": "Удалить",
"@settingsServersActionsDelete": {},
"settingsServersActionsEdit": "Редактировать сервер",
"@settingsServersActionsEdit": {},
"settingsServersActionsSave": "Сохранить",
"@settingsServersActionsSave": {},
"settingsServersActionsTestConnection": "Проверить подключение",
"@settingsServersActionsTestConnection": {},
"settingsServersFieldsAddress": "Адрес",
"@settingsServersFieldsAddress": {},
"settingsServersFieldsPassword": "Пароль",
"@settingsServersFieldsPassword": {},
"settingsServersFieldsUsername": "Имя пользователя",
"@settingsServersFieldsUsername": {},
"settingsServersMessagesConnectionFailed": "Не удалось подключиться к {address}, проверьте настройки или сервер",
"@settingsServersMessagesConnectionFailed": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersMessagesConnectionOk": "Подключение к {address} установлено!",
"@settingsServersMessagesConnectionOk": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersName": "Серверы",
"@settingsServersName": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOff": "Отправить пароль в виде токена",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOff": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOn": "Отправить пароль в виде текста (устарело, убедитесь, что ваше соединение безопасно!)",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOn": {},
"settingsServersOptionsForcePlaintextPasswordTitle": "Принудительно использовать текстовой пароль",
"@settingsServersOptionsForcePlaintextPasswordTitle": {}
}
"actionsStar": "Избранное",
"@actionsStar": {},
"actionsUnstar": "Убрать из избранного",
"@actionsUnstar": {},
"messagesNothingHere": "Здесь ничего нет…",
"@messagesNothingHere": {},
"navigationTabsHome": "Главная",
"@navigationTabsHome": {},
"navigationTabsLibrary": "Библиотека",
"@navigationTabsLibrary": {},
"navigationTabsSearch": "Поиск",
"@navigationTabsSearch": {},
"navigationTabsSettings": "Настройки",
"@navigationTabsSettings": {},
"resourcesAlbumActionsPlay": "Воспроизвести альбом",
"@resourcesAlbumActionsPlay": {},
"resourcesAlbumActionsView": "Посмотреть альбом",
"@resourcesAlbumActionsView": {},
"resourcesAlbumListsSort": "Сортировка альбомов",
"@resourcesAlbumListsSort": {},
"resourcesAlbumName": "{count,plural, =1{Альбом} few{Альбомы} many{Альбомов} other{Альбомов}}",
"@resourcesAlbumName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesArtistActionsView": "Посмотреть исполнителя",
"@resourcesArtistActionsView": {},
"resourcesArtistListsSort": "Сортировать исполнителей",
"@resourcesArtistListsSort": {},
"resourcesArtistName": "{count,plural, =1{Исполнитель} few{Исполнители} many{Исполнителей} other{Исполнителей}}",
"@resourcesArtistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesFilterGenre": "По жанру",
"@resourcesFilterGenre": {},
"resourcesFilterStarred": "Избранные",
"@resourcesFilterStarred": {},
"resourcesPlaylistActionsPlay": "Воспроизвести плейлист",
"@resourcesPlaylistActionsPlay": {},
"resourcesPlaylistName": "{count,plural, =1{Плейлист} few{Плейлисты} many{Плейлистов} other{Плейлистов}}",
"@resourcesPlaylistName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesQueueName": "{count,plural, =1{Очередь} few{Очереди} many{Очередей} other{Очередей}}",
"@resourcesQueueName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSongListsArtistTopSongs": "Лучшие треки",
"@resourcesSongListsArtistTopSongs": {},
"resourcesSongName": "{count,plural, =1{Трек} few{Трека} many{Треков} other{Треков}}",
"@resourcesSongName": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSortByAdded": "Недавно добавленные",
"@resourcesSortByAdded": {},
"resourcesSortByArtist": "По исполнителям",
"@resourcesSortByArtist": {},
"resourcesSortByFrequentlyPlayed": "Часто проигрываемые",
"@resourcesSortByFrequentlyPlayed": {},
"resourcesSortByName": "По имени",
"@resourcesSortByName": {},
"resourcesSortByRandom": "Случайно",
"@resourcesSortByRandom": {},
"resourcesSortByRecentlyPlayed": "Недавно проигранные",
"@resourcesSortByRecentlyPlayed": {},
"resourcesSortByYear": "По году",
"@resourcesSortByYear": {},
"searchHeaderTitle": "Поиск: {query}",
"@searchHeaderTitle": {
"placeholders": {
"query": {
"type": "String"
}
}
},
"searchInputPlaceholder": "Поиск",
"@searchInputPlaceholder": {},
"searchMoreResults": "Больше…",
"@searchMoreResults": {},
"searchNowPlayingContext": "Результаты поиска",
"@searchNowPlayingContext": {},
"settingsAboutActionsLicenses": "Лицензии",
"@settingsAboutActionsLicenses": {},
"settingsAboutActionsProjectHomepage": "Сайт проекта",
"@settingsAboutActionsProjectHomepage": {},
"settingsAboutName": "О Subtracks",
"@settingsAboutName": {},
"settingsAboutVersion": "версия {version}",
"@settingsAboutVersion": {
"placeholders": {
"version": {
"type": "String"
}
}
},
"settingsMusicName": "Музыка",
"@settingsMusicName": {},
"settingsMusicOptionsScrobbleDescriptionOff": "Не отправлять историю воспроизведений",
"@settingsMusicOptionsScrobbleDescriptionOff": {},
"settingsMusicOptionsScrobbleDescriptionOn": "Скробблинг истории воспроизведения",
"@settingsMusicOptionsScrobbleDescriptionOn": {},
"settingsMusicOptionsScrobbleTitle": "Скробблинг",
"@settingsMusicOptionsScrobbleTitle": {},
"settingsNetworkName": "Сеть",
"@settingsNetworkName": {},
"settingsNetworkOptionsMaxBitrateMobileTitle": "Максимальный битрейт (мобильный интернет)",
"@settingsNetworkOptionsMaxBitrateMobileTitle": {},
"settingsNetworkOptionsMaxBitrateWifiTitle": "Максимальный битрейт (Wi-Fi)",
"@settingsNetworkOptionsMaxBitrateWifiTitle": {},
"settingsNetworkOptionsMaxBufferTitle": "Максимальное время буферизации",
"@settingsNetworkOptionsMaxBufferTitle": {},
"settingsNetworkOptionsMinBufferTitle": "Минимальное время буферизации",
"@settingsNetworkOptionsMinBufferTitle": {},
"settingsNetworkValuesKbps": "{value} кбит/с",
"@settingsNetworkValuesKbps": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesSeconds": "{value} секунд",
"@settingsNetworkValuesSeconds": {
"placeholders": {
"value": {
"type": "String"
}
}
},
"settingsNetworkValuesUnlimitedKbps": "Без ограничений",
"@settingsNetworkValuesUnlimitedKbps": {},
"settingsResetActionsClearImageCache": "Очистить кэш изображения",
"@settingsResetActionsClearImageCache": {},
"settingsResetName": "Сброс",
"@settingsResetName": {},
"settingsServersActionsAdd": "Добавить сервер",
"@settingsServersActionsAdd": {},
"settingsServersActionsDelete": "Удалить",
"@settingsServersActionsDelete": {},
"settingsServersActionsEdit": "Редактировать сервер",
"@settingsServersActionsEdit": {},
"settingsServersActionsSave": "Сохранить",
"@settingsServersActionsSave": {},
"settingsServersActionsTestConnection": "Проверить подключение",
"@settingsServersActionsTestConnection": {},
"settingsServersFieldsAddress": "Адрес",
"@settingsServersFieldsAddress": {},
"settingsServersFieldsPassword": "Пароль",
"@settingsServersFieldsPassword": {},
"settingsServersFieldsUsername": "Имя пользователя",
"@settingsServersFieldsUsername": {},
"settingsServersMessagesConnectionFailed": "Не удалось подключиться к {address}, проверьте настройки или сервер",
"@settingsServersMessagesConnectionFailed": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersMessagesConnectionOk": "Подключение к {address} установлено!",
"@settingsServersMessagesConnectionOk": {
"placeholders": {
"address": {
"type": "String"
}
}
},
"settingsServersName": "Серверы",
"@settingsServersName": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOff": "Отправить пароль в виде токена",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOff": {},
"settingsServersOptionsForcePlaintextPasswordDescriptionOn": "Отправить пароль в виде текста (устарело, убедитесь, что ваше соединение безопасно!)",
"@settingsServersOptionsForcePlaintextPasswordDescriptionOn": {},
"settingsServersOptionsForcePlaintextPasswordTitle": "Принудительно использовать текстовой пароль",
"@settingsServersOptionsForcePlaintextPasswordTitle": {},
"settingsAboutShareLogs": "Поделиться журналами",
"@settingsAboutShareLogs": {},
"settingsAboutChooseLog": "Выбрать файл журнала",
"@settingsAboutChooseLog": {},
"settingsNetworkOptionsStreamFormatServerDefault": "Использовать сервер по умолчанию",
"@settingsNetworkOptionsStreamFormatServerDefault": {},
"actionsDownload": "Скачать",
"@actionsDownload": {},
"actionsDownloadCancel": "Отменить загрузку",
"@actionsDownloadCancel": {},
"actionsCancel": "Отменить",
"@actionsCancel": {},
"resourcesSongCount": "{count,plural, =1{{count} трек} other{{count} треки}}",
"@resourcesSongCount": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesSortByAlbum": "По альбомам",
"@resourcesSortByAlbum": {},
"resourcesSortByTitle": "По заголовку",
"@resourcesSortByTitle": {},
"resourcesSortByUpdated": "По недавно обновленному",
"@resourcesSortByUpdated": {},
"resourcesSortByAlbumCount": "По количеству альбомов",
"@resourcesSortByAlbumCount": {},
"settingsNetworkOptionsOfflineMode": "Автономный режим",
"@settingsNetworkOptionsOfflineMode": {},
"settingsNetworkOptionsOfflineModeOff": "Использовать интернет для синхронизации музыки.",
"@settingsNetworkOptionsOfflineModeOff": {},
"settingsServersFieldsName": "Имя",
"@settingsServersFieldsName": {},
"actionsDelete": "Удалить",
"@actionsDelete": {},
"actionsDownloadDelete": "Удалить загруженное",
"@actionsDownloadDelete": {},
"actionsOk": "ОК",
"@actionsOk": {},
"controlsShuffle": "Перемешать",
"@controlsShuffle": {},
"resourcesFilterArtist": "По исполнителю",
"@resourcesFilterArtist": {},
"resourcesFilterAlbum": "По альбомам",
"@resourcesFilterAlbum": {},
"resourcesFilterYear": "По годам",
"@resourcesFilterYear": {},
"resourcesFilterOwner": "По владельцу",
"@resourcesFilterOwner": {},
"resourcesSongListDeleteAllContent": "Это удалит все загруженные файлы песен.",
"@resourcesSongListDeleteAllContent": {},
"settingsNetworkOptionsStreamFormat": "Предпочтительный формат потока",
"@settingsNetworkOptionsStreamFormat": {},
"resourcesSongListDeleteAllTitle": "Удалить загрузки?",
"@resourcesSongListDeleteAllTitle": {},
"settingsNetworkOptionsOfflineModeOn": "Не использовать интернет для синхронизации или воспроизведения музыки.",
"@settingsNetworkOptionsOfflineModeOn": {},
"settingsAboutActionsSupport": "Поддержать разработчика",
"@settingsAboutActionsSupport": {},
"resourcesArtistCount": "{count,plural, =1{{count} исполнитель} other{{count} исполнители}}",
"@resourcesArtistCount": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesPlaylistCount": "{count,plural, =1{{count} плейлист} other{{count} плейлисты}}",
"@resourcesPlaylistCount": {
"placeholders": {
"count": {
"type": "int"
}
}
},
"resourcesAlbumCount": "{count,plural, =1{{count} альбом} other{{count} альбомы}}",
"@resourcesAlbumCount": {
"placeholders": {
"count": {
"type": "int"
}
}
}
}

209
lib/log.dart Normal file
View File

@@ -0,0 +1,209 @@
// import 'dart:convert';
import 'dart:io';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';
class AnsiColor {
/// ANSI Control Sequence Introducer, signals the terminal for new settings.
static const ansiEsc = '\x1B[';
/// Reset all colors and options for current SGRs to terminal defaults.
static const ansiDefault = '${ansiEsc}0m';
final int? fg;
final int? bg;
final bool color;
AnsiColor.none()
: fg = null,
bg = null,
color = false;
AnsiColor.fg(this.fg)
: bg = null,
color = true;
AnsiColor.bg(this.bg)
: fg = null,
color = true;
@override
String toString() {
if (fg != null) {
return '${ansiEsc}38;5;${fg}m';
} else if (bg != null) {
return '${ansiEsc}48;5;${bg}m';
} else {
return '';
}
}
String call(String msg) {
if (color) {
// ignore: unnecessary_brace_in_string_interps
return '${this}$msg$ansiDefault';
} else {
return msg;
}
}
AnsiColor toFg() => AnsiColor.fg(bg);
AnsiColor toBg() => AnsiColor.bg(fg);
/// Defaults the terminal's foreground color without altering the background.
String get resetForeground => color ? '${ansiEsc}39m' : '';
/// Defaults the terminal's background color without altering the foreground.
String get resetBackground => color ? '${ansiEsc}49m' : '';
static int grey(double level) => 232 + (level.clamp(0.0, 1.0) * 23).round();
}
final levelColors = {
Level.FINEST: AnsiColor.fg(AnsiColor.grey(0.5)),
Level.FINER: AnsiColor.fg(AnsiColor.grey(0.5)),
Level.FINE: AnsiColor.fg(AnsiColor.grey(0.5)),
Level.CONFIG: AnsiColor.fg(81),
Level.INFO: AnsiColor.fg(12),
Level.WARNING: AnsiColor.fg(208),
Level.SEVERE: AnsiColor.fg(196),
Level.SHOUT: AnsiColor.fg(199),
};
class LogData {
final String? message;
final Object? data;
const LogData(this.message, this.data);
}
String _format(
LogRecord event, {
bool color = false,
bool time = true,
bool level = true,
bool redact = true,
}) {
var message = '';
if (time) message += '${event.time.toIso8601String()} ';
if (level) message += '${event.level.name} ';
final object = event.object;
if (object is LogData) {
message += '${object.message}';
message += '\n${object.data}';
} else if (object != null) {
message += 'Object';
message += '\n$object';
} else {
message += event.message;
}
if (event.error != null) {
message += '\n${event.error}';
}
if (redact) {
message = _redactUrl(message);
}
if (event.stackTrace != null) {
message += '\n${event.stackTrace}';
}
return color
? message.split('\n').map((e) => levelColors[event.level]!(e)).join('\n')
: message;
}
String _redactUrl(String message) {
if (!_queryReplace('u').hasMatch(message)) {
return message;
}
message = _redactParam(message, 'u');
message = _redactParam(message, 'p');
message = _redactParam(message, 's');
message = _redactParam(message, 't');
return message;
}
RegExp _queryReplace(String key) => RegExp('$key=([^&|\\n|\\t\\s]+)');
String _redactParam(String url, String key) =>
url.replaceAll(_queryReplace(key), '$key=REDACTED');
Future<Directory> logDirectory() async {
return Directory(
p.join((await getApplicationDocumentsDirectory()).path, 'logs'),
);
}
Future<List<File>> logFiles() async {
final dir = await logDirectory();
return dir.listSync().whereType<File>().toList()
..sort(
(a, b) => b.statSync().modified.compareTo(a.statSync().modified),
);
}
File _currentLogFile(String logDir) {
final now = DateTime.now();
return File(p.join(logDir, '${now.year}-${now.month}-${now.day}.txt'));
}
Future<void> _printFile(String event, String logDir) async {
final file = _currentLogFile(logDir);
if (!event.endsWith('\n')) {
event += '\n';
}
await file.writeAsString(event, mode: FileMode.writeOnlyAppend, flush: true);
}
void _printDebug(LogRecord event) {
// ignore: avoid_print
print(_format(event, color: true, time: false, level: false, redact: false));
}
Future<void> _printRelease(LogRecord event, String logDir) async {
await _printFile(
_format(event, color: false, time: true, level: true, redact: true),
logDir,
);
}
final log = Logger('default');
Future<void> initLogging() async {
final dir = (await logDirectory())..create();
final file = _currentLogFile(dir.path);
if (!(await file.exists())) {
await file.create();
}
final files = await logFiles();
if (files.length > 7) {
for (var file in files.slice(7)) {
await file.delete();
}
}
Logger.root.level = kDebugMode ? Level.ALL : Level.INFO;
Logger.root.onRecord.asyncMap((event) async {
if (kDebugMode) {
_printDebug(event);
} else {
await _printRelease(event, dir.path);
}
}).listen((_) {}, cancelOnError: false);
}

View File

@@ -4,6 +4,7 @@ import 'package:stack_trace/stack_trace.dart' as stack_trace;
import 'package:worker_manager/worker_manager.dart';
import 'app/app.dart';
import 'log.dart';
void main() async {
// TOOD: probably remove before live
@@ -18,5 +19,8 @@ void main() async {
await Executor().warmUp();
WidgetsFlutterBinding.ensureInitialized();
await initLogging();
runApp(const ProviderScope(child: MyApp()));
}

View File

@@ -12,7 +12,7 @@ part of 'music.dart';
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$SourceId {
@@ -62,21 +62,22 @@ class _$SourceIdCopyWithImpl<$Res, $Val extends SourceId>
}
/// @nodoc
abstract class _$$_SourceIdCopyWith<$Res> implements $SourceIdCopyWith<$Res> {
factory _$$_SourceIdCopyWith(
_$_SourceId value, $Res Function(_$_SourceId) then) =
__$$_SourceIdCopyWithImpl<$Res>;
abstract class _$$SourceIdImplCopyWith<$Res>
implements $SourceIdCopyWith<$Res> {
factory _$$SourceIdImplCopyWith(
_$SourceIdImpl value, $Res Function(_$SourceIdImpl) then) =
__$$SourceIdImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({int sourceId, String id});
}
/// @nodoc
class __$$_SourceIdCopyWithImpl<$Res>
extends _$SourceIdCopyWithImpl<$Res, _$_SourceId>
implements _$$_SourceIdCopyWith<$Res> {
__$$_SourceIdCopyWithImpl(
_$_SourceId _value, $Res Function(_$_SourceId) _then)
class __$$SourceIdImplCopyWithImpl<$Res>
extends _$SourceIdCopyWithImpl<$Res, _$SourceIdImpl>
implements _$$SourceIdImplCopyWith<$Res> {
__$$SourceIdImplCopyWithImpl(
_$SourceIdImpl _value, $Res Function(_$SourceIdImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -85,7 +86,7 @@ class __$$_SourceIdCopyWithImpl<$Res>
Object? sourceId = null,
Object? id = null,
}) {
return _then(_$_SourceId(
return _then(_$SourceIdImpl(
sourceId: null == sourceId
? _value.sourceId
: sourceId // ignore: cast_nullable_to_non_nullable
@@ -100,8 +101,8 @@ class __$$_SourceIdCopyWithImpl<$Res>
/// @nodoc
class _$_SourceId with DiagnosticableTreeMixin implements _SourceId {
const _$_SourceId({required this.sourceId, required this.id});
class _$SourceIdImpl with DiagnosticableTreeMixin implements _SourceId {
const _$SourceIdImpl({required this.sourceId, required this.id});
@override
final int sourceId;
@@ -123,10 +124,10 @@ class _$_SourceId with DiagnosticableTreeMixin implements _SourceId {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_SourceId &&
other is _$SourceIdImpl &&
(identical(other.sourceId, sourceId) ||
other.sourceId == sourceId) &&
(identical(other.id, id) || other.id == id));
@@ -138,13 +139,13 @@ class _$_SourceId with DiagnosticableTreeMixin implements _SourceId {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SourceIdCopyWith<_$_SourceId> get copyWith =>
__$$_SourceIdCopyWithImpl<_$_SourceId>(this, _$identity);
_$$SourceIdImplCopyWith<_$SourceIdImpl> get copyWith =>
__$$SourceIdImplCopyWithImpl<_$SourceIdImpl>(this, _$identity);
}
abstract class _SourceId implements SourceId {
const factory _SourceId(
{required final int sourceId, required final String id}) = _$_SourceId;
{required final int sourceId, required final String id}) = _$SourceIdImpl;
@override
int get sourceId;
@@ -152,7 +153,7 @@ abstract class _SourceId implements SourceId {
String get id;
@override
@JsonKey(ignore: true)
_$$_SourceIdCopyWith<_$_SourceId> get copyWith =>
_$$SourceIdImplCopyWith<_$SourceIdImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -205,22 +206,22 @@ class _$SourceIdSetCopyWithImpl<$Res, $Val extends SourceIdSet>
}
/// @nodoc
abstract class _$$_SourceIdSetCopyWith<$Res>
abstract class _$$SourceIdSetImplCopyWith<$Res>
implements $SourceIdSetCopyWith<$Res> {
factory _$$_SourceIdSetCopyWith(
_$_SourceIdSet value, $Res Function(_$_SourceIdSet) then) =
__$$_SourceIdSetCopyWithImpl<$Res>;
factory _$$SourceIdSetImplCopyWith(
_$SourceIdSetImpl value, $Res Function(_$SourceIdSetImpl) then) =
__$$SourceIdSetImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({int sourceId, ISet<String> ids});
}
/// @nodoc
class __$$_SourceIdSetCopyWithImpl<$Res>
extends _$SourceIdSetCopyWithImpl<$Res, _$_SourceIdSet>
implements _$$_SourceIdSetCopyWith<$Res> {
__$$_SourceIdSetCopyWithImpl(
_$_SourceIdSet _value, $Res Function(_$_SourceIdSet) _then)
class __$$SourceIdSetImplCopyWithImpl<$Res>
extends _$SourceIdSetCopyWithImpl<$Res, _$SourceIdSetImpl>
implements _$$SourceIdSetImplCopyWith<$Res> {
__$$SourceIdSetImplCopyWithImpl(
_$SourceIdSetImpl _value, $Res Function(_$SourceIdSetImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -229,7 +230,7 @@ class __$$_SourceIdSetCopyWithImpl<$Res>
Object? sourceId = null,
Object? ids = null,
}) {
return _then(_$_SourceIdSet(
return _then(_$SourceIdSetImpl(
sourceId: null == sourceId
? _value.sourceId
: sourceId // ignore: cast_nullable_to_non_nullable
@@ -244,8 +245,8 @@ class __$$_SourceIdSetCopyWithImpl<$Res>
/// @nodoc
class _$_SourceIdSet with DiagnosticableTreeMixin implements _SourceIdSet {
const _$_SourceIdSet({required this.sourceId, required this.ids});
class _$SourceIdSetImpl with DiagnosticableTreeMixin implements _SourceIdSet {
const _$SourceIdSetImpl({required this.sourceId, required this.ids});
@override
final int sourceId;
@@ -267,10 +268,10 @@ class _$_SourceIdSet with DiagnosticableTreeMixin implements _SourceIdSet {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_SourceIdSet &&
other is _$SourceIdSetImpl &&
(identical(other.sourceId, sourceId) ||
other.sourceId == sourceId) &&
const DeepCollectionEquality().equals(other.ids, ids));
@@ -283,14 +284,14 @@ class _$_SourceIdSet with DiagnosticableTreeMixin implements _SourceIdSet {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SourceIdSetCopyWith<_$_SourceIdSet> get copyWith =>
__$$_SourceIdSetCopyWithImpl<_$_SourceIdSet>(this, _$identity);
_$$SourceIdSetImplCopyWith<_$SourceIdSetImpl> get copyWith =>
__$$SourceIdSetImplCopyWithImpl<_$SourceIdSetImpl>(this, _$identity);
}
abstract class _SourceIdSet implements SourceIdSet {
const factory _SourceIdSet(
{required final int sourceId,
required final ISet<String> ids}) = _$_SourceIdSet;
required final ISet<String> ids}) = _$SourceIdSetImpl;
@override
int get sourceId;
@@ -298,7 +299,7 @@ abstract class _SourceIdSet implements SourceIdSet {
ISet<String> get ids;
@override
@JsonKey(ignore: true)
_$$_SourceIdSetCopyWith<_$_SourceIdSet> get copyWith =>
_$$SourceIdSetImplCopyWith<_$SourceIdSetImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -372,9 +373,10 @@ class _$ArtistCopyWithImpl<$Res, $Val extends Artist>
}
/// @nodoc
abstract class _$$_ArtistCopyWith<$Res> implements $ArtistCopyWith<$Res> {
factory _$$_ArtistCopyWith(_$_Artist value, $Res Function(_$_Artist) then) =
__$$_ArtistCopyWithImpl<$Res>;
abstract class _$$ArtistImplCopyWith<$Res> implements $ArtistCopyWith<$Res> {
factory _$$ArtistImplCopyWith(
_$ArtistImpl value, $Res Function(_$ArtistImpl) then) =
__$$ArtistImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -386,10 +388,11 @@ abstract class _$$_ArtistCopyWith<$Res> implements $ArtistCopyWith<$Res> {
}
/// @nodoc
class __$$_ArtistCopyWithImpl<$Res>
extends _$ArtistCopyWithImpl<$Res, _$_Artist>
implements _$$_ArtistCopyWith<$Res> {
__$$_ArtistCopyWithImpl(_$_Artist _value, $Res Function(_$_Artist) _then)
class __$$ArtistImplCopyWithImpl<$Res>
extends _$ArtistCopyWithImpl<$Res, _$ArtistImpl>
implements _$$ArtistImplCopyWith<$Res> {
__$$ArtistImplCopyWithImpl(
_$ArtistImpl _value, $Res Function(_$ArtistImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -401,7 +404,7 @@ class __$$_ArtistCopyWithImpl<$Res>
Object? albumCount = null,
Object? starred = freezed,
}) {
return _then(_$_Artist(
return _then(_$ArtistImpl(
sourceId: null == sourceId
? _value.sourceId
: sourceId // ignore: cast_nullable_to_non_nullable
@@ -428,8 +431,8 @@ class __$$_ArtistCopyWithImpl<$Res>
/// @nodoc
class _$_Artist with DiagnosticableTreeMixin implements _Artist {
const _$_Artist(
class _$ArtistImpl with DiagnosticableTreeMixin implements _Artist {
const _$ArtistImpl(
{required this.sourceId,
required this.id,
required this.name,
@@ -465,10 +468,10 @@ class _$_Artist with DiagnosticableTreeMixin implements _Artist {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_Artist &&
other is _$ArtistImpl &&
(identical(other.sourceId, sourceId) ||
other.sourceId == sourceId) &&
(identical(other.id, id) || other.id == id) &&
@@ -485,8 +488,8 @@ class _$_Artist with DiagnosticableTreeMixin implements _Artist {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_ArtistCopyWith<_$_Artist> get copyWith =>
__$$_ArtistCopyWithImpl<_$_Artist>(this, _$identity);
_$$ArtistImplCopyWith<_$ArtistImpl> get copyWith =>
__$$ArtistImplCopyWithImpl<_$ArtistImpl>(this, _$identity);
}
abstract class _Artist implements Artist {
@@ -495,7 +498,7 @@ abstract class _Artist implements Artist {
required final String id,
required final String name,
required final int albumCount,
final DateTime? starred}) = _$_Artist;
final DateTime? starred}) = _$ArtistImpl;
@override
int get sourceId;
@@ -509,7 +512,7 @@ abstract class _Artist implements Artist {
DateTime? get starred;
@override
@JsonKey(ignore: true)
_$$_ArtistCopyWith<_$_Artist> get copyWith =>
_$$ArtistImplCopyWith<_$ArtistImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -648,9 +651,10 @@ class _$AlbumCopyWithImpl<$Res, $Val extends Album>
}
/// @nodoc
abstract class _$$_AlbumCopyWith<$Res> implements $AlbumCopyWith<$Res> {
factory _$$_AlbumCopyWith(_$_Album value, $Res Function(_$_Album) then) =
__$$_AlbumCopyWithImpl<$Res>;
abstract class _$$AlbumImplCopyWith<$Res> implements $AlbumCopyWith<$Res> {
factory _$$AlbumImplCopyWith(
_$AlbumImpl value, $Res Function(_$AlbumImpl) then) =
__$$AlbumImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -671,9 +675,11 @@ abstract class _$$_AlbumCopyWith<$Res> implements $AlbumCopyWith<$Res> {
}
/// @nodoc
class __$$_AlbumCopyWithImpl<$Res> extends _$AlbumCopyWithImpl<$Res, _$_Album>
implements _$$_AlbumCopyWith<$Res> {
__$$_AlbumCopyWithImpl(_$_Album _value, $Res Function(_$_Album) _then)
class __$$AlbumImplCopyWithImpl<$Res>
extends _$AlbumCopyWithImpl<$Res, _$AlbumImpl>
implements _$$AlbumImplCopyWith<$Res> {
__$$AlbumImplCopyWithImpl(
_$AlbumImpl _value, $Res Function(_$AlbumImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -694,7 +700,7 @@ class __$$_AlbumCopyWithImpl<$Res> extends _$AlbumCopyWithImpl<$Res, _$_Album>
Object? frequentRank = freezed,
Object? recentRank = freezed,
}) {
return _then(_$_Album(
return _then(_$AlbumImpl(
sourceId: null == sourceId
? _value.sourceId
: sourceId // ignore: cast_nullable_to_non_nullable
@@ -757,8 +763,8 @@ class __$$_AlbumCopyWithImpl<$Res> extends _$AlbumCopyWithImpl<$Res, _$_Album>
/// @nodoc
class _$_Album with DiagnosticableTreeMixin implements _Album {
const _$_Album(
class _$AlbumImpl with DiagnosticableTreeMixin implements _Album {
const _$AlbumImpl(
{required this.sourceId,
required this.id,
required this.name,
@@ -833,10 +839,10 @@ class _$_Album with DiagnosticableTreeMixin implements _Album {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_Album &&
other is _$AlbumImpl &&
(identical(other.sourceId, sourceId) ||
other.sourceId == sourceId) &&
(identical(other.id, id) || other.id == id) &&
@@ -882,8 +888,8 @@ class _$_Album with DiagnosticableTreeMixin implements _Album {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_AlbumCopyWith<_$_Album> get copyWith =>
__$$_AlbumCopyWithImpl<_$_Album>(this, _$identity);
_$$AlbumImplCopyWith<_$AlbumImpl> get copyWith =>
__$$AlbumImplCopyWithImpl<_$AlbumImpl>(this, _$identity);
}
abstract class _Album implements Album {
@@ -901,7 +907,7 @@ abstract class _Album implements Album {
required final int songCount,
final bool isDeleted,
final int? frequentRank,
final int? recentRank}) = _$_Album;
final int? recentRank}) = _$AlbumImpl;
@override
int get sourceId;
@@ -933,7 +939,7 @@ abstract class _Album implements Album {
int? get recentRank;
@override
@JsonKey(ignore: true)
_$$_AlbumCopyWith<_$_Album> get copyWith =>
_$$AlbumImplCopyWith<_$AlbumImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -1022,10 +1028,11 @@ class _$PlaylistCopyWithImpl<$Res, $Val extends Playlist>
}
/// @nodoc
abstract class _$$_PlaylistCopyWith<$Res> implements $PlaylistCopyWith<$Res> {
factory _$$_PlaylistCopyWith(
_$_Playlist value, $Res Function(_$_Playlist) then) =
__$$_PlaylistCopyWithImpl<$Res>;
abstract class _$$PlaylistImplCopyWith<$Res>
implements $PlaylistCopyWith<$Res> {
factory _$$PlaylistImplCopyWith(
_$PlaylistImpl value, $Res Function(_$PlaylistImpl) then) =
__$$PlaylistImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -1039,11 +1046,11 @@ abstract class _$$_PlaylistCopyWith<$Res> implements $PlaylistCopyWith<$Res> {
}
/// @nodoc
class __$$_PlaylistCopyWithImpl<$Res>
extends _$PlaylistCopyWithImpl<$Res, _$_Playlist>
implements _$$_PlaylistCopyWith<$Res> {
__$$_PlaylistCopyWithImpl(
_$_Playlist _value, $Res Function(_$_Playlist) _then)
class __$$PlaylistImplCopyWithImpl<$Res>
extends _$PlaylistCopyWithImpl<$Res, _$PlaylistImpl>
implements _$$PlaylistImplCopyWith<$Res> {
__$$PlaylistImplCopyWithImpl(
_$PlaylistImpl _value, $Res Function(_$PlaylistImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -1057,7 +1064,7 @@ class __$$_PlaylistCopyWithImpl<$Res>
Object? songCount = null,
Object? created = null,
}) {
return _then(_$_Playlist(
return _then(_$PlaylistImpl(
sourceId: null == sourceId
? _value.sourceId
: sourceId // ignore: cast_nullable_to_non_nullable
@@ -1092,8 +1099,8 @@ class __$$_PlaylistCopyWithImpl<$Res>
/// @nodoc
class _$_Playlist with DiagnosticableTreeMixin implements _Playlist {
const _$_Playlist(
class _$PlaylistImpl with DiagnosticableTreeMixin implements _Playlist {
const _$PlaylistImpl(
{required this.sourceId,
required this.id,
required this.name,
@@ -1137,10 +1144,10 @@ class _$_Playlist with DiagnosticableTreeMixin implements _Playlist {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_Playlist &&
other is _$PlaylistImpl &&
(identical(other.sourceId, sourceId) ||
other.sourceId == sourceId) &&
(identical(other.id, id) || other.id == id) &&
@@ -1160,8 +1167,8 @@ class _$_Playlist with DiagnosticableTreeMixin implements _Playlist {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_PlaylistCopyWith<_$_Playlist> get copyWith =>
__$$_PlaylistCopyWithImpl<_$_Playlist>(this, _$identity);
_$$PlaylistImplCopyWith<_$PlaylistImpl> get copyWith =>
__$$PlaylistImplCopyWithImpl<_$PlaylistImpl>(this, _$identity);
}
abstract class _Playlist implements Playlist {
@@ -1172,7 +1179,7 @@ abstract class _Playlist implements Playlist {
final String? comment,
final String? coverArt,
required final int songCount,
required final DateTime created}) = _$_Playlist;
required final DateTime created}) = _$PlaylistImpl;
@override
int get sourceId;
@@ -1190,7 +1197,7 @@ abstract class _Playlist implements Playlist {
DateTime get created;
@override
@JsonKey(ignore: true)
_$$_PlaylistCopyWith<_$_Playlist> get copyWith =>
_$$PlaylistImplCopyWith<_$PlaylistImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -1334,9 +1341,10 @@ class _$SongCopyWithImpl<$Res, $Val extends Song>
}
/// @nodoc
abstract class _$$_SongCopyWith<$Res> implements $SongCopyWith<$Res> {
factory _$$_SongCopyWith(_$_Song value, $Res Function(_$_Song) then) =
__$$_SongCopyWithImpl<$Res>;
abstract class _$$SongImplCopyWith<$Res> implements $SongCopyWith<$Res> {
factory _$$SongImplCopyWith(
_$SongImpl value, $Res Function(_$SongImpl) then) =
__$$SongImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -1358,9 +1366,10 @@ abstract class _$$_SongCopyWith<$Res> implements $SongCopyWith<$Res> {
}
/// @nodoc
class __$$_SongCopyWithImpl<$Res> extends _$SongCopyWithImpl<$Res, _$_Song>
implements _$$_SongCopyWith<$Res> {
__$$_SongCopyWithImpl(_$_Song _value, $Res Function(_$_Song) _then)
class __$$SongImplCopyWithImpl<$Res>
extends _$SongCopyWithImpl<$Res, _$SongImpl>
implements _$$SongImplCopyWith<$Res> {
__$$SongImplCopyWithImpl(_$SongImpl _value, $Res Function(_$SongImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -1382,7 +1391,7 @@ class __$$_SongCopyWithImpl<$Res> extends _$SongCopyWithImpl<$Res, _$_Song>
Object? downloadFilePath = freezed,
Object? isDeleted = null,
}) {
return _then(_$_Song(
return _then(_$SongImpl(
sourceId: null == sourceId
? _value.sourceId
: sourceId // ignore: cast_nullable_to_non_nullable
@@ -1449,8 +1458,8 @@ class __$$_SongCopyWithImpl<$Res> extends _$SongCopyWithImpl<$Res, _$_Song>
/// @nodoc
class _$_Song with DiagnosticableTreeMixin implements _Song {
const _$_Song(
class _$SongImpl with DiagnosticableTreeMixin implements _Song {
const _$SongImpl(
{required this.sourceId,
required this.id,
this.albumId,
@@ -1527,10 +1536,10 @@ class _$_Song with DiagnosticableTreeMixin implements _Song {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_Song &&
other is _$SongImpl &&
(identical(other.sourceId, sourceId) ||
other.sourceId == sourceId) &&
(identical(other.id, id) || other.id == id) &&
@@ -1576,8 +1585,8 @@ class _$_Song with DiagnosticableTreeMixin implements _Song {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SongCopyWith<_$_Song> get copyWith =>
__$$_SongCopyWithImpl<_$_Song>(this, _$identity);
_$$SongImplCopyWith<_$SongImpl> get copyWith =>
__$$SongImplCopyWithImpl<_$SongImpl>(this, _$identity);
}
abstract class _Song implements Song {
@@ -1596,7 +1605,7 @@ abstract class _Song implements Song {
final String? genre,
final String? downloadTaskId,
final String? downloadFilePath,
final bool isDeleted}) = _$_Song;
final bool isDeleted}) = _$SongImpl;
@override
int get sourceId;
@@ -1630,7 +1639,8 @@ abstract class _Song implements Song {
bool get isDeleted;
@override
@JsonKey(ignore: true)
_$$_SongCopyWith<_$_Song> get copyWith => throw _privateConstructorUsedError;
_$$SongImplCopyWith<_$SongImpl> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
@@ -1698,11 +1708,11 @@ class _$SearchResultsCopyWithImpl<$Res, $Val extends SearchResults>
}
/// @nodoc
abstract class _$$_SearchResultsCopyWith<$Res>
abstract class _$$SearchResultsImplCopyWith<$Res>
implements $SearchResultsCopyWith<$Res> {
factory _$$_SearchResultsCopyWith(
_$_SearchResults value, $Res Function(_$_SearchResults) then) =
__$$_SearchResultsCopyWithImpl<$Res>;
factory _$$SearchResultsImplCopyWith(
_$SearchResultsImpl value, $Res Function(_$SearchResultsImpl) then) =
__$$SearchResultsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -1713,11 +1723,11 @@ abstract class _$$_SearchResultsCopyWith<$Res>
}
/// @nodoc
class __$$_SearchResultsCopyWithImpl<$Res>
extends _$SearchResultsCopyWithImpl<$Res, _$_SearchResults>
implements _$$_SearchResultsCopyWith<$Res> {
__$$_SearchResultsCopyWithImpl(
_$_SearchResults _value, $Res Function(_$_SearchResults) _then)
class __$$SearchResultsImplCopyWithImpl<$Res>
extends _$SearchResultsCopyWithImpl<$Res, _$SearchResultsImpl>
implements _$$SearchResultsImplCopyWith<$Res> {
__$$SearchResultsImplCopyWithImpl(
_$SearchResultsImpl _value, $Res Function(_$SearchResultsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -1728,7 +1738,7 @@ class __$$_SearchResultsCopyWithImpl<$Res>
Object? albums = null,
Object? artists = null,
}) {
return _then(_$_SearchResults(
return _then(_$SearchResultsImpl(
query: freezed == query
? _value.query
: query // ignore: cast_nullable_to_non_nullable
@@ -1751,8 +1761,10 @@ class __$$_SearchResultsCopyWithImpl<$Res>
/// @nodoc
class _$_SearchResults with DiagnosticableTreeMixin implements _SearchResults {
const _$_SearchResults(
class _$SearchResultsImpl
with DiagnosticableTreeMixin
implements _SearchResults {
const _$SearchResultsImpl(
{this.query,
this.songs = const IListConst([]),
this.albums = const IListConst([]),
@@ -1787,10 +1799,10 @@ class _$_SearchResults with DiagnosticableTreeMixin implements _SearchResults {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_SearchResults &&
other is _$SearchResultsImpl &&
(identical(other.query, query) || other.query == query) &&
const DeepCollectionEquality().equals(other.songs, songs) &&
const DeepCollectionEquality().equals(other.albums, albums) &&
@@ -1808,8 +1820,8 @@ class _$_SearchResults with DiagnosticableTreeMixin implements _SearchResults {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SearchResultsCopyWith<_$_SearchResults> get copyWith =>
__$$_SearchResultsCopyWithImpl<_$_SearchResults>(this, _$identity);
_$$SearchResultsImplCopyWith<_$SearchResultsImpl> get copyWith =>
__$$SearchResultsImplCopyWithImpl<_$SearchResultsImpl>(this, _$identity);
}
abstract class _SearchResults implements SearchResults {
@@ -1817,7 +1829,7 @@ abstract class _SearchResults implements SearchResults {
{final String? query,
final IList<Song> songs,
final IList<Album> albums,
final IList<Artist> artists}) = _$_SearchResults;
final IList<Artist> artists}) = _$SearchResultsImpl;
@override
String? get query;
@@ -1829,6 +1841,6 @@ abstract class _SearchResults implements SearchResults {
IList<Artist> get artists;
@override
@JsonKey(ignore: true)
_$$_SearchResultsCopyWith<_$_SearchResults> get copyWith =>
_$$SearchResultsImplCopyWith<_$SearchResultsImpl> get copyWith =>
throw _privateConstructorUsedError;
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,25 +6,26 @@ part of 'query.dart';
// JsonSerializableGenerator
// **************************************************************************
_$_Pagination _$$_PaginationFromJson(Map<String, dynamic> json) =>
_$_Pagination(
limit: json['limit'] as int,
offset: json['offset'] as int? ?? 0,
_$PaginationImpl _$$PaginationImplFromJson(Map<String, dynamic> json) =>
_$PaginationImpl(
limit: (json['limit'] as num).toInt(),
offset: (json['offset'] as num?)?.toInt() ?? 0,
);
Map<String, dynamic> _$$_PaginationToJson(_$_Pagination instance) =>
Map<String, dynamic> _$$PaginationImplToJson(_$PaginationImpl instance) =>
<String, dynamic>{
'limit': instance.limit,
'offset': instance.offset,
};
_$_SortBy _$$_SortByFromJson(Map<String, dynamic> json) => _$_SortBy(
_$SortByImpl _$$SortByImplFromJson(Map<String, dynamic> json) => _$SortByImpl(
column: json['column'] as String,
dir: $enumDecodeNullable(_$SortDirectionEnumMap, json['dir']) ??
SortDirection.asc,
);
Map<String, dynamic> _$$_SortByToJson(_$_SortBy instance) => <String, dynamic>{
Map<String, dynamic> _$$SortByImplToJson(_$SortByImpl instance) =>
<String, dynamic>{
'column': instance.column,
'dir': _$SortDirectionEnumMap[instance.dir]!,
};
@@ -34,15 +35,17 @@ const _$SortDirectionEnumMap = {
SortDirection.desc: 'desc',
};
_$_FilterWithEquals _$$_FilterWithEqualsFromJson(Map<String, dynamic> json) =>
_$_FilterWithEquals(
_$FilterWithEqualsImpl _$$FilterWithEqualsImplFromJson(
Map<String, dynamic> json) =>
_$FilterWithEqualsImpl(
column: json['column'] as String,
value: json['value'] as String,
invert: json['invert'] as bool? ?? false,
$type: json['runtimeType'] as String?,
);
Map<String, dynamic> _$$_FilterWithEqualsToJson(_$_FilterWithEquals instance) =>
Map<String, dynamic> _$$FilterWithEqualsImplToJson(
_$FilterWithEqualsImpl instance) =>
<String, dynamic>{
'column': instance.column,
'value': instance.value,
@@ -50,17 +53,17 @@ Map<String, dynamic> _$$_FilterWithEqualsToJson(_$_FilterWithEquals instance) =>
'runtimeType': instance.$type,
};
_$_FilterWithGreaterThan _$$_FilterWithGreaterThanFromJson(
_$FilterWithGreaterThanImpl _$$FilterWithGreaterThanImplFromJson(
Map<String, dynamic> json) =>
_$_FilterWithGreaterThan(
_$FilterWithGreaterThanImpl(
column: json['column'] as String,
value: json['value'] as String,
orEquals: json['orEquals'] as bool? ?? false,
$type: json['runtimeType'] as String?,
);
Map<String, dynamic> _$$_FilterWithGreaterThanToJson(
_$_FilterWithGreaterThan instance) =>
Map<String, dynamic> _$$FilterWithGreaterThanImplToJson(
_$FilterWithGreaterThanImpl instance) =>
<String, dynamic>{
'column': instance.column,
'value': instance.value,
@@ -68,31 +71,33 @@ Map<String, dynamic> _$$_FilterWithGreaterThanToJson(
'runtimeType': instance.$type,
};
_$_FilterWithIsNull _$$_FilterWithIsNullFromJson(Map<String, dynamic> json) =>
_$_FilterWithIsNull(
_$FilterWithIsNullImpl _$$FilterWithIsNullImplFromJson(
Map<String, dynamic> json) =>
_$FilterWithIsNullImpl(
column: json['column'] as String,
invert: json['invert'] as bool? ?? false,
$type: json['runtimeType'] as String?,
);
Map<String, dynamic> _$$_FilterWithIsNullToJson(_$_FilterWithIsNull instance) =>
Map<String, dynamic> _$$FilterWithIsNullImplToJson(
_$FilterWithIsNullImpl instance) =>
<String, dynamic>{
'column': instance.column,
'invert': instance.invert,
'runtimeType': instance.$type,
};
_$_FilterWithBetweenInt _$$_FilterWithBetweenIntFromJson(
_$FilterWithBetweenIntImpl _$$FilterWithBetweenIntImplFromJson(
Map<String, dynamic> json) =>
_$_FilterWithBetweenInt(
_$FilterWithBetweenIntImpl(
column: json['column'] as String,
from: json['from'] as int,
to: json['to'] as int,
from: (json['from'] as num).toInt(),
to: (json['to'] as num).toInt(),
$type: json['runtimeType'] as String?,
);
Map<String, dynamic> _$$_FilterWithBetweenIntToJson(
_$_FilterWithBetweenInt instance) =>
Map<String, dynamic> _$$FilterWithBetweenIntImplToJson(
_$FilterWithBetweenIntImpl instance) =>
<String, dynamic>{
'column': instance.column,
'from': instance.from,
@@ -100,8 +105,8 @@ Map<String, dynamic> _$$_FilterWithBetweenIntToJson(
'runtimeType': instance.$type,
};
_$_FilterWithIsIn _$$_FilterWithIsInFromJson(Map<String, dynamic> json) =>
_$_FilterWithIsIn(
_$FilterWithIsInImpl _$$FilterWithIsInImplFromJson(Map<String, dynamic> json) =>
_$FilterWithIsInImpl(
column: json['column'] as String,
invert: json['invert'] as bool? ?? false,
values: json['values'] == null
@@ -110,7 +115,8 @@ _$_FilterWithIsIn _$$_FilterWithIsInFromJson(Map<String, dynamic> json) =>
$type: json['runtimeType'] as String?,
);
Map<String, dynamic> _$$_FilterWithIsInToJson(_$_FilterWithIsIn instance) =>
Map<String, dynamic> _$$FilterWithIsInImplToJson(
_$FilterWithIsInImpl instance) =>
<String, dynamic>{
'column': instance.column,
'invert': instance.invert,
@@ -120,7 +126,8 @@ Map<String, dynamic> _$$_FilterWithIsInToJson(_$_FilterWithIsIn instance) =>
'runtimeType': instance.$type,
};
_$_ListQuery _$$_ListQueryFromJson(Map<String, dynamic> json) => _$_ListQuery(
_$ListQueryImpl _$$ListQueryImplFromJson(Map<String, dynamic> json) =>
_$ListQueryImpl(
page: json['page'] == null
? const Pagination(limit: -1, offset: 0)
: Pagination.fromJson(json['page'] as Map<String, dynamic>),
@@ -133,7 +140,7 @@ _$_ListQuery _$$_ListQueryFromJson(Map<String, dynamic> json) => _$_ListQuery(
(value) => FilterWith.fromJson(value as Map<String, dynamic>)),
);
Map<String, dynamic> _$$_ListQueryToJson(_$_ListQuery instance) =>
Map<String, dynamic> _$$ListQueryImplToJson(_$ListQueryImpl instance) =>
<String, dynamic>{
'page': instance.page,
'sort': instance.sort,

View File

@@ -12,7 +12,7 @@ part of 'settings.dart';
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$Settings {
@@ -81,10 +81,11 @@ class _$SettingsCopyWithImpl<$Res, $Val extends Settings>
}
/// @nodoc
abstract class _$$_SettingsCopyWith<$Res> implements $SettingsCopyWith<$Res> {
factory _$$_SettingsCopyWith(
_$_Settings value, $Res Function(_$_Settings) then) =
__$$_SettingsCopyWithImpl<$Res>;
abstract class _$$SettingsImplCopyWith<$Res>
implements $SettingsCopyWith<$Res> {
factory _$$SettingsImplCopyWith(
_$SettingsImpl value, $Res Function(_$SettingsImpl) then) =
__$$SettingsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -97,11 +98,11 @@ abstract class _$$_SettingsCopyWith<$Res> implements $SettingsCopyWith<$Res> {
}
/// @nodoc
class __$$_SettingsCopyWithImpl<$Res>
extends _$SettingsCopyWithImpl<$Res, _$_Settings>
implements _$$_SettingsCopyWith<$Res> {
__$$_SettingsCopyWithImpl(
_$_Settings _value, $Res Function(_$_Settings) _then)
class __$$SettingsImplCopyWithImpl<$Res>
extends _$SettingsCopyWithImpl<$Res, _$SettingsImpl>
implements _$$SettingsImplCopyWith<$Res> {
__$$SettingsImplCopyWithImpl(
_$SettingsImpl _value, $Res Function(_$SettingsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -111,7 +112,7 @@ class __$$_SettingsCopyWithImpl<$Res>
Object? activeSource = freezed,
Object? app = null,
}) {
return _then(_$_Settings(
return _then(_$SettingsImpl(
sources: null == sources
? _value.sources
: sources // ignore: cast_nullable_to_non_nullable
@@ -130,8 +131,8 @@ class __$$_SettingsCopyWithImpl<$Res>
/// @nodoc
class _$_Settings implements _Settings {
const _$_Settings(
class _$SettingsImpl implements _Settings {
const _$SettingsImpl(
{this.sources = const IListConst([]),
this.activeSource,
this.app = const AppSettings()});
@@ -151,10 +152,10 @@ class _$_Settings implements _Settings {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_Settings &&
other is _$SettingsImpl &&
const DeepCollectionEquality().equals(other.sources, sources) &&
(identical(other.activeSource, activeSource) ||
other.activeSource == activeSource) &&
@@ -168,15 +169,15 @@ class _$_Settings implements _Settings {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SettingsCopyWith<_$_Settings> get copyWith =>
__$$_SettingsCopyWithImpl<_$_Settings>(this, _$identity);
_$$SettingsImplCopyWith<_$SettingsImpl> get copyWith =>
__$$SettingsImplCopyWithImpl<_$SettingsImpl>(this, _$identity);
}
abstract class _Settings implements Settings {
const factory _Settings(
{final IList<SourceSettings> sources,
final SourceSettings? activeSource,
final AppSettings app}) = _$_Settings;
final AppSettings app}) = _$SettingsImpl;
@override
IList<SourceSettings> get sources;
@@ -186,7 +187,7 @@ abstract class _Settings implements Settings {
AppSettings get app;
@override
@JsonKey(ignore: true)
_$$_SettingsCopyWith<_$_Settings> get copyWith =>
_$$SettingsImplCopyWith<_$SettingsImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -245,22 +246,22 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings>
}
/// @nodoc
abstract class _$$_AppSettingsCopyWith<$Res>
abstract class _$$AppSettingsImplCopyWith<$Res>
implements $AppSettingsCopyWith<$Res> {
factory _$$_AppSettingsCopyWith(
_$_AppSettings value, $Res Function(_$_AppSettings) then) =
__$$_AppSettingsCopyWithImpl<$Res>;
factory _$$AppSettingsImplCopyWith(
_$AppSettingsImpl value, $Res Function(_$AppSettingsImpl) then) =
__$$AppSettingsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({int maxBitrateWifi, int maxBitrateMobile, String? streamFormat});
}
/// @nodoc
class __$$_AppSettingsCopyWithImpl<$Res>
extends _$AppSettingsCopyWithImpl<$Res, _$_AppSettings>
implements _$$_AppSettingsCopyWith<$Res> {
__$$_AppSettingsCopyWithImpl(
_$_AppSettings _value, $Res Function(_$_AppSettings) _then)
class __$$AppSettingsImplCopyWithImpl<$Res>
extends _$AppSettingsCopyWithImpl<$Res, _$AppSettingsImpl>
implements _$$AppSettingsImplCopyWith<$Res> {
__$$AppSettingsImplCopyWithImpl(
_$AppSettingsImpl _value, $Res Function(_$AppSettingsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -270,7 +271,7 @@ class __$$_AppSettingsCopyWithImpl<$Res>
Object? maxBitrateMobile = null,
Object? streamFormat = freezed,
}) {
return _then(_$_AppSettings(
return _then(_$AppSettingsImpl(
maxBitrateWifi: null == maxBitrateWifi
? _value.maxBitrateWifi
: maxBitrateWifi // ignore: cast_nullable_to_non_nullable
@@ -289,8 +290,8 @@ class __$$_AppSettingsCopyWithImpl<$Res>
/// @nodoc
class _$_AppSettings extends _AppSettings {
const _$_AppSettings(
class _$AppSettingsImpl extends _AppSettings {
const _$AppSettingsImpl(
{this.maxBitrateWifi = 0,
this.maxBitrateMobile = 192,
this.streamFormat = 'mp3'})
@@ -312,10 +313,10 @@ class _$_AppSettings extends _AppSettings {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_AppSettings &&
other is _$AppSettingsImpl &&
(identical(other.maxBitrateWifi, maxBitrateWifi) ||
other.maxBitrateWifi == maxBitrateWifi) &&
(identical(other.maxBitrateMobile, maxBitrateMobile) ||
@@ -331,15 +332,15 @@ class _$_AppSettings extends _AppSettings {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_AppSettingsCopyWith<_$_AppSettings> get copyWith =>
__$$_AppSettingsCopyWithImpl<_$_AppSettings>(this, _$identity);
_$$AppSettingsImplCopyWith<_$AppSettingsImpl> get copyWith =>
__$$AppSettingsImplCopyWithImpl<_$AppSettingsImpl>(this, _$identity);
}
abstract class _AppSettings extends AppSettings {
const factory _AppSettings(
{final int maxBitrateWifi,
final int maxBitrateMobile,
final String? streamFormat}) = _$_AppSettings;
final String? streamFormat}) = _$AppSettingsImpl;
const _AppSettings._() : super._();
@override
@@ -350,7 +351,7 @@ abstract class _AppSettings extends AppSettings {
String? get streamFormat;
@override
@JsonKey(ignore: true)
_$$_AppSettingsCopyWith<_$_AppSettings> get copyWith =>
_$$AppSettingsImplCopyWith<_$AppSettingsImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -454,11 +455,11 @@ class _$SubsonicSettingsCopyWithImpl<$Res, $Val extends SubsonicSettings>
}
/// @nodoc
abstract class _$$_SubsonicSettingsCopyWith<$Res>
abstract class _$$SubsonicSettingsImplCopyWith<$Res>
implements $SubsonicSettingsCopyWith<$Res> {
factory _$$_SubsonicSettingsCopyWith(
_$_SubsonicSettings value, $Res Function(_$_SubsonicSettings) then) =
__$$_SubsonicSettingsCopyWithImpl<$Res>;
factory _$$SubsonicSettingsImplCopyWith(_$SubsonicSettingsImpl value,
$Res Function(_$SubsonicSettingsImpl) then) =
__$$SubsonicSettingsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -474,11 +475,11 @@ abstract class _$$_SubsonicSettingsCopyWith<$Res>
}
/// @nodoc
class __$$_SubsonicSettingsCopyWithImpl<$Res>
extends _$SubsonicSettingsCopyWithImpl<$Res, _$_SubsonicSettings>
implements _$$_SubsonicSettingsCopyWith<$Res> {
__$$_SubsonicSettingsCopyWithImpl(
_$_SubsonicSettings _value, $Res Function(_$_SubsonicSettings) _then)
class __$$SubsonicSettingsImplCopyWithImpl<$Res>
extends _$SubsonicSettingsCopyWithImpl<$Res, _$SubsonicSettingsImpl>
implements _$$SubsonicSettingsImplCopyWith<$Res> {
__$$SubsonicSettingsImplCopyWithImpl(_$SubsonicSettingsImpl _value,
$Res Function(_$SubsonicSettingsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -494,7 +495,7 @@ class __$$_SubsonicSettingsCopyWithImpl<$Res>
Object? password = null,
Object? useTokenAuth = null,
}) {
return _then(_$_SubsonicSettings(
return _then(_$SubsonicSettingsImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
@@ -537,8 +538,8 @@ class __$$_SubsonicSettingsCopyWithImpl<$Res>
/// @nodoc
class _$_SubsonicSettings extends _SubsonicSettings {
const _$_SubsonicSettings(
class _$SubsonicSettingsImpl extends _SubsonicSettings {
const _$SubsonicSettingsImpl(
{required this.id,
this.features = const IListConst([]),
required this.name,
@@ -577,10 +578,10 @@ class _$_SubsonicSettings extends _SubsonicSettings {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_SubsonicSettings &&
other is _$SubsonicSettingsImpl &&
(identical(other.id, id) || other.id == id) &&
const DeepCollectionEquality().equals(other.features, features) &&
(identical(other.name, name) || other.name == name) &&
@@ -613,8 +614,9 @@ class _$_SubsonicSettings extends _SubsonicSettings {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SubsonicSettingsCopyWith<_$_SubsonicSettings> get copyWith =>
__$$_SubsonicSettingsCopyWithImpl<_$_SubsonicSettings>(this, _$identity);
_$$SubsonicSettingsImplCopyWith<_$SubsonicSettingsImpl> get copyWith =>
__$$SubsonicSettingsImplCopyWithImpl<_$SubsonicSettingsImpl>(
this, _$identity);
}
abstract class _SubsonicSettings extends SubsonicSettings {
@@ -627,7 +629,7 @@ abstract class _SubsonicSettings extends SubsonicSettings {
required final DateTime createdAt,
required final String username,
required final String password,
final bool useTokenAuth}) = _$_SubsonicSettings;
final bool useTokenAuth}) = _$SubsonicSettingsImpl;
const _SubsonicSettings._() : super._();
@override
@@ -650,7 +652,7 @@ abstract class _SubsonicSettings extends SubsonicSettings {
bool get useTokenAuth;
@override
@JsonKey(ignore: true)
_$$_SubsonicSettingsCopyWith<_$_SubsonicSettings> get copyWith =>
_$$SubsonicSettingsImplCopyWith<_$SubsonicSettingsImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -714,11 +716,12 @@ class _$SubsonicSourceSettingsCopyWithImpl<$Res,
}
/// @nodoc
abstract class _$$_SubsonicSourceSettingsCopyWith<$Res>
abstract class _$$SubsonicSourceSettingsImplCopyWith<$Res>
implements $SubsonicSourceSettingsCopyWith<$Res> {
factory _$$_SubsonicSourceSettingsCopyWith(_$_SubsonicSourceSettings value,
$Res Function(_$_SubsonicSourceSettings) then) =
__$$_SubsonicSourceSettingsCopyWithImpl<$Res>;
factory _$$SubsonicSourceSettingsImplCopyWith(
_$SubsonicSourceSettingsImpl value,
$Res Function(_$SubsonicSourceSettingsImpl) then) =
__$$SubsonicSourceSettingsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({SourceSettings source, SubsonicSettings subsonic});
@@ -728,12 +731,13 @@ abstract class _$$_SubsonicSourceSettingsCopyWith<$Res>
}
/// @nodoc
class __$$_SubsonicSourceSettingsCopyWithImpl<$Res>
class __$$SubsonicSourceSettingsImplCopyWithImpl<$Res>
extends _$SubsonicSourceSettingsCopyWithImpl<$Res,
_$_SubsonicSourceSettings>
implements _$$_SubsonicSourceSettingsCopyWith<$Res> {
__$$_SubsonicSourceSettingsCopyWithImpl(_$_SubsonicSourceSettings _value,
$Res Function(_$_SubsonicSourceSettings) _then)
_$SubsonicSourceSettingsImpl>
implements _$$SubsonicSourceSettingsImplCopyWith<$Res> {
__$$SubsonicSourceSettingsImplCopyWithImpl(
_$SubsonicSourceSettingsImpl _value,
$Res Function(_$SubsonicSourceSettingsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -742,7 +746,7 @@ class __$$_SubsonicSourceSettingsCopyWithImpl<$Res>
Object? source = null,
Object? subsonic = null,
}) {
return _then(_$_SubsonicSourceSettings(
return _then(_$SubsonicSourceSettingsImpl(
source: null == source
? _value.source
: source // ignore: cast_nullable_to_non_nullable
@@ -757,8 +761,8 @@ class __$$_SubsonicSourceSettingsCopyWithImpl<$Res>
/// @nodoc
class _$_SubsonicSourceSettings extends _SubsonicSourceSettings {
const _$_SubsonicSourceSettings(
class _$SubsonicSourceSettingsImpl extends _SubsonicSourceSettings {
const _$SubsonicSourceSettingsImpl(
{required this.source, required this.subsonic})
: super._();
@@ -773,10 +777,10 @@ class _$_SubsonicSourceSettings extends _SubsonicSourceSettings {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_SubsonicSourceSettings &&
other is _$SubsonicSourceSettingsImpl &&
(identical(other.source, source) || other.source == source) &&
(identical(other.subsonic, subsonic) ||
other.subsonic == subsonic));
@@ -788,15 +792,15 @@ class _$_SubsonicSourceSettings extends _SubsonicSourceSettings {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_SubsonicSourceSettingsCopyWith<_$_SubsonicSourceSettings> get copyWith =>
__$$_SubsonicSourceSettingsCopyWithImpl<_$_SubsonicSourceSettings>(
this, _$identity);
_$$SubsonicSourceSettingsImplCopyWith<_$SubsonicSourceSettingsImpl>
get copyWith => __$$SubsonicSourceSettingsImplCopyWithImpl<
_$SubsonicSourceSettingsImpl>(this, _$identity);
}
abstract class _SubsonicSourceSettings extends SubsonicSourceSettings {
const factory _SubsonicSourceSettings(
{required final SourceSettings source,
required final SubsonicSettings subsonic}) = _$_SubsonicSourceSettings;
required final SubsonicSettings subsonic}) = _$SubsonicSourceSettingsImpl;
const _SubsonicSourceSettings._() : super._();
@override
@@ -805,6 +809,6 @@ abstract class _SubsonicSourceSettings extends SubsonicSourceSettings {
SubsonicSettings get subsonic;
@override
@JsonKey(ignore: true)
_$$_SubsonicSourceSettingsCopyWith<_$_SubsonicSourceSettings> get copyWith =>
throw _privateConstructorUsedError;
_$$SubsonicSourceSettingsImplCopyWith<_$SubsonicSourceSettingsImpl>
get copyWith => throw _privateConstructorUsedError;
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,15 +6,16 @@ part of 'support.dart';
// JsonSerializableGenerator
// **************************************************************************
_$_QueueItemState _$$_QueueItemStateFromJson(Map<String, dynamic> json) =>
_$_QueueItemState(
_$QueueItemStateImpl _$$QueueItemStateImplFromJson(Map<String, dynamic> json) =>
_$QueueItemStateImpl(
id: json['id'] as String,
contextType: $enumDecode(_$QueueContextTypeEnumMap, json['contextType']),
contextId: json['contextId'] as String?,
contextTitle: json['contextTitle'] as String?,
);
Map<String, dynamic> _$$_QueueItemStateToJson(_$_QueueItemState instance) =>
Map<String, dynamic> _$$QueueItemStateImplToJson(
_$QueueItemStateImpl instance) =>
<String, dynamic>{
'id': instance.id,
'contextType': _$QueueContextTypeEnumMap[instance.contextType]!,
@@ -31,9 +32,9 @@ const _$QueueContextTypeEnumMap = {
QueueContextType.artist: 'artist',
};
_$_MediaItemData _$$_MediaItemDataFromJson(Map<String, dynamic> json) =>
_$_MediaItemData(
sourceId: json['sourceId'] as int,
_$MediaItemDataImpl _$$MediaItemDataImplFromJson(Map<String, dynamic> json) =>
_$MediaItemDataImpl(
sourceId: (json['sourceId'] as num).toInt(),
albumId: json['albumId'] as String?,
artCache:
_$JsonConverterFromJson<Map<String, dynamic>, MediaItemArtCache>(
@@ -42,7 +43,7 @@ _$_MediaItemData _$$_MediaItemDataFromJson(Map<String, dynamic> json) =>
contextId: json['contextId'] as String?,
);
Map<String, dynamic> _$$_MediaItemDataToJson(_$_MediaItemData instance) =>
Map<String, dynamic> _$$MediaItemDataImplToJson(_$MediaItemDataImpl instance) =>
<String, dynamic>{
'sourceId': instance.sourceId,
'albumId': instance.albumId,
@@ -65,16 +66,17 @@ Json? _$JsonConverterToJson<Json, Value>(
) =>
value == null ? null : toJson(value);
_$_MediaItemArtCache _$$_MediaItemArtCacheFromJson(Map<String, dynamic> json) =>
_$_MediaItemArtCache(
_$MediaItemArtCacheImpl _$$MediaItemArtCacheImplFromJson(
Map<String, dynamic> json) =>
_$MediaItemArtCacheImpl(
fullArtUri: Uri.parse(json['fullArtUri'] as String),
fullArtCacheKey: json['fullArtCacheKey'] as String,
thumbnailArtUri: Uri.parse(json['thumbnailArtUri'] as String),
thumbnailArtCacheKey: json['thumbnailArtCacheKey'] as String,
);
Map<String, dynamic> _$$_MediaItemArtCacheToJson(
_$_MediaItemArtCache instance) =>
Map<String, dynamic> _$$MediaItemArtCacheImplToJson(
_$MediaItemArtCacheImpl instance) =>
<String, dynamic>{
'fullArtUri': instance.fullArtUri.toString(),
'fullArtCacheKey': instance.fullArtCacheKey,

View File

@@ -4,7 +4,6 @@ import 'dart:math';
import 'package:audio_service/audio_service.dart';
import 'package:collection/collection.dart';
import 'package:drift/drift.dart' show Value;
import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:just_audio/just_audio.dart';
import 'package:pool/pool.dart';
@@ -14,6 +13,7 @@ import 'package:synchronized/synchronized.dart';
import '../cache/image_cache.dart';
import '../database/database.dart';
import '../log.dart';
import '../models/music.dart';
import '../models/query.dart';
import '../models/support.dart';
@@ -122,6 +122,10 @@ class AudioControl extends BaseAudioHandler with QueueHandler, SeekHandler {
));
});
_player.playbackEventStream.doOnError((e, st) async {
log.warning('playbackEventStream', e, st);
});
shuffleIndicies.listen((value) {
playbackState.add(playbackState.value.copyWith(
shuffleMode: value != null
@@ -137,7 +141,7 @@ class AudioControl extends BaseAudioHandler with QueueHandler, SeekHandler {
_player.processingStateStream.listen((event) async {
if (event == ProcessingState.completed) {
if (_audioSource.length > 0) {
yell('completed');
log.fine('completed');
await stop();
await seek(Duration.zero);
}
@@ -386,7 +390,7 @@ class AudioControl extends BaseAudioHandler with QueueHandler, SeekHandler {
mediaItem.add(slice.current!.mediaItem);
queue.add(list.map((e) => e.mediaItem).toList());
yell('addAll');
log.fine('addAll');
await _audioSource.addAll(list.map((e) => e.audioSource).toList());
await _player.seek(Duration.zero, index: list.indexOf(slice.current!));
}
@@ -410,7 +414,7 @@ class AudioControl extends BaseAudioHandler with QueueHandler, SeekHandler {
final sourceNeedsPrev = sourceIndex == 0;
if (sourceNeedsNext && slice.next != null) {
yell('add');
log.fine('add');
await _audioSource.add(slice.next!.audioSource);
}
if (sourceNeedsPrev && slice.prev != null) {
@@ -497,7 +501,7 @@ class AudioControl extends BaseAudioHandler with QueueHandler, SeekHandler {
}
Future<void> _insertFirstAudioSource(AudioSource source) {
yell('insert');
log.fine('insert');
final wait = _audioSource.insert(0, source);
_currentIndexIgnore.add(1);
return wait;
@@ -505,20 +509,20 @@ class AudioControl extends BaseAudioHandler with QueueHandler, SeekHandler {
Future<void> _pruneAudioSources(int keepIndex) async {
if (keepIndex > 0) {
yell('removeRange 0');
log.fine('removeRange 0');
final wait = _audioSource.removeRange(0, keepIndex);
_currentIndexIgnore.add(0);
await wait;
}
if (_audioSource.length > 1) {
yell('removeRange 1');
log.fine('removeRange 1');
await _audioSource.removeRange(1, _audioSource.length);
}
}
Future<void> _clearAudioSource([bool clearMetadata = false]) async {
// await _player.stop();
yell('_clearAudioSource');
log.fine('_clearAudioSource');
await _audioSource.clear();
if (clearMetadata) {
@@ -697,11 +701,3 @@ class AudioControl extends BaseAudioHandler with QueueHandler, SeekHandler {
}
}
}
void yell(String msg) {
if (kDebugMode) {
print('=================================================================<');
print(msg);
print('=================================================================>');
}
}

View File

@@ -35,4 +35,5 @@ final audioControlProvider = Provider<AudioControl>.internal(
);
typedef AudioControlRef = ProviderRef<AudioControl>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -20,4 +20,5 @@ final cacheServiceProvider = Provider<CacheService>.internal(
);
typedef CacheServiceRef = ProviderRef<CacheService>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -534,7 +534,7 @@ class DownloadService extends _$DownloadService {
_port.asyncMap((dynamic data) async {
final taskId = (data as List<dynamic>)[0] as String;
final status = DownloadTaskStatus(data[1] as int);
final status = DownloadTaskStatus.fromInt(data[1] as int);
final progress = data[2] as int;
var download = state.downloads.firstWhereOrNull(
@@ -579,11 +579,11 @@ class DownloadService extends _$DownloadService {
@pragma('vm:entry-point')
static void downloadCallback(
String id,
DownloadTaskStatus status,
int status,
int progress,
) {
IsolateNameServer.lookupPortByName('downloader_send_port')?.send(
[id, status.value, progress],
[id, status, progress],
);
}
}

View File

@@ -12,7 +12,7 @@ part of 'download_service.dart';
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
/// @nodoc
mixin _$DownloadState {
@@ -86,11 +86,11 @@ class _$DownloadStateCopyWithImpl<$Res, $Val extends DownloadState>
}
/// @nodoc
abstract class _$$_DownloadStateCopyWith<$Res>
abstract class _$$DownloadStateImplCopyWith<$Res>
implements $DownloadStateCopyWith<$Res> {
factory _$$_DownloadStateCopyWith(
_$_DownloadState value, $Res Function(_$_DownloadState) then) =
__$$_DownloadStateCopyWithImpl<$Res>;
factory _$$DownloadStateImplCopyWith(
_$DownloadStateImpl value, $Res Function(_$DownloadStateImpl) then) =
__$$DownloadStateImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -102,11 +102,11 @@ abstract class _$$_DownloadStateCopyWith<$Res>
}
/// @nodoc
class __$$_DownloadStateCopyWithImpl<$Res>
extends _$DownloadStateCopyWithImpl<$Res, _$_DownloadState>
implements _$$_DownloadStateCopyWith<$Res> {
__$$_DownloadStateCopyWithImpl(
_$_DownloadState _value, $Res Function(_$_DownloadState) _then)
class __$$DownloadStateImplCopyWithImpl<$Res>
extends _$DownloadStateCopyWithImpl<$Res, _$DownloadStateImpl>
implements _$$DownloadStateImplCopyWith<$Res> {
__$$DownloadStateImplCopyWithImpl(
_$DownloadStateImpl _value, $Res Function(_$DownloadStateImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -118,7 +118,7 @@ class __$$_DownloadStateCopyWithImpl<$Res>
Object? listCancels = null,
Object? saveDir = null,
}) {
return _then(_$_DownloadState(
return _then(_$DownloadStateImpl(
downloads: null == downloads
? _value.downloads
: downloads // ignore: cast_nullable_to_non_nullable
@@ -145,8 +145,8 @@ class __$$_DownloadStateCopyWithImpl<$Res>
/// @nodoc
class _$_DownloadState implements _DownloadState {
const _$_DownloadState(
class _$DownloadStateImpl implements _DownloadState {
const _$DownloadStateImpl(
{this.downloads = const IListConst([]),
this.deletes = const IListConst([]),
this.listDownloads = const IListConst([]),
@@ -174,10 +174,10 @@ class _$_DownloadState implements _DownloadState {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_DownloadState &&
other is _$DownloadStateImpl &&
const DeepCollectionEquality().equals(other.downloads, downloads) &&
const DeepCollectionEquality().equals(other.deletes, deletes) &&
const DeepCollectionEquality()
@@ -199,8 +199,8 @@ class _$_DownloadState implements _DownloadState {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_DownloadStateCopyWith<_$_DownloadState> get copyWith =>
__$$_DownloadStateCopyWithImpl<_$_DownloadState>(this, _$identity);
_$$DownloadStateImplCopyWith<_$DownloadStateImpl> get copyWith =>
__$$DownloadStateImplCopyWithImpl<_$DownloadStateImpl>(this, _$identity);
}
abstract class _DownloadState implements DownloadState {
@@ -209,7 +209,7 @@ abstract class _DownloadState implements DownloadState {
final IList<SourceId> deletes,
final IList<SourceId> listDownloads,
final IList<SourceId> listCancels,
required final String saveDir}) = _$_DownloadState;
required final String saveDir}) = _$DownloadStateImpl;
@override
IList<Download> get downloads;
@@ -223,7 +223,7 @@ abstract class _DownloadState implements DownloadState {
String get saveDir;
@override
@JsonKey(ignore: true)
_$$_DownloadStateCopyWith<_$_DownloadState> get copyWith =>
_$$DownloadStateImplCopyWith<_$DownloadStateImpl> get copyWith =>
throw _privateConstructorUsedError;
}
@@ -319,10 +319,11 @@ class _$DownloadCopyWithImpl<$Res, $Val extends Download>
}
/// @nodoc
abstract class _$$_DownloadCopyWith<$Res> implements $DownloadCopyWith<$Res> {
factory _$$_DownloadCopyWith(
_$_Download value, $Res Function(_$_Download) then) =
__$$_DownloadCopyWithImpl<$Res>;
abstract class _$$DownloadImplCopyWith<$Res>
implements $DownloadCopyWith<$Res> {
factory _$$DownloadImplCopyWith(
_$DownloadImpl value, $Res Function(_$DownloadImpl) then) =
__$$DownloadImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
@@ -337,11 +338,11 @@ abstract class _$$_DownloadCopyWith<$Res> implements $DownloadCopyWith<$Res> {
}
/// @nodoc
class __$$_DownloadCopyWithImpl<$Res>
extends _$DownloadCopyWithImpl<$Res, _$_Download>
implements _$$_DownloadCopyWith<$Res> {
__$$_DownloadCopyWithImpl(
_$_Download _value, $Res Function(_$_Download) _then)
class __$$DownloadImplCopyWithImpl<$Res>
extends _$DownloadCopyWithImpl<$Res, _$DownloadImpl>
implements _$$DownloadImplCopyWith<$Res> {
__$$DownloadImplCopyWithImpl(
_$DownloadImpl _value, $Res Function(_$DownloadImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@@ -356,7 +357,7 @@ class __$$_DownloadCopyWithImpl<$Res>
Object? timeCreated = null,
Object? allowCellular = null,
}) {
return _then(_$_Download(
return _then(_$DownloadImpl(
taskId: null == taskId
? _value.taskId
: taskId // ignore: cast_nullable_to_non_nullable
@@ -395,8 +396,8 @@ class __$$_DownloadCopyWithImpl<$Res>
/// @nodoc
class _$_Download extends _Download {
const _$_Download(
class _$DownloadImpl extends _Download {
const _$DownloadImpl(
{required this.taskId,
required this.status,
required this.progress,
@@ -430,10 +431,10 @@ class _$_Download extends _Download {
}
@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$_Download &&
other is _$DownloadImpl &&
(identical(other.taskId, taskId) || other.taskId == taskId) &&
(identical(other.status, status) || other.status == status) &&
(identical(other.progress, progress) ||
@@ -456,8 +457,8 @@ class _$_Download extends _Download {
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$_DownloadCopyWith<_$_Download> get copyWith =>
__$$_DownloadCopyWithImpl<_$_Download>(this, _$identity);
_$$DownloadImplCopyWith<_$DownloadImpl> get copyWith =>
__$$DownloadImplCopyWithImpl<_$DownloadImpl>(this, _$identity);
}
abstract class _Download extends Download {
@@ -469,7 +470,7 @@ abstract class _Download extends Download {
required final String? filename,
required final String savedDir,
required final int timeCreated,
required final bool allowCellular}) = _$_Download;
required final bool allowCellular}) = _$DownloadImpl;
const _Download._() : super._();
@override
@@ -490,6 +491,6 @@ abstract class _Download extends Download {
bool get allowCellular;
@override
@JsonKey(ignore: true)
_$$_DownloadCopyWith<_$_Download> get copyWith =>
_$$DownloadImplCopyWith<_$DownloadImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -6,7 +6,7 @@ part of 'download_service.dart';
// RiverpodGenerator
// **************************************************************************
String _$downloadServiceHash() => r'c72c49f980e307f3013467e76b6564d14a34a736';
String _$downloadServiceHash() => r'd2aeed2c026de4dc7fa26b2331244b49e7e9f003';
/// See also [DownloadService].
@ProviderFor(DownloadService)
@@ -22,4 +22,5 @@ final downloadServiceProvider =
);
typedef _$DownloadService = Notifier<DownloadState>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -46,13 +46,15 @@ class SettingsService extends _$SettingsService {
features: IList(),
username: subsonic.username.value,
password: subsonic.password.value,
useTokenAuth: true,
useTokenAuth: subsonic.useTokenAuth.value,
isActive: true,
createdAt: DateTime.now(),
),
ref.read(httpClientProvider),
);
await client.test();
final features = IList([
if (await client.testFeature(SubsonicFeature.emptyQuerySearch))
SubsonicFeature.emptyQuerySearch,
@@ -66,6 +68,10 @@ class SettingsService extends _$SettingsService {
}
Future<void> updateSource(SubsonicSettings source) async {
final client = SubsonicClient(source, ref.read(httpClientProvider));
await client.test();
await _db.updateSource(source);
await init();
}

View File

@@ -6,7 +6,7 @@ part of 'settings_service.dart';
// RiverpodGenerator
// **************************************************************************
String _$settingsServiceHash() => r'85f2bd5eedc3f791fe03a6707748bc95277c6aaf';
String _$settingsServiceHash() => r'b53814d7d06c5d0a7ac82f447ac510e59a9598f0';
/// See also [SettingsService].
@ProviderFor(SettingsService)
@@ -22,4 +22,5 @@ final settingsServiceProvider =
);
typedef _$SettingsService = Notifier<Settings>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -20,4 +20,5 @@ final syncServiceProvider = NotifierProvider<SyncService, DateTime>.internal(
);
typedef _$SyncService = Notifier<DateTime>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -1,6 +1,8 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:rxdart/rxdart.dart';
import '../database/database.dart';
import '../log.dart';
import '../state/settings.dart';
abstract class BaseMusicSource {
@@ -40,25 +42,33 @@ class MusicSource implements BaseMusicSource {
@override
Stream<Iterable<AlbumsCompanion>> allAlbums() {
_testOnline();
return _source.allAlbums();
return _source
.allAlbums()
.doOnError((e, st) => log.severe('allAlbums', e, st));
}
@override
Stream<Iterable<ArtistsCompanion>> allArtists() {
_testOnline();
return _source.allArtists();
return _source
.allArtists()
.doOnError((e, st) => log.severe('allArtists', e, st));
}
@override
Stream<Iterable<PlaylistWithSongsCompanion>> allPlaylists() {
_testOnline();
return _source.allPlaylists();
return _source
.allPlaylists()
.doOnError((e, st) => log.severe('allPlaylists', e, st));
}
@override
Stream<Iterable<SongsCompanion>> allSongs() {
_testOnline();
return _source.allSongs();
return _source
.allSongs()
.doOnError((e, st) => log.severe('allSongs', e, st));
}
@override

View File

@@ -6,6 +6,7 @@ import 'package:crypto/crypto.dart';
import 'package:http/http.dart';
import 'package:xml/xml.dart';
import '../../log.dart';
import '../../models/settings.dart';
import 'xml.dart';
@@ -89,12 +90,16 @@ class SubsonicClient {
final subsonicResponse =
SubsonicResponse(XmlDocument.parse(utf8.decode(res.bodyBytes)));
if (subsonicResponse.status == Status.failed) {
throw SubsonicException(subsonicResponse.xml);
final error = SubsonicException(subsonicResponse.xml);
log.severe('Subsonic error', error);
throw error;
}
return subsonicResponse;
}
Future<void> test() => get('ping');
Future<bool> testFeature(SubsonicFeature feature) async {
switch (feature) {
case SubsonicFeature.emptyQuerySearch:

View File

@@ -144,7 +144,7 @@ class SubsonicSource implements MusicSource {
return Uri.tryParse(res.xml
.getElement('artistInfo2')
?.getElement(thumbnail ? 'smallImageUrl' : 'largeImageUrl')
?.text ??
?.value ??
'');
}

View File

@@ -226,4 +226,5 @@ final lastAudioStateServiceProvider =
);
typedef _$LastAudioStateService = AsyncNotifier<void>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -94,4 +94,5 @@ final initProvider = FutureProvider<void>.internal(
);
typedef InitRef = FutureProviderRef<void>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

File diff suppressed because it is too large Load Diff

View File

@@ -76,4 +76,5 @@ final offlineModeProvider = NotifierProvider<OfflineMode, bool>.internal(
);
typedef _$OfflineMode = Notifier<bool>;
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View File

@@ -87,7 +87,6 @@ ColorTheme _colorTheme(_ColorThemeRef ref, Palette palette) {
final colorScheme = ColorScheme.fromSeed(
brightness: Brightness.dark,
seedColor: background?.color ?? Colors.purple[800]!,
background: background?.color,
primaryContainer: primary?.color,
onPrimaryContainer: primary?.bodyTextColor,
secondaryContainer: secondary?.color,
@@ -96,8 +95,8 @@ ColorTheme _colorTheme(_ColorThemeRef ref, Palette palette) {
surfaceTint: vibrant?.color,
);
final hsv = HSVColor.fromColor(colorScheme.background);
final hsl = HSLColor.fromColor(colorScheme.background);
final hsv = HSVColor.fromColor(colorScheme.surface);
final hsl = HSLColor.fromColor(colorScheme.surface);
return base.copyWith(
theme: ThemeData(
@@ -106,7 +105,7 @@ ColorTheme _colorTheme(_ColorThemeRef ref, Palette palette) {
brightness: base.theme.brightness,
cardTheme: base.theme.cardTheme,
),
gradientHigh: colorScheme.background,
gradientHigh: colorScheme.surface,
darkBackground: hsv.withValue(kDarkBackgroundValue).toColor(),
darkerBackground: hsl.withLightness(kDarkerBackgroundLightness).toColor(),
onDarkerBackground:
@@ -128,13 +127,13 @@ ColorTheme baseTheme(BaseThemeRef ref) {
),
);
final hsv = HSVColor.fromColor(theme.colorScheme.background);
final hsl = HSLColor.fromColor(theme.colorScheme.background);
final hsv = HSVColor.fromColor(theme.colorScheme.surface);
final hsl = HSLColor.fromColor(theme.colorScheme.surface);
return ColorTheme(
theme: theme,
gradientHigh: theme.colorScheme.background,
gradientLow: HSLColor.fromColor(theme.colorScheme.background)
gradientHigh: theme.colorScheme.surface,
gradientLow: HSLColor.fromColor(theme.colorScheme.surface)
.withLightness(0.06)
.toColor(),
darkBackground: hsv.withValue(kDarkBackgroundValue).toColor(),

View File

@@ -6,7 +6,7 @@ part of 'theme.dart';
// RiverpodGenerator
// **************************************************************************
String _$colorThemeHash() => r'f5cc23cb5e2af379c02ae4b9756df72f9f6da5e6';
String _$colorThemeHash() => r'37d4eb17395341800b67f4f257c2cc49bf3dc91b';
/// Copied from Dart SDK
class _SystemHash {
@@ -29,8 +29,6 @@ class _SystemHash {
}
}
typedef _ColorThemeRef = AutoDisposeProviderRef<ColorTheme>;
/// See also [_colorTheme].
@ProviderFor(_colorTheme)
const _colorThemeProvider = _ColorThemeFamily();
@@ -77,10 +75,10 @@ class _ColorThemeFamily extends Family<ColorTheme> {
class _ColorThemeProvider extends AutoDisposeProvider<ColorTheme> {
/// See also [_colorTheme].
_ColorThemeProvider(
this.palette,
) : super.internal(
Palette palette,
) : this._internal(
(ref) => _colorTheme(
ref,
ref as _ColorThemeRef,
palette,
),
from: _colorThemeProvider,
@@ -92,10 +90,44 @@ class _ColorThemeProvider extends AutoDisposeProvider<ColorTheme> {
dependencies: _ColorThemeFamily._dependencies,
allTransitiveDependencies:
_ColorThemeFamily._allTransitiveDependencies,
palette: palette,
);
_ColorThemeProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.palette,
}) : super.internal();
final Palette palette;
@override
Override overrideWith(
ColorTheme Function(_ColorThemeRef provider) create,
) {
return ProviderOverride(
origin: this,
override: _ColorThemeProvider._internal(
(ref) => create(ref as _ColorThemeRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
palette: palette,
),
);
}
@override
AutoDisposeProviderElement<ColorTheme> createElement() {
return _ColorThemeProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is _ColorThemeProvider && other.palette == palette;
@@ -110,7 +142,20 @@ class _ColorThemeProvider extends AutoDisposeProvider<ColorTheme> {
}
}
String _$baseThemeHash() => r'317a5ef77def208357a54b7938ef3d91666fce70';
mixin _ColorThemeRef on AutoDisposeProviderRef<ColorTheme> {
/// The parameter `palette` of this provider.
Palette get palette;
}
class _ColorThemeProviderElement extends AutoDisposeProviderElement<ColorTheme>
with _ColorThemeRef {
_ColorThemeProviderElement(super.provider);
@override
Palette get palette => (origin as _ColorThemeProvider).palette;
}
String _$baseThemeHash() => r'489ea7dcf66a57e6eda300c75d8af5fcaef85e8e';
/// See also [baseTheme].
@ProviderFor(baseTheme)
@@ -125,7 +170,6 @@ final baseThemeProvider = AutoDisposeProvider<ColorTheme>.internal(
typedef BaseThemeRef = AutoDisposeProviderRef<ColorTheme>;
String _$albumArtPaletteHash() => r'8130b954ee3c67f53207593d4ed3dfbffb00c95d';
typedef AlbumArtPaletteRef = AutoDisposeFutureProviderRef<Palette>;
/// See also [albumArtPalette].
@ProviderFor(albumArtPalette)
@@ -173,10 +217,10 @@ class AlbumArtPaletteFamily extends Family<AsyncValue<Palette>> {
class AlbumArtPaletteProvider extends AutoDisposeFutureProvider<Palette> {
/// See also [albumArtPalette].
AlbumArtPaletteProvider(
this.id,
) : super.internal(
String id,
) : this._internal(
(ref) => albumArtPalette(
ref,
ref as AlbumArtPaletteRef,
id,
),
from: albumArtPaletteProvider,
@@ -188,10 +232,44 @@ class AlbumArtPaletteProvider extends AutoDisposeFutureProvider<Palette> {
dependencies: AlbumArtPaletteFamily._dependencies,
allTransitiveDependencies:
AlbumArtPaletteFamily._allTransitiveDependencies,
id: id,
);
AlbumArtPaletteProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.id,
}) : super.internal();
final String id;
@override
Override overrideWith(
FutureOr<Palette> Function(AlbumArtPaletteRef provider) create,
) {
return ProviderOverride(
origin: this,
override: AlbumArtPaletteProvider._internal(
(ref) => create(ref as AlbumArtPaletteRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
id: id,
),
);
}
@override
AutoDisposeFutureProviderElement<Palette> createElement() {
return _AlbumArtPaletteProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is AlbumArtPaletteProvider && other.id == id;
@@ -206,9 +284,21 @@ class AlbumArtPaletteProvider extends AutoDisposeFutureProvider<Palette> {
}
}
mixin AlbumArtPaletteRef on AutoDisposeFutureProviderRef<Palette> {
/// The parameter `id` of this provider.
String get id;
}
class _AlbumArtPaletteProviderElement
extends AutoDisposeFutureProviderElement<Palette> with AlbumArtPaletteRef {
_AlbumArtPaletteProviderElement(super.provider);
@override
String get id => (origin as AlbumArtPaletteProvider).id;
}
String _$playlistArtPaletteHash() =>
r'6bc015688f354ea8d91dde86e2a7191ef1ef6496';
typedef PlaylistArtPaletteRef = AutoDisposeFutureProviderRef<Palette>;
/// See also [playlistArtPalette].
@ProviderFor(playlistArtPalette)
@@ -256,10 +346,10 @@ class PlaylistArtPaletteFamily extends Family<AsyncValue<Palette>> {
class PlaylistArtPaletteProvider extends AutoDisposeFutureProvider<Palette> {
/// See also [playlistArtPalette].
PlaylistArtPaletteProvider(
this.id,
) : super.internal(
String id,
) : this._internal(
(ref) => playlistArtPalette(
ref,
ref as PlaylistArtPaletteRef,
id,
),
from: playlistArtPaletteProvider,
@@ -271,10 +361,44 @@ class PlaylistArtPaletteProvider extends AutoDisposeFutureProvider<Palette> {
dependencies: PlaylistArtPaletteFamily._dependencies,
allTransitiveDependencies:
PlaylistArtPaletteFamily._allTransitiveDependencies,
id: id,
);
PlaylistArtPaletteProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.id,
}) : super.internal();
final String id;
@override
Override overrideWith(
FutureOr<Palette> Function(PlaylistArtPaletteRef provider) create,
) {
return ProviderOverride(
origin: this,
override: PlaylistArtPaletteProvider._internal(
(ref) => create(ref as PlaylistArtPaletteRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
id: id,
),
);
}
@override
AutoDisposeFutureProviderElement<Palette> createElement() {
return _PlaylistArtPaletteProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is PlaylistArtPaletteProvider && other.id == id;
@@ -289,6 +413,20 @@ class PlaylistArtPaletteProvider extends AutoDisposeFutureProvider<Palette> {
}
}
mixin PlaylistArtPaletteRef on AutoDisposeFutureProviderRef<Palette> {
/// The parameter `id` of this provider.
String get id;
}
class _PlaylistArtPaletteProviderElement
extends AutoDisposeFutureProviderElement<Palette>
with PlaylistArtPaletteRef {
_PlaylistArtPaletteProviderElement(super.provider);
@override
String get id => (origin as PlaylistArtPaletteProvider).id;
}
String _$mediaItemPaletteHash() => r'2f2744aa735c6056919197c283a367714d7e04e4';
/// See also [mediaItemPalette].
@@ -320,7 +458,6 @@ final mediaItemThemeProvider = AutoDisposeFutureProvider<ColorTheme>.internal(
typedef MediaItemThemeRef = AutoDisposeFutureProviderRef<ColorTheme>;
String _$albumArtThemeHash() => r'd3ee71b2df856f1763ec925e158ae2e0f613b9e0';
typedef AlbumArtThemeRef = AutoDisposeFutureProviderRef<ColorTheme>;
/// See also [albumArtTheme].
@ProviderFor(albumArtTheme)
@@ -368,10 +505,10 @@ class AlbumArtThemeFamily extends Family<AsyncValue<ColorTheme>> {
class AlbumArtThemeProvider extends AutoDisposeFutureProvider<ColorTheme> {
/// See also [albumArtTheme].
AlbumArtThemeProvider(
this.id,
) : super.internal(
String id,
) : this._internal(
(ref) => albumArtTheme(
ref,
ref as AlbumArtThemeRef,
id,
),
from: albumArtThemeProvider,
@@ -383,10 +520,44 @@ class AlbumArtThemeProvider extends AutoDisposeFutureProvider<ColorTheme> {
dependencies: AlbumArtThemeFamily._dependencies,
allTransitiveDependencies:
AlbumArtThemeFamily._allTransitiveDependencies,
id: id,
);
AlbumArtThemeProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.id,
}) : super.internal();
final String id;
@override
Override overrideWith(
FutureOr<ColorTheme> Function(AlbumArtThemeRef provider) create,
) {
return ProviderOverride(
origin: this,
override: AlbumArtThemeProvider._internal(
(ref) => create(ref as AlbumArtThemeRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
id: id,
),
);
}
@override
AutoDisposeFutureProviderElement<ColorTheme> createElement() {
return _AlbumArtThemeProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is AlbumArtThemeProvider && other.id == id;
@@ -401,8 +572,20 @@ class AlbumArtThemeProvider extends AutoDisposeFutureProvider<ColorTheme> {
}
}
mixin AlbumArtThemeRef on AutoDisposeFutureProviderRef<ColorTheme> {
/// The parameter `id` of this provider.
String get id;
}
class _AlbumArtThemeProviderElement
extends AutoDisposeFutureProviderElement<ColorTheme> with AlbumArtThemeRef {
_AlbumArtThemeProviderElement(super.provider);
@override
String get id => (origin as AlbumArtThemeProvider).id;
}
String _$playlistArtThemeHash() => r'1629552e1f3aa2a1e7d223ac1e078893042e5e3b';
typedef PlaylistArtThemeRef = AutoDisposeFutureProviderRef<ColorTheme>;
/// See also [playlistArtTheme].
@ProviderFor(playlistArtTheme)
@@ -450,10 +633,10 @@ class PlaylistArtThemeFamily extends Family<AsyncValue<ColorTheme>> {
class PlaylistArtThemeProvider extends AutoDisposeFutureProvider<ColorTheme> {
/// See also [playlistArtTheme].
PlaylistArtThemeProvider(
this.id,
) : super.internal(
String id,
) : this._internal(
(ref) => playlistArtTheme(
ref,
ref as PlaylistArtThemeRef,
id,
),
from: playlistArtThemeProvider,
@@ -465,10 +648,44 @@ class PlaylistArtThemeProvider extends AutoDisposeFutureProvider<ColorTheme> {
dependencies: PlaylistArtThemeFamily._dependencies,
allTransitiveDependencies:
PlaylistArtThemeFamily._allTransitiveDependencies,
id: id,
);
PlaylistArtThemeProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.id,
}) : super.internal();
final String id;
@override
Override overrideWith(
FutureOr<ColorTheme> Function(PlaylistArtThemeRef provider) create,
) {
return ProviderOverride(
origin: this,
override: PlaylistArtThemeProvider._internal(
(ref) => create(ref as PlaylistArtThemeRef),
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
id: id,
),
);
}
@override
AutoDisposeFutureProviderElement<ColorTheme> createElement() {
return _PlaylistArtThemeProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is PlaylistArtThemeProvider && other.id == id;
@@ -482,4 +699,19 @@ class PlaylistArtThemeProvider extends AutoDisposeFutureProvider<ColorTheme> {
return _SystemHash.finish(hash);
}
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
mixin PlaylistArtThemeRef on AutoDisposeFutureProviderRef<ColorTheme> {
/// The parameter `id` of this provider.
String get id;
}
class _PlaylistArtThemeProviderElement
extends AutoDisposeFutureProviderElement<ColorTheme>
with PlaylistArtThemeRef {
_PlaylistArtThemeProviderElement(super.provider);
@override
String get id => (origin as PlaylistArtThemeProvider).id;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,10 @@ homepage: https://github.com/austinried/subtracks
repository: https://github.com/austinried/subtracks
issue_tracker: https://github.com/austinried/subtracks/issues
publish_to: 'none'
version: 2.0.0-alpha.2+11
version: 2.0.0-alpha.3+12
environment:
sdk: '>=2.19.2 <3.0.0'
sdk: '>=3.5.0 <4.0.0'
dependencies:
flutter:
@@ -22,7 +22,7 @@ dependencies:
path: ^1.8.2
path_provider: ^2.0.12
flutter_dotenv: ^5.0.2 # TODO: remove before release
collection: ^1.17.0
collection: ^1.17.1
intl: any
flutter_hooks: ^0.18.5+1
hooks_riverpod: ^2.3.2
@@ -55,18 +55,17 @@ dependencies:
synchronized: ^3.1.0
flutter_keyboard_visibility: ^5.4.0
connectivity_plus: ^3.0.4
package_info_plus: ^3.1.1
package_info_plus: ^8.1.1
url_launcher: ^6.1.10
logging: ^1.1.1
share_plus: ^7.0.0
# https://github.com/dart-lang/intl/issues/522#issuecomment-1469961807
dependency_overrides:
intl: ^0.18.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
test: ^1.22.0
build_runner:
riverpod_generator: ^2.1.4
freezed: ^2.3.2