diff --git a/.vscode/settings.json b/.vscode/settings.json index 3229a158..8ae9c74f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "fuzzywuzzy", "gapless", "instrumentalness", + "isrc", "Mpris", "RGBO", "riverpod", diff --git a/README.md b/README.md index b2c388e4..03205741 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@
Spotube Logo -An open source, cross-platform Spotify client compatible across multiple platforms
-utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source,
-eliminating the need for Spotify Premium +An open source, cross-platform music client
+utilizing selected music provider API and YouTube, Piped.video or JioSaavn as an audio source Btw it's not just another Electron app 😉 @@ -27,7 +26,7 @@ Btw it's not just another Electron app 😉 ## 🌃 Features -- 🚫 No ads, thanks to the use of public & free Spotify and YT Music APIs¹ +- 🚫 No ads, thanks to the use of public & free music metadata providers and YT Music APIs¹ - ⬇️ Freely downloadable tracks - 🖥️ 📱 Cross-platform support - 🪶 Small size & less data usage @@ -38,12 +37,12 @@ Btw it's not just another Electron app 😉 - 📖 Open source/libre software - 🔉 Playback control is done locally, not on the server -**¹** It is still **recommended** to support creators by engaging with their YouTube channels/Spotify tracks (or preferably by buying their merch/concert tickets/physical media). +**¹** It is still **recommended** to support creators by engaging with their YouTube channels/tracks in music platforms (or preferably by buying their merch/concert tickets/physical media). ### ❌ Unsupported features -- 🗣️ **Spotify Shows & Podcasts:** Shows and Podcasts will **never be supported** because the audio tracks are _only_ available on Spotify and accessing them would require Spotify Premium. -- 🎧 **Spotify Listen Along:** [Coming soon!](https://github.com/KRTirtho/spotube/issues/8) +- 🗣️ **Shows & Podcasts:** Shows and Podcasts will **never be supported** because the audio tracks are _only_ available on music providers and accessing them would require premium. +- 🎧 **Listen Along:** [Coming soon!](https://github.com/KRTirtho/spotube/issues/8) ## 📜 ⬇️ Installation guide @@ -210,7 +209,6 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [Flutter](https://flutter.dev) - Flutter transforms the app development process. Build, test, and deploy beautiful mobile, web, desktop, and embedded apps from a single codebase 1. [MPV](https://mpv.io) - mpv is a free (as in freedom) media player for the command line. It supports a wide variety of media file formats, audio and video codecs, and subtitle types. -1. [Spotify API](https://developer.spotify.com/documentation/web-api) - The Spotify Web API is a RESTful API that provides access to Spotify data 1. [Piped](https://piped-docs.kavin.rocks/) - Piped is a privacy friendly alternative YouTube frontend, which is efficient and scalable by design. 1. [Invidious](https://invidious.io/) - Invidious is an open source alternative front-end to YouTube. 1. [YouTube](https://youtube.com/) - YouTube is an American online video-sharing platform headquartered in San Bruno, California. Three former PayPal employees—Chad Hurley, Steve Chen, and Jawed Karim—created the service in February 2005 @@ -304,7 +302,6 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [sliding_up_panel](https://github.com/akshathjain/sliding_up_panel) - A draggable Flutter widget that makes implementing a SlidingUpPanel much easier! 1. [sliver_tools](https://github.com/Kavantix) - A set of useful sliver tools that are missing from the flutter framework 1. [smtc_windows](https://pub.dev/packages/smtc_windows) - Windows `SystemMediaTransportControls` implementation for Flutter giving access to Windows OS Media Control applet. -1. [spotify](https://github.com/rinukkusu/spotify-dart) - An incomplete dart library for interfacing with the Spotify Web API. 1. [sqlite3](https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3) - Provides lightweight yet convenient bindings to SQLite by using dart:ffi 1. [sqlite3_flutter_libs](https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3_flutter_libs) - Flutter plugin to include native sqlite3 libraries with your app 1. [stroke_text](https://github.com/MohamedAbd0/stroke_text) - A Simple Flutter plugin for applying stroke (border) style to a text widget @@ -350,4 +347,4 @@ If you are concerned, you can [read the reason of choosing this license](https:/ 1. [flutter_new_pipe_extractor](https://github.com/KRTirtho/flutter_new_pipe_extractor) - NewPipeExtractor binding for Flutter (Android only) -

© Copyright Spotube 2024

+

© Copyright Spotube 2025

diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index 700901e8..17a13e9d 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -18,4 +18,33 @@ -keep class org.schabi.newpipe.extractor.timeago.patterns.** { *; } -keep class org.mozilla.javascript.** { *; } -keep class org.mozilla.classfile.ClassFileWriter --dontwarn org.mozilla.javascript.tools.** \ No newline at end of file +-dontwarn org.mozilla.javascript.tools.** + +-dontwarn javax.script.AbstractScriptEngine +-dontwarn javax.script.Bindings +-dontwarn javax.script.Compilable +-dontwarn javax.script.CompiledScript +-dontwarn javax.script.Invocable +-dontwarn javax.script.ScriptContext +-dontwarn javax.script.ScriptEngine +-dontwarn javax.script.ScriptEngineFactory +-dontwarn javax.script.ScriptException +-dontwarn javax.script.SimpleBindings +-dontwarn jdk.dynalink.CallSiteDescriptor +-dontwarn jdk.dynalink.DynamicLinker +-dontwarn jdk.dynalink.DynamicLinkerFactory +-dontwarn jdk.dynalink.NamedOperation +-dontwarn jdk.dynalink.Namespace +-dontwarn jdk.dynalink.NamespaceOperation +-dontwarn jdk.dynalink.Operation +-dontwarn jdk.dynalink.RelinkableCallSite +-dontwarn jdk.dynalink.StandardNamespace +-dontwarn jdk.dynalink.StandardOperation +-dontwarn jdk.dynalink.linker.GuardedInvocation +-dontwarn jdk.dynalink.linker.GuardingDynamicLinker +-dontwarn jdk.dynalink.linker.LinkRequest +-dontwarn jdk.dynalink.linker.LinkerServices +-dontwarn jdk.dynalink.linker.TypeBasedGuardingDynamicLinker +-dontwarn jdk.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker +-dontwarn jdk.dynalink.linker.support.Guards +-dontwarn jdk.dynalink.support.ChainedCallSite \ No newline at end of file diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index a32d12af..400c91e8 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -3,4 +3,17 @@ to allow setting breakpoints, to provide hot reload, etc. --> + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable-hdpi-v31/android12branding.png b/android/app/src/main/res/drawable-hdpi-v31/android12branding.png index fff3f148..22a9b8d3 100644 Binary files a/android/app/src/main/res/drawable-hdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-hdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-hdpi/android12splash.png b/android/app/src/main/res/drawable-hdpi/android12splash.png index 0d4e1c68..adeebcd1 100644 Binary files a/android/app/src/main/res/drawable-hdpi/android12splash.png and b/android/app/src/main/res/drawable-hdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-hdpi/branding.png b/android/app/src/main/res/drawable-hdpi/branding.png index fff3f148..22a9b8d3 100644 Binary files a/android/app/src/main/res/drawable-hdpi/branding.png and b/android/app/src/main/res/drawable-hdpi/branding.png differ diff --git a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png index a65caa1b..204ffe94 100644 Binary files a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-hdpi/splash.png b/android/app/src/main/res/drawable-hdpi/splash.png index 0979b5e4..87eebe5c 100644 Binary files a/android/app/src/main/res/drawable-hdpi/splash.png and b/android/app/src/main/res/drawable-hdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-mdpi-v31/android12branding.png b/android/app/src/main/res/drawable-mdpi-v31/android12branding.png index 5a197da3..3ff2a2da 100644 Binary files a/android/app/src/main/res/drawable-mdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-mdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-mdpi/android12splash.png b/android/app/src/main/res/drawable-mdpi/android12splash.png index 5d9760d4..72c22614 100644 Binary files a/android/app/src/main/res/drawable-mdpi/android12splash.png and b/android/app/src/main/res/drawable-mdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-mdpi/branding.png b/android/app/src/main/res/drawable-mdpi/branding.png index 5a197da3..3ff2a2da 100644 Binary files a/android/app/src/main/res/drawable-mdpi/branding.png and b/android/app/src/main/res/drawable-mdpi/branding.png differ diff --git a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png index 3ad0f47e..e7a75c9a 100644 Binary files a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-mdpi/splash.png b/android/app/src/main/res/drawable-mdpi/splash.png index c5e4aca0..6e04efdc 100644 Binary files a/android/app/src/main/res/drawable-mdpi/splash.png and b/android/app/src/main/res/drawable-mdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-night-hdpi-v31/android12branding.png b/android/app/src/main/res/drawable-night-hdpi-v31/android12branding.png index fff3f148..22a9b8d3 100644 Binary files a/android/app/src/main/res/drawable-night-hdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-night-hdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-night-hdpi/android12splash.png b/android/app/src/main/res/drawable-night-hdpi/android12splash.png index 0d4e1c68..adeebcd1 100644 Binary files a/android/app/src/main/res/drawable-night-hdpi/android12splash.png and b/android/app/src/main/res/drawable-night-hdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-mdpi-v31/android12branding.png b/android/app/src/main/res/drawable-night-mdpi-v31/android12branding.png index 5a197da3..3ff2a2da 100644 Binary files a/android/app/src/main/res/drawable-night-mdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-night-mdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-night-mdpi/android12splash.png b/android/app/src/main/res/drawable-night-mdpi/android12splash.png index 5d9760d4..72c22614 100644 Binary files a/android/app/src/main/res/drawable-night-mdpi/android12splash.png and b/android/app/src/main/res/drawable-night-mdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xhdpi-v31/android12branding.png b/android/app/src/main/res/drawable-night-xhdpi-v31/android12branding.png index efc7e6c8..8e2bb197 100644 Binary files a/android/app/src/main/res/drawable-night-xhdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-night-xhdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-night-xhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xhdpi/android12splash.png index 8e5ceb0a..5adba278 100644 Binary files a/android/app/src/main/res/drawable-night-xhdpi/android12splash.png and b/android/app/src/main/res/drawable-night-xhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxhdpi-v31/android12branding.png b/android/app/src/main/res/drawable-night-xxhdpi-v31/android12branding.png index 593877e0..d301093a 100644 Binary files a/android/app/src/main/res/drawable-night-xxhdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-night-xxhdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png index fb89da37..4e294a2d 100644 Binary files a/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png and b/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxxhdpi-v31/android12branding.png b/android/app/src/main/res/drawable-night-xxxhdpi-v31/android12branding.png index 9d233302..42b0bdc2 100644 Binary files a/android/app/src/main/res/drawable-night-xxxhdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-night-xxxhdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png index 38e4a12c..dcc70377 100644 Binary files a/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png and b/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-v21/background.png b/android/app/src/main/res/drawable-v21/background.png index 203fc77a..4bebb9de 100644 Binary files a/android/app/src/main/res/drawable-v21/background.png and b/android/app/src/main/res/drawable-v21/background.png differ diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index 52e8749e..5367a886 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -6,7 +6,7 @@ - + diff --git a/android/app/src/main/res/drawable-xhdpi-v31/android12branding.png b/android/app/src/main/res/drawable-xhdpi-v31/android12branding.png index efc7e6c8..8e2bb197 100644 Binary files a/android/app/src/main/res/drawable-xhdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-xhdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/android12splash.png b/android/app/src/main/res/drawable-xhdpi/android12splash.png index 8e5ceb0a..5adba278 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/android12splash.png and b/android/app/src/main/res/drawable-xhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/branding.png b/android/app/src/main/res/drawable-xhdpi/branding.png index efc7e6c8..8e2bb197 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/branding.png and b/android/app/src/main/res/drawable-xhdpi/branding.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png index 8774c0ff..b608dca7 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png index 41222c6c..51a669aa 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/splash.png and b/android/app/src/main/res/drawable-xhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi-v31/android12branding.png b/android/app/src/main/res/drawable-xxhdpi-v31/android12branding.png index 593877e0..d301093a 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-xxhdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxhdpi/android12splash.png index fb89da37..4e294a2d 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/android12splash.png and b/android/app/src/main/res/drawable-xxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/branding.png b/android/app/src/main/res/drawable-xxhdpi/branding.png index 593877e0..d301093a 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/branding.png and b/android/app/src/main/res/drawable-xxhdpi/branding.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png index a379c006..b1e93458 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png index 5ab19d32..cc79cb85 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/splash.png and b/android/app/src/main/res/drawable-xxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi-v31/android12branding.png b/android/app/src/main/res/drawable-xxxhdpi-v31/android12branding.png index 9d233302..42b0bdc2 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi-v31/android12branding.png and b/android/app/src/main/res/drawable-xxxhdpi-v31/android12branding.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png index 38e4a12c..dcc70377 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png and b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/branding.png b/android/app/src/main/res/drawable-xxxhdpi/branding.png index 9d233302..42b0bdc2 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/branding.png and b/android/app/src/main/res/drawable-xxxhdpi/branding.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png index 44621df8..d178ba12 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png index a6d40b89..f526b26d 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/splash.png and b/android/app/src/main/res/drawable-xxxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable/background.png b/android/app/src/main/res/drawable/background.png index 203fc77a..4bebb9de 100644 Binary files a/android/app/src/main/res/drawable/background.png and b/android/app/src/main/res/drawable/background.png differ diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 52e8749e..5367a886 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -6,7 +6,7 @@ - + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index f606c4d8..c79c58a3 100644 --- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,9 @@ - - + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index d26a3a6e..c9e5cfad 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 63d16c60..159b302f 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index fe2957ad..9c81fb60 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 85c1d793..3450fb00 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index f22fa5cf..f94fd407 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/nightly/res/drawable-hdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-hdpi-v31/android12branding.png index 9e62c813..22a9b8d3 100644 Binary files a/android/app/src/nightly/res/drawable-hdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-hdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-hdpi/android12splash.png b/android/app/src/nightly/res/drawable-hdpi/android12splash.png index 98fd87f4..1d1cb853 100644 Binary files a/android/app/src/nightly/res/drawable-hdpi/android12splash.png and b/android/app/src/nightly/res/drawable-hdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-hdpi/branding.png b/android/app/src/nightly/res/drawable-hdpi/branding.png index 9e62c813..22a9b8d3 100644 Binary files a/android/app/src/nightly/res/drawable-hdpi/branding.png and b/android/app/src/nightly/res/drawable-hdpi/branding.png differ diff --git a/android/app/src/nightly/res/drawable-hdpi/ic_launcher_foreground.png b/android/app/src/nightly/res/drawable-hdpi/ic_launcher_foreground.png index 20a57ba2..7373eec1 100644 Binary files a/android/app/src/nightly/res/drawable-hdpi/ic_launcher_foreground.png and b/android/app/src/nightly/res/drawable-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/nightly/res/drawable-hdpi/splash.png b/android/app/src/nightly/res/drawable-hdpi/splash.png index 07c7024a..e3869211 100644 Binary files a/android/app/src/nightly/res/drawable-hdpi/splash.png and b/android/app/src/nightly/res/drawable-hdpi/splash.png differ diff --git a/android/app/src/nightly/res/drawable-mdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-mdpi-v31/android12branding.png index 80579983..3ff2a2da 100644 Binary files a/android/app/src/nightly/res/drawable-mdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-mdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-mdpi/android12splash.png b/android/app/src/nightly/res/drawable-mdpi/android12splash.png index a86a2222..3f2a1a0a 100644 Binary files a/android/app/src/nightly/res/drawable-mdpi/android12splash.png and b/android/app/src/nightly/res/drawable-mdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-mdpi/branding.png b/android/app/src/nightly/res/drawable-mdpi/branding.png index 80579983..3ff2a2da 100644 Binary files a/android/app/src/nightly/res/drawable-mdpi/branding.png and b/android/app/src/nightly/res/drawable-mdpi/branding.png differ diff --git a/android/app/src/nightly/res/drawable-mdpi/ic_launcher_foreground.png b/android/app/src/nightly/res/drawable-mdpi/ic_launcher_foreground.png index 43f5e0fe..8d5a9656 100644 Binary files a/android/app/src/nightly/res/drawable-mdpi/ic_launcher_foreground.png and b/android/app/src/nightly/res/drawable-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/nightly/res/drawable-mdpi/splash.png b/android/app/src/nightly/res/drawable-mdpi/splash.png index 86d3fe74..d8f7cc0e 100644 Binary files a/android/app/src/nightly/res/drawable-mdpi/splash.png and b/android/app/src/nightly/res/drawable-mdpi/splash.png differ diff --git a/android/app/src/nightly/res/drawable-night-hdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-night-hdpi-v31/android12branding.png index 9e62c813..22a9b8d3 100644 Binary files a/android/app/src/nightly/res/drawable-night-hdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-night-hdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-night-hdpi/android12splash.png b/android/app/src/nightly/res/drawable-night-hdpi/android12splash.png index 98fd87f4..1d1cb853 100644 Binary files a/android/app/src/nightly/res/drawable-night-hdpi/android12splash.png and b/android/app/src/nightly/res/drawable-night-hdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-night-mdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-night-mdpi-v31/android12branding.png index 80579983..3ff2a2da 100644 Binary files a/android/app/src/nightly/res/drawable-night-mdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-night-mdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-night-mdpi/android12splash.png b/android/app/src/nightly/res/drawable-night-mdpi/android12splash.png index a86a2222..3f2a1a0a 100644 Binary files a/android/app/src/nightly/res/drawable-night-mdpi/android12splash.png and b/android/app/src/nightly/res/drawable-night-mdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-night-xhdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-night-xhdpi-v31/android12branding.png index 0bcf138d..8e2bb197 100644 Binary files a/android/app/src/nightly/res/drawable-night-xhdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-night-xhdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-night-xhdpi/android12splash.png b/android/app/src/nightly/res/drawable-night-xhdpi/android12splash.png index ad3f39d0..ba73b0e2 100644 Binary files a/android/app/src/nightly/res/drawable-night-xhdpi/android12splash.png and b/android/app/src/nightly/res/drawable-night-xhdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-night-xxhdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-night-xxhdpi-v31/android12branding.png index c7d01776..d301093a 100644 Binary files a/android/app/src/nightly/res/drawable-night-xxhdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-night-xxhdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-night-xxhdpi/android12splash.png b/android/app/src/nightly/res/drawable-night-xxhdpi/android12splash.png index 133fb647..5e5cdc45 100644 Binary files a/android/app/src/nightly/res/drawable-night-xxhdpi/android12splash.png and b/android/app/src/nightly/res/drawable-night-xxhdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-night-xxxhdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-night-xxxhdpi-v31/android12branding.png index 5477b799..42b0bdc2 100644 Binary files a/android/app/src/nightly/res/drawable-night-xxxhdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-night-xxxhdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-night-xxxhdpi/android12splash.png b/android/app/src/nightly/res/drawable-night-xxxhdpi/android12splash.png index fa5a8c92..adff9bec 100644 Binary files a/android/app/src/nightly/res/drawable-night-xxxhdpi/android12splash.png and b/android/app/src/nightly/res/drawable-night-xxxhdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-v21/background.png b/android/app/src/nightly/res/drawable-v21/background.png index 203fc77a..4bebb9de 100644 Binary files a/android/app/src/nightly/res/drawable-v21/background.png and b/android/app/src/nightly/res/drawable-v21/background.png differ diff --git a/android/app/src/nightly/res/drawable-v21/launch_background.xml b/android/app/src/nightly/res/drawable-v21/launch_background.xml index 52e8749e..5367a886 100644 --- a/android/app/src/nightly/res/drawable-v21/launch_background.xml +++ b/android/app/src/nightly/res/drawable-v21/launch_background.xml @@ -6,7 +6,7 @@ - + diff --git a/android/app/src/nightly/res/drawable-xhdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-xhdpi-v31/android12branding.png index 0bcf138d..8e2bb197 100644 Binary files a/android/app/src/nightly/res/drawable-xhdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-xhdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-xhdpi/android12splash.png b/android/app/src/nightly/res/drawable-xhdpi/android12splash.png index ad3f39d0..ba73b0e2 100644 Binary files a/android/app/src/nightly/res/drawable-xhdpi/android12splash.png and b/android/app/src/nightly/res/drawable-xhdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-xhdpi/branding.png b/android/app/src/nightly/res/drawable-xhdpi/branding.png index 0bcf138d..8e2bb197 100644 Binary files a/android/app/src/nightly/res/drawable-xhdpi/branding.png and b/android/app/src/nightly/res/drawable-xhdpi/branding.png differ diff --git a/android/app/src/nightly/res/drawable-xhdpi/ic_launcher_foreground.png b/android/app/src/nightly/res/drawable-xhdpi/ic_launcher_foreground.png index 4cf86d25..f4f416f7 100644 Binary files a/android/app/src/nightly/res/drawable-xhdpi/ic_launcher_foreground.png and b/android/app/src/nightly/res/drawable-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/nightly/res/drawable-xhdpi/splash.png b/android/app/src/nightly/res/drawable-xhdpi/splash.png index dbb0ea02..17a2c373 100644 Binary files a/android/app/src/nightly/res/drawable-xhdpi/splash.png and b/android/app/src/nightly/res/drawable-xhdpi/splash.png differ diff --git a/android/app/src/nightly/res/drawable-xxhdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-xxhdpi-v31/android12branding.png index c7d01776..d301093a 100644 Binary files a/android/app/src/nightly/res/drawable-xxhdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-xxhdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-xxhdpi/android12splash.png b/android/app/src/nightly/res/drawable-xxhdpi/android12splash.png index 133fb647..5e5cdc45 100644 Binary files a/android/app/src/nightly/res/drawable-xxhdpi/android12splash.png and b/android/app/src/nightly/res/drawable-xxhdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-xxhdpi/branding.png b/android/app/src/nightly/res/drawable-xxhdpi/branding.png index c7d01776..d301093a 100644 Binary files a/android/app/src/nightly/res/drawable-xxhdpi/branding.png and b/android/app/src/nightly/res/drawable-xxhdpi/branding.png differ diff --git a/android/app/src/nightly/res/drawable-xxhdpi/ic_launcher_foreground.png b/android/app/src/nightly/res/drawable-xxhdpi/ic_launcher_foreground.png index 95fa3443..9f88e976 100644 Binary files a/android/app/src/nightly/res/drawable-xxhdpi/ic_launcher_foreground.png and b/android/app/src/nightly/res/drawable-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/nightly/res/drawable-xxhdpi/splash.png b/android/app/src/nightly/res/drawable-xxhdpi/splash.png index 12eb5531..db53f016 100644 Binary files a/android/app/src/nightly/res/drawable-xxhdpi/splash.png and b/android/app/src/nightly/res/drawable-xxhdpi/splash.png differ diff --git a/android/app/src/nightly/res/drawable-xxxhdpi-v31/android12branding.png b/android/app/src/nightly/res/drawable-xxxhdpi-v31/android12branding.png index 5477b799..42b0bdc2 100644 Binary files a/android/app/src/nightly/res/drawable-xxxhdpi-v31/android12branding.png and b/android/app/src/nightly/res/drawable-xxxhdpi-v31/android12branding.png differ diff --git a/android/app/src/nightly/res/drawable-xxxhdpi/android12splash.png b/android/app/src/nightly/res/drawable-xxxhdpi/android12splash.png index fa5a8c92..adff9bec 100644 Binary files a/android/app/src/nightly/res/drawable-xxxhdpi/android12splash.png and b/android/app/src/nightly/res/drawable-xxxhdpi/android12splash.png differ diff --git a/android/app/src/nightly/res/drawable-xxxhdpi/branding.png b/android/app/src/nightly/res/drawable-xxxhdpi/branding.png index 5477b799..42b0bdc2 100644 Binary files a/android/app/src/nightly/res/drawable-xxxhdpi/branding.png and b/android/app/src/nightly/res/drawable-xxxhdpi/branding.png differ diff --git a/android/app/src/nightly/res/drawable-xxxhdpi/ic_launcher_foreground.png b/android/app/src/nightly/res/drawable-xxxhdpi/ic_launcher_foreground.png index 3de8a2ee..7e2bb4c3 100644 Binary files a/android/app/src/nightly/res/drawable-xxxhdpi/ic_launcher_foreground.png and b/android/app/src/nightly/res/drawable-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/nightly/res/drawable-xxxhdpi/splash.png b/android/app/src/nightly/res/drawable-xxxhdpi/splash.png index 68e806f4..a74c95a4 100644 Binary files a/android/app/src/nightly/res/drawable-xxxhdpi/splash.png and b/android/app/src/nightly/res/drawable-xxxhdpi/splash.png differ diff --git a/android/app/src/nightly/res/drawable/background.png b/android/app/src/nightly/res/drawable/background.png index 203fc77a..4bebb9de 100644 Binary files a/android/app/src/nightly/res/drawable/background.png and b/android/app/src/nightly/res/drawable/background.png differ diff --git a/android/app/src/nightly/res/drawable/launch_background.xml b/android/app/src/nightly/res/drawable/launch_background.xml index 52e8749e..5367a886 100644 --- a/android/app/src/nightly/res/drawable/launch_background.xml +++ b/android/app/src/nightly/res/drawable/launch_background.xml @@ -6,7 +6,7 @@ - + diff --git a/android/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher.xml index 83e651db..c79c58a3 100644 --- a/android/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/android/app/src/nightly/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,9 @@ - - - - \ No newline at end of file + + + + + diff --git a/android/app/src/nightly/res/mipmap-hdpi/ic_launcher.png b/android/app/src/nightly/res/mipmap-hdpi/ic_launcher.png index a826bb73..8164cc67 100644 Binary files a/android/app/src/nightly/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/nightly/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/nightly/res/mipmap-mdpi/ic_launcher.png b/android/app/src/nightly/res/mipmap-mdpi/ic_launcher.png index 3743861d..bff95e97 100644 Binary files a/android/app/src/nightly/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/nightly/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/nightly/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/nightly/res/mipmap-xhdpi/ic_launcher.png index 1be1daa7..df515ed1 100644 Binary files a/android/app/src/nightly/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/nightly/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.png index 3a8a7832..e58ef25f 100644 Binary files a/android/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/nightly/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.png index 781c9c1a..d39a5e64 100644 Binary files a/android/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/nightly/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/assets/fonts/Cookie-Regular.ttf b/assets/fonts/Cookie-Regular.ttf new file mode 100644 index 00000000..e3ac74eb Binary files /dev/null and b/assets/fonts/Cookie-Regular.ttf differ diff --git a/assets/mobile-screenshots/android-4.jpg b/assets/mobile-screenshots/android-4.jpg index 3057c69a..278aae21 100644 Binary files a/assets/mobile-screenshots/android-4.jpg and b/assets/mobile-screenshots/android-4.jpg differ diff --git a/assets/mobile-screenshots/combined.png b/assets/mobile-screenshots/combined.png index 9584e9c7..a7a394f6 100644 Binary files a/assets/mobile-screenshots/combined.png and b/assets/mobile-screenshots/combined.png differ diff --git a/assets/spotube-logo-foreground.jpg b/assets/spotube-logo-foreground.jpg deleted file mode 100644 index 0af774c9..00000000 Binary files a/assets/spotube-logo-foreground.jpg and /dev/null differ diff --git a/assets/spotube-logo-foreground.png b/assets/spotube-logo-foreground.png new file mode 100644 index 00000000..997d3209 Binary files /dev/null and b/assets/spotube-logo-foreground.png differ diff --git a/assets/spotube-logo-item.png b/assets/spotube-logo-item.png new file mode 100644 index 00000000..476dda29 Binary files /dev/null and b/assets/spotube-logo-item.png differ diff --git a/assets/spotube-logo-light.png b/assets/spotube-logo-light.png new file mode 100644 index 00000000..8c86d621 Binary files /dev/null and b/assets/spotube-logo-light.png differ diff --git a/assets/spotube-logo-macos.png b/assets/spotube-logo-macos.png index b14a7691..2694b530 100644 Binary files a/assets/spotube-logo-macos.png and b/assets/spotube-logo-macos.png differ diff --git a/assets/spotube-logo.bmp b/assets/spotube-logo.bmp index c3503e85..f95df092 100644 Binary files a/assets/spotube-logo.bmp and b/assets/spotube-logo.bmp differ diff --git a/assets/spotube-logo.ico b/assets/spotube-logo.ico index 84906308..562110b9 100644 Binary files a/assets/spotube-logo.ico and b/assets/spotube-logo.ico differ diff --git a/assets/spotube-logo.png b/assets/spotube-logo.png index b24a8c23..d46d9ce5 100644 Binary files a/assets/spotube-logo.png and b/assets/spotube-logo.png differ diff --git a/assets/spotube-logo.svg b/assets/spotube-logo.svg deleted file mode 100644 index 5cd88f8e..00000000 --- a/assets/spotube-logo.svg +++ /dev/null @@ -1,349 +0,0 @@ - - diff --git a/assets/spotube-logo_android12.png b/assets/spotube-logo_android12.png index f04e25b0..4af89de4 100644 Binary files a/assets/spotube-logo_android12.png and b/assets/spotube-logo_android12.png differ diff --git a/assets/spotube-nightly-item.png b/assets/spotube-nightly-item.png new file mode 100644 index 00000000..61ef1c5d Binary files /dev/null and b/assets/spotube-nightly-item.png differ diff --git a/assets/spotube-nightly-logo-foreground.jpg b/assets/spotube-nightly-logo-foreground.jpg deleted file mode 100644 index a0c849b6..00000000 Binary files a/assets/spotube-nightly-logo-foreground.jpg and /dev/null differ diff --git a/assets/spotube-nightly-logo-foreground.png b/assets/spotube-nightly-logo-foreground.png new file mode 100644 index 00000000..def278cf Binary files /dev/null and b/assets/spotube-nightly-logo-foreground.png differ diff --git a/assets/spotube-nightly-logo-foreground.svg b/assets/spotube-nightly-logo-foreground.svg new file mode 100644 index 00000000..de2bf370 --- /dev/null +++ b/assets/spotube-nightly-logo-foreground.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/spotube-nightly-logo.png b/assets/spotube-nightly-logo.png index ea7a8b20..269aaabc 100644 Binary files a/assets/spotube-nightly-logo.png and b/assets/spotube-nightly-logo.png differ diff --git a/assets/spotube-nightly-logo.svg b/assets/spotube-nightly-logo.svg deleted file mode 100644 index 7601108e..00000000 --- a/assets/spotube-nightly-logo.svg +++ /dev/null @@ -1,359 +0,0 @@ - - diff --git a/assets/spotube-nightly-logo_android12.png b/assets/spotube-nightly-logo_android12.png index 1a5bf4f1..e5683399 100644 Binary files a/assets/spotube-nightly-logo_android12.png and b/assets/spotube-nightly-logo_android12.png differ diff --git a/assets/spotube-tall-capsule.png b/assets/spotube-tall-capsule.png index 43fb8229..53bff791 100644 Binary files a/assets/spotube-tall-capsule.png and b/assets/spotube-tall-capsule.png differ diff --git a/assets/spotube-wide-capsule-large.png b/assets/spotube-wide-capsule-large.png index 09a93d83..41614c80 100644 Binary files a/assets/spotube-wide-capsule-large.png and b/assets/spotube-wide-capsule-large.png differ diff --git a/assets/spotube-wide-capsule-small.png b/assets/spotube-wide-capsule-small.png index 17566550..e0717dc5 100644 Binary files a/assets/spotube-wide-capsule-small.png and b/assets/spotube-wide-capsule-small.png differ diff --git a/assets/spotube_banner.png b/assets/spotube_banner.png index b2be4539..c9450265 100644 Binary files a/assets/spotube_banner.png and b/assets/spotube_banner.png differ diff --git a/aur-struct/.SRCINFO b/aur-struct/.SRCINFO index 772594f6..0460932b 100644 --- a/aur-struct/.SRCINFO +++ b/aur-struct/.SRCINFO @@ -1,5 +1,5 @@ pkgbase = spotube-bin -pkgdesc = Open source Spotify client that doesn't require Premium nor uses Electron! Available for both desktop & mobile! +pkgdesc = Open source Music client that doesn't require Premium nor uses Electron! Available for both desktop & mobile! pkgver = 4.0.0 pkgrel = 1 url = https://spotube.krtirtho.dev diff --git a/aur-struct/PKGBUILD b/aur-struct/PKGBUILD index cf6c0134..4f884f0d 100644 --- a/aur-struct/PKGBUILD +++ b/aur-struct/PKGBUILD @@ -3,7 +3,7 @@ pkgname=spotube-bin pkgver=%{{SPOTUBE_VERSION}}% pkgrel=%{{PKGREL}}% epoch= -pkgdesc="Open source Spotify client that doesn't require Premium nor uses Electron! Available for both desktop & mobile!" +pkgdesc="Open source Music client that doesn't require Premium nor uses Electron! Available for both desktop & mobile!" arch=(x86_64) url="https://spotube.krtirtho.dev" license=('BSD-4-Clause') diff --git a/choco-struct/spotube.nuspec b/choco-struct/spotube.nuspec index 1ebcd3c7..e3588d98 100644 --- a/choco-struct/spotube.nuspec +++ b/choco-struct/spotube.nuspec @@ -23,12 +23,13 @@ enclosed in quotation marks, you should use an editor that supports UTF-8, not t https://github.com/KRTirtho/spotube https://spotube.krtirtho.dev https://github.com/KRTirtho/spotube/issues/new - spotube music audio spotify youtube flutter - 🎧 Open source Spotify client that doesn't require Premium nor uses Electron! Available + spotube music audio youtube flutter + 🎧 Open source music client that doesn't require Premium nor uses Electron! Available for both desktop & mobile! - Spotube is a Flutter based lightweight spotify client. It utilizes the power - of Spotify & Youtube's public API & creates a hazardless, performant & resource + Spotube is a Flutter based lightweight music client. It utilizes the power + of music metadata providers & Youtube's public API & creates a hazardless, performant + & resource friendly User Experience # Features @@ -40,10 +41,9 @@ enclosed in quotation marks, you should use an editor that supports UTF-8, not t - Native performance (Thanks to Flutter+Skia) - Playback control is done locally instead of on the server - Small size & less data usage - - No Spotify or YouTube ads since it uses all public & free APIs (It is still recommended + - No ads since it uses all public & free APIs (It is still recommended to support the creators by watching/liking/subscribing to the artists' YouTube channels or - liking their tracks on Spotify. Purchasing Spotify Premium is usually the best way to support - their valuable creations.) + liking their tracks on different music platforms.) - Time synced lyrics - Downloadable tracks diff --git a/drift_schemas/app_db/drift_schema_v5.json b/drift_schemas/app_db/drift_schema_v5.json new file mode 100644 index 00000000..eefe0205 --- /dev/null +++ b/drift_schemas/app_db/drift_schema_v5.json @@ -0,0 +1 @@ +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":false},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"authentication_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"cookie","getter_name":"cookie","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"EncryptedTextConverter()","dart_type_name":"DecryptedText"}},{"name":"access_token","getter_name":"accessToken","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"EncryptedTextConverter()","dart_type_name":"DecryptedText"}},{"name":"expiration","getter_name":"expiration","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":1,"references":[],"type":"table","data":{"name":"blacklist_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"element_type","getter_name":"elementType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(BlacklistedType.values)","dart_type_name":"BlacklistedType"}},{"name":"element_id","getter_name":"elementId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":2,"references":[],"type":"table","data":{"name":"preferences_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"audio_quality","getter_name":"audioQuality","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceQualities.high.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceQualities.values)","dart_type_name":"SourceQualities"}},{"name":"album_color_sync","getter_name":"albumColorSync","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"album_color_sync\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"album_color_sync\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"amoled_dark_theme","getter_name":"amoledDarkTheme","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"amoled_dark_theme\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"amoled_dark_theme\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"check_update","getter_name":"checkUpdate","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"check_update\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"check_update\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"normalize_audio","getter_name":"normalizeAudio","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"normalize_audio\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"normalize_audio\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"show_system_tray_icon","getter_name":"showSystemTrayIcon","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"show_system_tray_icon\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"show_system_tray_icon\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"system_title_bar","getter_name":"systemTitleBar","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"system_title_bar\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"system_title_bar\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"skip_non_music","getter_name":"skipNonMusic","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"skip_non_music\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"skip_non_music\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"close_behavior","getter_name":"closeBehavior","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(CloseBehavior.close.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(CloseBehavior.values)","dart_type_name":"CloseBehavior"}},{"name":"accent_color_scheme","getter_name":"accentColorScheme","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"Orange:0xFFf97315\")","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const SpotubeColorConverter()","dart_type_name":"SpotubeColor"}},{"name":"layout_mode","getter_name":"layoutMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(LayoutMode.adaptive.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(LayoutMode.values)","dart_type_name":"LayoutMode"}},{"name":"locale","getter_name":"locale","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant('{\"languageCode\":\"system\",\"countryCode\":\"system\"}')","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const LocaleConverter()","dart_type_name":"Locale"}},{"name":"market","getter_name":"market","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(Market.US.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(Market.values)","dart_type_name":"Market"}},{"name":"search_mode","getter_name":"searchMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SearchMode.youtube.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SearchMode.values)","dart_type_name":"SearchMode"}},{"name":"download_location","getter_name":"downloadLocation","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"\")","default_client_dart":null,"dsl_features":[]},{"name":"local_library_location","getter_name":"localLibraryLocation","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"\")","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const StringListConverter()","dart_type_name":"List"}},{"name":"piped_instance","getter_name":"pipedInstance","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"https://pipedapi.kavin.rocks\")","default_client_dart":null,"dsl_features":[]},{"name":"invidious_instance","getter_name":"invidiousInstance","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"https://inv.nadeko.net\")","default_client_dart":null,"dsl_features":[]},{"name":"theme_mode","getter_name":"themeMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(ThemeMode.system.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(ThemeMode.values)","dart_type_name":"ThemeMode"}},{"name":"audio_source","getter_name":"audioSource","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(AudioSource.youtube.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(AudioSource.values)","dart_type_name":"AudioSource"}},{"name":"youtube_client_engine","getter_name":"youtubeClientEngine","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(YoutubeClientEngine.youtubeExplode.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(YoutubeClientEngine.values)","dart_type_name":"YoutubeClientEngine"}},{"name":"stream_music_codec","getter_name":"streamMusicCodec","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceCodecs.weba.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceCodecs.values)","dart_type_name":"SourceCodecs"}},{"name":"download_music_codec","getter_name":"downloadMusicCodec","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceCodecs.m4a.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceCodecs.values)","dart_type_name":"SourceCodecs"}},{"name":"discord_presence","getter_name":"discordPresence","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"discord_presence\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"discord_presence\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"endless_playback","getter_name":"endlessPlayback","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"endless_playback\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"endless_playback\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"enable_connect","getter_name":"enableConnect","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"enable_connect\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"enable_connect\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"cache_music","getter_name":"cacheMusic","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"cache_music\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"cache_music\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":3,"references":[],"type":"table","data":{"name":"scrobbler_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]},{"name":"username","getter_name":"username","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"password_hash","getter_name":"passwordHash","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"EncryptedTextConverter()","dart_type_name":"DecryptedText"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":4,"references":[],"type":"table","data":{"name":"skip_segment_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"start","getter_name":"start","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"end","getter_name":"end","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"track_id","getter_name":"trackId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":5,"references":[],"type":"table","data":{"name":"source_match_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"track_id","getter_name":"trackId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_id","getter_name":"sourceId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_type","getter_name":"sourceType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceType.youtube.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceType.values)","dart_type_name":"SourceType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":6,"references":[],"type":"table","data":{"name":"audio_player_state_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"playing","getter_name":"playing","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"playing\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"playing\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"loop_mode","getter_name":"loopMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(PlaylistMode.values)","dart_type_name":"PlaylistMode"}},{"name":"shuffled","getter_name":"shuffled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"shuffled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"shuffled\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"collections","getter_name":"collections","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const StringListConverter()","dart_type_name":"List"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":7,"references":[6],"type":"table","data":{"name":"playlist_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"audio_player_state_id","getter_name":"audioPlayerStateId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES audio_player_state_table (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES audio_player_state_table (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"index","getter_name":"index","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":8,"references":[7],"type":"table","data":{"name":"playlist_media_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"playlist_id","getter_name":"playlistId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES playlist_table (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES playlist_table (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"uri","getter_name":"uri","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"extras","getter_name":"extras","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MapTypeConverter()","dart_type_name":"Map"}},{"name":"http_headers","getter_name":"httpHeaders","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MapTypeConverter()","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":9,"references":[],"type":"table","data":{"name":"history_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(HistoryEntryType.values)","dart_type_name":"HistoryEntryType"}},{"name":"item_id","getter_name":"itemId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MapTypeConverter()","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":10,"references":[],"type":"table","data":{"name":"lyrics_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"track_id","getter_name":"trackId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"SubtitleTypeConverter()","dart_type_name":"SubtitleSimple"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":11,"references":[1],"type":"index","data":{"on":1,"name":"unique_blacklist","sql":null,"unique":true,"columns":["element_type","element_id"]}},{"id":12,"references":[5],"type":"index","data":{"on":5,"name":"uniq_track_match","sql":null,"unique":true,"columns":["track_id","source_id","source_type"]}}]} \ No newline at end of file diff --git a/drift_schemas/app_db/drift_schema_v6.json b/drift_schemas/app_db/drift_schema_v6.json new file mode 100644 index 00000000..8a646be1 --- /dev/null +++ b/drift_schemas/app_db/drift_schema_v6.json @@ -0,0 +1 @@ +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":false},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"authentication_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"cookie","getter_name":"cookie","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"EncryptedTextConverter()","dart_type_name":"DecryptedText"}},{"name":"access_token","getter_name":"accessToken","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"EncryptedTextConverter()","dart_type_name":"DecryptedText"}},{"name":"expiration","getter_name":"expiration","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":1,"references":[],"type":"table","data":{"name":"blacklist_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"element_type","getter_name":"elementType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(BlacklistedType.values)","dart_type_name":"BlacklistedType"}},{"name":"element_id","getter_name":"elementId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":2,"references":[],"type":"table","data":{"name":"preferences_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"audio_quality","getter_name":"audioQuality","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceQualities.high.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceQualities.values)","dart_type_name":"SourceQualities"}},{"name":"album_color_sync","getter_name":"albumColorSync","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"album_color_sync\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"album_color_sync\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"amoled_dark_theme","getter_name":"amoledDarkTheme","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"amoled_dark_theme\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"amoled_dark_theme\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"check_update","getter_name":"checkUpdate","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"check_update\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"check_update\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"normalize_audio","getter_name":"normalizeAudio","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"normalize_audio\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"normalize_audio\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"show_system_tray_icon","getter_name":"showSystemTrayIcon","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"show_system_tray_icon\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"show_system_tray_icon\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"system_title_bar","getter_name":"systemTitleBar","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"system_title_bar\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"system_title_bar\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"skip_non_music","getter_name":"skipNonMusic","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"skip_non_music\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"skip_non_music\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"close_behavior","getter_name":"closeBehavior","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(CloseBehavior.close.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(CloseBehavior.values)","dart_type_name":"CloseBehavior"}},{"name":"accent_color_scheme","getter_name":"accentColorScheme","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"Orange:0xFFf97315\")","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const SpotubeColorConverter()","dart_type_name":"SpotubeColor"}},{"name":"layout_mode","getter_name":"layoutMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(LayoutMode.adaptive.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(LayoutMode.values)","dart_type_name":"LayoutMode"}},{"name":"locale","getter_name":"locale","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant('{\"languageCode\":\"system\",\"countryCode\":\"system\"}')","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const LocaleConverter()","dart_type_name":"Locale"}},{"name":"market","getter_name":"market","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(Market.US.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(Market.values)","dart_type_name":"Market"}},{"name":"search_mode","getter_name":"searchMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SearchMode.youtube.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SearchMode.values)","dart_type_name":"SearchMode"}},{"name":"download_location","getter_name":"downloadLocation","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"\")","default_client_dart":null,"dsl_features":[]},{"name":"local_library_location","getter_name":"localLibraryLocation","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"\")","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const StringListConverter()","dart_type_name":"List"}},{"name":"piped_instance","getter_name":"pipedInstance","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"https://pipedapi.kavin.rocks\")","default_client_dart":null,"dsl_features":[]},{"name":"invidious_instance","getter_name":"invidiousInstance","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const Constant(\"https://inv.nadeko.net\")","default_client_dart":null,"dsl_features":[]},{"name":"theme_mode","getter_name":"themeMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(ThemeMode.system.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(ThemeMode.values)","dart_type_name":"ThemeMode"}},{"name":"audio_source","getter_name":"audioSource","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(AudioSource.youtube.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(AudioSource.values)","dart_type_name":"AudioSource"}},{"name":"youtube_client_engine","getter_name":"youtubeClientEngine","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(YoutubeClientEngine.youtubeExplode.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(YoutubeClientEngine.values)","dart_type_name":"YoutubeClientEngine"}},{"name":"stream_music_codec","getter_name":"streamMusicCodec","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceCodecs.weba.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceCodecs.values)","dart_type_name":"SourceCodecs"}},{"name":"download_music_codec","getter_name":"downloadMusicCodec","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceCodecs.m4a.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceCodecs.values)","dart_type_name":"SourceCodecs"}},{"name":"discord_presence","getter_name":"discordPresence","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"discord_presence\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"discord_presence\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"endless_playback","getter_name":"endlessPlayback","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"endless_playback\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"endless_playback\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]},{"name":"enable_connect","getter_name":"enableConnect","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"enable_connect\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"enable_connect\" IN (0, 1))"},"default_dart":"const Constant(false)","default_client_dart":null,"dsl_features":[]},{"name":"connect_port","getter_name":"connectPort","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const Constant(-1)","default_client_dart":null,"dsl_features":[]},{"name":"cache_music","getter_name":"cacheMusic","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"cache_music\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"cache_music\" IN (0, 1))"},"default_dart":"const Constant(true)","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":3,"references":[],"type":"table","data":{"name":"scrobbler_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]},{"name":"username","getter_name":"username","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"password_hash","getter_name":"passwordHash","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"EncryptedTextConverter()","dart_type_name":"DecryptedText"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":4,"references":[],"type":"table","data":{"name":"skip_segment_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"start","getter_name":"start","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"end","getter_name":"end","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"track_id","getter_name":"trackId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":5,"references":[],"type":"table","data":{"name":"source_match_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"track_id","getter_name":"trackId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_id","getter_name":"sourceId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_type","getter_name":"sourceType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"Constant(SourceType.youtube.name)","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(SourceType.values)","dart_type_name":"SourceType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":6,"references":[],"type":"table","data":{"name":"audio_player_state_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"playing","getter_name":"playing","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"playing\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"playing\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"loop_mode","getter_name":"loopMode","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(PlaylistMode.values)","dart_type_name":"PlaylistMode"}},{"name":"shuffled","getter_name":"shuffled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"shuffled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"shuffled\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"collections","getter_name":"collections","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const StringListConverter()","dart_type_name":"List"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":7,"references":[6],"type":"table","data":{"name":"playlist_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"audio_player_state_id","getter_name":"audioPlayerStateId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES audio_player_state_table (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES audio_player_state_table (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"index","getter_name":"index","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":8,"references":[7],"type":"table","data":{"name":"playlist_media_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"playlist_id","getter_name":"playlistId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES playlist_table (id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES playlist_table (id)"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"uri","getter_name":"uri","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"extras","getter_name":"extras","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MapTypeConverter()","dart_type_name":"Map"}},{"name":"http_headers","getter_name":"httpHeaders","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MapTypeConverter()","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":9,"references":[],"type":"table","data":{"name":"history_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"currentDateAndTime","default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(HistoryEntryType.values)","dart_type_name":"HistoryEntryType"}},{"name":"item_id","getter_name":"itemId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const MapTypeConverter()","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":10,"references":[],"type":"table","data":{"name":"lyrics_table","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"track_id","getter_name":"trackId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"SubtitleTypeConverter()","dart_type_name":"SubtitleSimple"}}],"is_virtual":false,"without_rowid":false,"constraints":[]}},{"id":11,"references":[1],"type":"index","data":{"on":1,"name":"unique_blacklist","sql":null,"unique":true,"columns":["element_type","element_id"]}},{"id":12,"references":[5],"type":"index","data":{"on":5,"name":"uniq_track_match","sql":null,"unique":true,"columns":["track_id","source_id","source_type"]}}]} \ No newline at end of file diff --git a/flutter_launcher_icons-nightly.yaml b/flutter_launcher_icons-nightly.yaml index c6892d4b..770033bd 100644 --- a/flutter_launcher_icons-nightly.yaml +++ b/flutter_launcher_icons-nightly.yaml @@ -2,5 +2,5 @@ flutter_launcher_icons: android: true ios: true image_path: "assets/spotube-nightly-logo.png" - adaptive_icon_foreground: "assets/spotube-nightly-logo-foreground.jpg" + adaptive_icon_foreground: "assets/spotube-nightly-logo-foreground.png" adaptive_icon_background: "#242832" diff --git a/flutter_launcher_icons.yaml b/flutter_launcher_icons.yaml index 372117b1..2c558583 100644 --- a/flutter_launcher_icons.yaml +++ b/flutter_launcher_icons.yaml @@ -6,7 +6,7 @@ flutter_launcher_icons: # image_path_android: "assets/icon/icon.png" min_sdk_android: 21 # android min sdk min:16, default 21 adaptive_icon_background: "#242832" - adaptive_icon_foreground: "assets/spotube-logo-foreground.jpg" + adaptive_icon_foreground: "assets/spotube-logo-foreground.png" # adaptive_icon_monochrome: "assets/icon/monochrome.png" ios: true diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index bbfc1404..88a40d6f 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -2135,7 +2135,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2159,7 +2159,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2183,7 +2183,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2207,7 +2207,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2230,7 +2230,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2253,7 +2253,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2276,7 +2276,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2299,7 +2299,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2322,7 +2322,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2472,7 +2472,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2617,7 +2617,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2759,7 +2759,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-nightly"; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = nightly.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; @@ -2781,9 +2781,9 @@ E612EC4A2D0F07AD0022720C /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -2824,9 +2824,9 @@ E612EC4B2D0F07AD0022720C /* Debug-nightly */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -2867,9 +2867,9 @@ E612EC4C2D0F07AD0022720C /* Debug-dev */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -2910,9 +2910,9 @@ E612EC4D2D0F07AD0022720C /* Debug-stable */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -2953,9 +2953,9 @@ E612EC4E2D0F07AD0022720C /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -2993,9 +2993,9 @@ E612EC4F2D0F07AD0022720C /* Release-nightly */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -3033,9 +3033,9 @@ E612EC502D0F07AD0022720C /* Release-dev */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -3073,9 +3073,9 @@ E612EC512D0F07AD0022720C /* Release-stable */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -3113,9 +3113,9 @@ E612EC522D0F07AD0022720C /* Profile */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -3153,9 +3153,9 @@ E612EC532D0F07AD0022720C /* Profile-nightly */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -3193,9 +3193,9 @@ E612EC542D0F07AD0022720C /* Profile-dev */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; @@ -3233,9 +3233,9 @@ E612EC552D0F07AD0022720C /* Profile-stable */ = { isa = XCBuildConfiguration; buildSettings = { - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AppIcon; + ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = AppIcon; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_ENABLE_OBJC_WEAK = YES; diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-1024x1024@1x.png index dbc4596b..2185c35d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-1024x1024@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@1x.png index 4836771d..172bc383 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@2x.png index 90954ce9..876617d9 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@3x.png index 9c0ebd5f..fec86d87 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@3x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@1x.png index 94cd79be..fbb0f45a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@2x.png index ff70cab7..854e1e45 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@3x.png index 6cdda1b6..420d2a17 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@3x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@1x.png index 90954ce9..876617d9 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@2x.png index 5184f84f..6b7a608d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@3x.png index 57e21a75..d871fa3f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@3x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@1x.png index 93e157b6..e77b38df 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@2x.png index d175beb2..358cb28f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@1x.png index 6d634c87..87f4290b 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@2x.png index 22da4950..53c10a09 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@2x.png index 57e21a75..d871fa3f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@3x.png index 3cfd01c2..4bb39789 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@3x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@1x.png index a826bb73..8164cc67 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@2x.png index 3a8a7832..e58ef25f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@1x.png index f233322b..f5e1ae5a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@1x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@2x.png index 2f5b082a..99bd36c9 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-83.5x83.5@2x.png index e4ecc19a..8d199658 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon-nightly.appiconset/AppIcon-nightly-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index 05843b52..d0d98aa1 100644 --- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1 +1 @@ -{"images":[{"size":"20x20","idiom":"iphone","filename":"AppIcon-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"AppIcon-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"AppIcon-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"AppIcon-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"AppIcon-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"AppIcon-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"AppIcon-40x40@3x.png","scale":"3x"},{"size":"50x50","idiom":"ipad","filename":"AppIcon-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"AppIcon-50x50@2x.png","scale":"2x"},{"size":"57x57","idiom":"iphone","filename":"AppIcon-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"AppIcon-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"AppIcon-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"AppIcon-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"AppIcon-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"AppIcon-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"AppIcon-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"AppIcon-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"AppIcon-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"AppIcon-40x40@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"AppIcon-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"AppIcon-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"AppIcon-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"AppIcon-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"AppIcon-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"AppIcon-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file +{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 00000000..59407b44 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 00000000..5eacaa5f Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 00000000..bbb9f839 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 00000000..28d0d8a8 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 00000000..b1df0e72 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 00000000..24b76e25 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 00000000..5c0b6d57 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 00000000..bbb9f839 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 00000000..bdc5656b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 00000000..c03c89fe Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 00000000..40b88968 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png new file mode 100644 index 00000000..2050f427 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 00000000..d1ccab30 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 00000000..47c629f3 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 00000000..c03c89fe Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 00000000..22d28c12 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 00000000..c9e5cfad Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 00000000..3450fb00 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 00000000..3dd3eda3 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 00000000..2e69c843 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 00000000..f769eb6e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage.png b/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage.png index 5a197da3..3ff2a2da 100644 Binary files a/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage.png and b/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage.png differ diff --git a/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@2x.png b/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@2x.png index efc7e6c8..8e2bb197 100644 Binary files a/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@2x.png and b/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@3x.png b/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@3x.png index 593877e0..d301093a 100644 Binary files a/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@3x.png and b/ios/Runner/Assets.xcassets/BrandingImage.imageset/BrandingImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage.png b/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage.png index 80579983..3ff2a2da 100644 Binary files a/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage.png and b/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage.png differ diff --git a/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@2x.png b/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@2x.png index 0bcf138d..8e2bb197 100644 Binary files a/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@2x.png and b/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@3x.png b/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@3x.png index c7d01776..d301093a 100644 Binary files a/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@3x.png and b/ios/Runner/Assets.xcassets/BrandingImageNightly.imageset/BrandingImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png index 203fc77a..4bebb9de 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png and b/ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchBackgroundNightly.imageset/background.png b/ios/Runner/Assets.xcassets/LaunchBackgroundNightly.imageset/background.png index 203fc77a..4bebb9de 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchBackgroundNightly.imageset/background.png and b/ios/Runner/Assets.xcassets/LaunchBackgroundNightly.imageset/background.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png index c5e4aca0..6e04efdc 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png index 41222c6c..51a669aa 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png index 5ab19d32..cc79cb85 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage.png index 86d3fe74..d8f7cc0e 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage.png and b/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@2x.png index dbb0ea02..17a2c373 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@2x.png and b/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@3x.png index 12eb5531..db53f016 100644 Binary files a/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@3x.png and b/ios/Runner/Assets.xcassets/LaunchImageNightly.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard index 208e1c53..ec8a1de3 100644 --- a/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -22,7 +22,7 @@ - + diff --git a/ios/Runner/Base.lproj/LaunchScreenNightly.storyboard b/ios/Runner/Base.lproj/LaunchScreenNightly.storyboard index 6869214f..645a417f 100644 --- a/ios/Runner/Base.lproj/LaunchScreenNightly.storyboard +++ b/ios/Runner/Base.lproj/LaunchScreenNightly.storyboard @@ -22,7 +22,7 @@ - + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 91b7ad94..8d6c09a2 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -1,82 +1,82 @@ - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Spotube - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - spotube - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsArbitraryLoadsForMedia - - - NSCameraUsageDescription - This app require access to the device camera - NSMicrophoneUsageDescription - This app does not require access to the device microphone - NSPhotoLibraryUsageDescription - This app require access to the photo library - UIApplicationSupportsIndirectInputEvents - - UIBackgroundModes - - audio - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIStatusBarHidden - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - NSLocalNetworkUsageDescription - To allow other devices on the network control playback of Spotube securely. - NSBonjourServices - - _spotube._tcp - - UIFileSharingEnabled - - LSSupportsOpeningDocumentsInPlace - - UISupportsDocumentBrowser - - + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Spotube + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + spotube + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsArbitraryLoadsForMedia + + + NSCameraUsageDescription + This app require access to the device camera + NSMicrophoneUsageDescription + This app does not require access to the device microphone + NSPhotoLibraryUsageDescription + This app require access to the photo library + UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + audio + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + NSLocalNetworkUsageDescription + To allow other devices on the network control playback of Spotube securely. + NSBonjourServices + + _spotube._tcp + + UIFileSharingEnabled + + LSSupportsOpeningDocumentsInPlace + + UISupportsDocumentBrowser + + diff --git a/lib/collections/assets.gen.dart b/lib/collections/assets.gen.dart index 004001f2..09b6cdd2 100644 --- a/lib/collections/assets.gen.dart +++ b/lib/collections/assets.gen.dart @@ -151,7 +151,11 @@ class Assets { static const AssetGenImage spotubeHeroBanner = AssetGenImage('assets/spotube-hero-banner.png'); static const AssetGenImage spotubeLogoForeground = - AssetGenImage('assets/spotube-logo-foreground.jpg'); + AssetGenImage('assets/spotube-logo-foreground.png'); + static const AssetGenImage spotubeLogoItem = + AssetGenImage('assets/spotube-logo-item.png'); + static const AssetGenImage spotubeLogoLight = + AssetGenImage('assets/spotube-logo-light.png'); static const AssetGenImage spotubeLogoMacos = AssetGenImage('assets/spotube-logo-macos.png'); static const AssetGenImage spotubeLogoBmp = @@ -159,14 +163,16 @@ class Assets { static const String spotubeLogoIco = 'assets/spotube-logo.ico'; static const AssetGenImage spotubeLogoPng = AssetGenImage('assets/spotube-logo.png'); - static const String spotubeLogoSvg = 'assets/spotube-logo.svg'; static const AssetGenImage spotubeLogoAndroid12 = AssetGenImage('assets/spotube-logo_android12.png'); - static const AssetGenImage spotubeNightlyLogoForeground = - AssetGenImage('assets/spotube-nightly-logo-foreground.jpg'); - static const AssetGenImage spotubeNightlyLogoPng = + static const AssetGenImage spotubeNightlyItem = + AssetGenImage('assets/spotube-nightly-item.png'); + static const AssetGenImage spotubeNightlyLogoForegroundPng = + AssetGenImage('assets/spotube-nightly-logo-foreground.png'); + static const String spotubeNightlyLogoForegroundSvg = + 'assets/spotube-nightly-logo-foreground.svg'; + static const AssetGenImage spotubeNightlyLogo = AssetGenImage('assets/spotube-nightly-logo.png'); - static const String spotubeNightlyLogoSvg = 'assets/spotube-nightly-logo.svg'; static const AssetGenImage spotubeNightlyLogoAndroid12 = AssetGenImage('assets/spotube-nightly-logo_android12.png'); static const AssetGenImage spotubeScreenshot = @@ -197,15 +203,17 @@ class Assets { placeholder, spotubeHeroBanner, spotubeLogoForeground, + spotubeLogoItem, + spotubeLogoLight, spotubeLogoMacos, spotubeLogoBmp, spotubeLogoIco, spotubeLogoPng, - spotubeLogoSvg, spotubeLogoAndroid12, - spotubeNightlyLogoForeground, - spotubeNightlyLogoPng, - spotubeNightlyLogoSvg, + spotubeNightlyItem, + spotubeNightlyLogoForegroundPng, + spotubeNightlyLogoForegroundSvg, + spotubeNightlyLogo, spotubeNightlyLogoAndroid12, spotubeScreenshot, spotubeTallCapsule, diff --git a/lib/collections/fake.dart b/lib/collections/fake.dart index 31f97e0c..8af40e71 100644 --- a/lib/collections/fake.dart +++ b/lib/collections/fake.dart @@ -94,6 +94,7 @@ abstract class FakeData { ..trackNumber = 1 ..type = "type" ..uri = "uri" + ..externalIds = externalIds ..isPlayable = true ..explicit = false ..linkedFrom = trackLink; diff --git a/lib/collections/intents.dart b/lib/collections/intents.dart index e4e3fa07..42c580ca 100644 --- a/lib/collections/intents.dart +++ b/lib/collections/intents.dart @@ -75,7 +75,7 @@ class HomeTabAction extends Action { router.navigate(const SearchRoute()); break; case HomeTabs.lyrics: - router.navigate(LyricsRoute()); + router.navigate(const LyricsRoute()); break; case HomeTabs.userPlaylists: router.navigate(const UserPlaylistsRoute()); diff --git a/lib/collections/side_bar_tiles.dart b/lib/collections/side_bar_tiles.dart index 80ca7306..c647c9fb 100644 --- a/lib/collections/side_bar_tiles.dart +++ b/lib/collections/side_bar_tiles.dart @@ -38,7 +38,7 @@ List getSidebarTileList(AppLocalizations l10n) => [ SideBarTiles( id: "lyrics", pathPrefix: "/lyrics", - route: LyricsRoute(), + route: const LyricsRoute(), icon: SpotubeIcons.music, title: l10n.lyrics, ), diff --git a/lib/components/adaptive/adaptive_pop_sheet_list.dart b/lib/components/adaptive/adaptive_pop_sheet_list.dart index 0f02ee73..6eba1148 100644 --- a/lib/components/adaptive/adaptive_pop_sheet_list.dart +++ b/lib/components/adaptive/adaptive_pop_sheet_list.dart @@ -1,4 +1,3 @@ -import 'package:flutter/material.dart' show showModalBottomSheet; import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotube/collections/spotube_icons.dart'; @@ -26,7 +25,7 @@ class AdaptiveMenuButton extends MenuButton { /// An adaptive widget that shows a [PopupMenuButton] when screen size is above /// or equal to 640px -/// In smaller screen, a [IconButton] with a [showModalBottomSheet] is shown +/// In smaller screen, a [IconButton] with a [openDrawer] is shown class AdaptivePopSheetList extends StatelessWidget { final List> Function(BuildContext context) items; final Widget? icon; @@ -39,7 +38,7 @@ class AdaptivePopSheetList extends StatelessWidget { final Offset offset; - final ButtonVariance variance; + final AbstractButtonStyle variance; const AdaptivePopSheetList({ super.key, @@ -92,23 +91,23 @@ class AdaptivePopSheetList extends StatelessWidget { // ), position: position, builder: (context) { - return DropdownMenu( - children: childrenModified(context), + return WidgetStatesProvider.boundary( + child: DropdownMenu( + children: childrenModified(context), + ), ); }, ).future; return; } - showModalBottomSheet( + await openDrawer( context: context, - enableDrag: true, + draggable: true, showDragHandle: true, - useRootNavigator: true, - shape: RoundedRectangleBorder( - borderRadius: context.theme.borderRadiusMd, - ), - backgroundColor: context.theme.colorScheme.card, + position: OverlayPosition.bottom, + borderRadius: context.theme.borderRadiusMd, + transformBackdrop: false, builder: (context) { final children = childrenModified(context); return ListView.builder( @@ -125,7 +124,7 @@ class AdaptivePopSheetList extends StatelessWidget { onPressed: () { data.onPressed?.call(context); if (data.autoClose) { - Navigator.of(context).pop(); + closeDrawer(context); } }, leading: data.leading, @@ -147,7 +146,7 @@ class AdaptivePopSheetList extends StatelessWidget { return Tooltip( tooltip: TooltipContainer( child: Text(tooltip), - ), + ).call, child: IconButton( variance: variance, icon: icon ?? const Icon(SpotubeIcons.moreVertical), @@ -171,7 +170,7 @@ class AdaptivePopSheetList extends StatelessWidget { if (child != null) { return Tooltip( - tooltip: TooltipContainer(child: Text(tooltip)), + tooltip: TooltipContainer(child: Text(tooltip)).call, child: Button( onPressed: () => showDropdownMenu(context, Offset.zero), style: variance, @@ -181,7 +180,7 @@ class AdaptivePopSheetList extends StatelessWidget { } return Tooltip( - tooltip: TooltipContainer(child: Text(tooltip)), + tooltip: TooltipContainer(child: Text(tooltip)).call, child: IconButton( variance: variance, icon: icon ?? const Icon(SpotubeIcons.moreVertical), diff --git a/lib/components/expandable_search/expandable_search.dart b/lib/components/expandable_search/expandable_search.dart index 0c40b843..279a3e5f 100644 --- a/lib/components/expandable_search/expandable_search.dart +++ b/lib/components/expandable_search/expandable_search.dart @@ -40,7 +40,9 @@ class ExpandableSearchField extends StatelessWidget { focusNode: searchFocus, controller: searchController, placeholder: Text(context.l10n.search_tracks), - leading: const Icon(SpotubeIcons.search), + features: const [ + InputFeature.leading(Icon(SpotubeIcons.search)) + ], ), ), ), diff --git a/lib/components/form/text_form_field.dart b/lib/components/form/text_form_field.dart index 56ef34a5..b07c33e3 100644 --- a/lib/components/form/text_form_field.dart +++ b/lib/components/form/text_form_field.dart @@ -15,8 +15,7 @@ class TextFormBuilderField extends StatelessWidget { // final AlignmentGeometry? leadingAlignment; // final AlignmentGeometry? trailingAlignment; final bool border; - final Widget? leading; - final Widget? trailing; + final List features; final EdgeInsetsGeometry? padding; final ValueChanged? onSubmitted; final VoidCallback? onEditingComplete; @@ -63,8 +62,6 @@ class TextFormBuilderField extends StatelessWidget { this.filled = false, this.placeholder, this.border = true, - this.leading, - this.trailing, this.padding, this.onSubmitted, this.onEditingComplete, @@ -96,6 +93,7 @@ class TextFormBuilderField extends StatelessWidget { // this.leadingAlignment, // this.trailingAlignment, this.statesController, + this.features = const [], }); @override @@ -130,8 +128,7 @@ class TextFormBuilderField extends StatelessWidget { filled: filled, placeholder: placeholder, border: border, - leading: leading, - trailing: trailing, + features: features, padding: padding, onSubmitted: (value) { field.validate(); diff --git a/lib/components/heart_button/heart_button.dart b/lib/components/heart_button/heart_button.dart index 56cb22ab..275d5db1 100644 --- a/lib/components/heart_button/heart_button.dart +++ b/lib/components/heart_button/heart_button.dart @@ -13,7 +13,7 @@ class HeartButton extends HookConsumerWidget { final IconData? icon; final Color? color; final String? tooltip; - final ButtonVariance variance; + final AbstractButtonStyle variance; final ButtonSize size; const HeartButton({ required this.isLiked, @@ -33,7 +33,7 @@ class HeartButton extends HookConsumerWidget { if (auth.asData?.value == null) return const SizedBox.shrink(); return Tooltip( - tooltip: TooltipContainer(child: Text(tooltip ?? "")), + tooltip: TooltipContainer(child: Text(tooltip ?? "")).call, child: IconButton( variance: variance, size: size, diff --git a/lib/components/playbutton_view/playbutton_card.dart b/lib/components/playbutton_view/playbutton_card.dart index 0b47ae28..ea28c738 100644 --- a/lib/components/playbutton_view/playbutton_card.dart +++ b/lib/components/playbutton_view/playbutton_card.dart @@ -151,7 +151,7 @@ class PlaybuttonCard extends StatelessWidget { ], ), title: Tooltip( - tooltip: TooltipContainer(child: Text(title)), + tooltip: TooltipContainer(child: Text(title)).call, child: Text( title, maxLines: 1, diff --git a/lib/components/playbutton_view/playbutton_tile.dart b/lib/components/playbutton_view/playbutton_tile.dart index ec1ca95f..7470105d 100644 --- a/lib/components/playbutton_view/playbutton_tile.dart +++ b/lib/components/playbutton_view/playbutton_tile.dart @@ -71,7 +71,7 @@ class PlaybuttonTile extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ Tooltip( - tooltip: TooltipContainer(child: Text(context.l10n.add_to_queue)), + tooltip: TooltipContainer(child: Text(context.l10n.add_to_queue)).call, child: IconButton.outline( icon: const Icon(SpotubeIcons.queueAdd), onPressed: onAddToQueuePressed, @@ -80,7 +80,7 @@ class PlaybuttonTile extends StatelessWidget { ), const Gap(8), Tooltip( - tooltip: TooltipContainer(child: Text(context.l10n.play)), + tooltip: TooltipContainer(child: Text(context.l10n.play)).call, child: IconButton.secondary( icon: switch ((isLoading, isPlaying)) { (true, _) => const CircularProgressIndicator( diff --git a/lib/components/shimmers/shimmer_lyrics.dart b/lib/components/shimmers/shimmer_lyrics.dart index f8d29722..9312865e 100644 --- a/lib/components/shimmers/shimmer_lyrics.dart +++ b/lib/components/shimmers/shimmer_lyrics.dart @@ -1,6 +1,5 @@ import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:gap/gap.dart'; import 'package:skeletonizer/skeletonizer.dart'; diff --git a/lib/components/titlebar/titlebar_icon_buttons.dart b/lib/components/titlebar/titlebar_icon_buttons.dart index 481a22ce..0a3f6178 100644 --- a/lib/components/titlebar/titlebar_icon_buttons.dart +++ b/lib/components/titlebar/titlebar_icon_buttons.dart @@ -1,7 +1,6 @@ import 'dart:math'; import 'package:shadcn_flutter/shadcn_flutter.dart'; -import 'package:spotube/extensions/button_variance.dart'; class ShadcnWindowButton extends StatelessWidget { final Widget icon; @@ -22,7 +21,7 @@ class ShadcnWindowButton extends StatelessWidget { height: 32, child: IconButton( variance: ButtonVariance.ghost.copyWith( - decoration: (context, states) { + decoration: (context, states, value) { final decoration = ButtonVariance.ghost.decoration(context, states) as BoxDecoration; if (hoverBackgroundColor != null && diff --git a/lib/components/track_presentation/presentation_actions.dart b/lib/components/track_presentation/presentation_actions.dart index 4948cf69..bbeb90a5 100644 --- a/lib/components/track_presentation/presentation_actions.dart +++ b/lib/components/track_presentation/presentation_actions.dart @@ -74,6 +74,26 @@ class TrackPresentationActionsSection extends HookConsumerWidget { ref.watch(presentationStateProvider(options.collection).notifier); final selectedTracks = state.selectedTracks; + Future actionDownloadTracks({ + required BuildContext context, + required List tracks, + required String action, + }) async { + final confirmed = audioSource == AudioSource.piped || + (await showDialog( + context: context, + builder: (context) { + return const ConfirmDownloadDialog(); + }, + ) ?? + false); + if (confirmed != true) return; + downloader.batchAddToQueue(tracks); + notifier.deselectAllTracks(); + if (!context.mounted) return; + showToastForAction(context, action, tracks.length); + } + return AdaptivePopSheetList( tooltip: context.l10n.more_actions, headings: [ @@ -95,22 +115,12 @@ class TrackPresentationActionsSection extends HookConsumerWidget { switch (action) { case "download": - { - final confirmed = audioSource == AudioSource.piped || - (await showDialog( - context: context, - builder: (context) { - return const ConfirmDownloadDialog(); - }, - ) ?? - false); - if (confirmed != true) return; - downloader.batchAddToQueue(tracks); - notifier.deselectAllTracks(); - if (!context.mounted) return; - showToastForAction(context, action, tracks.length); - break; - } + await actionDownloadTracks( + context: context, + tracks: tracks, + action: action, + ); + break; case "add-to-playlist": { if (context.mounted) { diff --git a/lib/components/track_presentation/presentation_modifiers.dart b/lib/components/track_presentation/presentation_modifiers.dart index c46fef3f..42c3cb4f 100644 --- a/lib/components/track_presentation/presentation_modifiers.dart +++ b/lib/components/track_presentation/presentation_modifiers.dart @@ -67,10 +67,6 @@ class TrackPresentationModifiersSection extends HookConsumerWidget { child: TextField( controller: controller, focusNode: focusNode, - leading: Icon( - SpotubeIcons.search, - color: context.theme.colorScheme.mutedForeground, - ), placeholder: Text(context.l10n.search_tracks), onChanged: (value) { if (value.isEmpty) { @@ -79,30 +75,41 @@ class TrackPresentationModifiersSection extends HookConsumerWidget { notifier.filterTracks(value); } }, - trailing: ListenableBuilder( - listenable: controller, - builder: (context, _) { - return AnimatedCrossFade( - duration: const Duration(milliseconds: 300), - crossFadeState: controller.text.isEmpty - ? CrossFadeState.showFirst - : CrossFadeState.showSecond, - firstChild: - const SizedBox.square(dimension: 20), - secondChild: AnimatedScale( - duration: const Duration(milliseconds: 300), - scale: controller.text.isEmpty ? 0 : 1, - child: IconButton.ghost( - size: const ButtonSize(.6), - icon: const Icon(SpotubeIcons.close), - onPressed: () { - controller.clear(); - notifier.clearFilter(); - }, - ), - ), - ); - }), + features: [ + InputFeature.leading( + Icon( + SpotubeIcons.search, + color: context.theme.colorScheme.mutedForeground, + ), + ), + InputFeature.trailing( + ListenableBuilder( + listenable: controller, + builder: (context, _) { + return AnimatedCrossFade( + duration: const Duration(milliseconds: 300), + crossFadeState: controller.text.isEmpty + ? CrossFadeState.showFirst + : CrossFadeState.showSecond, + firstChild: + const SizedBox.square(dimension: 20), + secondChild: AnimatedScale( + duration: + const Duration(milliseconds: 300), + scale: controller.text.isEmpty ? 0 : 1, + child: IconButton.ghost( + size: const ButtonSize(.6), + icon: const Icon(SpotubeIcons.close), + onPressed: () { + controller.clear(); + notifier.clearFilter(); + }, + ), + ), + ); + }), + ) + ], ), ), ), diff --git a/lib/components/track_presentation/presentation_top.dart b/lib/components/track_presentation/presentation_top.dart index 8da2f51c..5935fa13 100644 --- a/lib/components/track_presentation/presentation_top.dart +++ b/lib/components/track_presentation/presentation_top.dart @@ -57,7 +57,7 @@ class TrackPresentationTopSection extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.shuffle_playlist), - ), + ).call, child: IconButton.secondary( icon: isLoading ? const Center( @@ -73,7 +73,7 @@ class TrackPresentationTopSection extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.add_to_queue), - ), + ).call, child: IconButton.secondary( icon: const Icon(SpotubeIcons.queueAdd), enabled: !isLoading && !isActive, @@ -126,7 +126,7 @@ class TrackPresentationTopSection extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.share), - ), + ).call, child: IconButton.outline( icon: const Icon(SpotubeIcons.share), size: ButtonSize.small, diff --git a/lib/components/track_tile/track_options.dart b/lib/components/track_tile/track_options.dart index 05e67d02..a0738165 100644 --- a/lib/components/track_tile/track_options.dart +++ b/lib/components/track_tile/track_options.dart @@ -91,24 +91,14 @@ class TrackOptions extends HookConsumerWidget { ) { /// showDialog doesn't work for some reason. So we have to /// manually push a Dialog Route in the Navigator to get it working - Navigator.push( - context, - DialogRoute( - alignment: Alignment.bottomCenter, - transitionBuilder: (context, animation, secondaryAnimation, child) { - return FadeTransition(opacity: animation, child: child); - }, - context: context, - barrierColor: Colors.black.withValues(alpha: 0.5), - builder: (context) { - return Center( - child: PlaylistAddTrackDialog( - tracks: [track], - openFromPlaylist: playlistId, - ), - ); - }, - ), + showDialog( + context: context, + builder: (context) { + return PlaylistAddTrackDialog( + tracks: [track], + openFromPlaylist: playlistId, + ); + }, ); } @@ -338,6 +328,7 @@ class TrackOptions extends HookConsumerWidget { } }, icon: icon ?? const Icon(SpotubeIcons.moreHorizontal), + variance: ButtonVariance.outline, headings: [ Basic( leading: AspectRatio( @@ -483,7 +474,7 @@ class TrackOptions extends HookConsumerWidget { leading: Assets.logos.songlinkTransparent.image( width: 22, height: 22, - color: colorScheme.foreground.withOpacity(0.5), + color: colorScheme.foreground.withValues(alpha: 0.5), ), child: Text(context.l10n.song_link), ), diff --git a/lib/components/track_tile/track_tile.dart b/lib/components/track_tile/track_tile.dart index 524575e5..f47980cd 100644 --- a/lib/components/track_tile/track_tile.dart +++ b/lib/components/track_tile/track_tile.dart @@ -5,7 +5,7 @@ import 'package:flutter/gestures.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/collections/routes.gr.dart'; @@ -17,7 +17,6 @@ import 'package:spotube/components/links/link_text.dart'; import 'package:spotube/components/track_tile/track_options.dart'; import 'package:spotube/components/ui/button_tile.dart'; import 'package:spotube/extensions/artist_simple.dart'; -import 'package:spotube/extensions/button_variance.dart'; import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/duration.dart'; import 'package:spotube/extensions/image.dart'; @@ -108,7 +107,7 @@ class TrackTile extends HookConsumerWidget { ? ButtonVariance.destructive : ButtonVariance.ghost) .copyWith( - padding: (context, states) => + padding: (context, states, value) => const EdgeInsets.symmetric(vertical: 8, horizontal: 0), ), leading: Row( @@ -229,7 +228,8 @@ class TrackTile extends HookConsumerWidget { Flexible( child: Button( style: ButtonVariance.link.copyWith( - padding: (context, states) => EdgeInsets.zero, + padding: (context, states, value) => + EdgeInsets.zero, ), onPressed: () { context diff --git a/lib/components/ui/button_tile.dart b/lib/components/ui/button_tile.dart index 8f5a7581..e31a09a5 100644 --- a/lib/components/ui/button_tile.dart +++ b/lib/components/ui/button_tile.dart @@ -9,7 +9,7 @@ class ButtonTile extends StatelessWidget { final VoidCallback? onPressed; final VoidCallback? onLongPress; final bool selected; - final ButtonVariance style; + final AbstractButtonStyle style; final EdgeInsets? padding; const ButtonTile({ diff --git a/lib/extensions/track.dart b/lib/extensions/track.dart index 215a5ab2..92d8b0da 100644 --- a/lib/extensions/track.dart +++ b/lib/extensions/track.dart @@ -4,7 +4,9 @@ import 'dart:typed_data'; import 'package:metadata_god/metadata_god.dart'; import 'package:path/path.dart'; import 'package:spotify/spotify.dart'; +import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/services/audio_player/audio_player.dart'; +import 'package:spotube/services/logger/logger.dart'; extension TrackExtensions on Track { Track fromFile( @@ -67,27 +69,40 @@ extension TrackExtensions on Track { } } -extension TrackSimpleExtensions on TrackSimple { - Track asTrack(AlbumSimple album) { - Track track = Track(); - track.name = name; - track.album = album; - track.artists = artists; - track.availableMarkets = availableMarkets; - track.discNumber = discNumber; - track.durationMs = durationMs; - track.explicit = explicit; - track.externalUrls = externalUrls; - track.href = href; - track.id = id; - track.isPlayable = isPlayable; - track.linkedFrom = linkedFrom; - track.name = name; - track.previewUrl = previewUrl; - track.trackNumber = trackNumber; - track.type = type; - track.uri = uri; - return track; +extension IterableTrackSimpleExtensions on Iterable { + Future> asTracks(AlbumSimple album, ref) async { + try { + final spotify = ref.read(spotifyProvider); + final tracks = await spotify.invoke( + (api) => api.tracks.list(map((trackSimple) => trackSimple.id!).toList())); + return tracks.toList(); + } catch (e, stack) { + // Ignore errors and create the track locally + AppLogger.reportError(e, stack); + + List tracks = []; + for (final trackSimple in this) { + Track track = Track(); + track.album = album; + track.name = trackSimple.name; + track.artists = trackSimple.artists; + track.availableMarkets = trackSimple.availableMarkets; + track.discNumber = trackSimple.discNumber; + track.durationMs = trackSimple.durationMs; + track.explicit = trackSimple.explicit; + track.externalUrls = trackSimple.externalUrls; + track.href = trackSimple.href; + track.id = trackSimple.id; + track.isPlayable = trackSimple.isPlayable; + track.linkedFrom = trackSimple.linkedFrom; + track.previewUrl = trackSimple.previewUrl; + track.trackNumber = trackSimple.trackNumber; + track.type = trackSimple.type; + track.uri = trackSimple.uri; + tracks.add(track); + } + return tracks; + } } } diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index f4cbde9b..4a7f176d 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -426,5 +426,9 @@ "download": "تنزيل", "file_not_found": "الملف غير موجود", "custom": "مخصص", - "add_custom_url": "إضافة URL مخصص" + "add_custom_url": "إضافة URL مخصص", + "edit_port": "تعديل المنفذ", + "port_helper_msg": "القيمة الافتراضية هي -1 والتي تشير إلى رقم عشوائي. إذا كان لديك جدار ناري مُعد، يُوصى بتعيين هذا.", + "connect_request": "السماح لـ {client} بالاتصال؟", + "connection_request_denied": "تم رفض الاتصال. المستخدم رفض الوصول." } \ No newline at end of file diff --git a/lib/l10n/app_bn.arb b/lib/l10n/app_bn.arb index cc2971ce..7d5a3e5a 100644 --- a/lib/l10n/app_bn.arb +++ b/lib/l10n/app_bn.arb @@ -426,5 +426,9 @@ "download": "ডাউনলোড", "file_not_found": "ফাইল পাওয়া যায়নি", "custom": "কাস্টম", - "add_custom_url": "কাস্টম URL যোগ করুন" + "add_custom_url": "কাস্টম URL যোগ করুন", + "edit_port": "পোর্ট সম্পাদনা করুন", + "port_helper_msg": "ডিফল্ট হল -1 যা এলোমেলো সংখ্যা নির্দেশ করে। যদি আপনার ফায়ারওয়াল কনফিগার করা থাকে, তবে এটি সেট করা সুপারিশ করা হয়।", + "connect_request": "{client} কে সংযোগ করতে অনুমতি দেবেন?", + "connection_request_denied": "সংযোগ অস্বীকৃত। ব্যবহারকারী প্রবেশাধিকার অস্বীকার করেছে।" } \ No newline at end of file diff --git a/lib/l10n/app_ca.arb b/lib/l10n/app_ca.arb index 7cb007c4..8afb33f3 100644 --- a/lib/l10n/app_ca.arb +++ b/lib/l10n/app_ca.arb @@ -426,5 +426,9 @@ "download": "Descarregar", "file_not_found": "Fitxer no trobat", "custom": "Personalitzat", - "add_custom_url": "Afegir URL personalitzada" + "add_custom_url": "Afegir URL personalitzada", + "edit_port": "Editar port", + "port_helper_msg": "El valor per defecte és -1, que indica un número aleatori. Si teniu un tallafoc configurat, es recomana establir-ho.", + "connect_request": "Permetre que {client} es connecti?", + "connection_request_denied": "Connexió denegada. L'usuari ha denegat l'accés." } \ No newline at end of file diff --git a/lib/l10n/app_cs.arb b/lib/l10n/app_cs.arb index a6fdf25c..44631945 100644 --- a/lib/l10n/app_cs.arb +++ b/lib/l10n/app_cs.arb @@ -426,5 +426,9 @@ "download": "Stáhnout", "file_not_found": "Soubor nenalezen", "custom": "Vlastní", - "add_custom_url": "Přidat vlastní URL" + "add_custom_url": "Přidat vlastní URL", + "edit_port": "Upravit port", + "port_helper_msg": "Výchozí hodnota je -1, což znamená náhodné číslo. Pokud máte nakonfigurován firewall, doporučuje se to nastavit.", + "connect_request": "Povolit {client} připojení?", + "connection_request_denied": "Připojení bylo zamítnuto. Uživatel odmítl přístup." } \ No newline at end of file diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index af2b26ad..7ce9c333 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -426,5 +426,9 @@ "download": "Herunterladen", "file_not_found": "Datei nicht gefunden", "custom": "Benutzerdefiniert", - "add_custom_url": "Benutzerdefinierte URL hinzufügen" + "add_custom_url": "Benutzerdefinierte URL hinzufügen", + "edit_port": "Port bearbeiten", + "port_helper_msg": "Der Standardwert ist -1, was eine zufällige Zahl bedeutet. Wenn Sie eine Firewall konfiguriert haben, wird empfohlen, dies einzustellen.", + "connect_request": "{client} die Verbindung erlauben?", + "connection_request_denied": "Verbindung abgelehnt. Benutzer hat den Zugriff verweigert." } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index e3e6d330..4da423a8 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -424,5 +424,9 @@ "download": "Download", "file_not_found": "File not found", "custom": "Custom", - "add_custom_url": "Add custom URL" + "add_custom_url": "Add custom URL", + "edit_port": "Edit port", + "port_helper_msg": "Default is -1 which indicates random number. If you've firewall configured, setting this is recommended.", + "connect_request": "Allow {client} to connect?", + "connection_request_denied": "Connection denied. User denied access." } diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 565c786a..8a6e02ad 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -426,5 +426,9 @@ "download": "Descargar", "file_not_found": "Archivo no encontrado", "custom": "Personalizado", - "add_custom_url": "Agregar URL personalizada" + "add_custom_url": "Agregar URL personalizada", + "edit_port": "Editar puerto", + "port_helper_msg": "El valor predeterminado es -1, lo que indica un número aleatorio. Si tienes un firewall configurado, se recomienda establecer esto.", + "connect_request": "¿Permitir que {client} se conecte?", + "connection_request_denied": "Conexión denegada. El usuario denegó el acceso." } \ No newline at end of file diff --git a/lib/l10n/app_eu.arb b/lib/l10n/app_eu.arb index 70a581a7..f28d5f8e 100644 --- a/lib/l10n/app_eu.arb +++ b/lib/l10n/app_eu.arb @@ -426,5 +426,9 @@ "download": "Deskargatu", "file_not_found": "Fitxategia ez da aurkitu", "custom": "Pertsonalizatua", - "add_custom_url": "Gehitu URL pertsonalizatua" + "add_custom_url": "Gehitu URL pertsonalizatua", + "edit_port": "Editatu portua", + "port_helper_msg": "Lehenetsitako balioa -1 da, zenbaki aleatorioa adierazten duena. Su firewall konfiguratu baduzu, gomendatzen da hau ezartzea.", + "connect_request": "{client} konektatzea baimendu?", + "connection_request_denied": "Konektatzea ukatu da. Erabiltzaileak sarbidea ukatu du." } \ No newline at end of file diff --git a/lib/l10n/app_fa.arb b/lib/l10n/app_fa.arb index d3918e55..0791d0b6 100644 --- a/lib/l10n/app_fa.arb +++ b/lib/l10n/app_fa.arb @@ -426,5 +426,9 @@ "download": "دانلود", "file_not_found": "فایل پیدا نشد", "custom": "شخصی‌سازی شده", - "add_custom_url": "اضافه کردن URL سفارشی" + "add_custom_url": "اضافه کردن URL سفارشی", + "edit_port": "ویرایش پورت", + "port_helper_msg": "پیش‌فرض -1 است که نشان‌دهنده یک عدد تصادفی است. اگر فایروال شما پیکربندی شده است، توصیه می‌شود این را تنظیم کنید.", + "connect_request": "آیا اجازه می‌دهید {client} متصل شود؟", + "connection_request_denied": "اتصال رد شد. کاربر دسترسی را رد کرد." } \ No newline at end of file diff --git a/lib/l10n/app_fi.arb b/lib/l10n/app_fi.arb index 797c36f7..57a5a0b8 100644 --- a/lib/l10n/app_fi.arb +++ b/lib/l10n/app_fi.arb @@ -426,5 +426,9 @@ "download": "Lataa", "file_not_found": "Tiedostoa ei löydy", "custom": "Mukautettu", - "add_custom_url": "Lisää mukautettu URL" + "add_custom_url": "Lisää mukautettu URL", + "edit_port": "Muokkaa porttia", + "port_helper_msg": "Oletusarvo on -1, mikä tarkoittaa satunnaista numeroa. Jos sinulla on palomuuri määritetty, tämän asettamista suositellaan.", + "connect_request": "Salli {client} yhdistää?", + "connection_request_denied": "Yhteys evätty. Käyttäjä eväsi pääsyn." } \ No newline at end of file diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 636cffec..192b6c5c 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -426,5 +426,9 @@ "download": "Télécharger", "file_not_found": "Fichier non trouvé", "custom": "Personnalisé", - "add_custom_url": "Ajouter une URL personnalisée" + "add_custom_url": "Ajouter une URL personnalisée", + "edit_port": "Modifier le port", + "port_helper_msg": "La valeur par défaut est -1, ce qui indique un nombre aléatoire. Si vous avez configuré un pare-feu, il est recommandé de le définir.", + "connect_request": "Autoriser {client} à se connecter ?", + "connection_request_denied ": "Connexion refusée. L'utilisateur a refusé l'accès." } \ No newline at end of file diff --git a/lib/l10n/app_hi.arb b/lib/l10n/app_hi.arb index fc59d31a..124d0634 100644 --- a/lib/l10n/app_hi.arb +++ b/lib/l10n/app_hi.arb @@ -426,5 +426,9 @@ "download": "डाउनलोड करें", "file_not_found": "फाइल नहीं मिली", "custom": "कस्टम", - "add_custom_url": "कस्टम URL जोड़ें" + "add_custom_url": "कस्टम URL जोड़ें", + "edit_port": "पोर्ट संपादित करें", + "port_helper_msg": "डिफ़ॉल्ट -1 है जो यादृच्छिक संख्या को दर्शाता है। यदि आपने फ़ायरवॉल कॉन्फ़िगर किया है, तो इसे सेट करना अनुशंसित है।", + "connect_request": "{client} को कनेक्ट करने की अनुमति दें?", + "connection_request_denied": "कनेक्शन अस्वीकृत। उपयोगकर्ता ने पहुंच अस्वीकृत कर दी।" } \ No newline at end of file diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 91bc9aef..ffe36295 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -426,5 +426,9 @@ "download": "Download", "file_not_found": "File not found", "custom": "Custom", - "add_custom_url": "Add custom URL" + "add_custom_url": "Add custom URL", + "edit_port": "Edit port", + "port_helper_msg": "Default adalah -1 yang menunjukkan angka acak. Jika Anda telah mengonfigurasi firewall, disarankan untuk mengatur ini.", + "connect_request": "Izinkan {client} untuk terhubung?", + "connection_request_denied": "Koneksi ditolak. Pengguna menolak akses." } \ No newline at end of file diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index f598d363..1c7dc114 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -427,5 +427,9 @@ "download": "Scarica", "file_not_found": "File non trovato", "custom": "Personalizzato", - "add_custom_url": "Aggiungi URL personalizzato" + "add_custom_url": "Aggiungi URL personalizzato", + "edit_port": "Modifica porta", + "port_helper_msg": "Il valore predefinito è -1, che indica un numero casuale. Se hai configurato un firewall, si consiglia di impostarlo.", + "connect_request": "Consentire a {client} di connettersi?", + "connection_request_denied": "Connessione negata. L'utente ha negato l'accesso." } \ No newline at end of file diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index b885fa59..230b2b49 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -426,5 +426,9 @@ "download": "ダウンロード", "file_not_found": "ファイルが見つかりません", "custom": "カスタム", - "add_custom_url": "カスタムURLを追加" + "add_custom_url": "カスタムURLを追加", + "edit_port": "ポートを編集", + "port_helper_msg": "デフォルトは-1で、ランダムな番号を示します。ファイアウォールを設定している場合は、これを設定することをお勧めします。", + "connect_request": "{client}の接続を許可しますか?", + "connection_request_denied": "接続が拒否されました。ユーザーがアクセスを拒否しました。" } \ No newline at end of file diff --git a/lib/l10n/app_ka.arb b/lib/l10n/app_ka.arb index 8bc9cf36..67f90361 100644 --- a/lib/l10n/app_ka.arb +++ b/lib/l10n/app_ka.arb @@ -426,5 +426,9 @@ "download": "ჩამოტვირთვა", "file_not_found": "ფაილი ვერ მოიძებნა", "custom": "პერსონალიზირებული", - "add_custom_url": "დამატება პერსონალური URL" + "add_custom_url": "დამატება პერსონალური URL", + "edit_port": "პორტის რედაქტირება", + "port_helper_msg": "ნაგულისხმევი არის -1, რაც შემთხვევითი ნომრის მითითებას ნიშნავს. თუ لديك firewall настроен, рекомендуется установить это.", + "connect_request": "{client}-ის დაკავშირების ნებართვა?", + "connection_request_denied": "კავშირი უარყოფილია. მომხმარებელმა უარყო წვდომა." } \ No newline at end of file diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index 6c8031b5..037e1fb1 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -427,5 +427,9 @@ "download": "다운로드", "file_not_found": "파일을 찾을 수 없습니다", "custom": "사용자 정의", - "add_custom_url": "사용자 정의 URL 추가" + "add_custom_url": "사용자 정의 URL 추가", + "edit_port": "포트 편집", + "port_helper_msg": "기본값은 -1로 무작위 숫자를 나타냅니다. 방화벽이 구성된 경우 이를 설정하는 것이 좋습니다.", + "connect_request": "{client}의 연결을 허용하시겠습니까?", + "connection_request_denied": "연결이 거부되었습니다. 사용자가 액세스를 거부했습니다." } \ No newline at end of file diff --git a/lib/l10n/app_ne.arb b/lib/l10n/app_ne.arb index beddc3ad..823dadb1 100644 --- a/lib/l10n/app_ne.arb +++ b/lib/l10n/app_ne.arb @@ -426,5 +426,9 @@ "download": "डाउनलोड", "file_not_found": "फ़ाइल नहीं मिली", "custom": "कस्टम", - "add_custom_url": "कस्टम URL जोड़ें" + "add_custom_url": "कस्टम URL जोड़ें", + "edit_port": "पोर्ट सम्पादन गर्नुहोस्", + "port_helper_msg": "डिफ़ॉल्ट -1 हो जुन यादृच्छिक संख्या जनाउँछ। यदि तपाईंले फायरवाल कन्फिगर गर्नुभएको छ भने, यसलाई सेट गर्न सिफारिस गरिन्छ।", + "connect_request": "{client} लाई जडान गर्न अनुमति दिनुहोस्?", + "connection_request_denied": "जडान अस्वीकृत। प्रयोगकर्ताले पहुँच अस्वीकृत गर्यो।" } \ No newline at end of file diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 2127b382..01aa6ef8 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -427,5 +427,9 @@ "download": "Downloaden", "file_not_found": "Bestand niet gevonden", "custom": "Aangepast", - "add_custom_url": "Voeg aangepaste URL toe" + "add_custom_url": "Voeg aangepaste URL toe", + "edit_port": "Poort bewerken", + "port_helper_msg": "Standaard is -1, wat een willekeurig nummer aangeeft. Als je een firewall hebt geconfigureerd, wordt aanbevolen dit in te stellen.", + "connect_request": "Toestaan dat {client} verbinding maakt?", + "connection_request_denied": "Verbinding geweigerd. Gebruiker heeft toegang geweigerd." } \ No newline at end of file diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index ade74c90..a2388614 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -426,5 +426,9 @@ "download": "Pobierz", "file_not_found": "Plik nie znaleziony", "custom": "Niestandardowy", - "add_custom_url": "Dodaj niestandardowy URL" + "add_custom_url": "Dodaj niestandardowy URL", + "edit_port": "Edytuj port", + "port_helper_msg": "Domyślna wartość to -1, co oznacza losową liczbę. Jeśli masz skonfigurowany zaporę, zaleca się jej ustawienie.", + "connect_request": "Zezwolić {client} na połączenie?", + "connection_request_denied": "Połączenie odrzucone. Użytkownik odmówił dostępu." } \ No newline at end of file diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 6b1098a9..bec4f7c9 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -426,5 +426,9 @@ "download": "Baixar", "file_not_found": "Arquivo não encontrado", "custom": "Personalizado", - "add_custom_url": "Adicionar URL personalizada" + "add_custom_url": "Adicionar URL personalizada", + "edit_port": "Editar porta", + "port_helper_msg": "O padrão é -1, que indica um número aleatório. Se você tiver um firewall configurado, é recomendável definir isso.", + "connect_request": "Permitir que {client} se conecte?", + "connection_request_denied": "Conexão negada. O usuário negou o acesso ." } \ No newline at end of file diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 461e8da8..9e8cbb3f 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -426,5 +426,9 @@ "download": "Скачать", "file_not_found": "Файл не найден", "custom": "Пользовательский", - "add_custom_url": "Добавить пользовательский URL" + "add_custom_url": "Добавить пользовательский URL", + "edit_port": "Редактировать порт", + "port_helper_msg": "По умолчанию -1, что означает случайное число. Если у вас настроен брандмауэр, рекомендуется установить это.", + "connect_request": "Разрешить {client} подключение?", + "connection_request_denied": "Подключение отклонено. Пользователь отказал в доступе." } \ No newline at end of file diff --git a/lib/l10n/app_ta.arb b/lib/l10n/app_ta.arb index 396a16fb..15c8d54f 100644 --- a/lib/l10n/app_ta.arb +++ b/lib/l10n/app_ta.arb @@ -1,428 +1,432 @@ { - "guest": "விருந்தினர்", - "browse": "உலாவு", - "search": "தேடுக", - "library": "நூலகம்", - "lyrics": "பாடல் வரிகள்", - "settings": "அமைப்புகள்", - "genre_categories_filter": "வகைகள் அல்லது பாணிகளை வடிகட்டுக...", - "genre": "பாணி", - "personalized": "தனிப்பயனாக்கப்பட்ட", - "featured": "சிறப்பிடம் பெற்ற", - "new_releases": "புதிய வெளியீடுகள்", - "songs": "பாடல்கள்", - "playing_track": "{track} இயங்குகிறது", - "queue_clear_alert": "இது தற்போதைய வரிசையை அழிக்கும். {track_length} பாடல்கள் நீக்கப்படும்\nதொடர விரும்புகிறீர்களா?", - "load_more": "மேலும் ஏற்றுக", - "playlists": "பாடல் பட்டியல்கள்", - "artists": "கலைஞர்கள்", - "albums": "ஆல்பங்கள்", - "tracks": "பாடல்கள்", - "downloads": "பதிவிறக்கங்கள்", - "filter_playlists": "உங்கள் பாடல் பட்டியல்களை வடிகட்டுக...", - "liked_tracks": "விரும்பிய பாடல்கள்", - "liked_tracks_description": "உங்கள் விரும்பிய பாடல்கள் அனைத்தும்", - "playlist": "பாடல் பட்டியல்", - "create_a_playlist": "பாடல் பட்டியலை உருவாக்குக", - "update_playlist": "பாடல் பட்டியலைப் புதுப்பிக்க", - "create": "உருவாக்கு", - "cancel": "ரத்து செய்", - "update": "புதுப்பி", - "playlist_name": "பாடல் பட்டியல் பெயர்", - "name_of_playlist": "பாடல் பட்டியலின் பெயர்", - "description": "விளக்கம்", - "public": "பொது", - "collaborative": "கூட்டு", - "search_local_tracks": "உள்ளூர் பாடல்களைத் தேடுக...", - "play": "இயக்கு", - "delete": "அழி", - "none": "எதுவுமில்லை", - "sort_a_z": "A-Z வரிசைப்படுத்து", - "sort_z_a": "Z-A வரிசைப்படுத்து", - "sort_artist": "கலைஞர் மூலம் வரிசைப்படுத்து", - "sort_album": "ஆல்பம் மூலம் வரிசைப்படுத்து", - "sort_duration": "கால அளவு மூலம் வரிசைப்படுத்து", - "sort_tracks": "பாடல்களை வரிசைப்படுத்து", - "currently_downloading": "தற்போது பதிவிறக்குகிறது ({tracks_length})", - "cancel_all": "அனைத்தையும் ரத்து செய்", - "filter_artist": "கலைஞர்களை வடிகட்டுக...", - "followers": "{followers} பின்தொடர்பவர்கள்", - "add_artist_to_blacklist": "கலைஞரை தடைப்பட்டியலில் சேர்க்க", - "top_tracks": "சிறந்த பாடல்கள்", - "fans_also_like": "ரசிகர்கள் விரும்புவது", - "loading": "ஏற்றுகிறது...", - "artist": "கலைஞர்", - "blacklisted": "தடைப்பட்டியலில் உள்ளது", - "following": "பின்தொடர்கிறது", - "follow": "பின்தொடர்", - "artist_url_copied": "கலைஞர் URL கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது", - "added_to_queue": "{tracks} பாடல்கள் வரிசையில் சேர்க்கப்பட்டன", - "filter_albums": "ஆல்பங்களை வடிகட்டுக...", - "synced": "ஒத்திசைக்கப்பட்டது", - "plain": "சாதாரண", - "shuffle": "கலக்கு", - "search_tracks": "பாடல்களைத் தேடுக...", - "released": "வெளியிடப்பட்டது", - "error": "பிழை {error}", - "title": "தலைப்பு", - "time": "நேரம்", - "more_actions": "மேலும் செயல்கள்", - "download_count": "பதிவிறக்கு ({count})", - "add_count_to_playlist": "({count}) பாடல் பட்டியலில் சேர்", - "add_count_to_queue": "({count}) வரிசையில் சேர்", - "play_count_next": "({count}) அடுத்து இயக்கு", - "album": "ஆல்பம்", - "copied_to_clipboard": "{data} கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது", - "add_to_following_playlists": "{track} பின்வரும் பாடல் பட்டியல்களில் சேர்", - "add": "சேர்", - "added_track_to_queue": "{track} வரிசையில் சேர்க்கப்பட்டது", - "add_to_queue": "வரிசையில் சேர்", - "track_will_play_next": "{track} அடுத்து இயக்கப்படும்", - "play_next": "அடுத்து இயக்கு", - "removed_track_from_queue": "{track} வரிசையிலிருந்து நீக்கப்பட்டது", - "remove_from_queue": "வரிசையிலிருந்து நீக்கு", - "remove_from_favorites": "பிடித்தவையிலிருந்து நீக்கு", - "save_as_favorite": "பிடித்தவையாக சேமி", - "add_to_playlist": "பாடல் பட்டியலில் சேர்", - "remove_from_playlist": "பாடல் பட்டியலிலிருந்து நீக்கு", - "add_to_blacklist": "தடைப்பட்டியலில் சேர்", - "remove_from_blacklist": "தடைப்பட்டியலிலிருந்து நீக்கு", - "share": "பகிர்", - "mini_player": "சிறிய இயக்கி", - "slide_to_seek": "முன்னோக்கி அல்லது பின்னோக்கி செல்ல சறுக்கவும்", - "shuffle_playlist": "பாடல் பட்டியலை கலக்கு", - "unshuffle_playlist": "பாடல் பட்டியலை கலக்காதே", - "previous_track": "முந்தைய பாடல்", - "next_track": "அடுத்த பாடல்", - "pause_playback": "இயக்கத்தை நிறுத்து", - "resume_playback": "இயக்கத்தை தொடர்", - "loop_track": "பாடலை சுழற்று", - "no_loop": "சுழற்சி இல்லை", - "repeat_playlist": "பாடல் பட்டியலை மீண்டும் இயக்கு", - "queue": "வரிசை", - "alternative_track_sources": "மாற்று பாடல் மூலங்கள்", - "download_track": "பாடலைப் பதிவிறக்கு", - "tracks_in_queue": "வரிசையில் {tracks} பாடல்கள்", - "clear_all": "அனைத்தையும் அழி", - "show_hide_ui_on_hover": "மேலே வரும்போது UI ஐக் காட்டு/மறை", - "always_on_top": "எப்போதும் மேலே", - "exit_mini_player": "சிறிய இயக்கியிலிருந்து வெளியேறு", - "download_location": "பதிவிறக்க இடம்", - "local_library": "உள்ளூர் நூலகம்", - "add_library_location": "நூலகத்தில் சேர்", - "remove_library_location": "நூலகத்திலிருந்து நீக்கு", - "account": "கணக்கு", - "login_with_spotify": "உங்கள் Spotify கணக்கில் உள்நுழைக", - "connect_with_spotify": "Spotify உடன் இணைக்கவும்", - "logout": "வெளியேறு", - "logout_of_this_account": "இந்த கணக்கிலிருந்து வெளியேறு", - "language_region": "மொழி & பிராந்தியம்", - "language": "மொழி", - "system_default": "கணினி இயல்புநிலை", - "market_place_region": "சந்தை பிராந்தியம்", - "recommendation_country": "பரிந்துரை நாடு", - "appearance": "தோற்றம்", - "layout_mode": "அமைப்பு முறை", - "override_layout_settings": "தளவமைப்பு அமைப்புகளை மாற்றியமை", - "adaptive": "தகவமைப்பு", - "compact": "சுருக்கமான", - "extended": "விரிவான", - "theme": "தீம்", - "dark": "இருள்", - "light": "வெளிர்", - "system": "கணினி வழி", - "accent_color": "அழுத்த நிறம்", - "sync_album_color": "ஆல்பம் நிறத்தை ஒத்திசை", - "sync_album_color_description": "ஆல்பம் படத்தின் முக்கிய நிறத்தை அழுத்த நிறமாகப் பயன்படுத்துகிறது", - "playback": "பின்னணி", - "audio_quality": "ஒலி தரம்", - "high": "உயர்", - "low": "குறைந்த", - "pre_download_play": "முன்பதிவிறக்கம் மற்றும் இயக்கம்", - "pre_download_play_description": "ஒலியை ஸ்ட்ரீம் செய்வதற்குப் பதிலாக, பைட்டுகளைப் பதிவிறக்கி இயக்கவும் (அதிக பேண்ட்விட்த் பயனர்களுக்கு பரிந்துரைக்கப்படுகிறது)", - "skip_non_music": "இசையல்லாத பகுதிகளைத் தவிர் (SponsorBlock)", - "blacklist_description": "தடைசெய்யப்பட்ட பாடல்கள் மற்றும் கலைஞர்கள்", - "wait_for_download_to_finish": "தற்போதைய பதிவிறக்கம் முடியும் வரை காத்திருக்கவும்", - "desktop": "கணினி", - "close_behavior": "மூடும் நடத்தை", - "close": "மூடு", - "minimize_to_tray": "ட்ரேயை குறைக்கவும்", - "show_tray_icon": "ட்ரே ஐகானைக் காட்டு", - "about": "பற்றி", - "u_love_spotube": "நீங்கள் Spotube ஐ நேசிக்கிறீர்கள் என்பது எங்களுக்குத் தெரியும்", - "check_for_updates": "புதுப்பிப்புகளைச் சரிபார்", - "about_spotube": "Spotube பற்றி", - "blacklist": "தடைப்பட்டியல்", - "please_sponsor": "தயவுசெய்து ஆதரவு/நன்கொடை அளியுங்கள்", - "spotube_description": "Spotube, ஒரு லேசான, பல தளங்களில் இயங்கும், அனைவருக்கும் இலவசமான spotify கிளையன்ட்", - "version": "பதிப்பு", - "build_number": "கட்டமைப்பு எண்", - "founder": "நிறுவனர்", - "repository": "களஞ்சியம்", - "bug_issues": "பிழை_சிக்கல்கள்", - "made_with": "வங்காளதேசத்திலிருந்து🇧🇩 ❤️ உருவாக்கப்பட்டது", - "kingkor_roy_tirtho": "கிங்கர் ராய் திர்தோ", - "copyright": "© 2021-{current_year} கிங்கர் ராய் திர்தோ", - "license": "உரிமம்", - "add_spotify_credentials": "தொடங்குவதற்கு உங்கள் spotify சான்றுகளைச் சேர்க்கவும்", - "credentials_will_not_be_shared_disclaimer": "கவலைப்பட வேண்டாம், உங்கள் சான்றுகள் எதுவும் சேகரிக்கப்படாது அல்லது யாருடனும் பகிரப்படாது", - "know_how_to_login": "இதை எப்படி செய்வது என்று தெரியவில்லையா?", - "follow_step_by_step_guide": "படிப்படியான வழிகாட்டியைப் பின்பற்றவும்", - "spotify_cookie": "Spotify {name} நட்புநிரல்", - "cookie_name_cookie": "{name} நட்புநிரல்", - "fill_in_all_fields": "அனைத்து களங்களையும் நிரப்பவும்", - "submit": "சமர்ப்பி", - "exit": "வெளியேறு", - "previous": "முந்தைய", - "next": "அடுத்து", - "done": "முடிந்தது", - "step_1": "முதல் படி", - "first_go_to": "முதலில், செல்லவேண்டியது", - "login_if_not_logged_in": "நீங்கள் உள்நுழையவில்லை என்றால் உள்நுழைக/பதிவுசெய்க", - "step_2": "இரண்டாம் படி", - "step_2_steps": "1. நீங்கள் உள்நுழைந்தவுடன், F12 ஐ அழுத்தவும் அல்லது வலது கிளிக் செய்து > ஆய்வு செய்யவும் உலாவி டெவ்டூல்களைத் திறக்கவும்.\n2. பின்னர் \"பயன்பாடு\" தாவலுக்குச் செல்லவும் (Chrome, Edge, Brave போன்றவை) அல்லது \"சேமிப்பகம்\" தாவல் (Firefox, Palemoon போன்றவை)\n3. \"குக்கிகள்\" பிரிவுக்குச் சென்று பின்னர் \"https://accounts.spotify.com\" பிரிவுக்குச் செல்லவும்", - "step_3": "மூன்றாம் படி", - "step_3_steps": "\"sp_dc\" நட்புநிரலின் மதிப்பை நகலெடுக்கவும்", - "success_emoji": "வெற்றி🥳", - "success_message": "இப்போது நீங்கள் உங்கள் Spotify கணக்கில் வெற்றிகரமாக உள்நுழைந்துள்ளீர்கள். நல்லது, நண்பரே!", - "step_4": "நான்காம் படி", - "step_4_steps": "நகலெடுக்கப்பட்ட \"sp_dc\" மதிப்பை ஒட்டவும்", - "something_went_wrong": "ஏதோ தவறு நடந்துவிட்டது", - "piped_instance": "Piped சேவையகம் நிகழ்வு", - "piped_description": "பாடல் பொருத்தத்திற்குப் பயன்படுத்த வேண்டிய Piped சேவையகம் நிகழ்வு", - "piped_warning": "அவற்றில் சில நன்றாக வேலை செய்யாமல் இருக்கலாம். எனவே உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்", - "invidious_instance": "Invidious சேவையக நிகழ்வு", - "invidious_description": "பாடல் பொருத்தத்திற்குப் பயன்படுத்த வேண்டிய Invidious சேவையக நிகழ்வு", - "invidious_warning": "அவற்றில் சில நன்றாக வேலை செய்யாமல் இருக்கலாம். எனவே உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்", - "generate": "உருவாக்கு", - "track_exists": "பாடல் {track} ஏற்கனவே உள்ளது", - "replace_downloaded_tracks": "பதிவிறக்கம் செய்யப்பட்ட அனைத்து பாடல்களையும் மாற்றவும்", - "skip_download_tracks": "பதிவிறக்கம் செய்யப்பட்ட அனைத்து பாடல்களையும் தவிர்க்கவும்", - "do_you_want_to_replace": "ஏற்கனவே உள்ள பாடலை மாற்ற விரும்புகிறீர்களா?", - "replace": "மாற்று", - "skip": "தவிர்", - "select_up_to_count_type": "{count} {type} வரை தேர்ந்தெடுக்கவும்", - "select_genres": "வகைகளைத் தேர்ந்தெடுக்கவும்", - "add_genres": "வகைகளைச் சேர்க்கவும்", - "country": "நாடு", - "number_of_tracks_generate": "உருவாக்க வேண்டிய பாடல்களின் எண்ணிக்கை", - "acousticness": "அகவுஸ்டிக்னெஸ்", - "danceability": "நடனத்தன்மை", - "energy": "ஆற்றல்", - "instrumentalness": "கருவித்தன்மை", - "liveness": "உயிர்ப்புத்தன்மை", - "loudness": "ஒலி அளவு", - "speechiness": "பேச்சுத்தன்மை", - "valence": "உணர்வு", - "popularity": "பிரபலம்", - "key": "இசை குறிப்பு", - "duration": "கால அளவு (வினாடிகள்)", - "tempo": "வேகம் (BPM)", - "mode": "முறை", - "time_signature": "நேர கையொப்பம்", - "short": "குறுகிய", - "medium": "நடுத்தர", - "long": "நீண்ட", - "min": "குறைந்தபட்சம்", - "max": "அதிகபட்சம்", - "target": "இலக்கு", - "moderate": "மிதமான", - "deselect_all": "அனைத்தையும் தேர்வுநீக்கு", - "select_all": "அனைத்தையும் தேர்ந்தெடு", - "are_you_sure": "உறுதியாக இருக்கிறீர்களா?", - "generating_playlist": "உங்கள் தனிப்பயன்பாட்டிற்கான பாடல் பட்டியலை உருவாக்குகிறது...", - "selected_count_tracks": "{count} பாடல்கள் தேர்ந்தெடுக்கப்பட்டன", - "download_warning": "நீங்கள் அனைத்து பாடல்களையும் மொத்தமாக பதிவிறக்கினால், நீங்கள் தெளிவாக இசையைத் திருடுகிறீர்கள் மற்றும் இசையின் படைப்பாற்றல் சமூகத்திற்கு சேதம் விளைவிக்கிறீர்கள். நீங்கள் இதை அறிந்திருக்கிறீர்கள் என்று நம்புகிறேன். எப்போதும், கலைஞரின் கடின உழைப்பை மதித்து ஆதரிக்க முயற்சி செய்யுங்கள்", - "download_ip_ban_warning": "மேலும், அதிகப்படியான பதிவிறக்க கோரிக்கைகள் காரணமாக உங்கள் IP YouTube இல் தடைசெய்யப்படலாம். IP தடை என்பது குறைந்தது 2-3 மாதங்களுக்கு அந்த IP சாதனத்திலிருந்து YouTube ஐப் பயன்படுத்த முடியாது (நீங்கள் உள்நுழைந்திருந்தாலும் கூட). இது ஒருபோதும் நடந்தால் Spotube பொறுப்பேற்காது", - "by_clicking_accept_terms": "'ஏற்றுக்கொள்' என்பதைக் கிளிக் செய்வதன் மூலம் பின்வரும் விதிமுறைகளுக்கு நீங்கள் ஒப்புக்கொள்கிறீர்கள்:", - "download_agreement_1": "நான் இசையைத் திருடுகிறேன் என்பது எனக்குத் தெரியும். நான் கெட்டவன்", - "download_agreement_2": "நான் கலைஞரை முடிந்தவரை ஆதரிப்பேன், அவர்களின் கலைக்கு பணம் செலுத்த எனக்கு பணம் இல்லாததால் மட்டுமே இதைச் செய்கிறேன்", - "download_agreement_3": "என் IP YouTube இல் தடைசெய்யப்படலாம் என்பதை நான் முழுமையாக அறிவேன், மேலும் என் தற்போதைய செயலால் ஏற்படும் எந்த விபத்துகளுக்கும் Spotube அல்லது அதன் உரிமையாளர்கள்/பங்களிப்பாளர்களை பொறுப்பாக்க மாட்டேன்", - "decline": "மறு", - "accept": "ஏற்றுக்கொள்", - "details": "விவரங்கள்", - "youtube": "YouTube", - "channel": "சேனல்", - "likes": "விருப்பங்கள்", - "dislikes": "விருப்பமில்லாதவை", - "views": "பார்வைகள்", - "streamUrl": "ஸ்ட்ரீம் URL", - "stop": "நிறுத்து", - "sort_newest": "புதிதாக சேர்க்கப்பட்டவற்றை வரிசைப்படுத்து", - "sort_oldest": "பழமையானவற்றை வரிசைப்படுத்து", - "sleep_timer": "உறக்க நேரம்", - "mins": "{minutes} நிமிடங்கள்", - "hours": "{hours} மணிநேரங்கள்", - "hour": "{hours} மணிநேரம்", - "custom_hours": "தனிப்பயன் மணிநேரங்கள்", - "logs": "பதிவுகள்", - "developers": "உருவாக்குநர்கள்", - "not_logged_in": "நீங்கள் உள்நுழையவில்லை", - "search_mode": "தேடல் முறை", - "audio_source": "ஒலி மூலம்", - "ok": "சரி", - "failed_to_encrypt": "குறியாக்கம் தோல்வியடைந்தது", - "encryption_failed_warning": "Spotube உங்கள் தரவை பாதுகாப்பாக சேமிக்க குறியாக்கத்தைப் பயன்படுத்துகிறது. ஆனால் அவ்வாறு செய்ய முடியவில்லை. எனவே இது பாதுகாப்பற்ற சேமிப்பகத்திற்கு மாறும்\nநீங்கள் லினக்ஸ் பயன்படுத்துகிறீர்கள் என்றால், எந்த ரகசிய சேவையும் (gnome-keyring, kde-wallet, keepassxc போன்றவை) நிறுவப்பட்டுள்ளதா என்பதை உறுதிப்படுத்தவும்", - "querying_info": "தகவலைக் கேட்கிறது...", - "piped_api_down": "Piped API செயலிழந்துள்ளது", - "piped_down_error_instructions": "Piped நிகழ்வு {pipedInstance} தற்போது செயலிழந்துள்ளது\n\nநிகழ்வை மாற்றவும் அல்லது 'API வகை'யை அதிகாரப்பூர்வ YouTube API க்கு மாற்றவும்\n\nமாற்றத்திற்குப் பிறகு பயன்பாட்டை மறுதொடக்கம் செய்வதை உறுதிப்படுத்தவும்", - "you_are_offline": "நீங்கள் தற்போது ஆஃப்லைனில் உள்ளீர்கள்", - "connection_restored": "உங்கள் இணைய இணைப்பு மீட்டெடுக்கப்பட்டது", - "use_system_title_bar": "கணினி தலைப்புப் பட்டியைப் பயன்படுத்தவும்", - "crunching_results": "முடிவுகளை செயலாக்குகிறது...", - "search_to_get_results": "முடிவுகளைப் பெற தேடவும்", - "use_amoled_mode": "கருமை நிற இருண்ட தீம்", - "pitch_dark_theme": "AMOLED முறை", - "normalize_audio": "ஒலியை சீரமை", - "change_cover": "அட்டையை மாற்று", - "add_cover": "அட்டையைச் சேர்", - "restore_defaults": "இயல்புநிலைகளை மீட்டமை", - "download_music_codec": "இசை கோடெக்கை பதிவிறக்கு", - "streaming_music_codec": "இசை கோடெக்கை ஸ்ட்ரீம் செய்", - "login_with_lastfm": "Last.fm உடன் உள்நுழைக", - "connect": "இணை", - "disconnect_lastfm": "Last.fm இலிருந்து துண்டி", - "disconnect": "துண்டி", - "username": "பயனர்பெயர்", - "password": "கடவுச்சொல்", - "login": "உள்நுழைக", - "login_with_your_lastfm": "உங்கள் Last.fm கணக்குடன் உள்நுழைக", - "scrobble_to_lastfm": "Last.fm க்கு ஸ்க்ரோபிள் செய்", - "go_to_album": "ஆல்பத்திற்குச் செல்", - "discord_rich_presence": "Discord செழுமையான தோற்றம்", - "browse_all": "அனைத்தையும் உலாவு", - "genres": "வகைகள்", - "explore_genres": "வகைகளை ஆராயுங்கள்", - "friends": "நண்பர்கள்", - "no_lyrics_available": "மன்னிக்கவும், இந்தப் பாடலுக்கான பாடல் வரிகளைக் கண்டுபிடிக்க முடியவில்லை", - "start_a_radio": "வானொலியைத் தொடங்கு", - "how_to_start_radio": "வானொலியை எவ்வாறு தொடங்க விரும்புகிறீர்கள்?", - "replace_queue_question": "தற்போதைய வரிசையை மாற்ற விரும்புகிறீர்களா அல்லது அதனுடன் சேர்க்க விரும்புகிறீர்களா?", - "endless_playback": "முடிவற்ற இயக்கம்", - "delete_playlist": "பாடல் பட்டியலை நீக்கு", - "delete_playlist_confirmation": "இந்த பாடல் பட்டியலை நீக்க விரும்புகிறீர்களா?", - "local_tracks": "உள்ளூர் பாடல்கள்", - "local_tab": "உள்ளூர்", - "song_link": "பாடல் இணைப்பு", - "skip_this_nonsense": "இந்த அர்த்தமற்றதைத் தவிர்", - "freedom_of_music": "\"இசையின் சுதந்திரம்\"", - "freedom_of_music_palm": "\"உங்கள் கைகளில் இசையின் சுதந்திரம்\"", - "get_started": "தொடங்குவோம்", - "youtube_source_description": "பரிந்துரைக்கப்படுகிறது மற்றும் சிறப்பாக செயல்படுகிறது.", - "piped_source_description": "சுதந்திரமாக உணர்கிறீர்களா? YouTube போலவே ஆனால் மிகவும் சுதந்திரமானது.", - "jiosaavn_source_description": "தெற்காசியப் பிராந்தியத்திற்கு சிறந்தது.", - "invidious_source_description": "Piped ஐப் போன்றது ஆனால் அதிக கிடைக்கும் தன்மையுடன்.", - "highest_quality": "உயர்ந்த தரம்: {quality}", - "select_audio_source": "ஒலி மூலத்தைத் தேர்ந்தெடுக்கவும்", - "endless_playback_description": "வரிசையின் இறுதியில் புதிய பாடல்களை\nதானாகவே சேர்க்கவும்", - "choose_your_region": "உங்கள் பிராந்தியத்தைத் தேர்ந்தெடுக்கவும்", - "choose_your_region_description": "இது உங்கள் இருப்பிடத்திற்கான சரியான உள்ளடக்கத்தை\nSpotube காட்ட உதவும்.", - "choose_your_language": "உங்கள் மொழியைத் தேர்ந்தெடுக்கவும்", - "help_project_grow": "இந்த திட்டம் வளர உதவுங்கள்", - "help_project_grow_description": "Spotube ஒரு திறந்த மூல திட்டம். திட்டத்திற்கு பங்களிப்பு செய்வதன் மூலம், பிழைகளைப் புகாரளிப்பதன் மூலம் அல்லது புதிய அம்சங்களைப் பரிந்துரைப்பதன் மூலம் இந்தத் திட்டம் வளர உதவலாம்.", - "contribute_on_github": "GitHub இல் பங்களியுங்கள்", - "donate_on_open_collective": "Open Collective இல் நன்கொடை அளியுங்கள்", - "browse_anonymously": "அநாமதேயமாக உலாவுக", - "enable_connect": "இணைப்பை இயக்கு", - "enable_connect_description": "மற்ற சாதனங்களிலிருந்து Spotube ஐக் கட்டுப்படுத்தவும்", - "devices": "சாதனங்கள்", - "select": "தேர்ந்தெடு", - "connect_client_alert": "நீங்கள் {client} ஆல் கட்டுப்படுத்தப்படுகிறீர்கள்", - "this_device": "இந்த சாதனம்", - "remote": "தொலைநிலை", - "stats": "புள்ளிவிவரங்கள்", - "and_n_more": "மற்றும் {count} கூடுதலாக", - "recently_played": "சமீபத்தில் இயக்கியவை", - "browse_more": "மேலும் உலாவு", - "no_title": "தலைப்பு இல்லை", - "not_playing": "இயக்கப்படவில்லை", - "epic_failure": "மோசமான தோல்வி!", - "added_num_tracks_to_queue": "{tracks_length} பாடல்கள் வரிசையில் சேர்க்கப்பட்டன", - "spotube_has_an_update": "Spotube க்கு ஒரு புதுப்பிப்பு உள்ளது", - "download_now": "இப்போது பதிவிறக்கு", - "nightly_version": "Spotube Nightly {nightlyBuildNum} வெளியிடப்பட்டுள்ளது", - "release_version": "Spotube v{version} வெளியிடப்பட்டுள்ளது", - "read_the_latest": "சமீபத்திய ", - "release_notes": "வெளியீட்டு குறிப்புகளைப் படிக்கவும்", - "pick_color_scheme": "வண்ணத் திட்டத்தைத் தேர்ந்தெடுக்கவும்", - "save": "சேமி", - "choose_the_device": "சாதனத்தைத் தேர்ந்தெடுக்கவும்:", - "multiple_device_connected": "பல சாதனங்கள் இணைக்கப்பட்டுள்ளன.\nஇந்த செயல் நடைபெற வேண்டிய சாதனத்தைத் தேர்ந்தெடுக்கவும்", - "nothing_found": "எதுவும் கிடைக்கவில்லை", - "the_box_is_empty": "பெட்டி காலியாக உள்ளது", - "top_artists": "சிறந்த கலைஞர்கள்", - "top_albums": "சிறந்த ஆல்பங்கள்", - "this_week": "இந்த வாரம்", - "this_month": "இந்த மாதம்", - "last_6_months": "கடந்த 6 மாதங்கள்", - "this_year": "இந்த ஆண்டு", - "last_2_years": "கடந்த 2 ஆண்டுகள்", - "all_time": "எல்லா நேரமும்", - "powered_by_provider": "{providerName} ஆல் இயக்கப்படுகிறது", - "email": "மின்னஞ்சல்", - "profile_followers": "பின்தொடர்பவர்கள்", - "birthday": "பிறந்த நாள்", - "subscription": "சந்தா", - "not_born": "பிறக்கவில்லை", - "hacker": "ஹேக்கர்", - "profile": "சுயவிவரம்", - "no_name": "பெயர் இல்லை", - "edit": "திருத்து", - "user_profile": "பயனர் சுயவிவரம்", - "count_plays": "{count} முறை இசைக்கப்பட்டது", - "streaming_fees_hypothetical": "ஸ்ட்ரீமிங் கட்டணங்கள் (கற்பனை)", - "minutes_listened": "காலம் கேட்டது", - "streamed_songs": "ஸ்ட்ரீமிங் செய்யப்பட்ட பாடல்கள்", - "count_streams": "{count} ஸ்ட்ரீம்கள்", - "owned_by_you": "உங்களால் கொண்டது", - "copied_shareurl_to_clipboard": "நகலெடுக்கப்பட்டது {shareUrl} கிளிப்போர்டுக்காக", - "spotify_hipotetical_calculation": "*இது Spotify இன் ஒவ்வொரு ஸ்ட்ரீமிற்கும்\n$0.003 முதல் $0.005 வரை அளவீடு அடிப்படையில் கணக்கிடப்படுகிறது. இது ஒரு கற்பனை\nகணக்கீடு ஆகும், பயனர் எந்த அளவிற்கு கலைஞர்களுக்கு\nஅதோர் பாடலை Spotify மென்பொருளில் கேட்டால் எவ்வளவு பணம் செலுத்தினார்கள் என்பதைக் கண்டுபிடிக்க.", - "count_mins": "{minutes} நிமிடங்கள்", - "summary_minutes": "நிமிடங்கள்", - "summary_listened_to_music": "இசை கேட்டது", - "summary_songs": "பாடல்கள்", - "summary_streamed_overall": "மொத்தமாக ஸ்ட்ரீமிங்", - "summary_owed_to_artists": "கலைஞர்களுக்கு\nஇந்த மாதம் சொந்தமானது", - "summary_artists": "கலைஞர்கள்", - "summary_music_reached_you": "இசை உங்களுக்கு வந்தது", - "summary_full_albums": "முழு ஆல்பங்கள்", - "summary_got_your_love": "உங்கள் அன்பை பெற்றுக்கொண்டேன்", - "summary_playlists": "பாடல் பட்டியல்கள்", - "summary_were_on_repeat": "மீண்டும் மீண்டும் இருந்தன", - "total_money": "மொத்தம் {money}", - "webview_not_found": "வெப்வியூ கிடைக்கவில்லை", - "webview_not_found_description": "உங்கள் சாதனத்தில் எந்தவொரு வெப்வியூ இயக்கத்தை நிறுவவில்லை.\nஇது நிறுவப்பட்டிருந்தால், சுற்றுச்சூழல் பாதையில் PATH உள்ளது என்பதை உறுதிபடுத்தவும்\n\nநிறுவித்த பிறகு, செயலியை மறுதொடக்கம் செய்யவும்", - "unsupported_platform": "அதிர்ஷ்டகாத உருப்படியை ஆதரிக்கவில்லை", - "cache_music": "இசையை கேஷ் செய்", - "open": "திறக்கவும்", - "cache_folder": "கேஷ் அடைவு", - "export": "ஏற்றுமதி", - "clear_cache": "கேஷ் அழிக்கவும்", - "clear_cache_confirmation": "கேஷைப் அழிக்க விரும்புகிறீர்களா?", - "export_cache_files": "கேஷில் உள்ள கோப்புகளை ஏற்றுமதி செய்யவும்", - "found_n_files": "{count} கோப்புகள் கிடைத்தன", - "export_cache_confirmation": "இந்த கோப்புகளை ஏற்றுமதி செய்ய விரும்புகிறீர்களா?", - "exported_n_out_of_m_files": "{filesExported} கோப்புகள் ஏற்றுமதி செய்யப்பட்டன, {files} கோப்புகளில்", - "undo": "செயல்தவிர்", - "download_all": "அனைத்தையும் பதிவிறக்குக", - "add_all_to_playlist": "அனைத்தையும் பாடல் பட்டியலில் சேர்க்கவும்", - "add_all_to_queue": "அனைத்தையும் வரிசைப்படுத்து", - "play_all_next": "அடுத்த உள்ள அனைத்தையும் இயக்கு", - "pause": "நிறுத்து", - "view_all": "அனைத்தையும் காண்க", - "no_tracks_added_yet": "உங்கள் பாடல்களை இன்னும் சேர்க்கவில்லை என்றால் தெரியாதே", - "no_tracks": "இங்கு பாடல்கள் எதுவும் இல்லை", - "no_tracks_listened_yet": "இன்னும் எதையும் கேள்வியில்லை", - "not_following_artists": "நீங்கள் எந்த கலைஞரையும் பின்தொடரவில்லை", - "no_favorite_albums_yet": "நீங்கள் இன்னும் எந்த ஆல்பங்களையும் பிடித்தவையாகச் சேர்க்கவில்லை", - "no_logs_found": "பதிவுகள் எதுவும் கிடைக்கவில்லை", - "youtube_engine": "YouTube இயந்திரம்", - "youtube_engine_not_installed_title": "{engine} நிறுவியதில்லை", - "youtube_engine_not_installed_message": "{engine} உங்கள் கணினியில் நிறுவியதில்லை.", - "youtube_engine_set_path": "PATH மாறியில் கிடைக்கிறதா என்பதை உறுதிப்படுத்தவும் அல்லது\n{engine} செயல் செய்யக்கூடிய முறையை கீழே அமைக்கவும்", - "youtube_engine_unix_issue_message": "macOS/Linux/unix போல் OS இல், .zshrc/.bashrc/.bash_profile போன்றவை அமைப்பில் பாதையை PATH அமைப்பது இயலாது.\nநீங்கள்.shell configuration file இல் பாதையை அமைக்க வேண்டும்", - "download": "பதிவிறக்கு", - "file_not_found": "கோப்பு கிடைக்கவில்லை", - "custom": "தனிப்பயன்", - "add_custom_url": "தனிப்பயன் URL ஐச் சேர்க்கவும்" + "guest": "விருந்தினர்", + "browse": "உலாவு", + "search": "தேடுக", + "library": "நூலகம்", + "lyrics": "பாடல் வரிகள்", + "settings": "அமைப்புகள்", + "genre_categories_filter": "வகைகள் அல்லது பாணிகளை வடிகட்டுக...", + "genre": "பாணி", + "personalized": "தனிப்பயனாக்கப்பட்ட", + "featured": "சிறப்பிடம் பெற்ற", + "new_releases": "புதிய வெளியீடுகள்", + "songs": "பாடல்கள்", + "playing_track": "{track} இயங்குகிறது", + "queue_clear_alert": "இது தற்போதைய வரிசையை அழிக்கும். {track_length} பாடல்கள் நீக்கப்படும்\nதொடர விரும்புகிறீர்களா?", + "load_more": "மேலும் ஏற்றுக", + "playlists": "பாடல் பட்டியல்கள்", + "artists": "கலைஞர்கள்", + "albums": "ஆல்பங்கள்", + "tracks": "பாடல்கள்", + "downloads": "பதிவிறக்கங்கள்", + "filter_playlists": "உங்கள் பாடல் பட்டியல்களை வடிகட்டுக...", + "liked_tracks": "விரும்பிய பாடல்கள்", + "liked_tracks_description": "உங்கள் விரும்பிய பாடல்கள் அனைத்தும்", + "playlist": "பாடல் பட்டியல்", + "create_a_playlist": "பாடல் பட்டியலை உருவாக்குக", + "update_playlist": "பாடல் பட்டியலைப் புதுப்பிக்க", + "create": "உருவாக்கு", + "cancel": "ரத்து செய்", + "update": "புதுப்பி", + "playlist_name": "பாடல் பட்டியல் பெயர்", + "name_of_playlist": "பாடல் பட்டியலின் பெயர்", + "description": "விளக்கம்", + "public": "பொது", + "collaborative": "கூட்டு", + "search_local_tracks": "உள்ளூர் பாடல்களைத் தேடுக...", + "play": "இயக்கு", + "delete": "அழி", + "none": "எதுவுமில்லை", + "sort_a_z": "A-Z வரிசைப்படுத்து", + "sort_z_a": "Z-A வரிசைப்படுத்து", + "sort_artist": "கலைஞர் மூலம் வரிசைப்படுத்து", + "sort_album": "ஆல்பம் மூலம் வரிசைப்படுத்து", + "sort_duration": "கால அளவு மூலம் வரிசைப்படுத்து", + "sort_tracks": "பாடல்களை வரிசைப்படுத்து", + "currently_downloading": "தற்போது பதிவிறக்குகிறது ({tracks_length})", + "cancel_all": "அனைத்தையும் ரத்து செய்", + "filter_artist": "கலைஞர்களை வடிகட்டுக...", + "followers": "{followers} பின்தொடர்பவர்கள்", + "add_artist_to_blacklist": "கலைஞரை தடைப்பட்டியலில் சேர்க்க", + "top_tracks": "சிறந்த பாடல்கள்", + "fans_also_like": "ரசிகர்கள் விரும்புவது", + "loading": "ஏற்றுகிறது...", + "artist": "கலைஞர்", + "blacklisted": "தடைப்பட்டியலில் உள்ளது", + "following": "பின்தொடர்கிறது", + "follow": "பின்தொடர்", + "artist_url_copied": "கலைஞர் URL கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது", + "added_to_queue": "{tracks} பாடல்கள் வரிசையில் சேர்க்கப்பட்டன", + "filter_albums": "ஆல்பங்களை வடிகட்டுக...", + "synced": "ஒத்திசைக்கப்பட்டது", + "plain": "சாதாரண", + "shuffle": "கலக்கு", + "search_tracks": "பாடல்களைத் தேடுக...", + "released": "வெளியிடப்பட்டது", + "error": "பிழை {error}", + "title": "தலைப்பு", + "time": "நேரம்", + "more_actions": "மேலும் செயல்கள்", + "download_count": "பதிவிறக்கு ({count})", + "add_count_to_playlist": "({count}) பாடல் பட்டியலில் சேர்", + "add_count_to_queue": "({count}) வரிசையில் சேர்", + "play_count_next": "({count}) அடுத்து இயக்கு", + "album": "ஆல்பம்", + "copied_to_clipboard": "{data} கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது", + "add_to_following_playlists": "{track} பின்வரும் பாடல் பட்டியல்களில் சேர்", + "add": "சேர்", + "added_track_to_queue": "{track} வரிசையில் சேர்க்கப்பட்டது", + "add_to_queue": "வரிசையில் சேர்", + "track_will_play_next": "{track} அடுத்து இயக்கப்படும்", + "play_next": "அடுத்து இயக்கு", + "removed_track_from_queue": "{track} வரிசையிலிருந்து நீக்கப்பட்டது", + "remove_from_queue": "வரிசையிலிருந்து நீக்கு", + "remove_from_favorites": "பிடித்தவையிலிருந்து நீக்கு", + "save_as_favorite": "பிடித்தவையாக சேமி", + "add_to_playlist": "பாடல் பட்டியலில் சேர்", + "remove_from_playlist": "பாடல் பட்டியலிலிருந்து நீக்கு", + "add_to_blacklist": "தடைப்பட்டியலில் சேர்", + "remove_from_blacklist": "தடைப்பட்டியலிலிருந்து நீக்கு", + "share": "பகிர்", + "mini_player": "சிறிய இயக்கி", + "slide_to_seek": "முன்னோக்கி அல்லது பின்னோக்கி செல்ல சறுக்கவும்", + "shuffle_playlist": "பாடல் பட்டியலை கலக்கு", + "unshuffle_playlist": "பாடல் பட்டியலை கலக்காதே", + "previous_track": "முந்தைய பாடல்", + "next_track": "அடுத்த பாடல்", + "pause_playback": "இயக்கத்தை நிறுத்து", + "resume_playback": "இயக்கத்தை தொடர்", + "loop_track": "பாடலை சுழற்று", + "no_loop": "சுழற்சி இல்லை", + "repeat_playlist": "பாடல் பட்டியலை மீண்டும் இயக்கு", + "queue": "வரிசை", + "alternative_track_sources": "மாற்று பாடல் மூலங்கள்", + "download_track": "பாடலைப் பதிவிறக்கு", + "tracks_in_queue": "வரிசையில் {tracks} பாடல்கள்", + "clear_all": "அனைத்தையும் அழி", + "show_hide_ui_on_hover": "மேலே வரும்போது UI ஐக் காட்டு/மறை", + "always_on_top": "எப்போதும் மேலே", + "exit_mini_player": "சிறிய இயக்கியிலிருந்து வெளியேறு", + "download_location": "பதிவிறக்க இடம்", + "local_library": "உள்ளூர் நூலகம்", + "add_library_location": "நூலகத்தில் சேர்", + "remove_library_location": "நூலகத்திலிருந்து நீக்கு", + "account": "கணக்கு", + "login_with_spotify": "உங்கள் Spotify கணக்கில் உள்நுழைக", + "connect_with_spotify": "Spotify உடன் இணைக்கவும்", + "logout": "வெளியேறு", + "logout_of_this_account": "இந்த கணக்கிலிருந்து வெளியேறு", + "language_region": "மொழி & பிராந்தியம்", + "language": "மொழி", + "system_default": "கணினி இயல்புநிலை", + "market_place_region": "சந்தை பிராந்தியம்", + "recommendation_country": "பரிந்துரை நாடு", + "appearance": "தோற்றம்", + "layout_mode": "அமைப்பு முறை", + "override_layout_settings": "தளவமைப்பு அமைப்புகளை மாற்றியமை", + "adaptive": "தகவமைப்பு", + "compact": "சுருக்கமான", + "extended": "விரிவான", + "theme": "தீம்", + "dark": "இருள்", + "light": "வெளிர்", + "system": "கணினி வழி", + "accent_color": "அழுத்த நிறம்", + "sync_album_color": "ஆல்பம் நிறத்தை ஒத்திசை", + "sync_album_color_description": "ஆல்பம் படத்தின் முக்கிய நிறத்தை அழுத்த நிறமாகப் பயன்படுத்துகிறது", + "playback": "பின்னணி", + "audio_quality": "ஒலி தரம்", + "high": "உயர்", + "low": "குறைந்த", + "pre_download_play": "முன்பதிவிறக்கம் மற்றும் இயக்கம்", + "pre_download_play_description": "ஒலியை ஸ்ட்ரீம் செய்வதற்குப் பதிலாக, பைட்டுகளைப் பதிவிறக்கி இயக்கவும் (அதிக பேண்ட்விட்த் பயனர்களுக்கு பரிந்துரைக்கப்படுகிறது)", + "skip_non_music": "இசையல்லாத பகுதிகளைத் தவிர் (SponsorBlock)", + "blacklist_description": "தடைசெய்யப்பட்ட பாடல்கள் மற்றும் கலைஞர்கள்", + "wait_for_download_to_finish": "தற்போதைய பதிவிறக்கம் முடியும் வரை காத்திருக்கவும்", + "desktop": "கணினி", + "close_behavior": "மூடும் நடத்தை", + "close": "மூடு", + "minimize_to_tray": "ட்ரேயை குறைக்கவும்", + "show_tray_icon": "ட்ரே ஐகானைக் காட்டு", + "about": "பற்றி", + "u_love_spotube": "நீங்கள் Spotube ஐ நேசிக்கிறீர்கள் என்பது எங்களுக்குத் தெரியும்", + "check_for_updates": "புதுப்பிப்புகளைச் சரிபார்", + "about_spotube": "Spotube பற்றி", + "blacklist": "தடைப்பட்டியல்", + "please_sponsor": "தயவுசெய்து ஆதரவு/நன்கொடை அளியுங்கள்", + "spotube_description": "Spotube, ஒரு லேசான, பல தளங்களில் இயங்கும், அனைவருக்கும் இலவசமான spotify கிளையன்ட்", + "version": "பதிப்பு", + "build_number": "கட்டமைப்பு எண்", + "founder": "நிறுவனர்", + "repository": "களஞ்சியம்", + "bug_issues": "பிழை_சிக்கல்கள்", + "made_with": "வங்காளதேசத்திலிருந்து🇧🇩 ❤️ உருவாக்கப்பட்டது", + "kingkor_roy_tirtho": "கிங்கர் ராய் திர்தோ", + "copyright": "© 2021-{current_year} கிங்கர் ராய் திர்தோ", + "license": "உரிமம்", + "add_spotify_credentials": "தொடங்குவதற்கு உங்கள் spotify சான்றுகளைச் சேர்க்கவும்", + "credentials_will_not_be_shared_disclaimer": "கவலைப்பட வேண்டாம், உங்கள் சான்றுகள் எதுவும் சேகரிக்கப்படாது அல்லது யாருடனும் பகிரப்படாது", + "know_how_to_login": "இதை எப்படி செய்வது என்று தெரியவில்லையா?", + "follow_step_by_step_guide": "படிப்படியான வழிகாட்டியைப் பின்பற்றவும்", + "spotify_cookie": "Spotify {name} நட்புநிரல்", + "cookie_name_cookie": "{name} நட்புநிரல்", + "fill_in_all_fields": "அனைத்து களங்களையும் நிரப்பவும்", + "submit": "சமர்ப்பி", + "exit": "வெளியேறு", + "previous": "முந்தைய", + "next": "அடுத்து", + "done": "முடிந்தது", + "step_1": "முதல் படி", + "first_go_to": "முதலில், செல்லவேண்டியது", + "login_if_not_logged_in": "நீங்கள் உள்நுழையவில்லை என்றால் உள்நுழைக/பதிவுசெய்க", + "step_2": "இரண்டாம் படி", + "step_2_steps": "1. நீங்கள் உள்நுழைந்தவுடன், F12 ஐ அழுத்தவும் அல்லது வலது கிளிக் செய்து > ஆய்வு செய்யவும் உலாவி டெவ்டூல்களைத் திறக்கவும்.\n2. பின்னர் \"பயன்பாடு\" தாவலுக்குச் செல்லவும் (Chrome, Edge, Brave போன்றவை) அல்லது \"சேமிப்பகம்\" தாவல் (Firefox, Palemoon போன்றவை)\n3. \"குக்கிகள்\" பிரிவுக்குச் சென்று பின்னர் \"https://accounts.spotify.com\" பிரிவுக்குச் செல்லவும்", + "step_3": "மூன்றாம் படி", + "step_3_steps": "\"sp_dc\" நட்புநிரலின் மதிப்பை நகலெடுக்கவும்", + "success_emoji": "வெற்றி🥳", + "success_message": "இப்போது நீங்கள் உங்கள் Spotify கணக்கில் வெற்றிகரமாக உள்நுழைந்துள்ளீர்கள். நல்லது, நண்பரே!", + "step_4": "நான்காம் படி", + "step_4_steps": "நகலெடுக்கப்பட்ட \"sp_dc\" மதிப்பை ஒட்டவும்", + "something_went_wrong": "ஏதோ தவறு நடந்துவிட்டது", + "piped_instance": "Piped சேவையகம் நிகழ்வு", + "piped_description": "பாடல் பொருத்தத்திற்குப் பயன்படுத்த வேண்டிய Piped சேவையகம் நிகழ்வு", + "piped_warning": "அவற்றில் சில நன்றாக வேலை செய்யாமல் இருக்கலாம். எனவே உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்", + "invidious_instance": "Invidious சேவையக நிகழ்வு", + "invidious_description": "பாடல் பொருத்தத்திற்குப் பயன்படுத்த வேண்டிய Invidious சேவையக நிகழ்வு", + "invidious_warning": "அவற்றில் சில நன்றாக வேலை செய்யாமல் இருக்கலாம். எனவே உங்கள் சொந்த ஆபத்தில் பயன்படுத்தவும்", + "generate": "உருவாக்கு", + "track_exists": "பாடல் {track} ஏற்கனவே உள்ளது", + "replace_downloaded_tracks": "பதிவிறக்கம் செய்யப்பட்ட அனைத்து பாடல்களையும் மாற்றவும்", + "skip_download_tracks": "பதிவிறக்கம் செய்யப்பட்ட அனைத்து பாடல்களையும் தவிர்க்கவும்", + "do_you_want_to_replace": "ஏற்கனவே உள்ள பாடலை மாற்ற விரும்புகிறீர்களா?", + "replace": "மாற்று", + "skip": "தவிர்", + "select_up_to_count_type": "{count} {type} வரை தேர்ந்தெடுக்கவும்", + "select_genres": "வகைகளைத் தேர்ந்தெடுக்கவும்", + "add_genres": "வகைகளைச் சேர்க்கவும்", + "country": "நாடு", + "number_of_tracks_generate": "உருவாக்க வேண்டிய பாடல்களின் எண்ணிக்கை", + "acousticness": "அகவுஸ்டிக்னெஸ்", + "danceability": "நடனத்தன்மை", + "energy": "ஆற்றல்", + "instrumentalness": "கருவித்தன்மை", + "liveness": "உயிர்ப்புத்தன்மை", + "loudness": "ஒலி அளவு", + "speechiness": "பேச்சுத்தன்மை", + "valence": "உணர்வு", + "popularity": "பிரபலம்", + "key": "இசை குறிப்பு", + "duration": "கால அளவு (வினாடிகள்)", + "tempo": "வேகம் (BPM)", + "mode": "முறை", + "time_signature": "நேர கையொப்பம்", + "short": "குறுகிய", + "medium": "நடுத்தர", + "long": "நீண்ட", + "min": "குறைந்தபட்சம்", + "max": "அதிகபட்சம்", + "target": "இலக்கு", + "moderate": "மிதமான", + "deselect_all": "அனைத்தையும் தேர்வுநீக்கு", + "select_all": "அனைத்தையும் தேர்ந்தெடு", + "are_you_sure": "உறுதியாக இருக்கிறீர்களா?", + "generating_playlist": "உங்கள் தனிப்பயன்பாட்டிற்கான பாடல் பட்டியலை உருவாக்குகிறது...", + "selected_count_tracks": "{count} பாடல்கள் தேர்ந்தெடுக்கப்பட்டன", + "download_warning": "நீங்கள் அனைத்து பாடல்களையும் மொத்தமாக பதிவிறக்கினால், நீங்கள் தெளிவாக இசையைத் திருடுகிறீர்கள் மற்றும் இசையின் படைப்பாற்றல் சமூகத்திற்கு சேதம் விளைவிக்கிறீர்கள். நீங்கள் இதை அறிந்திருக்கிறீர்கள் என்று நம்புகிறேன். எப்போதும், கலைஞரின் கடின உழைப்பை மதித்து ஆதரிக்க முயற்சி செய்யுங்கள்", + "download_ip_ban_warning": "மேலும், அதிகப்படியான பதிவிறக்க கோரிக்கைகள் காரணமாக உங்கள் IP YouTube இல் தடைசெய்யப்படலாம். IP தடை என்பது குறைந்தது 2-3 மாதங்களுக்கு அந்த IP சாதனத்திலிருந்து YouTube ஐப் பயன்படுத்த முடியாது (நீங்கள் உள்நுழைந்திருந்தாலும் கூட). இது ஒருபோதும் நடந்தால் Spotube பொறுப்பேற்காது", + "by_clicking_accept_terms": "'ஏற்றுக்கொள்' என்பதைக் கிளிக் செய்வதன் மூலம் பின்வரும் விதிமுறைகளுக்கு நீங்கள் ஒப்புக்கொள்கிறீர்கள்:", + "download_agreement_1": "நான் இசையைத் திருடுகிறேன் என்பது எனக்குத் தெரியும். நான் கெட்டவன்", + "download_agreement_2": "நான் கலைஞரை முடிந்தவரை ஆதரிப்பேன், அவர்களின் கலைக்கு பணம் செலுத்த எனக்கு பணம் இல்லாததால் மட்டுமே இதைச் செய்கிறேன்", + "download_agreement_3": "என் IP YouTube இல் தடைசெய்யப்படலாம் என்பதை நான் முழுமையாக அறிவேன், மேலும் என் தற்போதைய செயலால் ஏற்படும் எந்த விபத்துகளுக்கும் Spotube அல்லது அதன் உரிமையாளர்கள்/பங்களிப்பாளர்களை பொறுப்பாக்க மாட்டேன்", + "decline": "மறு", + "accept": "ஏற்றுக்கொள்", + "details": "விவரங்கள்", + "youtube": "YouTube", + "channel": "சேனல்", + "likes": "விருப்பங்கள்", + "dislikes": "விருப்பமில்லாதவை", + "views": "பார்வைகள்", + "streamUrl": "ஸ்ட்ரீம் URL", + "stop": "நிறுத்து", + "sort_newest": "புதிதாக சேர்க்கப்பட்டவற்றை வரிசைப்படுத்து", + "sort_oldest": "பழமையானவற்றை வரிசைப்படுத்து", + "sleep_timer": "உறக்க நேரம்", + "mins": "{minutes} நிமிடங்கள்", + "hours": "{hours} மணிநேரங்கள்", + "hour": "{hours} மணிநேரம்", + "custom_hours": "தனிப்பயன் மணிநேரங்கள்", + "logs": "பதிவுகள்", + "developers": "உருவாக்குநர்கள்", + "not_logged_in": "நீங்கள் உள்நுழையவில்லை", + "search_mode": "தேடல் முறை", + "audio_source": "ஒலி மூலம்", + "ok": "சரி", + "failed_to_encrypt": "குறியாக்கம் தோல்வியடைந்தது", + "encryption_failed_warning": "Spotube உங்கள் தரவை பாதுகாப்பாக சேமிக்க குறியாக்கத்தைப் பயன்படுத்துகிறது. ஆனால் அவ்வாறு செய்ய முடியவில்லை. எனவே இது பாதுகாப்பற்ற சேமிப்பகத்திற்கு மாறும்\nநீங்கள் லினக்ஸ் பயன்படுத்துகிறீர்கள் என்றால், எந்த ரகசிய சேவையும் (gnome-keyring, kde-wallet, keepassxc போன்றவை) நிறுவப்பட்டுள்ளதா என்பதை உறுதிப்படுத்தவும்", + "querying_info": "தகவலைக் கேட்கிறது...", + "piped_api_down": "Piped API செயலிழந்துள்ளது", + "piped_down_error_instructions": "Piped நிகழ்வு {pipedInstance} தற்போது செயலிழந்துள்ளது\n\nநிகழ்வை மாற்றவும் அல்லது 'API வகை'யை அதிகாரப்பூர்வ YouTube API க்கு மாற்றவும்\n\nமாற்றத்திற்குப் பிறகு பயன்பாட்டை மறுதொடக்கம் செய்வதை உறுதிப்படுத்தவும்", + "you_are_offline": "நீங்கள் தற்போது ஆஃப்லைனில் உள்ளீர்கள்", + "connection_restored": "உங்கள் இணைய இணைப்பு மீட்டெடுக்கப்பட்டது", + "use_system_title_bar": "கணினி தலைப்புப் பட்டியைப் பயன்படுத்தவும்", + "crunching_results": "முடிவுகளை செயலாக்குகிறது...", + "search_to_get_results": "முடிவுகளைப் பெற தேடவும்", + "use_amoled_mode": "கருமை நிற இருண்ட தீம்", + "pitch_dark_theme": "AMOLED முறை", + "normalize_audio": "ஒலியை சீரமை", + "change_cover": "அட்டையை மாற்று", + "add_cover": "அட்டையைச் சேர்", + "restore_defaults": "இயல்புநிலைகளை மீட்டமை", + "download_music_codec": "இசை கோடெக்கை பதிவிறக்கு", + "streaming_music_codec": "இசை கோடெக்கை ஸ்ட்ரீம் செய்", + "login_with_lastfm": "Last.fm உடன் உள்நுழைக", + "connect": "இணை", + "disconnect_lastfm": "Last.fm இலிருந்து துண்டி", + "disconnect": "துண்டி", + "username": "பயனர்பெயர்", + "password": "கடவுச்சொல்", + "login": "உள்நுழைக", + "login_with_your_lastfm": "உங்கள் Last.fm கணக்குடன் உள்நுழைக", + "scrobble_to_lastfm": "Last.fm க்கு ஸ்க்ரோபிள் செய்", + "go_to_album": "ஆல்பத்திற்குச் செல்", + "discord_rich_presence": "Discord செழுமையான தோற்றம்", + "browse_all": "அனைத்தையும் உலாவு", + "genres": "வகைகள்", + "explore_genres": "வகைகளை ஆராயுங்கள்", + "friends": "நண்பர்கள்", + "no_lyrics_available": "மன்னிக்கவும், இந்தப் பாடலுக்கான பாடல் வரிகளைக் கண்டுபிடிக்க முடியவில்லை", + "start_a_radio": "வானொலியைத் தொடங்கு", + "how_to_start_radio": "வானொலியை எவ்வாறு தொடங்க விரும்புகிறீர்கள்?", + "replace_queue_question": "தற்போதைய வரிசையை மாற்ற விரும்புகிறீர்களா அல்லது அதனுடன் சேர்க்க விரும்புகிறீர்களா?", + "endless_playback": "முடிவற்ற இயக்கம்", + "delete_playlist": "பாடல் பட்டியலை நீக்கு", + "delete_playlist_confirmation": "இந்த பாடல் பட்டியலை நீக்க விரும்புகிறீர்களா?", + "local_tracks": "உள்ளூர் பாடல்கள்", + "local_tab": "உள்ளூர்", + "song_link": "பாடல் இணைப்பு", + "skip_this_nonsense": "இந்த அர்த்தமற்றதைத் தவிர்", + "freedom_of_music": "\"இசையின் சுதந்திரம்\"", + "freedom_of_music_palm": "\"உங்கள் கைகளில் இசையின் சுதந்திரம்\"", + "get_started": "தொடங்குவோம்", + "youtube_source_description": "பரிந்துரைக்கப்படுகிறது மற்றும் சிறப்பாக செயல்படுகிறது.", + "piped_source_description": "சுதந்திரமாக உணர்கிறீர்களா? YouTube போலவே ஆனால் மிகவும் சுதந்திரமானது.", + "jiosaavn_source_description": "தெற்காசியப் பிராந்தியத்திற்கு சிறந்தது.", + "invidious_source_description": "Piped ஐப் போன்றது ஆனால் அதிக கிடைக்கும் தன்மையுடன்.", + "highest_quality": "உயர்ந்த தரம்: {quality}", + "select_audio_source": "ஒலி மூலத்தைத் தேர்ந்தெடுக்கவும்", + "endless_playback_description": "வரிசையின் இறுதியில் புதிய பாடல்களை\nதானாகவே சேர்க்கவும்", + "choose_your_region": "உங்கள் பிராந்தியத்தைத் தேர்ந்தெடுக்கவும்", + "choose_your_region_description": "இது உங்கள் இருப்பிடத்திற்கான சரியான உள்ளடக்கத்தை\nSpotube காட்ட உதவும்.", + "choose_your_language": "உங்கள் மொழியைத் தேர்ந்தெடுக்கவும்", + "help_project_grow": "இந்த திட்டம் வளர உதவுங்கள்", + "help_project_grow_description": "Spotube ஒரு திறந்த மூல திட்டம். திட்டத்திற்கு பங்களிப்பு செய்வதன் மூலம், பிழைகளைப் புகாரளிப்பதன் மூலம் அல்லது புதிய அம்சங்களைப் பரிந்துரைப்பதன் மூலம் இந்தத் திட்டம் வளர உதவலாம்.", + "contribute_on_github": "GitHub இல் பங்களியுங்கள்", + "donate_on_open_collective": "Open Collective இல் நன்கொடை அளியுங்கள்", + "browse_anonymously": "அநாமதேயமாக உலாவுக", + "enable_connect": "இணைப்பை இயக்கு", + "enable_connect_description": "மற்ற சாதனங்களிலிருந்து Spotube ஐக் கட்டுப்படுத்தவும்", + "devices": "சாதனங்கள்", + "select": "தேர்ந்தெடு", + "connect_client_alert": "நீங்கள் {client} ஆல் கட்டுப்படுத்தப்படுகிறீர்கள்", + "this_device": "இந்த சாதனம்", + "remote": "தொலைநிலை", + "stats": "புள்ளிவிவரங்கள்", + "and_n_more": "மற்றும் {count} கூடுதலாக", + "recently_played": "சமீபத்தில் இயக்கியவை", + "browse_more": "மேலும் உலாவு", + "no_title": "தலைப்பு இல்லை", + "not_playing": "இயக்கப்படவில்லை", + "epic_failure": "மோசமான தோல்வி!", + "added_num_tracks_to_queue": "{tracks_length} பாடல்கள் வரிசையில் சேர்க்கப்பட்டன", + "spotube_has_an_update": "Spotube க்கு ஒரு புதுப்பிப்பு உள்ளது", + "download_now": "இப்போது பதிவிறக்கு", + "nightly_version": "Spotube Nightly {nightlyBuildNum} வெளியிடப்பட்டுள்ளது", + "release_version": "Spotube v{version} வெளியிடப்பட்டுள்ளது", + "read_the_latest": "சமீபத்திய ", + "release_notes": "வெளியீட்டு குறிப்புகளைப் படிக்கவும்", + "pick_color_scheme": "வண்ணத் திட்டத்தைத் தேர்ந்தெடுக்கவும்", + "save": "சேமி", + "choose_the_device": "சாதனத்தைத் தேர்ந்தெடுக்கவும்:", + "multiple_device_connected": "பல சாதனங்கள் இணைக்கப்பட்டுள்ளன.\nஇந்த செயல் நடைபெற வேண்டிய சாதனத்தைத் தேர்ந்தெடுக்கவும்", + "nothing_found": "எதுவும் கிடைக்கவில்லை", + "the_box_is_empty": "பெட்டி காலியாக உள்ளது", + "top_artists": "சிறந்த கலைஞர்கள்", + "top_albums": "சிறந்த ஆல்பங்கள்", + "this_week": "இந்த வாரம்", + "this_month": "இந்த மாதம்", + "last_6_months": "கடந்த 6 மாதங்கள்", + "this_year": "இந்த ஆண்டு", + "last_2_years": "கடந்த 2 ஆண்டுகள்", + "all_time": "எல்லா நேரமும்", + "powered_by_provider": "{providerName} ஆல் இயக்கப்படுகிறது", + "email": "மின்னஞ்சல்", + "profile_followers": "பின்தொடர்பவர்கள்", + "birthday": "பிறந்த நாள்", + "subscription": "சந்தா", + "not_born": "பிறக்கவில்லை", + "hacker": "ஹேக்கர்", + "profile": "சுயவிவரம்", + "no_name": "பெயர் இல்லை", + "edit": "திருத்து", + "user_profile": "பயனர் சுயவிவரம்", + "count_plays": "{count} முறை இசைக்கப்பட்டது", + "streaming_fees_hypothetical": "ஸ்ட்ரீமிங் கட்டணங்கள் (கற்பனை)", + "minutes_listened": "காலம் கேட்டது", + "streamed_songs": "ஸ்ட்ரீமிங் செய்யப்பட்ட பாடல்கள்", + "count_streams": "{count} ஸ்ட்ரீம்கள்", + "owned_by_you": "உங்களால் கொண்டது", + "copied_shareurl_to_clipboard": "நகலெடுக்கப்பட்டது {shareUrl} கிளிப்போர்டுக்காக", + "spotify_hipotetical_calculation": "*இது Spotify இன் ஒவ்வொரு ஸ்ட்ரீமிற்கும்\n$0.003 முதல் $0.005 வரை அளவீடு அடிப்படையில் கணக்கிடப்படுகிறது. இது ஒரு கற்பனை\nகணக்கீடு ஆகும், பயனர் எந்த அளவிற்கு கலைஞர்களுக்கு\nஅதோர் பாடலை Spotify மென்பொருளில் கேட்டால் எவ்வளவு பணம் செலுத்தினார்கள் என்பதைக் கண்டுபிடிக்க.", + "count_mins": "{minutes} நிமிடங்கள்", + "summary_minutes": "நிமிடங்கள்", + "summary_listened_to_music": "இசை கேட்டது", + "summary_songs": "பாடல்கள்", + "summary_streamed_overall": "மொத்தமாக ஸ்ட்ரீமிங்", + "summary_owed_to_artists": "கலைஞர்களுக்கு\nஇந்த மாதம் சொந்தமானது", + "summary_artists": "கலைஞர்கள்", + "summary_music_reached_you": "இசை உங்களுக்கு வந்தது", + "summary_full_albums": "முழு ஆல்பங்கள்", + "summary_got_your_love": "உங்கள் அன்பை பெற்றுக்கொண்டேன்", + "summary_playlists": "பாடல் பட்டியல்கள்", + "summary_were_on_repeat": "மீண்டும் மீண்டும் இருந்தன", + "total_money": "மொத்தம் {money}", + "webview_not_found": "வெப்வியூ கிடைக்கவில்லை", + "webview_not_found_description": "உங்கள் சாதனத்தில் எந்தவொரு வெப்வியூ இயக்கத்தை நிறுவவில்லை.\nஇது நிறுவப்பட்டிருந்தால், சுற்றுச்சூழல் பாதையில் PATH உள்ளது என்பதை உறுதிபடுத்தவும்\n\nநிறுவித்த பிறகு, செயலியை மறுதொடக்கம் செய்யவும்", + "unsupported_platform": "அதிர்ஷ்டகாத உருப்படியை ஆதரிக்கவில்லை", + "cache_music": "இசையை கேஷ் செய்", + "open": "திறக்கவும்", + "cache_folder": "கேஷ் அடைவு", + "export": "ஏற்றுமதி", + "clear_cache": "கேஷ் அழிக்கவும்", + "clear_cache_confirmation": "கேஷைப் அழிக்க விரும்புகிறீர்களா?", + "export_cache_files": "கேஷில் உள்ள கோப்புகளை ஏற்றுமதி செய்யவும்", + "found_n_files": "{count} கோப்புகள் கிடைத்தன", + "export_cache_confirmation": "இந்த கோப்புகளை ஏற்றுமதி செய்ய விரும்புகிறீர்களா?", + "exported_n_out_of_m_files": "{filesExported} கோப்புகள் ஏற்றுமதி செய்யப்பட்டன, {files} கோப்புகளில்", + "undo": "செயல்தவிர்", + "download_all": "அனைத்தையும் பதிவிறக்குக", + "add_all_to_playlist": "அனைத்தையும் பாடல் பட்டியலில் சேர்க்கவும்", + "add_all_to_queue": "அனைத்தையும் வரிசைப்படுத்து", + "play_all_next": "அடுத்த உள்ள அனைத்தையும் இயக்கு", + "pause": "நிறுத்து", + "view_all": "அனைத்தையும் காண்க", + "no_tracks_added_yet": "உங்கள் பாடல்களை இன்னும் சேர்க்கவில்லை என்றால் தெரியாதே", + "no_tracks": "இங்கு பாடல்கள் எதுவும் இல்லை", + "no_tracks_listened_yet": "இன்னும் எதையும் கேள்வியில்லை", + "not_following_artists": "நீங்கள் எந்த கலைஞரையும் பின்தொடரவில்லை", + "no_favorite_albums_yet": "நீங்கள் இன்னும் எந்த ஆல்பங்களையும் பிடித்தவையாகச் சேர்க்கவில்லை", + "no_logs_found": "பதிவுகள் எதுவும் கிடைக்கவில்லை", + "youtube_engine": "YouTube இயந்திரம்", + "youtube_engine_not_installed_title": "{engine} நிறுவியதில்லை", + "youtube_engine_not_installed_message": "{engine} உங்கள் கணினியில் நிறுவியதில்லை.", + "youtube_engine_set_path": "PATH மாறியில் கிடைக்கிறதா என்பதை உறுதிப்படுத்தவும் அல்லது\n{engine} செயல் செய்யக்கூடிய முறையை கீழே அமைக்கவும்", + "youtube_engine_unix_issue_message": "macOS/Linux/unix போல் OS இல், .zshrc/.bashrc/.bash_profile போன்றவை அமைப்பில் பாதையை PATH அமைப்பது இயலாது.\nநீங்கள்.shell configuration file இல் பாதையை அமைக்க வேண்டும்", + "download": "பதிவிறக்கு", + "file_not_found": "கோப்பு கிடைக்கவில்லை", + "custom": "தனிப்பயன்", + "add_custom_url": "தனிப்பயன் URL ஐச் சேர்க்கவும்", + "edit_port": "போர்டு திருத்தவும்", + "port_helper_msg": "இயல்புநிலை -1 ஆகும், இது சீரற்ற எண்ணை குறிக்கிறது. நீங்கள் தீயணைப்பு அமைக்கப்பட்டிருந்தால், இதை அமைப்பது பரிந்துரைக்கப்படுகிறது.", + "connect_request": "{client} க்கு இணைக்க அனுமதிக்கவா?", + "connection_request_denied": "இணைப்பு மறுக்கப்பட்டது. பயனர் அணுகலை மறுத்தார்." } \ No newline at end of file diff --git a/lib/l10n/app_th.arb b/lib/l10n/app_th.arb index 8e9a0318..38decf66 100644 --- a/lib/l10n/app_th.arb +++ b/lib/l10n/app_th.arb @@ -427,5 +427,9 @@ "download": "ดาวน์โหลด", "file_not_found": "ไม่พบไฟล์", "custom": "กำหนดเอง", - "add_custom_url": "เพิ่ม URL แบบกำหนดเอง" + "add_custom_url": "เพิ่ม URL แบบกำหนดเอง", + "edit_port": "แก้ไขพอร์ต", + "port_helper_msg": "ค่าเริ่มต้นคือ -1 ซึ่งหมายถึงหมายเลขสุ่ม หากคุณได้กำหนดค่าไฟร์วอลล์แล้ว แนะนำให้ตั้งค่านี้", + "connect_request": "อนุญาตให้ {client} เชื่อมต่อหรือไม่?", + "connection_request_denied": "การเชื่อมต่อล้มเหลว ผู้ใช้ปฏิเสธการเข้าถึง" } \ No newline at end of file diff --git a/lib/l10n/app_tl.arb b/lib/l10n/app_tl.arb index c395cdc7..a1c4264c 100644 --- a/lib/l10n/app_tl.arb +++ b/lib/l10n/app_tl.arb @@ -1,428 +1,432 @@ { - "guest": "Bisita", - "browse": "Mag-browse", - "search": "Maghanap", - "library": "Silid-aklatan", - "lyrics": "Mga Liriko", - "settings": "Mga Setting", - "genre_categories_filter": "I-filter ang mga kategorya o genre...", - "genre": "Genre", - "personalized": "Naka-personalize", - "featured": "Tampok", - "new_releases": "Mga Bagong Paglabas", - "songs": "Mga Kanta", - "playing_track": "Tumutugtog ang {track}", - "queue_clear_alert": "Ito ay magbubura ng kasalukuyang pila. {track_length} na mga track ang tatanggalin\nGusto mo bang magpatuloy?", - "load_more": "Mag-load pa", - "playlists": "Mga Playlist", - "artists": "Mga Artista", - "albums": "Mga Album", - "tracks": "Mga Track", - "downloads": "Mga Download", - "filter_playlists": "I-filter ang iyong mga playlist...", - "liked_tracks": "Mga Nagustuhang Track", - "liked_tracks_description": "Lahat ng mga track na iyong nagustuhan", - "playlist": "Playlist", - "create_a_playlist": "Gumawa ng playlist", - "update_playlist": "I-update ang playlist", - "create": "Lumikha", - "cancel": "Ikansela", - "update": "I-update", - "playlist_name": "Pangalan ng Playlist", - "name_of_playlist": "Pangalan ng playlist", - "description": "Paglalarawan", - "public": "Pampubliko", - "collaborative": "Pakikipagtulungan", - "search_local_tracks": "Maghanap ng mga lokal na track...", - "play": "I-play", - "delete": "Burahin", - "none": "Wala", - "sort_a_z": "Ayusin ayon sa A-Z", - "sort_z_a": "Ayusin ayon sa Z-A", - "sort_artist": "Ayusin ayon sa Artista", - "sort_album": "Ayusin ayon sa Album", - "sort_duration": "Ayusin ayon sa Tagal", - "sort_tracks": "Ayusin ang mga Track", - "currently_downloading": "Kasalukuyang Nagda-download ({tracks_length})", - "cancel_all": "Kanselahin Lahat", - "filter_artist": "I-filter ang mga artista...", - "followers": "{followers} na mga Tagasunod", - "add_artist_to_blacklist": "Idagdag ang artista sa blacklist", - "top_tracks": "Mga Nangungunang Track", - "fans_also_like": "Gusto rin ng mga tagahanga", - "loading": "Naglo-load...", - "artist": "Artista", - "blacklisted": "Naka-blacklist", - "following": "Sinusundan", - "follow": "Sundan", - "artist_url_copied": "Na-copy sa clipboard ang URL ng artista", - "added_to_queue": "Idinagdag ang {tracks} na mga track sa pila", - "filter_albums": "I-filter ang mga album...", - "synced": "Naka-sync", - "plain": "Simpleng", - "shuffle": "I-shuffle", - "search_tracks": "Maghanap ng mga track...", - "released": "Inilabas", - "error": "Error {error}", - "title": "Pamagat", - "time": "Oras", - "more_actions": "Higit pang mga aksyon", - "download_count": "I-download ({count})", - "add_count_to_playlist": "Idagdag ({count}) sa Playlist", - "add_count_to_queue": "Idagdag ({count}) sa Pila", - "play_count_next": "I-play ({count}) kasunod", - "album": "Album", - "copied_to_clipboard": "Na-copy ang {data} sa clipboard", - "add_to_following_playlists": "Idagdag ang {track} sa mga sumusunod na Playlist", - "add": "Idagdag", - "added_track_to_queue": "Idinagdag ang {track} sa pila", - "add_to_queue": "Idagdag sa pila", - "track_will_play_next": "Ang {track} ay tutugtog susunod", - "play_next": "I-play susunod", - "removed_track_from_queue": "Tinanggal ang {track} mula sa pila", - "remove_from_queue": "Alisin mula sa pila", - "remove_from_favorites": "Alisin mula sa mga paborito", - "save_as_favorite": "I-save bilang paborito", - "add_to_playlist": "Idagdag sa playlist", - "remove_from_playlist": "Alisin mula sa playlist", - "add_to_blacklist": "Idagdag sa blacklist", - "remove_from_blacklist": "Alisin mula sa blacklist", - "share": "Ibahagi", - "mini_player": "Mini Player", - "slide_to_seek": "I-slide para mag-seek pasulong o pabalik", - "shuffle_playlist": "I-shuffle ang playlist", - "unshuffle_playlist": "I-unshuffle ang playlist", - "previous_track": "Nakaraang track", - "next_track": "Susunod na track", - "pause_playback": "I-pause ang Playback", - "resume_playback": "Ipagpatuloy ang Playback", - "loop_track": "I-loop ang track", - "no_loop": "Walang loop", - "repeat_playlist": "Ulitin ang playlist", - "queue": "Pila", - "alternative_track_sources": "Alternatibong mga pinagmulan ng track", - "download_track": "I-download ang track", - "tracks_in_queue": "{tracks} na mga track sa pila", - "clear_all": "Burahin lahat", - "show_hide_ui_on_hover": "Ipakita/Itago ang UI sa hover", - "always_on_top": "Palaging nasa ibabaw", - "exit_mini_player": "Lumabas sa Mini player", - "download_location": "Lokasyon ng pag-download", - "local_library": "Lokal na silid-aklatan", - "add_library_location": "Idagdag sa silid-aklatan", - "remove_library_location": "Alisin mula sa silid-aklatan", - "account": "Account", - "login_with_spotify": "Mag-login gamit ang iyong Spotify account", - "connect_with_spotify": "Kumonekta sa Spotify", - "logout": "Mag-logout", - "logout_of_this_account": "Mag-logout sa account na ito", - "language_region": "Wika at Rehiyon", - "language": "Wika", - "system_default": "Default ng Sistema", - "market_place_region": "Rehiyon ng Marketplace", - "recommendation_country": "Bansang Inirerekomenda", - "appearance": "Hitsura", - "layout_mode": "Mode ng Layout", - "override_layout_settings": "I-override ang mga setting ng responsive layout mode", - "adaptive": "Umaangkop", - "compact": "Kompakto", - "extended": "Pinalawig", - "theme": "Tema", - "dark": "Madilim", - "light": "Maliwanag", - "system": "Sistema", - "accent_color": "Kulay ng Accent", - "sync_album_color": "I-sync ang kulay ng album", - "sync_album_color_description": "Ginagamit ang pangunahing kulay ng album art bilang kulay ng accent", - "playback": "Playback", - "audio_quality": "Kalidad ng Audio", - "high": "Mataas", - "low": "Mababa", - "pre_download_play": "Mag-pre-download at i-play", - "pre_download_play_description": "Sa halip na mag-stream ng audio, mag-download ng bytes at i-play sa halip (Inirerekomenda para sa mga gumagamit ng mataas na bandwidth)", - "skip_non_music": "Laktawan ang mga segment na hindi musika (SponsorBlock)", - "blacklist_description": "Mga track at artista na nasa blacklist", - "wait_for_download_to_finish": "Mangyaring maghintay para matapos ang kasalukuyang pag-download", - "desktop": "Desktop", - "close_behavior": "Pag-uugali ng Pagsara", - "close": "Isara", - "minimize_to_tray": "I-minimize sa tray", - "show_tray_icon": "Ipakita ang icon ng System tray", - "about": "Tungkol sa", - "u_love_spotube": "Alam naming gusto mo ang Spotube", - "check_for_updates": "Maghanap ng mga update", - "about_spotube": "Tungkol sa Spotube", - "blacklist": "Blacklist", - "please_sponsor": "Mangyaring Mag-sponsor/Mag-donate", - "spotube_description": "Spotube, isang magaan, cross-platform, libreng-para-sa-lahat na spotify client", - "version": "Bersyon", - "build_number": "Build Number", - "founder": "Nagtatag", - "repository": "Repository", - "bug_issues": "Bug+Mga Isyu", - "made_with": "Ginawa nang may ❤️ sa Bangladesh🇧🇩", - "kingkor_roy_tirtho": "Kingkor Roy Tirtho", - "copyright": "© 2021-{current_year} Kingkor Roy Tirtho", - "license": "Lisensya", - "add_spotify_credentials": "Idagdag ang iyong mga kredensyal sa spotify para makapagsimula", - "credentials_will_not_be_shared_disclaimer": "Huwag mag-alala, ang alinman sa iyong mga kredensyal ay hindi kokolektahin o ibabahagi sa sinuman", - "know_how_to_login": "Hindi mo alam kung paano gawin ito?", - "follow_step_by_step_guide": "Sundin ang Hakbang-hakbang na gabay", - "spotify_cookie": "Spotify {name} Cookie", - "cookie_name_cookie": "{name} Cookie", - "fill_in_all_fields": "Mangyaring punan ang lahat ng field", - "submit": "Isumite", - "exit": "Lumabas", - "previous": "Nakaraan", - "next": "Susunod", - "done": "Tapos na", - "step_1": "Hakbang 1", - "first_go_to": "Una, Pumunta sa", - "login_if_not_logged_in": "at Mag-login/Mag-signup kung hindi ka naka-log in", - "step_2": "Hakbang 2", - "step_2_steps": "1. Kapag naka-log in ka na, pindutin ang F12 o i-right click ang Mouse > Inspect para Buksan ang Browser devtools.\n2. Pagkatapos ay pumunta sa \"Application\" Tab (Chrome, Edge, Brave atbp..) o \"Storage\" Tab (Firefox, Palemoon atbp..)\n3. Pumunta sa \"Cookies\" na seksyon at pagkatapos sa \"https://accounts.spotify.com\" na subseksyon", - "step_3": "Hakbang 3", - "step_3_steps": "Kopyahin ang halaga ng \"sp_dc\" Cookie", - "success_emoji": "Tagumpay🥳", - "success_message": "Ngayon ay matagumpay kang Naka-log in gamit ang iyong Spotify account. Magaling, kaibigan!", - "step_4": "Hakbang 4", - "step_4_steps": "I-paste ang na-kopyang halaga ng \"sp_dc\"", - "something_went_wrong": "May nangyaring mali", - "piped_instance": "Instance ng Piped Server", - "piped_description": "Ang instance ng Piped server na gagamitin para sa pagtutugma ng track", - "piped_warning": "Maaaring hindi gumagana nang mabuti ang ilan sa mga ito. Kaya gamitin sa sarili mong peligro", - "invidious_instance": "Instance ng Invidious Server", - "invidious_description": "Ang instance ng Invidious server na gagamitin para sa pagtutugma ng track", - "invidious_warning": "Maaaring hindi gumagana nang mabuti ang ilan sa mga ito. Kaya gamitin sa sarili mong peligro", - "generate": "Gumawa", - "track_exists": "Ang Track na {track} ay umiiral na", - "replace_downloaded_tracks": "Palitan ang lahat ng na-download na mga track", - "skip_download_tracks": "Laktawan ang pag-download ng lahat ng na-download na mga track", - "do_you_want_to_replace": "Gusto mo bang palitan ang umiiral na track??", - "replace": "Palitan", - "skip": "Laktawan", - "select_up_to_count_type": "Pumili ng hanggang {count} {type}", - "select_genres": "Pumili ng mga Genre", - "add_genres": "Magdagdag ng mga Genre", - "country": "Bansa", - "number_of_tracks_generate": "Bilang ng mga track na gagawin", - "acousticness": "Acoustic-ness", - "danceability": "Kakayahang Sayawin", - "energy": "Enerhiya", - "instrumentalness": "Instrumental-ness", - "liveness": "Liveness", - "loudness": "Lakas", - "speechiness": "Pagsasalita", - "valence": "Valence", - "popularity": "Popularidad", - "key": "Key", - "duration": "Tagal (s)", - "tempo": "Tempo (BPM)", - "mode": "Mode", - "time_signature": "Time Signature", - "short": "Maikli", - "medium": "Katamtaman", - "long": "Mahaba", - "min": "Min", - "max": "Max", - "target": "Target", - "moderate": "Katamtaman", - "deselect_all": "Alisin ang Pagkakapili sa Lahat", - "select_all": "Piliin Lahat", - "are_you_sure": "Sigurado ka ba?", - "generating_playlist": "Gumagawa ng iyong custom na playlist...", - "selected_count_tracks": "Napili ang {count} na mga track", - "download_warning": "Kung nag-download ka ng lahat ng Track sa maramihan, malinaw na nagpa-pirate ka ng Musika at nagsasanhi ng pinsala sa creative society ng Musika. Sana ay alam mo ito. Palaging, subukang igalang at suportahan ang masipag na paggawa ng Artist", - "download_ip_ban_warning": "Sa nga pala, ang iyong IP ay maaaring ma-block sa YouTube dahil sa sobrang mga kahilingan sa pag-download kaysa sa karaniwan. Ang IP block ay nangangahulugang hindi mo magagamit ang YouTube (kahit na naka-log in ka) sa loob ng hindi bababa sa 2-3 buwan mula sa device na may IP na iyon. At hindi pinanghahawakan ng Spotube ang anumang responsibilidad kung mangyayari ito", - "by_clicking_accept_terms": "Sa pamamagitan ng pag-click sa 'tanggapin', sumasang-ayon ka sa mga sumusunod na tuntunin:", - "download_agreement_1": "Alam kong nagpa-pirate ako ng Musika. Masama ako", - "download_agreement_2": "Susuportahan ko ang Artist saan man ako maaari at ginagawa ko lang ito dahil wala akong pera para bumili ng kanilang sining", - "download_agreement_3": "Lubos kong nauunawaan na ang aking IP ay maaaring ma-block sa YouTube at hindi ko pinanghahawakan ang Spotube o ang kanyang mga may-ari/nag-ambag na responsable para sa anumang aksidente na sanhi ng aking kasalukuyang aksyon", - "decline": "Tanggihan", - "accept": "Tanggapin", - "details": "Mga Detalye", - "youtube": "YouTube", - "channel": "Channel", - "likes": "Mga Like", - "dislikes": "Mga Dislike", - "views": "Mga View", - "streamUrl": "Stream URL", - "stop": "Ihinto", - "sort_newest": "Ayusin ayon sa pinakabagong idinagdag", - "sort_oldest": "Ayusin ayon sa pinakalumang idinagdag", - "sleep_timer": "Sleep Timer", - "mins": "{minutes} Minuto", - "hours": "{hours} Oras", - "hour": "{hours} Oras", - "custom_hours": "Custom na Oras", - "logs": "Mga Log", - "developers": "Mga Developer", - "not_logged_in": "Hindi ka naka-log in", - "search_mode": "Mode ng Paghahanap", - "audio_source": "Pinagmulan ng Audio", - "ok": "Ok", - "failed_to_encrypt": "Nabigong i-encrypt", - "encryption_failed_warning": "Gumagamit ng encryption ang Spotube para ligtas na i-store ang iyong data. Ngunit nabigo. Kaya babalik ito sa hindi secure na storage\nKung gumagamit ka ng linux, mangyaring tiyakin na mayroon kang anumang secret-service na naka-install (gnome-keyring, kde-wallet, keepassxc atbp)", - "querying_info": "Kinukuha ang impormasyon...", - "piped_api_down": "Ang Piped API ay hindi gumagana", - "piped_down_error_instructions": "Ang instance ng Piped na {pipedInstance} ay kasalukuyang hindi gumagana\n\nMaaari mong baguhin ang instance o baguhin ang 'Uri ng API' sa opisyal na YouTube API\n\nSiguraduhing i-restart ang app pagkatapos ng pagbabago", - "you_are_offline": "Kasalukuyan kang offline", - "connection_restored": "Naibalik na ang iyong koneksyon sa internet", - "use_system_title_bar": "Gamitin ang title bar ng system", - "crunching_results": "Pinaproseso ang mga resulta...", - "search_to_get_results": "Maghanap para makakuha ng mga resulta", - "use_amoled_mode": "Matingkad na itim na madilim na tema", - "pitch_dark_theme": "AMOLED Mode", - "normalize_audio": "I-normalize ang audio", - "change_cover": "Baguhin ang cover", - "add_cover": "Magdagdag ng cover", - "restore_defaults": "Ibalik ang mga default", - "download_music_codec": "Codec para sa pag-download ng musika", - "streaming_music_codec": "Codec para sa pag-stream ng musika", - "login_with_lastfm": "Mag-login gamit ang Last.fm", - "connect": "Kumonekta", - "disconnect_lastfm": "Idiskonekta ang Last.fm", - "disconnect": "Idiskonekta", - "username": "Username", - "password": "Password", - "login": "Mag-login", - "login_with_your_lastfm": "Mag-login gamit ang iyong Last.fm account", - "scrobble_to_lastfm": "I-scrobble sa Last.fm", - "go_to_album": "Pumunta sa Album", - "discord_rich_presence": "Discord Rich Presence", - "browse_all": "I-browse Lahat", - "genres": "Mga Genre", - "explore_genres": "Tuklasin ang mga Genre", - "friends": "Mga Kaibigan", - "no_lyrics_available": "Paumanhin, hindi mahanap ang lyrics para sa track na ito", - "start_a_radio": "Magsimula ng Radio", - "how_to_start_radio": "Paano mo gustong simulan ang radio?", - "replace_queue_question": "Gusto mo bang palitan ang kasalukuyang pila o idagdag dito?", - "endless_playback": "Walang Hanggang Playback", - "delete_playlist": "Burahin ang Playlist", - "delete_playlist_confirmation": "Sigurado ka bang gusto mong burahin ang playlist na ito?", - "local_tracks": "Mga Lokal na Track", - "local_tab": "Lokal", - "song_link": "Link ng Kanta", - "skip_this_nonsense": "Laktawan ang kalokohan na ito", - "freedom_of_music": "\"Kalayaan ng Musika\"", - "freedom_of_music_palm": "\"Kalayaan ng Musika sa iyong palad\"", - "get_started": "Magsimula na tayo", - "youtube_source_description": "Inirerekomenda at pinakamahusay na gumagana.", - "piped_source_description": "Gusto ng kalayaan? Kapareho ng YouTube ngunit mas malaya.", - "jiosaavn_source_description": "Pinakamahusay para sa rehiyon ng South Asia.", - "invidious_source_description": "Katulad ng Piped ngunit may mas mataas na availability.", - "highest_quality": "Pinakamataas na Kalidad: {quality}", - "select_audio_source": "Pumili ng Pinagmulan ng Audio", - "endless_playback_description": "Awtomatikong magdagdag ng mga bagong kanta\nsa dulo ng pila", - "choose_your_region": "Piliin ang iyong rehiyon", - "choose_your_region_description": "Ito ay tutulong sa Spotube na ipakita sa iyo ang tamang content\npara sa iyong lokasyon.", - "choose_your_language": "Piliin ang iyong wika", - "help_project_grow": "Tulungan ang proyektong ito na lumago", - "help_project_grow_description": "Ang Spotube ay isang open-source na proyekto. Maaari mong tulungan ang proyektong ito na lumago sa pamamagitan ng pag-contribute sa proyekto, pag-ulat ng mga bug, o pagmungkahi ng mga bagong feature.", - "contribute_on_github": "Mag-contribute sa GitHub", - "donate_on_open_collective": "Mag-donate sa Open Collective", - "browse_anonymously": "Mag-browse nang Anonymous", - "enable_connect": "I-enable ang Connect", - "enable_connect_description": "Kontrolin ang Spotube mula sa ibang mga device", - "devices": "Mga Device", - "select": "Pumili", - "connect_client_alert": "Ikaw ay kontrolado ng {client}", - "this_device": "Ang Device na ito", - "remote": "Remote", - "stats": "Mga Stat", - "and_n_more": "at {count} pa", - "recently_played": "Kamakailan Lang na Ni-play", - "browse_more": "Mag-browse pa", - "no_title": "Walang Pamagat", - "not_playing": "Hindi tumutugtog", - "epic_failure": "Epic na pagkabigo!", - "added_num_tracks_to_queue": "Nagdagdag ng {tracks_length} na mga track sa pila", - "spotube_has_an_update": "Ang Spotube ay may update", - "download_now": "I-download Ngayon", - "nightly_version": "Ang Spotube Nightly {nightlyBuildNum} ay inilabas na", - "release_version": "Ang Spotube v{version} ay inilabas na", - "read_the_latest": "Basahin ang pinakabagong ", - "release_notes": "release notes", - "pick_color_scheme": "Pumili ng color scheme", - "save": "I-save", - "choose_the_device": "Piliin ang device:", - "multiple_device_connected": "Mayroong maraming device na nakakonekta.\nPiliin ang device kung saan mo gustong maganap ang aksyon na ito", - "nothing_found": "Walang nahanap", - "the_box_is_empty": "Ang kahon ay walang laman", - "top_artists": "Nangungunang mga Artista", - "top_albums": "Nangungunang mga Album", - "this_week": "Ngayong linggo", - "this_month": "Ngayong buwan", - "last_6_months": "Nakaraang 6 na buwan", - "this_year": "Ngayong taon", - "last_2_years": "Nakaraang 2 taon", - "all_time": "Lahat ng panahon", - "powered_by_provider": "Pinapagana ng {providerName}", - "email": "Email", - "profile_followers": "Mga Tagasunod", - "birthday": "Kaarawan", - "subscription": "Subscription", - "not_born": "Hindi pa ipinanganak", - "hacker": "Hacker", - "profile": "Profile", - "no_name": "Walang Pangalan", - "edit": "I-edit", - "user_profile": "Profile ng User", - "count_plays": "{count} na mga play", - "streaming_fees_hypothetical": "Mga bayarin sa streaming (hypothetical)", - "minutes_listened": "Mga minutong pinapakinggan", - "streamed_songs": "Mga na-stream na kanta", - "count_streams": "{count} na mga stream", - "owned_by_you": "Pag-aari mo", - "copied_shareurl_to_clipboard": "Na-kopya ang {shareUrl} sa clipboard", - "spotify_hipotetical_calculation": "*Ito ay kinalkula batay sa bawat stream\nna bayad ng Spotify na $0.003 hanggang $0.005. Ito ay isang hypothetical\nna pagkalkula para bigyan ang user ng ideya kung magkano\nang kanilang ibabayad sa mga artista kung sila ay nakikinig\nng kanilang kanta sa Spotify.", - "count_mins": "{minutes} minuto", - "summary_minutes": "minuto", - "summary_listened_to_music": "Nakinig sa musika", - "summary_songs": "mga kanta", - "summary_streamed_overall": "Na-stream sa kabuuan", - "summary_owed_to_artists": "Utang sa mga artista\nngayong buwan", - "summary_artists": "artista", - "summary_music_reached_you": "Umabot sa iyo ang musika", - "summary_full_albums": "buong album", - "summary_got_your_love": "Nakuha ang iyong pagmamahal", - "summary_playlists": "mga playlist", - "summary_were_on_repeat": "Pinu-playlst muli", - "total_money": "Kabuuang {money}", - "webview_not_found": "Hindi nahanap ang Webview", - "webview_not_found_description": "Walang webview runtime na naka-install sa iyong device.\nKung naka-install ito, siguraduhing nasa Environment PATH\n\nPagkatapos mag-install, i-restart ang app", - "unsupported_platform": "Hindi suportadong platform", - "cache_music": "I-cache ang musika", - "open": "Buksan", - "cache_folder": "Folder ng cache", - "export": "I-export", - "clear_cache": "Burahin ang cache", - "clear_cache_confirmation": "Gusto mo bang burahin ang cache?", - "export_cache_files": "I-export ang mga Naka-cache na File", - "found_n_files": "Nahanap ang {count} na mga file", - "export_cache_confirmation": "Gusto mo bang i-export ang mga file na ito sa", - "exported_n_out_of_m_files": "Na-export ang {filesExported} mula sa {files} na mga file", - "undo": "I-undo", - "download_all": "I-download lahat", - "add_all_to_playlist": "Idagdag lahat sa playlist", - "add_all_to_queue": "Idagdag lahat sa pila", - "play_all_next": "I-play lahat susunod", - "pause": "Pause", - "view_all": "Tingnan lahat", - "no_tracks_added_yet": "Mukhang wala ka pang idinaragdag na mga track", - "no_tracks": "Mukhang walang mga track dito", - "no_tracks_listened_yet": "Mukhang wala ka pang pinakikinggan", - "not_following_artists": "Hindi ka sumusunod sa anumang mga artista", - "no_favorite_albums_yet": "Mukhang wala ka pang idinagdag na anumang mga album sa iyong mga paborito", - "no_logs_found": "Walang nahanap na mga log", - "youtube_engine": "YouTube Engine", - "youtube_engine_not_installed_title": "Hindi naka-install ang {engine}", - "youtube_engine_not_installed_message": "Hindi naka-install ang {engine} sa iyong sistema.", - "youtube_engine_set_path": "Siguraduhing available ito sa PATH variable o\ni-set ang absolute path sa {engine} executable sa ibaba", - "youtube_engine_unix_issue_message": "Sa macOS/Linux/unix tulad ng OS, ang pag-set ng path sa .zshrc/.bashrc/.bash_profile atbp. ay hindi gagana.\nKailangan mong i-set ang path sa configuration file ng shell", - "download": "I-download", - "file_not_found": "Hindi nahanap ang file", - "custom": "Custom", - "add_custom_url": "Magdagdag ng custom URL" -} \ No newline at end of file + "guest": "Bisita", + "browse": "Mag-browse", + "search": "Maghanap", + "library": "Silid-aklatan", + "lyrics": "Mga Liriko", + "settings": "Mga Setting", + "genre_categories_filter": "I-filter ang mga kategorya o genre...", + "genre": "Genre", + "personalized": "Naka-personalize", + "featured": "Tampok", + "new_releases": "Mga Bagong Paglabas", + "songs": "Mga Kanta", + "playing_track": "Tumutugtog ang {track}", + "queue_clear_alert": "Ito ay magbubura ng kasalukuyang pila. {track_length} na mga track ang tatanggalin\nGusto mo bang magpatuloy?", + "load_more": "Mag-load pa", + "playlists": "Mga Playlist", + "artists": "Mga Artista", + "albums": "Mga Album", + "tracks": "Mga Track", + "downloads": "Mga Download", + "filter_playlists": "I-filter ang iyong mga playlist...", + "liked_tracks": "Mga Nagustuhang Track", + "liked_tracks_description": "Lahat ng mga track na iyong nagustuhan", + "playlist": "Playlist", + "create_a_playlist": "Gumawa ng playlist", + "update_playlist": "I-update ang playlist", + "create": "Lumikha", + "cancel": "Ikansela", + "update": "I-update", + "playlist_name": "Pangalan ng Playlist", + "name_of_playlist": "Pangalan ng playlist", + "description": "Paglalarawan", + "public": "Pampubliko", + "collaborative": "Pakikipagtulungan", + "search_local_tracks": "Maghanap ng mga lokal na track...", + "play": "I-play", + "delete": "Burahin", + "none": "Wala", + "sort_a_z": "Ayusin ayon sa A-Z", + "sort_z_a": "Ayusin ayon sa Z-A", + "sort_artist": "Ayusin ayon sa Artista", + "sort_album": "Ayusin ayon sa Album", + "sort_duration": "Ayusin ayon sa Tagal", + "sort_tracks": "Ayusin ang mga Track", + "currently_downloading": "Kasalukuyang Nagda-download ({tracks_length})", + "cancel_all": "Kanselahin Lahat", + "filter_artist": "I-filter ang mga artista...", + "followers": "{followers} na mga Tagasunod", + "add_artist_to_blacklist": "Idagdag ang artista sa blacklist", + "top_tracks": "Mga Nangungunang Track", + "fans_also_like": "Gusto rin ng mga tagahanga", + "loading": "Naglo-load...", + "artist": "Artista", + "blacklisted": "Naka-blacklist", + "following": "Sinusundan", + "follow": "Sundan", + "artist_url_copied": "Na-copy sa clipboard ang URL ng artista", + "added_to_queue": "Idinagdag ang {tracks} na mga track sa pila", + "filter_albums": "I-filter ang mga album...", + "synced": "Naka-sync", + "plain": "Simpleng", + "shuffle": "I-shuffle", + "search_tracks": "Maghanap ng mga track...", + "released": "Inilabas", + "error": "Error {error}", + "title": "Pamagat", + "time": "Oras", + "more_actions": "Higit pang mga aksyon", + "download_count": "I-download ({count})", + "add_count_to_playlist": "Idagdag ({count}) sa Playlist", + "add_count_to_queue": "Idagdag ({count}) sa Pila", + "play_count_next": "I-play ({count}) kasunod", + "album": "Album", + "copied_to_clipboard": "Na-copy ang {data} sa clipboard", + "add_to_following_playlists": "Idagdag ang {track} sa mga sumusunod na Playlist", + "add": "Idagdag", + "added_track_to_queue": "Idinagdag ang {track} sa pila", + "add_to_queue": "Idagdag sa pila", + "track_will_play_next": "Ang {track} ay tutugtog susunod", + "play_next": "I-play susunod", + "removed_track_from_queue": "Tinanggal ang {track} mula sa pila", + "remove_from_queue": "Alisin mula sa pila", + "remove_from_favorites": "Alisin mula sa mga paborito", + "save_as_favorite": "I-save bilang paborito", + "add_to_playlist": "Idagdag sa playlist", + "remove_from_playlist": "Alisin mula sa playlist", + "add_to_blacklist": "Idagdag sa blacklist", + "remove_from_blacklist": "Alisin mula sa blacklist", + "share": "Ibahagi", + "mini_player": "Mini Player", + "slide_to_seek": "I-slide para mag-seek pasulong o pabalik", + "shuffle_playlist": "I-shuffle ang playlist", + "unshuffle_playlist": "I-unshuffle ang playlist", + "previous_track": "Nakaraang track", + "next_track": "Susunod na track", + "pause_playback": "I-pause ang Playback", + "resume_playback": "Ipagpatuloy ang Playback", + "loop_track": "I-loop ang track", + "no_loop": "Walang loop", + "repeat_playlist": "Ulitin ang playlist", + "queue": "Pila", + "alternative_track_sources": "Alternatibong mga pinagmulan ng track", + "download_track": "I-download ang track", + "tracks_in_queue": "{tracks} na mga track sa pila", + "clear_all": "Burahin lahat", + "show_hide_ui_on_hover": "Ipakita/Itago ang UI sa hover", + "always_on_top": "Palaging nasa ibabaw", + "exit_mini_player": "Lumabas sa Mini player", + "download_location": "Lokasyon ng pag-download", + "local_library": "Lokal na silid-aklatan", + "add_library_location": "Idagdag sa silid-aklatan", + "remove_library_location": "Alisin mula sa silid-aklatan", + "account": "Account", + "login_with_spotify": "Mag-login gamit ang iyong Spotify account", + "connect_with_spotify": "Kumonekta sa Spotify", + "logout": "Mag-logout", + "logout_of_this_account": "Mag-logout sa account na ito", + "language_region": "Wika at Rehiyon", + "language": "Wika", + "system_default": "Default ng Sistema", + "market_place_region": "Rehiyon ng Marketplace", + "recommendation_country": "Bansang Inirerekomenda", + "appearance": "Hitsura", + "layout_mode": "Mode ng Layout", + "override_layout_settings": "I-override ang mga setting ng responsive layout mode", + "adaptive": "Umaangkop", + "compact": "Kompakto", + "extended": "Pinalawig", + "theme": "Tema", + "dark": "Madilim", + "light": "Maliwanag", + "system": "Sistema", + "accent_color": "Kulay ng Accent", + "sync_album_color": "I-sync ang kulay ng album", + "sync_album_color_description": "Ginagamit ang pangunahing kulay ng album art bilang kulay ng accent", + "playback": "Playback", + "audio_quality": "Kalidad ng Audio", + "high": "Mataas", + "low": "Mababa", + "pre_download_play": "Mag-pre-download at i-play", + "pre_download_play_description": "Sa halip na mag-stream ng audio, mag-download ng bytes at i-play sa halip (Inirerekomenda para sa mga gumagamit ng mataas na bandwidth)", + "skip_non_music": "Laktawan ang mga segment na hindi musika (SponsorBlock)", + "blacklist_description": "Mga track at artista na nasa blacklist", + "wait_for_download_to_finish": "Mangyaring maghintay para matapos ang kasalukuyang pag-download", + "desktop": "Desktop", + "close_behavior": "Pag-uugali ng Pagsara", + "close": "Isara", + "minimize_to_tray": "I-minimize sa tray", + "show_tray_icon": "Ipakita ang icon ng System tray", + "about": "Tungkol sa", + "u_love_spotube": "Alam naming gusto mo ang Spotube", + "check_for_updates": "Maghanap ng mga update", + "about_spotube": "Tungkol sa Spotube", + "blacklist": "Blacklist", + "please_sponsor": "Mangyaring Mag-sponsor/Mag-donate", + "spotube_description": "Spotube, isang magaan, cross-platform, libreng-para-sa-lahat na spotify client", + "version": "Bersyon", + "build_number": "Build Number", + "founder": "Nagtatag", + "repository": "Repository", + "bug_issues": "Bug+Mga Isyu", + "made_with": "Ginawa nang may ❤️ sa Bangladesh🇧🇩", + "kingkor_roy_tirtho": "Kingkor Roy Tirtho", + "copyright": "© 2021-{current_year} Kingkor Roy Tirtho", + "license": "Lisensya", + "add_spotify_credentials": "Idagdag ang iyong mga kredensyal sa spotify para makapagsimula", + "credentials_will_not_be_shared_disclaimer": "Huwag mag-alala, ang alinman sa iyong mga kredensyal ay hindi kokolektahin o ibabahagi sa sinuman", + "know_how_to_login": "Hindi mo alam kung paano gawin ito?", + "follow_step_by_step_guide": "Sundin ang Hakbang-hakbang na gabay", + "spotify_cookie": "Spotify {name} Cookie", + "cookie_name_cookie": "{name} Cookie", + "fill_in_all_fields": "Mangyaring punan ang lahat ng field", + "submit": "Isumite", + "exit": "Lumabas", + "previous": "Nakaraan", + "next": "Susunod", + "done": "Tapos na", + "step_1": "Hakbang 1", + "first_go_to": "Una, Pumunta sa", + "login_if_not_logged_in": "at Mag-login/Mag-signup kung hindi ka naka-log in", + "step_2": "Hakbang 2", + "step_2_steps": "1. Kapag naka-log in ka na, pindutin ang F12 o i-right click ang Mouse > Inspect para Buksan ang Browser devtools.\n2. Pagkatapos ay pumunta sa \"Application\" Tab (Chrome, Edge, Brave atbp..) o \"Storage\" Tab (Firefox, Palemoon atbp..)\n3. Pumunta sa \"Cookies\" na seksyon at pagkatapos sa \"https://accounts.spotify.com\" na subseksyon", + "step_3": "Hakbang 3", + "step_3_steps": "Kopyahin ang halaga ng \"sp_dc\" Cookie", + "success_emoji": "Tagumpay🥳", + "success_message": "Ngayon ay matagumpay kang Naka-log in gamit ang iyong Spotify account. Magaling, kaibigan!", + "step_4": "Hakbang 4", + "step_4_steps": "I-paste ang na-kopyang halaga ng \"sp_dc\"", + "something_went_wrong": "May nangyaring mali", + "piped_instance": "Instance ng Piped Server", + "piped_description": "Ang instance ng Piped server na gagamitin para sa pagtutugma ng track", + "piped_warning": "Maaaring hindi gumagana nang mabuti ang ilan sa mga ito. Kaya gamitin sa sarili mong peligro", + "invidious_instance": "Instance ng Invidious Server", + "invidious_description": "Ang instance ng Invidious server na gagamitin para sa pagtutugma ng track", + "invidious_warning": "Maaaring hindi gumagana nang mabuti ang ilan sa mga ito. Kaya gamitin sa sarili mong peligro", + "generate": "Gumawa", + "track_exists": "Ang Track na {track} ay umiiral na", + "replace_downloaded_tracks": "Palitan ang lahat ng na-download na mga track", + "skip_download_tracks": "Laktawan ang pag-download ng lahat ng na-download na mga track", + "do_you_want_to_replace": "Gusto mo bang palitan ang umiiral na track??", + "replace": "Palitan", + "skip": "Laktawan", + "select_up_to_count_type": "Pumili ng hanggang {count} {type}", + "select_genres": "Pumili ng mga Genre", + "add_genres": "Magdagdag ng mga Genre", + "country": "Bansa", + "number_of_tracks_generate": "Bilang ng mga track na gagawin", + "acousticness": "Acoustic-ness", + "danceability": "Kakayahang Sayawin", + "energy": "Enerhiya", + "instrumentalness": "Instrumental-ness", + "liveness": "Liveness", + "loudness": "Lakas", + "speechiness": "Pagsasalita", + "valence": "Valence", + "popularity": "Popularidad", + "key": "Key", + "duration": "Tagal (s)", + "tempo": "Tempo (BPM)", + "mode": "Mode", + "time_signature": "Time Signature", + "short": "Maikli", + "medium": "Katamtaman", + "long": "Mahaba", + "min": "Min", + "max": "Max", + "target": "Target", + "moderate": "Katamtaman", + "deselect_all": "Alisin ang Pagkakapili sa Lahat", + "select_all": "Piliin Lahat", + "are_you_sure": "Sigurado ka ba?", + "generating_playlist": "Gumagawa ng iyong custom na playlist...", + "selected_count_tracks": "Napili ang {count} na mga track", + "download_warning": "Kung nag-download ka ng lahat ng Track sa maramihan, malinaw na nagpa-pirate ka ng Musika at nagsasanhi ng pinsala sa creative society ng Musika. Sana ay alam mo ito. Palaging, subukang igalang at suportahan ang masipag na paggawa ng Artist", + "download_ip_ban_warning": "Sa nga pala, ang iyong IP ay maaaring ma-block sa YouTube dahil sa sobrang mga kahilingan sa pag-download kaysa sa karaniwan. Ang IP block ay nangangahulugang hindi mo magagamit ang YouTube (kahit na naka-log in ka) sa loob ng hindi bababa sa 2-3 buwan mula sa device na may IP na iyon. At hindi pinanghahawakan ng Spotube ang anumang responsibilidad kung mangyayari ito", + "by_clicking_accept_terms": "Sa pamamagitan ng pag-click sa 'tanggapin', sumasang-ayon ka sa mga sumusunod na tuntunin:", + "download_agreement_1": "Alam kong nagpa-pirate ako ng Musika. Masama ako", + "download_agreement_2": "Susuportahan ko ang Artist saan man ako maaari at ginagawa ko lang ito dahil wala akong pera para bumili ng kanilang sining", + "download_agreement_3": "Lubos kong nauunawaan na ang aking IP ay maaaring ma-block sa YouTube at hindi ko pinanghahawakan ang Spotube o ang kanyang mga may-ari/nag-ambag na responsable para sa anumang aksidente na sanhi ng aking kasalukuyang aksyon", + "decline": "Tanggihan", + "accept": "Tanggapin", + "details": "Mga Detalye", + "youtube": "YouTube", + "channel": "Channel", + "likes": "Mga Like", + "dislikes": "Mga Dislike", + "views": "Mga View", + "streamUrl": "Stream URL", + "stop": "Ihinto", + "sort_newest": "Ayusin ayon sa pinakabagong idinagdag", + "sort_oldest": "Ayusin ayon sa pinakalumang idinagdag", + "sleep_timer": "Sleep Timer", + "mins": "{minutes} Minuto", + "hours": "{hours} Oras", + "hour": "{hours} Oras", + "custom_hours": "Custom na Oras", + "logs": "Mga Log", + "developers": "Mga Developer", + "not_logged_in": "Hindi ka naka-log in", + "search_mode": "Mode ng Paghahanap", + "audio_source": "Pinagmulan ng Audio", + "ok": "Ok", + "failed_to_encrypt": "Nabigong i-encrypt", + "encryption_failed_warning": "Gumagamit ng encryption ang Spotube para ligtas na i-store ang iyong data. Ngunit nabigo. Kaya babalik ito sa hindi secure na storage\nKung gumagamit ka ng linux, mangyaring tiyakin na mayroon kang anumang secret-service na naka-install (gnome-keyring, kde-wallet, keepassxc atbp)", + "querying_info": "Kinukuha ang impormasyon...", + "piped_api_down": "Ang Piped API ay hindi gumagana", + "piped_down_error_instructions": "Ang instance ng Piped na {pipedInstance} ay kasalukuyang hindi gumagana\n\nMaaari mong baguhin ang instance o baguhin ang 'Uri ng API' sa opisyal na YouTube API\n\nSiguraduhing i-restart ang app pagkatapos ng pagbabago", + "you_are_offline": "Kasalukuyan kang offline", + "connection_restored": "Naibalik na ang iyong koneksyon sa internet", + "use_system_title_bar": "Gamitin ang title bar ng system", + "crunching_results": "Pinaproseso ang mga resulta...", + "search_to_get_results": "Maghanap para makakuha ng mga resulta", + "use_amoled_mode": "Matingkad na itim na madilim na tema", + "pitch_dark_theme": "AMOLED Mode", + "normalize_audio": "I-normalize ang audio", + "change_cover": "Baguhin ang cover", + "add_cover": "Magdagdag ng cover", + "restore_defaults": "Ibalik ang mga default", + "download_music_codec": "Codec para sa pag-download ng musika", + "streaming_music_codec": "Codec para sa pag-stream ng musika", + "login_with_lastfm": "Mag-login gamit ang Last.fm", + "connect": "Kumonekta", + "disconnect_lastfm": "Idiskonekta ang Last.fm", + "disconnect": "Idiskonekta", + "username": "Username", + "password": "Password", + "login": "Mag-login", + "login_with_your_lastfm": "Mag-login gamit ang iyong Last.fm account", + "scrobble_to_lastfm": "I-scrobble sa Last.fm", + "go_to_album": "Pumunta sa Album", + "discord_rich_presence": "Discord Rich Presence", + "browse_all": "I-browse Lahat", + "genres": "Mga Genre", + "explore_genres": "Tuklasin ang mga Genre", + "friends": "Mga Kaibigan", + "no_lyrics_available": "Paumanhin, hindi mahanap ang lyrics para sa track na ito", + "start_a_radio": "Magsimula ng Radio", + "how_to_start_radio": "Paano mo gustong simulan ang radio?", + "replace_queue_question": "Gusto mo bang palitan ang kasalukuyang pila o idagdag dito?", + "endless_playback": "Walang Hanggang Playback", + "delete_playlist": "Burahin ang Playlist", + "delete_playlist_confirmation": "Sigurado ka bang gusto mong burahin ang playlist na ito?", + "local_tracks": "Mga Lokal na Track", + "local_tab": "Lokal", + "song_link": "Link ng Kanta", + "skip_this_nonsense": "Laktawan ang kalokohan na ito", + "freedom_of_music": "\"Kalayaan ng Musika\"", + "freedom_of_music_palm": "\"Kalayaan ng Musika sa iyong palad\"", + "get_started": "Magsimula na tayo", + "youtube_source_description": "Inirerekomenda at pinakamahusay na gumagana.", + "piped_source_description": "Gusto ng kalayaan? Kapareho ng YouTube ngunit mas malaya.", + "jiosaavn_source_description": "Pinakamahusay para sa rehiyon ng South Asia.", + "invidious_source_description": "Katulad ng Piped ngunit may mas mataas na availability.", + "highest_quality": "Pinakamataas na Kalidad: {quality}", + "select_audio_source": "Pumili ng Pinagmulan ng Audio", + "endless_playback_description": "Awtomatikong magdagdag ng mga bagong kanta\nsa dulo ng pila", + "choose_your_region": "Piliin ang iyong rehiyon", + "choose_your_region_description": "Ito ay tutulong sa Spotube na ipakita sa iyo ang tamang content\npara sa iyong lokasyon.", + "choose_your_language": "Piliin ang iyong wika", + "help_project_grow": "Tulungan ang proyektong ito na lumago", + "help_project_grow_description": "Ang Spotube ay isang open-source na proyekto. Maaari mong tulungan ang proyektong ito na lumago sa pamamagitan ng pag-contribute sa proyekto, pag-ulat ng mga bug, o pagmungkahi ng mga bagong feature.", + "contribute_on_github": "Mag-contribute sa GitHub", + "donate_on_open_collective": "Mag-donate sa Open Collective", + "browse_anonymously": "Mag-browse nang Anonymous", + "enable_connect": "I-enable ang Connect", + "enable_connect_description": "Kontrolin ang Spotube mula sa ibang mga device", + "devices": "Mga Device", + "select": "Pumili", + "connect_client_alert": "Ikaw ay kontrolado ng {client}", + "this_device": "Ang Device na ito", + "remote": "Remote", + "stats": "Mga Stat", + "and_n_more": "at {count} pa", + "recently_played": "Kamakailan Lang na Ni-play", + "browse_more": "Mag-browse pa", + "no_title": "Walang Pamagat", + "not_playing": "Hindi tumutugtog", + "epic_failure": "Epic na pagkabigo!", + "added_num_tracks_to_queue": "Nagdagdag ng {tracks_length} na mga track sa pila", + "spotube_has_an_update": "Ang Spotube ay may update", + "download_now": "I-download Ngayon", + "nightly_version": "Ang Spotube Nightly {nightlyBuildNum} ay inilabas na", + "release_version": "Ang Spotube v{version} ay inilabas na", + "read_the_latest": "Basahin ang pinakabagong ", + "release_notes": "release notes", + "pick_color_scheme": "Pumili ng color scheme", + "save": "I-save", + "choose_the_device": "Piliin ang device:", + "multiple_device_connected": "Mayroong maraming device na nakakonekta.\nPiliin ang device kung saan mo gustong maganap ang aksyon na ito", + "nothing_found": "Walang nahanap", + "the_box_is_empty": "Ang kahon ay walang laman", + "top_artists": "Nangungunang mga Artista", + "top_albums": "Nangungunang mga Album", + "this_week": "Ngayong linggo", + "this_month": "Ngayong buwan", + "last_6_months": "Nakaraang 6 na buwan", + "this_year": "Ngayong taon", + "last_2_years": "Nakaraang 2 taon", + "all_time": "Lahat ng panahon", + "powered_by_provider": "Pinapagana ng {providerName}", + "email": "Email", + "profile_followers": "Mga Tagasunod", + "birthday": "Kaarawan", + "subscription": "Subscription", + "not_born": "Hindi pa ipinanganak", + "hacker": "Hacker", + "profile": "Profile", + "no_name": "Walang Pangalan", + "edit": "I-edit", + "user_profile": "Profile ng User", + "count_plays": "{count} na mga play", + "streaming_fees_hypothetical": "Mga bayarin sa streaming (hypothetical)", + "minutes_listened": "Mga minutong pinapakinggan", + "streamed_songs": "Mga na-stream na kanta", + "count_streams": "{count} na mga stream", + "owned_by_you": "Pag-aari mo", + "copied_shareurl_to_clipboard": "Na-kopya ang {shareUrl} sa clipboard", + "spotify_hipotetical_calculation": "*Ito ay kinalkula batay sa bawat stream\nna bayad ng Spotify na $0.003 hanggang $0.005. Ito ay isang hypothetical\nna pagkalkula para bigyan ang user ng ideya kung magkano\nang kanilang ibabayad sa mga artista kung sila ay nakikinig\nng kanilang kanta sa Spotify.", + "count_mins": "{minutes} minuto", + "summary_minutes": "minuto", + "summary_listened_to_music": "Nakinig sa musika", + "summary_songs": "mga kanta", + "summary_streamed_overall": "Na-stream sa kabuuan", + "summary_owed_to_artists": "Utang sa mga artista\nngayong buwan", + "summary_artists": "artista", + "summary_music_reached_you": "Umabot sa iyo ang musika", + "summary_full_albums": "buong album", + "summary_got_your_love": "Nakuha ang iyong pagmamahal", + "summary_playlists": "mga playlist", + "summary_were_on_repeat": "Pinu-playlst muli", + "total_money": "Kabuuang {money}", + "webview_not_found": "Hindi nahanap ang Webview", + "webview_not_found_description": "Walang webview runtime na naka-install sa iyong device.\nKung naka-install ito, siguraduhing nasa Environment PATH\n\nPagkatapos mag-install, i-restart ang app", + "unsupported_platform": "Hindi suportadong platform", + "cache_music": "I-cache ang musika", + "open": "Buksan", + "cache_folder": "Folder ng cache", + "export": "I-export", + "clear_cache": "Burahin ang cache", + "clear_cache_confirmation": "Gusto mo bang burahin ang cache?", + "export_cache_files": "I-export ang mga Naka-cache na File", + "found_n_files": "Nahanap ang {count} na mga file", + "export_cache_confirmation": "Gusto mo bang i-export ang mga file na ito sa", + "exported_n_out_of_m_files": "Na-export ang {filesExported} mula sa {files} na mga file", + "undo": "I-undo", + "download_all": "I-download lahat", + "add_all_to_playlist": "Idagdag lahat sa playlist", + "add_all_to_queue": "Idagdag lahat sa pila", + "play_all_next": "I-play lahat susunod", + "pause": "Pause", + "view_all": "Tingnan lahat", + "no_tracks_added_yet": "Mukhang wala ka pang idinaragdag na mga track", + "no_tracks": "Mukhang walang mga track dito", + "no_tracks_listened_yet": "Mukhang wala ka pang pinakikinggan", + "not_following_artists": "Hindi ka sumusunod sa anumang mga artista", + "no_favorite_albums_yet": "Mukhang wala ka pang idinagdag na anumang mga album sa iyong mga paborito", + "no_logs_found": "Walang nahanap na mga log", + "youtube_engine": "YouTube Engine", + "youtube_engine_not_installed_title": "Hindi naka-install ang {engine}", + "youtube_engine_not_installed_message": "Hindi naka-install ang {engine} sa iyong sistema.", + "youtube_engine_set_path": "Siguraduhing available ito sa PATH variable o\ni-set ang absolute path sa {engine} executable sa ibaba", + "youtube_engine_unix_issue_message": "Sa macOS/Linux/unix tulad ng OS, ang pag-set ng path sa .zshrc/.bashrc/.bash_profile atbp. ay hindi gagana.\nKailangan mong i-set ang path sa configuration file ng shell", + "download": "I-download", + "file_not_found": "Hindi nahanap ang file", + "custom": "Custom", + "add_custom_url": "Magdagdag ng custom URL", + "edit_port": "I-edit ang port", + "port_helper_msg": "Ang default ay -1 na nagpapahiwatig ng random na numero. Kung na-configure mo ang firewall, inirerekomenda na itakda ito.", + "connect_request": "Payagan ang {client} na kumonekta?", + "connection_request_denied": "Tanggihan ang koneksyon. Tinanggihan ng gumagamit ang pag-access." +} \ No newline at end of file diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 1e659cc5..7c3bc42f 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -426,5 +426,9 @@ "download": "İndir", "file_not_found": "Dosya bulunamadı", "custom": "Özel", - "add_custom_url": "Özel URL ekle" + "add_custom_url": "Özel URL ekle", + "edit_port": "Portu düzenle", + "port_helper_msg": "Varsayılan -1'dir, bu da rastgele bir sayıyı gösterir. Bir güvenlik duvarınız varsa, bunu ayarlamanız önerilir.", + "connect_request": "{client} bağlantısına izin verilsin mi?", + "connection_request_denied": "Bağlantı reddedildi. Kullanıcı erişimi reddetti." } \ No newline at end of file diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index bc731240..9cefc4a8 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -426,5 +426,9 @@ "download": "Завантажити", "file_not_found": "Файл не знайдено", "custom": "Користувацький", - "add_custom_url": "Додати користувацький URL" + "add_custom_url": "Додати користувацький URL", + "edit_port": "Редагувати порт", + "port_helper_msg": "За замовчуванням -1, що означає випадкове число. Якщо у вас налаштований брандмауер, рекомендується це налаштувати.", + "connect_request": "Дозволити {client} підключення?", + "connection_request_denied": "Підключення відхилено. Користувач відмовив у доступі." } \ No newline at end of file diff --git a/lib/l10n/app_vi.arb b/lib/l10n/app_vi.arb index 75f8e3f7..47e5cf27 100644 --- a/lib/l10n/app_vi.arb +++ b/lib/l10n/app_vi.arb @@ -426,5 +426,9 @@ "download": "Tải xuống", "file_not_found": "Không tìm thấy tệp", "custom": "Tùy chỉnh", - "add_custom_url": "Thêm URL tùy chỉnh" + "add_custom_url": "Thêm URL tùy chỉnh", + "edit_port": "Chỉnh sửa cổng", + "port_helper_msg": "Mặc định là -1, có nghĩa là số ngẫu nhiên. Nếu bạn đã cấu hình tường lửa, nên đặt điều này.", + "connect_request": "Cho phép {client} kết nối?", + "connection_request_denied": "Kết nối bị từ chối. Người dùng đã từ chối quyền truy cập." } \ No newline at end of file diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 03ebae12..f68b30f5 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -426,5 +426,9 @@ "download": "下载", "file_not_found": "文件未找到", "custom": "自定义", - "add_custom_url": "添加自定义 URL" + "add_custom_url": "添加自定义 URL", + "edit_port": "编辑端口", + "port_helper_msg": "默认值为-1,表示随机数。如果您已配置防火墙,建议设置此项。", + "connect_request": "允许 {client} 连接吗?", + "connection_request_denied": "连接被拒绝。用户拒绝访问。" } \ No newline at end of file diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index 457e29b6..35cafab8 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -2704,6 +2704,30 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Add custom URL'** String get add_custom_url; + + /// No description provided for @edit_port. + /// + /// In en, this message translates to: + /// **'Edit port'** + String get edit_port; + + /// No description provided for @port_helper_msg. + /// + /// In en, this message translates to: + /// **'Default is -1 which indicates random number. If you\'ve firewall configured, setting this is recommended.'** + String get port_helper_msg; + + /// No description provided for @connect_request. + /// + /// In en, this message translates to: + /// **'Allow {client} to connect?'** + String connect_request(Object client); + + /// No description provided for @connection_request_denied. + /// + /// In en, this message translates to: + /// **'Connection denied. User denied access.'** + String get connection_request_denied; } class _AppLocalizationsDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/generated/app_localizations_ar.dart b/lib/l10n/generated/app_localizations_ar.dart index 19f23d09..e713fe4e 100644 --- a/lib/l10n/generated/app_localizations_ar.dart +++ b/lib/l10n/generated/app_localizations_ar.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsAr extends AppLocalizations { @override String get add_custom_url => 'إضافة URL مخصص'; + + @override + String get edit_port => 'تعديل المنفذ'; + + @override + String get port_helper_msg => 'القيمة الافتراضية هي -1 والتي تشير إلى رقم عشوائي. إذا كان لديك جدار ناري مُعد، يُوصى بتعيين هذا.'; + + @override + String connect_request(Object client) { + return 'السماح لـ $client بالاتصال؟'; + } + + @override + String get connection_request_denied => 'تم رفض الاتصال. المستخدم رفض الوصول.'; } diff --git a/lib/l10n/generated/app_localizations_bn.dart b/lib/l10n/generated/app_localizations_bn.dart index 4009f3dd..ae9c842a 100644 --- a/lib/l10n/generated/app_localizations_bn.dart +++ b/lib/l10n/generated/app_localizations_bn.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsBn extends AppLocalizations { @override String get add_custom_url => 'কাস্টম URL যোগ করুন'; + + @override + String get edit_port => 'পোর্ট সম্পাদনা করুন'; + + @override + String get port_helper_msg => 'ডিফল্ট হল -1 যা এলোমেলো সংখ্যা নির্দেশ করে। যদি আপনার ফায়ারওয়াল কনফিগার করা থাকে, তবে এটি সেট করা সুপারিশ করা হয়।'; + + @override + String connect_request(Object client) { + return '$client কে সংযোগ করতে অনুমতি দেবেন?'; + } + + @override + String get connection_request_denied => 'সংযোগ অস্বীকৃত। ব্যবহারকারী প্রবেশাধিকার অস্বীকার করেছে।'; } diff --git a/lib/l10n/generated/app_localizations_ca.dart b/lib/l10n/generated/app_localizations_ca.dart index c9f80a5a..1e78b087 100644 --- a/lib/l10n/generated/app_localizations_ca.dart +++ b/lib/l10n/generated/app_localizations_ca.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsCa extends AppLocalizations { @override String get add_custom_url => 'Afegir URL personalitzada'; + + @override + String get edit_port => 'Editar port'; + + @override + String get port_helper_msg => 'El valor per defecte és -1, que indica un número aleatori. Si teniu un tallafoc configurat, es recomana establir-ho.'; + + @override + String connect_request(Object client) { + return 'Permetre que $client es connecti?'; + } + + @override + String get connection_request_denied => 'Connexió denegada. L\'usuari ha denegat l\'accés.'; } diff --git a/lib/l10n/generated/app_localizations_cs.dart b/lib/l10n/generated/app_localizations_cs.dart index 4bacb229..dcf39b70 100644 --- a/lib/l10n/generated/app_localizations_cs.dart +++ b/lib/l10n/generated/app_localizations_cs.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsCs extends AppLocalizations { @override String get add_custom_url => 'Přidat vlastní URL'; + + @override + String get edit_port => 'Upravit port'; + + @override + String get port_helper_msg => 'Výchozí hodnota je -1, což znamená náhodné číslo. Pokud máte nakonfigurován firewall, doporučuje se to nastavit.'; + + @override + String connect_request(Object client) { + return 'Povolit $client připojení?'; + } + + @override + String get connection_request_denied => 'Připojení bylo zamítnuto. Uživatel odmítl přístup.'; } diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index a3b51c8a..17b9eac4 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsDe extends AppLocalizations { @override String get add_custom_url => 'Benutzerdefinierte URL hinzufügen'; + + @override + String get edit_port => 'Port bearbeiten'; + + @override + String get port_helper_msg => 'Der Standardwert ist -1, was eine zufällige Zahl bedeutet. Wenn Sie eine Firewall konfiguriert haben, wird empfohlen, dies einzustellen.'; + + @override + String connect_request(Object client) { + return '$client die Verbindung erlauben?'; + } + + @override + String get connection_request_denied => 'Verbindung abgelehnt. Benutzer hat den Zugriff verweigert.'; } diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index 8ad7ca57..91ac3586 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsEn extends AppLocalizations { @override String get add_custom_url => 'Add custom URL'; + + @override + String get edit_port => 'Edit port'; + + @override + String get port_helper_msg => 'Default is -1 which indicates random number. If you\'ve firewall configured, setting this is recommended.'; + + @override + String connect_request(Object client) { + return 'Allow $client to connect?'; + } + + @override + String get connection_request_denied => 'Connection denied. User denied access.'; } diff --git a/lib/l10n/generated/app_localizations_es.dart b/lib/l10n/generated/app_localizations_es.dart index 7db6473a..5a05dc78 100644 --- a/lib/l10n/generated/app_localizations_es.dart +++ b/lib/l10n/generated/app_localizations_es.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsEs extends AppLocalizations { @override String get add_custom_url => 'Agregar URL personalizada'; + + @override + String get edit_port => 'Editar puerto'; + + @override + String get port_helper_msg => 'El valor predeterminado es -1, lo que indica un número aleatorio. Si tienes un firewall configurado, se recomienda establecer esto.'; + + @override + String connect_request(Object client) { + return '¿Permitir que $client se conecte?'; + } + + @override + String get connection_request_denied => 'Conexión denegada. El usuario denegó el acceso.'; } diff --git a/lib/l10n/generated/app_localizations_eu.dart b/lib/l10n/generated/app_localizations_eu.dart index 96615c5b..6a5d81d7 100644 --- a/lib/l10n/generated/app_localizations_eu.dart +++ b/lib/l10n/generated/app_localizations_eu.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsEu extends AppLocalizations { @override String get add_custom_url => 'Gehitu URL pertsonalizatua'; + + @override + String get edit_port => 'Editatu portua'; + + @override + String get port_helper_msg => 'Lehenetsitako balioa -1 da, zenbaki aleatorioa adierazten duena. Su firewall konfiguratu baduzu, gomendatzen da hau ezartzea.'; + + @override + String connect_request(Object client) { + return '$client konektatzea baimendu?'; + } + + @override + String get connection_request_denied => 'Konektatzea ukatu da. Erabiltzaileak sarbidea ukatu du.'; } diff --git a/lib/l10n/generated/app_localizations_fa.dart b/lib/l10n/generated/app_localizations_fa.dart index 657d01e1..d3e13d97 100644 --- a/lib/l10n/generated/app_localizations_fa.dart +++ b/lib/l10n/generated/app_localizations_fa.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsFa extends AppLocalizations { @override String get add_custom_url => 'اضافه کردن URL سفارشی'; + + @override + String get edit_port => 'ویرایش پورت'; + + @override + String get port_helper_msg => 'پیش‌فرض -1 است که نشان‌دهنده یک عدد تصادفی است. اگر فایروال شما پیکربندی شده است، توصیه می‌شود این را تنظیم کنید.'; + + @override + String connect_request(Object client) { + return 'آیا اجازه می‌دهید $client متصل شود؟'; + } + + @override + String get connection_request_denied => 'اتصال رد شد. کاربر دسترسی را رد کرد.'; } diff --git a/lib/l10n/generated/app_localizations_fi.dart b/lib/l10n/generated/app_localizations_fi.dart index a1c7579f..f31b6609 100644 --- a/lib/l10n/generated/app_localizations_fi.dart +++ b/lib/l10n/generated/app_localizations_fi.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsFi extends AppLocalizations { @override String get add_custom_url => 'Lisää mukautettu URL'; + + @override + String get edit_port => 'Muokkaa porttia'; + + @override + String get port_helper_msg => 'Oletusarvo on -1, mikä tarkoittaa satunnaista numeroa. Jos sinulla on palomuuri määritetty, tämän asettamista suositellaan.'; + + @override + String connect_request(Object client) { + return 'Salli $client yhdistää?'; + } + + @override + String get connection_request_denied => 'Yhteys evätty. Käyttäjä eväsi pääsyn.'; } diff --git a/lib/l10n/generated/app_localizations_fr.dart b/lib/l10n/generated/app_localizations_fr.dart index 4e56d666..56caeae7 100644 --- a/lib/l10n/generated/app_localizations_fr.dart +++ b/lib/l10n/generated/app_localizations_fr.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsFr extends AppLocalizations { @override String get add_custom_url => 'Ajouter une URL personnalisée'; + + @override + String get edit_port => 'Modifier le port'; + + @override + String get port_helper_msg => 'La valeur par défaut est -1, ce qui indique un nombre aléatoire. Si vous avez configuré un pare-feu, il est recommandé de le définir.'; + + @override + String connect_request(Object client) { + return 'Autoriser $client à se connecter ?'; + } + + @override + String get connection_request_denied => 'Connection denied. User denied access.'; } diff --git a/lib/l10n/generated/app_localizations_hi.dart b/lib/l10n/generated/app_localizations_hi.dart index fc9ceda4..440868f5 100644 --- a/lib/l10n/generated/app_localizations_hi.dart +++ b/lib/l10n/generated/app_localizations_hi.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsHi extends AppLocalizations { @override String get add_custom_url => 'कस्टम URL जोड़ें'; + + @override + String get edit_port => 'पोर्ट संपादित करें'; + + @override + String get port_helper_msg => 'डिफ़ॉल्ट -1 है जो यादृच्छिक संख्या को दर्शाता है। यदि आपने फ़ायरवॉल कॉन्फ़िगर किया है, तो इसे सेट करना अनुशंसित है।'; + + @override + String connect_request(Object client) { + return '$client को कनेक्ट करने की अनुमति दें?'; + } + + @override + String get connection_request_denied => 'कनेक्शन अस्वीकृत। उपयोगकर्ता ने पहुंच अस्वीकृत कर दी।'; } diff --git a/lib/l10n/generated/app_localizations_id.dart b/lib/l10n/generated/app_localizations_id.dart index 3e07ed0c..d76adc71 100644 --- a/lib/l10n/generated/app_localizations_id.dart +++ b/lib/l10n/generated/app_localizations_id.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsId extends AppLocalizations { @override String get add_custom_url => 'Add custom URL'; + + @override + String get edit_port => 'Edit port'; + + @override + String get port_helper_msg => 'Default adalah -1 yang menunjukkan angka acak. Jika Anda telah mengonfigurasi firewall, disarankan untuk mengatur ini.'; + + @override + String connect_request(Object client) { + return 'Izinkan $client untuk terhubung?'; + } + + @override + String get connection_request_denied => 'Koneksi ditolak. Pengguna menolak akses.'; } diff --git a/lib/l10n/generated/app_localizations_it.dart b/lib/l10n/generated/app_localizations_it.dart index abfc0fb4..82574b07 100644 --- a/lib/l10n/generated/app_localizations_it.dart +++ b/lib/l10n/generated/app_localizations_it.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsIt extends AppLocalizations { @override String get add_custom_url => 'Aggiungi URL personalizzato'; + + @override + String get edit_port => 'Modifica porta'; + + @override + String get port_helper_msg => 'Il valore predefinito è -1, che indica un numero casuale. Se hai configurato un firewall, si consiglia di impostarlo.'; + + @override + String connect_request(Object client) { + return 'Consentire a $client di connettersi?'; + } + + @override + String get connection_request_denied => 'Connessione negata. L\'utente ha negato l\'accesso.'; } diff --git a/lib/l10n/generated/app_localizations_ja.dart b/lib/l10n/generated/app_localizations_ja.dart index a8233a1d..b2f1a23d 100644 --- a/lib/l10n/generated/app_localizations_ja.dart +++ b/lib/l10n/generated/app_localizations_ja.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsJa extends AppLocalizations { @override String get add_custom_url => 'カスタムURLを追加'; + + @override + String get edit_port => 'ポートを編集'; + + @override + String get port_helper_msg => 'デフォルトは-1で、ランダムな番号を示します。ファイアウォールを設定している場合は、これを設定することをお勧めします。'; + + @override + String connect_request(Object client) { + return '$clientの接続を許可しますか?'; + } + + @override + String get connection_request_denied => '接続が拒否されました。ユーザーがアクセスを拒否しました。'; } diff --git a/lib/l10n/generated/app_localizations_ka.dart b/lib/l10n/generated/app_localizations_ka.dart index cefdc73e..0044d144 100644 --- a/lib/l10n/generated/app_localizations_ka.dart +++ b/lib/l10n/generated/app_localizations_ka.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsKa extends AppLocalizations { @override String get add_custom_url => 'დამატება პერსონალური URL'; + + @override + String get edit_port => 'პორტის რედაქტირება'; + + @override + String get port_helper_msg => 'ნაგულისხმევი არის -1, რაც შემთხვევითი ნომრის მითითებას ნიშნავს. თუ لديك firewall настроен, рекомендуется установить это.'; + + @override + String connect_request(Object client) { + return '$client-ის დაკავშირების ნებართვა?'; + } + + @override + String get connection_request_denied => 'კავშირი უარყოფილია. მომხმარებელმა უარყო წვდომა.'; } diff --git a/lib/l10n/generated/app_localizations_ko.dart b/lib/l10n/generated/app_localizations_ko.dart index 14628194..a3f11040 100644 --- a/lib/l10n/generated/app_localizations_ko.dart +++ b/lib/l10n/generated/app_localizations_ko.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsKo extends AppLocalizations { @override String get add_custom_url => '사용자 정의 URL 추가'; + + @override + String get edit_port => '포트 편집'; + + @override + String get port_helper_msg => '기본값은 -1로 무작위 숫자를 나타냅니다. 방화벽이 구성된 경우 이를 설정하는 것이 좋습니다.'; + + @override + String connect_request(Object client) { + return '$client의 연결을 허용하시겠습니까?'; + } + + @override + String get connection_request_denied => '연결이 거부되었습니다. 사용자가 액세스를 거부했습니다.'; } diff --git a/lib/l10n/generated/app_localizations_ne.dart b/lib/l10n/generated/app_localizations_ne.dart index 06fc54f9..f1d0f657 100644 --- a/lib/l10n/generated/app_localizations_ne.dart +++ b/lib/l10n/generated/app_localizations_ne.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsNe extends AppLocalizations { @override String get add_custom_url => 'कस्टम URL जोड़ें'; + + @override + String get edit_port => 'पोर्ट सम्पादन गर्नुहोस्'; + + @override + String get port_helper_msg => 'डिफ़ॉल्ट -1 हो जुन यादृच्छिक संख्या जनाउँछ। यदि तपाईंले फायरवाल कन्फिगर गर्नुभएको छ भने, यसलाई सेट गर्न सिफारिस गरिन्छ।'; + + @override + String connect_request(Object client) { + return '$client लाई जडान गर्न अनुमति दिनुहोस्?'; + } + + @override + String get connection_request_denied => 'जडान अस्वीकृत। प्रयोगकर्ताले पहुँच अस्वीकृत गर्यो।'; } diff --git a/lib/l10n/generated/app_localizations_nl.dart b/lib/l10n/generated/app_localizations_nl.dart index 3c17818f..338a664a 100644 --- a/lib/l10n/generated/app_localizations_nl.dart +++ b/lib/l10n/generated/app_localizations_nl.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsNl extends AppLocalizations { @override String get add_custom_url => 'Voeg aangepaste URL toe'; + + @override + String get edit_port => 'Poort bewerken'; + + @override + String get port_helper_msg => 'Standaard is -1, wat een willekeurig nummer aangeeft. Als je een firewall hebt geconfigureerd, wordt aanbevolen dit in te stellen.'; + + @override + String connect_request(Object client) { + return 'Toestaan dat $client verbinding maakt?'; + } + + @override + String get connection_request_denied => 'Verbinding geweigerd. Gebruiker heeft toegang geweigerd.'; } diff --git a/lib/l10n/generated/app_localizations_pl.dart b/lib/l10n/generated/app_localizations_pl.dart index d4001f8f..00e8cb9c 100644 --- a/lib/l10n/generated/app_localizations_pl.dart +++ b/lib/l10n/generated/app_localizations_pl.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsPl extends AppLocalizations { @override String get add_custom_url => 'Dodaj niestandardowy URL'; + + @override + String get edit_port => 'Edytuj port'; + + @override + String get port_helper_msg => 'Domyślna wartość to -1, co oznacza losową liczbę. Jeśli masz skonfigurowany zaporę, zaleca się jej ustawienie.'; + + @override + String connect_request(Object client) { + return 'Zezwolić $client na połączenie?'; + } + + @override + String get connection_request_denied => 'Połączenie odrzucone. Użytkownik odmówił dostępu.'; } diff --git a/lib/l10n/generated/app_localizations_pt.dart b/lib/l10n/generated/app_localizations_pt.dart index 87ac9bfa..87e065b6 100644 --- a/lib/l10n/generated/app_localizations_pt.dart +++ b/lib/l10n/generated/app_localizations_pt.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsPt extends AppLocalizations { @override String get add_custom_url => 'Adicionar URL personalizada'; + + @override + String get edit_port => 'Editar porta'; + + @override + String get port_helper_msg => 'O padrão é -1, que indica um número aleatório. Se você tiver um firewall configurado, é recomendável definir isso.'; + + @override + String connect_request(Object client) { + return 'Permitir que $client se conecte?'; + } + + @override + String get connection_request_denied => 'Conexão negada. O usuário negou o acesso .'; } diff --git a/lib/l10n/generated/app_localizations_ru.dart b/lib/l10n/generated/app_localizations_ru.dart index 7f38bb57..baca93f3 100644 --- a/lib/l10n/generated/app_localizations_ru.dart +++ b/lib/l10n/generated/app_localizations_ru.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsRu extends AppLocalizations { @override String get add_custom_url => 'Добавить пользовательский URL'; + + @override + String get edit_port => 'Редактировать порт'; + + @override + String get port_helper_msg => 'По умолчанию -1, что означает случайное число. Если у вас настроен брандмауэр, рекомендуется установить это.'; + + @override + String connect_request(Object client) { + return 'Разрешить $client подключение?'; + } + + @override + String get connection_request_denied => 'Подключение отклонено. Пользователь отказал в доступе.'; } diff --git a/lib/l10n/generated/app_localizations_ta.dart b/lib/l10n/generated/app_localizations_ta.dart index be0826b6..ec29a427 100644 --- a/lib/l10n/generated/app_localizations_ta.dart +++ b/lib/l10n/generated/app_localizations_ta.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsTa extends AppLocalizations { @override String get add_custom_url => 'தனிப்பயன் URL ஐச் சேர்க்கவும்'; + + @override + String get edit_port => 'போர்டு திருத்தவும்'; + + @override + String get port_helper_msg => 'இயல்புநிலை -1 ஆகும், இது சீரற்ற எண்ணை குறிக்கிறது. நீங்கள் தீயணைப்பு அமைக்கப்பட்டிருந்தால், இதை அமைப்பது பரிந்துரைக்கப்படுகிறது.'; + + @override + String connect_request(Object client) { + return '$client க்கு இணைக்க அனுமதிக்கவா?'; + } + + @override + String get connection_request_denied => 'இணைப்பு மறுக்கப்பட்டது. பயனர் அணுகலை மறுத்தார்.'; } diff --git a/lib/l10n/generated/app_localizations_th.dart b/lib/l10n/generated/app_localizations_th.dart index 679a12da..d421fa81 100644 --- a/lib/l10n/generated/app_localizations_th.dart +++ b/lib/l10n/generated/app_localizations_th.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsTh extends AppLocalizations { @override String get add_custom_url => 'เพิ่ม URL แบบกำหนดเอง'; + + @override + String get edit_port => 'แก้ไขพอร์ต'; + + @override + String get port_helper_msg => 'ค่าเริ่มต้นคือ -1 ซึ่งหมายถึงหมายเลขสุ่ม หากคุณได้กำหนดค่าไฟร์วอลล์แล้ว แนะนำให้ตั้งค่านี้'; + + @override + String connect_request(Object client) { + return 'อนุญาตให้ $client เชื่อมต่อหรือไม่?'; + } + + @override + String get connection_request_denied => 'การเชื่อมต่อล้มเหลว ผู้ใช้ปฏิเสธการเข้าถึง'; } diff --git a/lib/l10n/generated/app_localizations_tl.dart b/lib/l10n/generated/app_localizations_tl.dart index 49452c3b..30a4cdf9 100644 --- a/lib/l10n/generated/app_localizations_tl.dart +++ b/lib/l10n/generated/app_localizations_tl.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsTl extends AppLocalizations { @override String get add_custom_url => 'Magdagdag ng custom URL'; + + @override + String get edit_port => 'I-edit ang port'; + + @override + String get port_helper_msg => 'Ang default ay -1 na nagpapahiwatig ng random na numero. Kung na-configure mo ang firewall, inirerekomenda na itakda ito.'; + + @override + String connect_request(Object client) { + return 'Payagan ang $client na kumonekta?'; + } + + @override + String get connection_request_denied => 'Tanggihan ang koneksyon. Tinanggihan ng gumagamit ang pag-access.'; } diff --git a/lib/l10n/generated/app_localizations_tr.dart b/lib/l10n/generated/app_localizations_tr.dart index 11a78620..1df5a965 100644 --- a/lib/l10n/generated/app_localizations_tr.dart +++ b/lib/l10n/generated/app_localizations_tr.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsTr extends AppLocalizations { @override String get add_custom_url => 'Özel URL ekle'; + + @override + String get edit_port => 'Portu düzenle'; + + @override + String get port_helper_msg => 'Varsayılan -1\'dir, bu da rastgele bir sayıyı gösterir. Bir güvenlik duvarınız varsa, bunu ayarlamanız önerilir.'; + + @override + String connect_request(Object client) { + return '$client bağlantısına izin verilsin mi?'; + } + + @override + String get connection_request_denied => 'Bağlantı reddedildi. Kullanıcı erişimi reddetti.'; } diff --git a/lib/l10n/generated/app_localizations_uk.dart b/lib/l10n/generated/app_localizations_uk.dart index 2511b2c2..21ffca26 100644 --- a/lib/l10n/generated/app_localizations_uk.dart +++ b/lib/l10n/generated/app_localizations_uk.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsUk extends AppLocalizations { @override String get add_custom_url => 'Додати користувацький URL'; + + @override + String get edit_port => 'Редагувати порт'; + + @override + String get port_helper_msg => 'За замовчуванням -1, що означає випадкове число. Якщо у вас налаштований брандмауер, рекомендується це налаштувати.'; + + @override + String connect_request(Object client) { + return 'Дозволити $client підключення?'; + } + + @override + String get connection_request_denied => 'Підключення відхилено. Користувач відмовив у доступі.'; } diff --git a/lib/l10n/generated/app_localizations_vi.dart b/lib/l10n/generated/app_localizations_vi.dart index 0f773578..53e5aa7a 100644 --- a/lib/l10n/generated/app_localizations_vi.dart +++ b/lib/l10n/generated/app_localizations_vi.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsVi extends AppLocalizations { @override String get add_custom_url => 'Thêm URL tùy chỉnh'; + + @override + String get edit_port => 'Chỉnh sửa cổng'; + + @override + String get port_helper_msg => 'Mặc định là -1, có nghĩa là số ngẫu nhiên. Nếu bạn đã cấu hình tường lửa, nên đặt điều này.'; + + @override + String connect_request(Object client) { + return 'Cho phép $client kết nối?'; + } + + @override + String get connection_request_denied => 'Kết nối bị từ chối. Người dùng đã từ chối quyền truy cập.'; } diff --git a/lib/l10n/generated/app_localizations_zh.dart b/lib/l10n/generated/app_localizations_zh.dart index 58f7a37e..eb97a506 100644 --- a/lib/l10n/generated/app_localizations_zh.dart +++ b/lib/l10n/generated/app_localizations_zh.dart @@ -1371,4 +1371,18 @@ class AppLocalizationsZh extends AppLocalizations { @override String get add_custom_url => '添加自定义 URL'; + + @override + String get edit_port => '编辑端口'; + + @override + String get port_helper_msg => '默认值为-1,表示随机数。如果您已配置防火墙,建议设置此项。'; + + @override + String connect_request(Object client) { + return '允许 $client 连接吗?'; + } + + @override + String get connection_request_denied => '连接被拒绝。用户拒绝访问。'; } diff --git a/lib/models/database/database.dart b/lib/models/database/database.dart index 199e7147..151bbc78 100644 --- a/lib/models/database/database.dart +++ b/lib/models/database/database.dart @@ -62,7 +62,7 @@ class AppDatabase extends _$AppDatabase { AppDatabase() : super(_openConnection()); @override - int get schemaVersion => 4; + int get schemaVersion => 6; @override MigrationStrategy get migration { @@ -87,6 +87,40 @@ class AppDatabase extends _$AppDatabase { schema.preferencesTable.youtubeClientEngine, ); }, + from4To5: (m, schema) async { + final columnName = schema.preferencesTable.accentColorScheme + .escapedNameFor(SqlDialect.sqlite); + final columnNameOld = + '"${schema.preferencesTable.accentColorScheme.name}_old"'; + final tableName = schema.preferencesTable.actualTableName; + await customStatement( + "ALTER TABLE $tableName " + "RENAME COLUMN $columnName to $columnNameOld", + ); + await customStatement( + "ALTER TABLE $tableName " + "ADD COLUMN $columnName TEXT NOT NULL DEFAULT 'Orange:0xFFf97315'", + ); + await customStatement( + "UPDATE $tableName " + "SET $columnName = $columnNameOld", + ); + await customStatement( + "ALTER TABLE $tableName " + "DROP COLUMN $columnNameOld", + ); + await customStatement( + "UPDATE $tableName " + "SET $columnName = 'Orange:0xFFf97315' WHERE $columnName = 'Blue:0xFF2196F3'", + ); + }, + from5To6: (m, schema) async { + // Add new column to preferences table + await m.addColumn( + schema.preferencesTable, + schema.preferencesTable.connectPort, + ); + }, ), ); } diff --git a/lib/models/database/database.g.dart b/lib/models/database/database.g.dart index cd004d69..5dfe8db8 100644 --- a/lib/models/database/database.g.dart +++ b/lib/models/database/database.g.dart @@ -666,7 +666,7 @@ class $PreferencesTableTable extends PreferencesTable 'accent_color_scheme', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: false, - defaultValue: const Constant("Blue:0xFF2196F3")) + defaultValue: const Constant("Orange:0xFFf97315")) .withConverter( $PreferencesTableTable.$converteraccentColorScheme); static const VerificationMeta _layoutModeMeta = @@ -823,6 +823,14 @@ class $PreferencesTableTable extends PreferencesTable defaultConstraints: GeneratedColumn.constraintIsAlways( 'CHECK ("enable_connect" IN (0, 1))'), defaultValue: const Constant(false)); + static const VerificationMeta _connectPortMeta = + const VerificationMeta('connectPort'); + @override + late final GeneratedColumn connectPort = GeneratedColumn( + 'connect_port', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(-1)); static const VerificationMeta _cacheMusicMeta = const VerificationMeta('cacheMusic'); @override @@ -862,6 +870,7 @@ class $PreferencesTableTable extends PreferencesTable discordPresence, endlessPlayback, enableConnect, + connectPort, cacheMusic ]; @override @@ -971,6 +980,12 @@ class $PreferencesTableTable extends PreferencesTable enableConnect.isAcceptableOrUnknown( data['enable_connect']!, _enableConnectMeta)); } + if (data.containsKey('connect_port')) { + context.handle( + _connectPortMeta, + connectPort.isAcceptableOrUnknown( + data['connect_port']!, _connectPortMeta)); + } if (data.containsKey('cache_music')) { context.handle( _cacheMusicMeta, @@ -1054,6 +1069,8 @@ class $PreferencesTableTable extends PreferencesTable .read(DriftSqlType.bool, data['${effectivePrefix}endless_playback'])!, enableConnect: attachedDatabase.typeMapping .read(DriftSqlType.bool, data['${effectivePrefix}enable_connect'])!, + connectPort: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}connect_port'])!, cacheMusic: attachedDatabase.typeMapping .read(DriftSqlType.bool, data['${effectivePrefix}cache_music'])!, ); @@ -1126,6 +1143,7 @@ class PreferencesTableData extends DataClass final bool discordPresence; final bool endlessPlayback; final bool enableConnect; + final int connectPort; final bool cacheMusic; const PreferencesTableData( {required this.id, @@ -1155,6 +1173,7 @@ class PreferencesTableData extends DataClass required this.discordPresence, required this.endlessPlayback, required this.enableConnect, + required this.connectPort, required this.cacheMusic}); @override Map toColumns(bool nullToAbsent) { @@ -1230,6 +1249,7 @@ class PreferencesTableData extends DataClass map['discord_presence'] = Variable(discordPresence); map['endless_playback'] = Variable(endlessPlayback); map['enable_connect'] = Variable(enableConnect); + map['connect_port'] = Variable(connectPort); map['cache_music'] = Variable(cacheMusic); return map; } @@ -1263,6 +1283,7 @@ class PreferencesTableData extends DataClass discordPresence: Value(discordPresence), endlessPlayback: Value(endlessPlayback), enableConnect: Value(enableConnect), + connectPort: Value(connectPort), cacheMusic: Value(cacheMusic), ); } @@ -1310,6 +1331,7 @@ class PreferencesTableData extends DataClass discordPresence: serializer.fromJson(json['discordPresence']), endlessPlayback: serializer.fromJson(json['endlessPlayback']), enableConnect: serializer.fromJson(json['enableConnect']), + connectPort: serializer.fromJson(json['connectPort']), cacheMusic: serializer.fromJson(json['cacheMusic']), ); } @@ -1358,6 +1380,7 @@ class PreferencesTableData extends DataClass 'discordPresence': serializer.toJson(discordPresence), 'endlessPlayback': serializer.toJson(endlessPlayback), 'enableConnect': serializer.toJson(enableConnect), + 'connectPort': serializer.toJson(connectPort), 'cacheMusic': serializer.toJson(cacheMusic), }; } @@ -1390,6 +1413,7 @@ class PreferencesTableData extends DataClass bool? discordPresence, bool? endlessPlayback, bool? enableConnect, + int? connectPort, bool? cacheMusic}) => PreferencesTableData( id: id ?? this.id, @@ -1419,6 +1443,7 @@ class PreferencesTableData extends DataClass discordPresence: discordPresence ?? this.discordPresence, endlessPlayback: endlessPlayback ?? this.endlessPlayback, enableConnect: enableConnect ?? this.enableConnect, + connectPort: connectPort ?? this.connectPort, cacheMusic: cacheMusic ?? this.cacheMusic, ); PreferencesTableData copyWithCompanion(PreferencesTableCompanion data) { @@ -1492,6 +1517,8 @@ class PreferencesTableData extends DataClass enableConnect: data.enableConnect.present ? data.enableConnect.value : this.enableConnect, + connectPort: + data.connectPort.present ? data.connectPort.value : this.connectPort, cacheMusic: data.cacheMusic.present ? data.cacheMusic.value : this.cacheMusic, ); @@ -1527,6 +1554,7 @@ class PreferencesTableData extends DataClass ..write('discordPresence: $discordPresence, ') ..write('endlessPlayback: $endlessPlayback, ') ..write('enableConnect: $enableConnect, ') + ..write('connectPort: $connectPort, ') ..write('cacheMusic: $cacheMusic') ..write(')')) .toString(); @@ -1561,6 +1589,7 @@ class PreferencesTableData extends DataClass discordPresence, endlessPlayback, enableConnect, + connectPort, cacheMusic ]); @override @@ -1594,6 +1623,7 @@ class PreferencesTableData extends DataClass other.discordPresence == this.discordPresence && other.endlessPlayback == this.endlessPlayback && other.enableConnect == this.enableConnect && + other.connectPort == this.connectPort && other.cacheMusic == this.cacheMusic); } @@ -1625,6 +1655,7 @@ class PreferencesTableCompanion extends UpdateCompanion { final Value discordPresence; final Value endlessPlayback; final Value enableConnect; + final Value connectPort; final Value cacheMusic; const PreferencesTableCompanion({ this.id = const Value.absent(), @@ -1654,6 +1685,7 @@ class PreferencesTableCompanion extends UpdateCompanion { this.discordPresence = const Value.absent(), this.endlessPlayback = const Value.absent(), this.enableConnect = const Value.absent(), + this.connectPort = const Value.absent(), this.cacheMusic = const Value.absent(), }); PreferencesTableCompanion.insert({ @@ -1684,6 +1716,7 @@ class PreferencesTableCompanion extends UpdateCompanion { this.discordPresence = const Value.absent(), this.endlessPlayback = const Value.absent(), this.enableConnect = const Value.absent(), + this.connectPort = const Value.absent(), this.cacheMusic = const Value.absent(), }); static Insertable custom({ @@ -1714,6 +1747,7 @@ class PreferencesTableCompanion extends UpdateCompanion { Expression? discordPresence, Expression? endlessPlayback, Expression? enableConnect, + Expression? connectPort, Expression? cacheMusic, }) { return RawValuesInsertable({ @@ -1748,6 +1782,7 @@ class PreferencesTableCompanion extends UpdateCompanion { if (discordPresence != null) 'discord_presence': discordPresence, if (endlessPlayback != null) 'endless_playback': endlessPlayback, if (enableConnect != null) 'enable_connect': enableConnect, + if (connectPort != null) 'connect_port': connectPort, if (cacheMusic != null) 'cache_music': cacheMusic, }); } @@ -1780,6 +1815,7 @@ class PreferencesTableCompanion extends UpdateCompanion { Value? discordPresence, Value? endlessPlayback, Value? enableConnect, + Value? connectPort, Value? cacheMusic}) { return PreferencesTableCompanion( id: id ?? this.id, @@ -1809,6 +1845,7 @@ class PreferencesTableCompanion extends UpdateCompanion { discordPresence: discordPresence ?? this.discordPresence, endlessPlayback: endlessPlayback ?? this.endlessPlayback, enableConnect: enableConnect ?? this.enableConnect, + connectPort: connectPort ?? this.connectPort, cacheMusic: cacheMusic ?? this.cacheMusic, ); } @@ -1918,6 +1955,9 @@ class PreferencesTableCompanion extends UpdateCompanion { if (enableConnect.present) { map['enable_connect'] = Variable(enableConnect.value); } + if (connectPort.present) { + map['connect_port'] = Variable(connectPort.value); + } if (cacheMusic.present) { map['cache_music'] = Variable(cacheMusic.value); } @@ -1954,6 +1994,7 @@ class PreferencesTableCompanion extends UpdateCompanion { ..write('discordPresence: $discordPresence, ') ..write('endlessPlayback: $endlessPlayback, ') ..write('enableConnect: $enableConnect, ') + ..write('connectPort: $connectPort, ') ..write('cacheMusic: $cacheMusic') ..write(')')) .toString(); @@ -4626,6 +4667,7 @@ typedef $$PreferencesTableTableCreateCompanionBuilder Value discordPresence, Value endlessPlayback, Value enableConnect, + Value connectPort, Value cacheMusic, }); typedef $$PreferencesTableTableUpdateCompanionBuilder @@ -4657,6 +4699,7 @@ typedef $$PreferencesTableTableUpdateCompanionBuilder Value discordPresence, Value endlessPlayback, Value enableConnect, + Value connectPort, Value cacheMusic, }); @@ -4786,6 +4829,9 @@ class $$PreferencesTableTableFilterComposer ColumnFilters get enableConnect => $composableBuilder( column: $table.enableConnect, builder: (column) => ColumnFilters(column)); + ColumnFilters get connectPort => $composableBuilder( + column: $table.connectPort, builder: (column) => ColumnFilters(column)); + ColumnFilters get cacheMusic => $composableBuilder( column: $table.cacheMusic, builder: (column) => ColumnFilters(column)); } @@ -4899,6 +4945,9 @@ class $$PreferencesTableTableOrderingComposer column: $table.enableConnect, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get connectPort => $composableBuilder( + column: $table.connectPort, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get cacheMusic => $composableBuilder( column: $table.cacheMusic, builder: (column) => ColumnOrderings(column)); } @@ -5003,6 +5052,9 @@ class $$PreferencesTableTableAnnotationComposer GeneratedColumn get enableConnect => $composableBuilder( column: $table.enableConnect, builder: (column) => column); + GeneratedColumn get connectPort => $composableBuilder( + column: $table.connectPort, builder: (column) => column); + GeneratedColumn get cacheMusic => $composableBuilder( column: $table.cacheMusic, builder: (column) => column); } @@ -5063,6 +5115,7 @@ class $$PreferencesTableTableTableManager extends RootTableManager< Value discordPresence = const Value.absent(), Value endlessPlayback = const Value.absent(), Value enableConnect = const Value.absent(), + Value connectPort = const Value.absent(), Value cacheMusic = const Value.absent(), }) => PreferencesTableCompanion( @@ -5093,6 +5146,7 @@ class $$PreferencesTableTableTableManager extends RootTableManager< discordPresence: discordPresence, endlessPlayback: endlessPlayback, enableConnect: enableConnect, + connectPort: connectPort, cacheMusic: cacheMusic, ), createCompanionCallback: ({ @@ -5124,6 +5178,7 @@ class $$PreferencesTableTableTableManager extends RootTableManager< Value discordPresence = const Value.absent(), Value endlessPlayback = const Value.absent(), Value enableConnect = const Value.absent(), + Value connectPort = const Value.absent(), Value cacheMusic = const Value.absent(), }) => PreferencesTableCompanion.insert( @@ -5154,6 +5209,7 @@ class $$PreferencesTableTableTableManager extends RootTableManager< discordPresence: discordPresence, endlessPlayback: endlessPlayback, enableConnect: enableConnect, + connectPort: connectPort, cacheMusic: cacheMusic, ), withReferenceMapper: (p0) => p0 diff --git a/lib/models/database/database.steps.dart b/lib/models/database/database.steps.dart index 8e0f8e3f..3e416ea5 100644 --- a/lib/models/database/database.steps.dart +++ b/lib/models/database/database.steps.dart @@ -1,11 +1,11 @@ // dart format width=80 import 'package:drift/internal/versioned_schema.dart' as i0; import 'package:drift/drift.dart' as i1; -import 'package:drift/drift.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:drift/drift.dart'; // ignore_for_file: type=lint,unused_import +import 'package:flutter/material.dart'; import 'package:spotify/spotify.dart'; import 'package:spotube/models/database/database.dart'; -import 'package:spotube/services/sourced_track/enums.dart'; // ignore_for_file: type=lint,unused_import +import 'package:spotube/services/sourced_track/enums.dart'; // GENERATED BY drift_dev, DO NOT MODIFY. final class Schema2 extends i0.VersionedSchema { @@ -1188,10 +1188,516 @@ i1.GeneratedColumn _column_54(String aliasedName) => i1.GeneratedColumn('youtube_client_engine', aliasedName, false, type: i1.DriftSqlType.string, defaultValue: Constant(YoutubeClientEngine.youtubeExplode.name)); + +final class Schema5 extends i0.VersionedSchema { + Schema5({required super.database}) : super(version: 5); + @override + late final List entities = [ + authenticationTable, + blacklistTable, + preferencesTable, + scrobblerTable, + skipSegmentTable, + sourceMatchTable, + audioPlayerStateTable, + playlistTable, + playlistMediaTable, + historyTable, + lyricsTable, + uniqueBlacklist, + uniqTrackMatch, + ]; + late final Shape0 authenticationTable = Shape0( + source: i0.VersionedTable( + entityName: 'authentication_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape1 blacklistTable = Shape1( + source: i0.VersionedTable( + entityName: 'blacklist_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_4, + _column_5, + _column_6, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape12 preferencesTable = Shape12( + source: i0.VersionedTable( + entityName: 'preferences_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_7, + _column_8, + _column_9, + _column_10, + _column_11, + _column_12, + _column_13, + _column_14, + _column_15, + _column_55, + _column_17, + _column_18, + _column_19, + _column_20, + _column_21, + _column_22, + _column_23, + _column_24, + _column_25, + _column_26, + _column_54, + _column_27, + _column_28, + _column_29, + _column_30, + _column_31, + _column_53, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape3 scrobblerTable = Shape3( + source: i0.VersionedTable( + entityName: 'scrobbler_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_32, + _column_33, + _column_34, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape4 skipSegmentTable = Shape4( + source: i0.VersionedTable( + entityName: 'skip_segment_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_35, + _column_36, + _column_37, + _column_32, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape5 sourceMatchTable = Shape5( + source: i0.VersionedTable( + entityName: 'source_match_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_37, + _column_38, + _column_39, + _column_32, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape6 audioPlayerStateTable = Shape6( + source: i0.VersionedTable( + entityName: 'audio_player_state_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_40, + _column_41, + _column_42, + _column_43, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape7 playlistTable = Shape7( + source: i0.VersionedTable( + entityName: 'playlist_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_44, + _column_45, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape8 playlistMediaTable = Shape8( + source: i0.VersionedTable( + entityName: 'playlist_media_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_46, + _column_47, + _column_48, + _column_49, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape9 historyTable = Shape9( + source: i0.VersionedTable( + entityName: 'history_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_32, + _column_50, + _column_51, + _column_52, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape10 lyricsTable = Shape10( + source: i0.VersionedTable( + entityName: 'lyrics_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_37, + _column_52, + ], + attachedDatabase: database, + ), + alias: null); + final i1.Index uniqueBlacklist = i1.Index('unique_blacklist', + 'CREATE UNIQUE INDEX unique_blacklist ON blacklist_table (element_type, element_id)'); + final i1.Index uniqTrackMatch = i1.Index('uniq_track_match', + 'CREATE UNIQUE INDEX uniq_track_match ON source_match_table (track_id, source_id, source_type)'); +} + +i1.GeneratedColumn _column_55(String aliasedName) => + i1.GeneratedColumn('accent_color_scheme', aliasedName, false, + type: i1.DriftSqlType.string, + defaultValue: const Constant("Orange:0xFFf97315")); + +final class Schema6 extends i0.VersionedSchema { + Schema6({required super.database}) : super(version: 6); + @override + late final List entities = [ + authenticationTable, + blacklistTable, + preferencesTable, + scrobblerTable, + skipSegmentTable, + sourceMatchTable, + audioPlayerStateTable, + playlistTable, + playlistMediaTable, + historyTable, + lyricsTable, + uniqueBlacklist, + uniqTrackMatch, + ]; + late final Shape0 authenticationTable = Shape0( + source: i0.VersionedTable( + entityName: 'authentication_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_1, + _column_2, + _column_3, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape1 blacklistTable = Shape1( + source: i0.VersionedTable( + entityName: 'blacklist_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_4, + _column_5, + _column_6, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape13 preferencesTable = Shape13( + source: i0.VersionedTable( + entityName: 'preferences_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_7, + _column_8, + _column_9, + _column_10, + _column_11, + _column_12, + _column_13, + _column_14, + _column_15, + _column_55, + _column_17, + _column_18, + _column_19, + _column_20, + _column_21, + _column_22, + _column_23, + _column_24, + _column_25, + _column_26, + _column_54, + _column_27, + _column_28, + _column_29, + _column_30, + _column_31, + _column_56, + _column_53, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape3 scrobblerTable = Shape3( + source: i0.VersionedTable( + entityName: 'scrobbler_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_32, + _column_33, + _column_34, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape4 skipSegmentTable = Shape4( + source: i0.VersionedTable( + entityName: 'skip_segment_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_35, + _column_36, + _column_37, + _column_32, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape5 sourceMatchTable = Shape5( + source: i0.VersionedTable( + entityName: 'source_match_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_37, + _column_38, + _column_39, + _column_32, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape6 audioPlayerStateTable = Shape6( + source: i0.VersionedTable( + entityName: 'audio_player_state_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_40, + _column_41, + _column_42, + _column_43, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape7 playlistTable = Shape7( + source: i0.VersionedTable( + entityName: 'playlist_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_44, + _column_45, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape8 playlistMediaTable = Shape8( + source: i0.VersionedTable( + entityName: 'playlist_media_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_46, + _column_47, + _column_48, + _column_49, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape9 historyTable = Shape9( + source: i0.VersionedTable( + entityName: 'history_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_32, + _column_50, + _column_51, + _column_52, + ], + attachedDatabase: database, + ), + alias: null); + late final Shape10 lyricsTable = Shape10( + source: i0.VersionedTable( + entityName: 'lyrics_table', + withoutRowId: false, + isStrict: false, + tableConstraints: [], + columns: [ + _column_0, + _column_37, + _column_52, + ], + attachedDatabase: database, + ), + alias: null); + final i1.Index uniqueBlacklist = i1.Index('unique_blacklist', + 'CREATE UNIQUE INDEX unique_blacklist ON blacklist_table (element_type, element_id)'); + final i1.Index uniqTrackMatch = i1.Index('uniq_track_match', + 'CREATE UNIQUE INDEX uniq_track_match ON source_match_table (track_id, source_id, source_type)'); +} + +class Shape13 extends i0.VersionedTable { + Shape13({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get id => + columnsByName['id']! as i1.GeneratedColumn; + i1.GeneratedColumn get audioQuality => + columnsByName['audio_quality']! as i1.GeneratedColumn; + i1.GeneratedColumn get albumColorSync => + columnsByName['album_color_sync']! as i1.GeneratedColumn; + i1.GeneratedColumn get amoledDarkTheme => + columnsByName['amoled_dark_theme']! as i1.GeneratedColumn; + i1.GeneratedColumn get checkUpdate => + columnsByName['check_update']! as i1.GeneratedColumn; + i1.GeneratedColumn get normalizeAudio => + columnsByName['normalize_audio']! as i1.GeneratedColumn; + i1.GeneratedColumn get showSystemTrayIcon => + columnsByName['show_system_tray_icon']! as i1.GeneratedColumn; + i1.GeneratedColumn get systemTitleBar => + columnsByName['system_title_bar']! as i1.GeneratedColumn; + i1.GeneratedColumn get skipNonMusic => + columnsByName['skip_non_music']! as i1.GeneratedColumn; + i1.GeneratedColumn get closeBehavior => + columnsByName['close_behavior']! as i1.GeneratedColumn; + i1.GeneratedColumn get accentColorScheme => + columnsByName['accent_color_scheme']! as i1.GeneratedColumn; + i1.GeneratedColumn get layoutMode => + columnsByName['layout_mode']! as i1.GeneratedColumn; + i1.GeneratedColumn get locale => + columnsByName['locale']! as i1.GeneratedColumn; + i1.GeneratedColumn get market => + columnsByName['market']! as i1.GeneratedColumn; + i1.GeneratedColumn get searchMode => + columnsByName['search_mode']! as i1.GeneratedColumn; + i1.GeneratedColumn get downloadLocation => + columnsByName['download_location']! as i1.GeneratedColumn; + i1.GeneratedColumn get localLibraryLocation => + columnsByName['local_library_location']! as i1.GeneratedColumn; + i1.GeneratedColumn get pipedInstance => + columnsByName['piped_instance']! as i1.GeneratedColumn; + i1.GeneratedColumn get invidiousInstance => + columnsByName['invidious_instance']! as i1.GeneratedColumn; + i1.GeneratedColumn get themeMode => + columnsByName['theme_mode']! as i1.GeneratedColumn; + i1.GeneratedColumn get audioSource => + columnsByName['audio_source']! as i1.GeneratedColumn; + i1.GeneratedColumn get youtubeClientEngine => + columnsByName['youtube_client_engine']! as i1.GeneratedColumn; + i1.GeneratedColumn get streamMusicCodec => + columnsByName['stream_music_codec']! as i1.GeneratedColumn; + i1.GeneratedColumn get downloadMusicCodec => + columnsByName['download_music_codec']! as i1.GeneratedColumn; + i1.GeneratedColumn get discordPresence => + columnsByName['discord_presence']! as i1.GeneratedColumn; + i1.GeneratedColumn get endlessPlayback => + columnsByName['endless_playback']! as i1.GeneratedColumn; + i1.GeneratedColumn get enableConnect => + columnsByName['enable_connect']! as i1.GeneratedColumn; + i1.GeneratedColumn get connectPort => + columnsByName['connect_port']! as i1.GeneratedColumn; + i1.GeneratedColumn get cacheMusic => + columnsByName['cache_music']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_56(String aliasedName) => + i1.GeneratedColumn('connect_port', aliasedName, false, + type: i1.DriftSqlType.int, defaultValue: const Constant(-1)); i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema2 schema) from1To2, required Future Function(i1.Migrator m, Schema3 schema) from2To3, required Future Function(i1.Migrator m, Schema4 schema) from3To4, + required Future Function(i1.Migrator m, Schema5 schema) from4To5, + required Future Function(i1.Migrator m, Schema6 schema) from5To6, }) { return (currentVersion, database) async { switch (currentVersion) { @@ -1210,6 +1716,16 @@ i0.MigrationStepWithVersion migrationSteps({ final migrator = i1.Migrator(database, schema); await from3To4(migrator, schema); return 4; + case 4: + final schema = Schema5(database: database); + final migrator = i1.Migrator(database, schema); + await from4To5(migrator, schema); + return 5; + case 5: + final schema = Schema6(database: database); + final migrator = i1.Migrator(database, schema); + await from5To6(migrator, schema); + return 6; default: throw ArgumentError.value('Unknown migration from $currentVersion'); } @@ -1220,10 +1736,14 @@ i1.OnUpgrade stepByStep({ required Future Function(i1.Migrator m, Schema2 schema) from1To2, required Future Function(i1.Migrator m, Schema3 schema) from2To3, required Future Function(i1.Migrator m, Schema4 schema) from3To4, + required Future Function(i1.Migrator m, Schema5 schema) from4To5, + required Future Function(i1.Migrator m, Schema6 schema) from5To6, }) => i0.VersionedSchema.stepByStepHelper( step: migrationSteps( from1To2: from1To2, from2To3: from2To3, from3To4: from3To4, + from4To5: from4To5, + from5To6: from5To6, )); diff --git a/lib/models/database/tables/preferences.dart b/lib/models/database/tables/preferences.dart index 492ac1f9..377f288d 100644 --- a/lib/models/database/tables/preferences.dart +++ b/lib/models/database/tables/preferences.dart @@ -79,7 +79,7 @@ class PreferencesTable extends Table { TextColumn get closeBehavior => textEnum() .withDefault(Constant(CloseBehavior.close.name))(); TextColumn get accentColorScheme => text() - .withDefault(const Constant("Blue:0xFF2196F3")) + .withDefault(const Constant("Orange:0xFFf97315")) .map(const SpotubeColorConverter())(); TextColumn get layoutMode => textEnum().withDefault(Constant(LayoutMode.adaptive.name))(); @@ -115,6 +115,7 @@ class PreferencesTable extends Table { boolean().withDefault(const Constant(true))(); BoolColumn get enableConnect => boolean().withDefault(const Constant(false))(); + IntColumn get connectPort => integer().withDefault(const Constant(-1))(); BoolColumn get cacheMusic => boolean().withDefault(const Constant(true))(); // Default values as PreferencesTableData @@ -130,7 +131,7 @@ class PreferencesTable extends Table { systemTitleBar: false, skipNonMusic: false, closeBehavior: CloseBehavior.close, - accentColorScheme: SpotubeColor(Colors.blue.value, name: "Blue"), + accentColorScheme: SpotubeColor(Colors.orange.value, name: "Orange"), layoutMode: LayoutMode.adaptive, locale: const Locale("system", "system"), market: Market.US, @@ -148,6 +149,7 @@ class PreferencesTable extends Table { endlessPlayback: true, enableConnect: false, cacheMusic: true, + connectPort: -1, ); } } diff --git a/lib/models/database/typeconverters/color.dart b/lib/models/database/typeconverters/color.dart index 70c27374..513921a2 100644 --- a/lib/models/database/typeconverters/color.dart +++ b/lib/models/database/typeconverters/color.dart @@ -10,7 +10,7 @@ class ColorConverter extends TypeConverter { @override int toSql(Color value) { - return value.value; + return value.toARGB32(); } } diff --git a/lib/modules/album/album_card.dart b/lib/modules/album/album_card.dart index 84106594..5fee9cc4 100644 --- a/lib/modules/album/album_card.dart +++ b/lib/modules/album/album_card.dart @@ -54,7 +54,7 @@ class AlbumCard extends HookConsumerWidget { Future> fetchAllTrack() async { if (album.tracks != null && album.tracks!.isNotEmpty) { - return album.tracks!.map((track) => track.asTrack(album)).toList(); + return album.tracks!.asTracks(album, ref); } await ref.read(albumTracksProvider(album).future); return ref.read(albumTracksProvider(album).notifier).fetchAll(); diff --git a/lib/modules/home/sections/feed.dart b/lib/modules/home/sections/feed.dart index d3e363cc..216dc491 100644 --- a/lib/modules/home/sections/feed.dart +++ b/lib/modules/home/sections/feed.dart @@ -12,7 +12,7 @@ class HomePageFeedSection extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { final homeFeed = ref.watch(homeViewProvider); - final nonShortSections = homeFeed.asData?.value?.sections + final nonShortSections = homeFeed.asData?.value.sections .where((s) => s.typename == "HomeGenericSectionData") .toList() ?? []; diff --git a/lib/modules/home/sections/genres/genre_card_playlist_card.dart b/lib/modules/home/sections/genres/genre_card_playlist_card.dart index 1e1b3b76..328507cc 100644 --- a/lib/modules/home/sections/genres/genre_card_playlist_card.dart +++ b/lib/modules/home/sections/genres/genre_card_playlist_card.dart @@ -1,6 +1,6 @@ import 'package:auto_route/auto_route.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:spotify/spotify.dart' hide Image; import 'package:spotube/collections/env.dart'; import 'package:spotube/collections/routes.gr.dart'; diff --git a/lib/modules/library/playlist_generate/multi_select_field.dart b/lib/modules/library/playlist_generate/multi_select_field.dart index 7118d57d..00a09c95 100644 --- a/lib/modules/library/playlist_generate/multi_select_field.dart +++ b/lib/modules/library/playlist_generate/multi_select_field.dart @@ -68,7 +68,7 @@ class MultiSelectField extends HookWidget { side: BorderSide( color: enabled ? theme.colorScheme.onSurface - : theme.colorScheme.onSurface.withOpacity(0.1), + : theme.colorScheme.onSurface.withValues(alpha: 0.1), ), ), mouseCursor: WidgetStateMouseCursor.textable, diff --git a/lib/modules/library/playlist_generate/seeds_multi_autocomplete.dart b/lib/modules/library/playlist_generate/seeds_multi_autocomplete.dart index da1288f5..812d9367 100644 --- a/lib/modules/library/playlist_generate/seeds_multi_autocomplete.dart +++ b/lib/modules/library/playlist_generate/seeds_multi_autocomplete.dart @@ -119,8 +119,10 @@ class SeedsMultiAutocomplete extends HookWidget { focusNode: focusNode, onSubmitted: (_) => onFieldSubmitted(), enabled: enabled, - leading: leading, - trailing: trailing, + features: [ + if (leading != null) InputFeature.leading(leading!), + if (trailing != null) InputFeature.trailing(trailing!), + ], placeholder: placeholder, ); }, diff --git a/lib/modules/player/player.dart b/lib/modules/player/player.dart index aa5171d5..b02910e9 100644 --- a/lib/modules/player/player.dart +++ b/lib/modules/player/player.dart @@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'package:spotube/collections/assets.gen.dart'; @@ -132,7 +132,7 @@ class PlayerView extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.details), - ), + ).call, child: IconButton.ghost( icon: const Icon(SpotubeIcons.info, size: 18), onPressed: currentTrack == null diff --git a/lib/modules/player/player_actions.dart b/lib/modules/player/player_actions.dart index 0ed56ed2..53023a10 100644 --- a/lib/modules/player/player_actions.dart +++ b/lib/modules/player/player_actions.dart @@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotube/collections/routes.gr.dart'; @@ -82,7 +82,7 @@ class PlayerActions extends HookConsumerWidget { children: [ if (showQueue) Tooltip( - tooltip: TooltipContainer(child: Text(context.l10n.queue)), + tooltip: TooltipContainer(child: Text(context.l10n.queue)).call, child: IconButton.ghost( icon: const Icon(SpotubeIcons.queue), enabled: playlist.activeTrack != null, @@ -119,7 +119,8 @@ class PlayerActions extends HookConsumerWidget { if (!isLocalTrack) Tooltip( tooltip: TooltipContainer( - child: Text(context.l10n.alternative_track_sources)), + child: Text(context.l10n.alternative_track_sources), + ).call, child: IconButton.ghost( enabled: playlist.activeTrack != null, icon: const Icon(SpotubeIcons.alternativeRoute), @@ -160,7 +161,8 @@ class PlayerActions extends HookConsumerWidget { else Tooltip( tooltip: - TooltipContainer(child: Text(context.l10n.download_track)), + TooltipContainer(child: Text(context.l10n.download_track)) + .call, child: IconButton.ghost( icon: Icon( isDownloaded ? SpotubeIcons.done : SpotubeIcons.download, diff --git a/lib/modules/player/player_controls.dart b/lib/modules/player/player_controls.dart index 4d5d6deb..14b9cf43 100644 --- a/lib/modules/player/player_controls.dart +++ b/lib/modules/player/player_controls.dart @@ -3,7 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:media_kit/media_kit.dart'; import 'package:palette_generator/palette_generator.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/intents.dart'; @@ -89,7 +89,7 @@ class PlayerControls extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.slide_to_seek), - ), + ).call, child: SizedBox( width: mediaQuery.xlAndUp ? 600 : 500, child: Slider( @@ -147,7 +147,7 @@ class PlayerControls extends HookConsumerWidget { ? context.l10n.unshuffle_playlist : context.l10n.shuffle_playlist, ), - ), + ).call, child: IconButton( icon: Icon( SpotubeIcons.shuffle, @@ -170,7 +170,7 @@ class PlayerControls extends HookConsumerWidget { }), Tooltip( tooltip: TooltipContainer( - child: Text(context.l10n.previous_track)), + child: Text(context.l10n.previous_track)).call, child: IconButton.ghost( enabled: !isFetchingActiveTrack, icon: const Icon(SpotubeIcons.skipBack), @@ -184,7 +184,7 @@ class PlayerControls extends HookConsumerWidget { ? context.l10n.pause_playback : context.l10n.resume_playback, ), - ), + ).call, child: IconButton.primary( shape: ButtonShape.circle, icon: isFetchingActiveTrack @@ -206,7 +206,7 @@ class PlayerControls extends HookConsumerWidget { ), Tooltip( tooltip: - TooltipContainer(child: Text(context.l10n.next_track)), + TooltipContainer(child: Text(context.l10n.next_track)).call, child: IconButton.ghost( icon: const Icon(SpotubeIcons.skipForward), onPressed: @@ -226,7 +226,7 @@ class PlayerControls extends HookConsumerWidget { ? context.l10n.repeat_playlist : "", ), - ), + ).call, child: IconButton( icon: Icon( loopMode == PlaylistMode.single diff --git a/lib/modules/player/player_overlay_collapsed.dart b/lib/modules/player/player_overlay_collapsed.dart index d0961ade..aa5a3b38 100644 --- a/lib/modules/player/player_overlay_collapsed.dart +++ b/lib/modules/player/player_overlay_collapsed.dart @@ -1,6 +1,6 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:sliding_up_panel/sliding_up_panel.dart'; import 'package:spotube/collections/intents.dart'; import 'package:spotube/collections/spotube_icons.dart'; diff --git a/lib/modules/player/player_queue.dart b/lib/modules/player/player_queue.dart index 0ef86111..06d7e3c7 100644 --- a/lib/modules/player/player_queue.dart +++ b/lib/modules/player/player_queue.dart @@ -161,7 +161,7 @@ class PlayerQueue extends HookConsumerWidget { const SizedBox(width: 10), Tooltip( tooltip: TooltipContainer( - child: Text(context.l10n.clear_all)), + child: Text(context.l10n.clear_all)).call, child: IconButton.outline( icon: const Icon(SpotubeIcons.playlistRemove), onPressed: () { diff --git a/lib/modules/playlist/playlist_card.dart b/lib/modules/playlist/playlist_card.dart index 1e2ba1bf..c4ffffa7 100644 --- a/lib/modules/playlist/playlist_card.dart +++ b/lib/modules/playlist/playlist_card.dart @@ -1,7 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:spotify/spotify.dart' hide Offset, Image; import 'package:spotube/collections/env.dart'; import 'package:spotube/collections/routes.gr.dart'; diff --git a/lib/modules/root/bottom_player.dart b/lib/modules/root/bottom_player.dart index 18b4c221..c2e6369d 100644 --- a/lib/modules/root/bottom_player.dart +++ b/lib/modules/root/bottom_player.dart @@ -1,7 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotube/collections/assets.gen.dart'; @@ -76,7 +76,7 @@ class BottomPlayer extends HookConsumerWidget { extraActions: [ Tooltip( tooltip: - TooltipContainer(child: Text(context.l10n.mini_player)), + TooltipContainer(child: Text(context.l10n.mini_player)).call, child: IconButton( variance: ButtonVariance.ghost, icon: const Icon(SpotubeIcons.miniPlayer), diff --git a/lib/modules/root/sidebar/sidebar.dart b/lib/modules/root/sidebar/sidebar.dart index 743b339b..6b61c70b 100644 --- a/lib/modules/root/sidebar/sidebar.dart +++ b/lib/modules/root/sidebar/sidebar.dart @@ -20,13 +20,16 @@ class Sidebar extends HookConsumerWidget { super.key, }); - static Widget brandLogo() { + static Widget brandLogo(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(50), ), - child: Assets.spotubeLogoPng.image(height: 50), + child: Assets.spotubeLogoPng.image( + height: 50, + cacheHeight: (100 * MediaQuery.devicePixelRatioOf(context)).toInt(), + ), ); } @@ -62,13 +65,22 @@ class Sidebar extends HookConsumerWidget { final navigationButtons = [ NavigationLabel( - child: mediaQuery.lgAndUp ? const Text("Spotube") : const Text(""), + child: mediaQuery.lgAndUp + ? const DefaultTextStyle( + style: TextStyle( + fontFamily: "Cookie", + fontSize: 30, + letterSpacing: 1.8, + ), + child: Text("Spotube"), + ) + : const Text(""), ), for (final tile in sidebarTileList) NavigationButton( label: mediaQuery.lgAndUp ? Text(tile.title) : null, child: Tooltip( - tooltip: TooltipContainer(child: Text(tile.title)), + tooltip: TooltipContainer(child: Text(tile.title)).call, child: Icon(tile.icon), ), onPressed: () { @@ -85,7 +97,7 @@ class Sidebar extends HookConsumerWidget { context.navigateTo(tile.route); }, child: Tooltip( - tooltip: TooltipContainer(child: Text(tile.title)), + tooltip: TooltipContainer(child: Text(tile.title)).call, child: Icon(tile.icon), ), ), diff --git a/lib/modules/settings/color_scheme_picker_dialog.dart b/lib/modules/settings/color_scheme_picker_dialog.dart index 8092f825..3fb05e72 100644 --- a/lib/modules/settings/color_scheme_picker_dialog.dart +++ b/lib/modules/settings/color_scheme_picker_dialog.dart @@ -21,7 +21,7 @@ class SpotubeColor extends Color { @override String toString() { - return "$name:$value"; + return "$name:${toARGB32()}"; } } diff --git a/lib/modules/settings/playback/edit_connect_port_dialog.dart b/lib/modules/settings/playback/edit_connect_port_dialog.dart new file mode 100644 index 00000000..587f4388 --- /dev/null +++ b/lib/modules/settings/playback/edit_connect_port_dialog.dart @@ -0,0 +1,97 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:spotube/components/form/text_form_field.dart'; +import 'package:spotube/extensions/context.dart'; +import 'package:spotube/hooks/controllers/use_shadcn_text_editing_controller.dart'; +import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; + +class SettingsPlaybackEditConnectPortDialog extends HookConsumerWidget { + const SettingsPlaybackEditConnectPortDialog({super.key}); + + @override + Widget build(BuildContext context, ref) { + final connectPort = ref.watch( + userPreferencesProvider.select((s) => s.connectPort), + ); + final controller = useShadcnTextEditingController( + text: connectPort.toString(), + ); + final formKey = useMemoized(() => GlobalKey(), []); + + return ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400), + child: Alert( + title: Text(context.l10n.edit_port).h4(), + content: FormBuilder( + key: formKey, + child: Column( + children: [ + const Gap(10), + TextFormBuilderField( + name: "port", + controller: controller, + placeholder: const Text("3000"), + validator: FormBuilderValidators.integer(radix: 10), + keyboardType: TextInputType.number, + inputFormatters: [ + // Allow only signed integers + TextInputFormatter.withFunction( + (oldValue, newValue) { + if (newValue.text.isEmpty) { + return const TextEditingValue(); + } + if (newValue.text.length == 1 && newValue.text == "-") { + return newValue; + } + + final intValue = int.tryParse(newValue.text); + if (intValue == null) { + return oldValue; + } + return newValue; + }, + ), + ], + ), + const Gap(5), + Text(context.l10n.port_helper_msg).small.muted, + const Gap(20), + Row( + children: [ + Expanded( + child: Button.secondary( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(context.l10n.cancel), + ), + ), + const Gap(10), + Expanded( + child: Button.primary( + onPressed: () { + if (!formKey.currentState!.saveAndValidate()) { + return; + } + final port = int.parse(controller.text); + ref + .read(userPreferencesProvider.notifier) + .setConnectPort(port); + Navigator.of(context).pop(); + }, + child: Text(context.l10n.save), + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/modules/settings/playback/edit_instance_url_dialog.dart b/lib/modules/settings/playback/edit_instance_url_dialog.dart new file mode 100644 index 00000000..b2dda411 --- /dev/null +++ b/lib/modules/settings/playback/edit_instance_url_dialog.dart @@ -0,0 +1,75 @@ +import 'package:flutter_form_builder/flutter_form_builder.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:form_builder_validators/form_builder_validators.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:spotube/components/form/text_form_field.dart'; +import 'package:spotube/extensions/context.dart'; +import 'package:spotube/hooks/controllers/use_shadcn_text_editing_controller.dart'; + +class SettingsPlaybackEditInstanceUrlDialog extends HookConsumerWidget { + final String title; + final String? initialValue; + final ValueChanged onSave; + + const SettingsPlaybackEditInstanceUrlDialog({ + super.key, + required this.title, + required this.onSave, + this.initialValue, + }); + + @override + Widget build(BuildContext context, ref) { + final controller = useShadcnTextEditingController( + text: initialValue, + ); + final formKey = useMemoized(() => GlobalKey(), []); + + return Alert( + title: Text(title).h4(), + content: FormBuilder( + key: formKey, + child: Column( + children: [ + const Gap(10), + TextFormBuilderField( + name: "url", + controller: controller, + placeholder: Text(title), + validator: FormBuilderValidators.url(), + ), + const Gap(10), + Row( + children: [ + Expanded( + child: Button.secondary( + onPressed: () { + Navigator.of(context).pop(); + }, + child: Text(context.l10n.cancel), + ), + ), + const Gap(10), + Expanded( + child: Button.primary( + onPressed: () { + if (!formKey.currentState!.saveAndValidate()) { + return; + } + onSave( + controller.text, + ); + Navigator.of(context).pop(); + }, + child: Text(context.l10n.save), + ), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/modules/stats/top/artists.dart b/lib/modules/stats/top/artists.dart index c53c34fd..cb2a152f 100644 --- a/lib/modules/stats/top/artists.dart +++ b/lib/modules/stats/top/artists.dart @@ -25,7 +25,13 @@ class TopArtists extends HookConsumerWidget { ref.watch(historyTopTracksProvider(historyDuration).notifier); final artistsData = useMemoized( - () => topTracks.asData?.value.artists ?? [], [topTracks.asData?.value]); + () => topTracks.asData?.value.artists ?? [], + [topTracks.asData?.value], + ); + + for (final artist in artistsData) { + print("${artist.artist.name} has ${artist.artist.images?.length} images"); + } return Skeletonizer.sliver( enabled: topTracks.isLoading && !topTracks.isLoadingNextPage, diff --git a/lib/pages/artist/section/footer.dart b/lib/pages/artist/section/footer.dart index 0fe2ab68..9a1423b5 100644 --- a/lib/pages/artist/section/footer.dart +++ b/lib/pages/artist/section/footer.dart @@ -35,7 +35,7 @@ class ArtistPageFooter extends ConsumerWidget { borderRadius: BorderRadius.circular(10), image: DecorationImage( colorFilter: ColorFilter.mode( - Colors.black.withOpacity(0.5), + Colors.black.withValues(alpha: 0.5), BlendMode.darken, ), image: UniversalImage.imageProvider( diff --git a/lib/pages/artist/section/header.dart b/lib/pages/artist/section/header.dart index b6224428..62e66edc 100644 --- a/lib/pages/artist/section/header.dart +++ b/lib/pages/artist/section/header.dart @@ -1,7 +1,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/fake.dart'; import 'package:spotube/collections/spotube_icons.dart'; @@ -84,7 +84,7 @@ class ArtistPageHeader extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.add_artist_to_blacklist), - ), + ).call, child: IconButton( icon: Icon( SpotubeIcons.userRemove, diff --git a/lib/pages/connect/control/control.dart b/lib/pages/connect/control/control.dart index 2511809c..e28566fd 100644 --- a/lib/pages/connect/control/control.dart +++ b/lib/pages/connect/control/control.dart @@ -1,9 +1,13 @@ +import 'dart:convert'; + import 'package:auto_route/auto_route.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotube/collections/routes.gr.dart'; import 'package:spotube/collections/spotube_icons.dart'; +import 'package:spotube/models/connect/connect.dart'; import 'package:spotube/modules/player/player_queue.dart'; import 'package:spotube/modules/player/volume_slider.dart'; import 'package:spotube/components/image/universal_image.dart'; @@ -57,6 +61,7 @@ class ConnectControlPage extends HookConsumerWidget { final resolvedService = ref.watch(connectClientsProvider).asData?.value.resolvedService; + final connect = ref.watch(connectProvider); final connectNotifier = ref.read(connectProvider.notifier); final playlist = ref.watch(queueProvider); final playing = ref.watch(playingProvider); @@ -69,12 +74,32 @@ class ConnectControlPage extends HookConsumerWidget { } }); + useEffect(() { + if (connect.asData?.value == null) return null; + + final subscription = connect.asData?.value?.stream.listen((message) { + final event = WebSocketEvent.fromJson( + jsonDecode(message), + (data) => data, + ); + event.onError((event) { + if (event.data != "Connection denied") return; + if (!context.mounted) return; + context.back(); + }); + }); + + return () { + subscription?.cancel(); + }; + }, [connect.asData?.value]); + return SafeArea( bottom: false, child: Scaffold( headers: [ TitleBar( - title: Text(resolvedService!.name), + title: Text(resolvedService?.name ?? ""), ) ], child: LayoutBuilder(builder: (context, constrains) { @@ -188,7 +213,7 @@ class ConnectControlPage extends HookConsumerWidget { ? context.l10n.unshuffle_playlist : context.l10n.shuffle_playlist, ), - ), + ).call, child: IconButton( icon: const Icon(SpotubeIcons.shuffle), variance: shuffled @@ -204,7 +229,7 @@ class ConnectControlPage extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.previous_track), - ), + ).call, child: IconButton.ghost( icon: const Icon(SpotubeIcons.skipBack), onPressed: playlist.activeTrack == null @@ -219,7 +244,7 @@ class ConnectControlPage extends HookConsumerWidget { ? context.l10n.pause_playback : context.l10n.resume_playback, ), - ), + ).call, child: IconButton.primary( shape: ButtonShape.circle, icon: playlist.activeTrack == null @@ -247,7 +272,8 @@ class ConnectControlPage extends HookConsumerWidget { ), Tooltip( tooltip: TooltipContainer( - child: Text(context.l10n.next_track)), + child: Text(context.l10n.next_track)) + .call, child: IconButton.ghost( icon: const Icon(SpotubeIcons.skipForward), onPressed: playlist.activeTrack == null @@ -264,7 +290,7 @@ class ConnectControlPage extends HookConsumerWidget { ? context.l10n.repeat_playlist : context.l10n.no_loop, ), - ), + ).call, child: IconButton( icon: Icon( loopMode == PlaylistMode.single diff --git a/lib/pages/home/home.dart b/lib/pages/home/home.dart index 9ca71c04..1ef81027 100644 --- a/lib/pages/home/home.dart +++ b/lib/pages/home/home.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:auto_route/auto_route.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -28,6 +30,7 @@ class HomePage extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { + final theme = Theme.of(context); final controller = useScrollController(); final mediaQuery = MediaQuery.of(context); final layoutMode = @@ -45,7 +48,17 @@ class HomePage extends HookConsumerWidget { if (mediaQuery.smAndDown || layoutMode == LayoutMode.compact) SliverAppBar( floating: true, - title: Assets.spotubeLogoPng.image(height: 45), + title: Image.asset( + theme.brightness == Brightness.dark + ? Assets.spotubeLogoPng.path + : Assets.spotubeLogoLight.path, + height: 45, + width: 45, + color: theme.colorScheme.background, + colorBlendMode: BlendMode.saturation, + cacheHeight: + (100 * MediaQuery.devicePixelRatioOf(context)).toInt(), + ), backgroundColor: context.theme.colorScheme.background, foregroundColor: context.theme.colorScheme.foreground, actions: [ diff --git a/lib/pages/lastfm_login/lastfm_login.dart b/lib/pages/lastfm_login/lastfm_login.dart index ca0f5693..164b9b0d 100644 --- a/lib/pages/lastfm_login/lastfm_login.dart +++ b/lib/pages/lastfm_login/lastfm_login.dart @@ -119,15 +119,19 @@ class LastFMLoginPage extends HookConsumerWidget { ], obscureText: !passwordVisible.value, placeholder: Text(context.l10n.password), - trailing: IconButton.ghost( - icon: Icon( - passwordVisible.value - ? SpotubeIcons.eye - : SpotubeIcons.noEye, + features: [ + InputFeature.trailing( + IconButton.ghost( + icon: Icon( + passwordVisible.value + ? SpotubeIcons.eye + : SpotubeIcons.noEye, + ), + onPressed: () => passwordVisible.value = + !passwordVisible.value, + ), ), - onPressed: () => passwordVisible.value = - !passwordVisible.value, - ), + ], ), ), ], diff --git a/lib/pages/library/user_albums.dart b/lib/pages/library/user_albums.dart index 60ba7319..beaa779f 100644 --- a/lib/pages/library/user_albums.dart +++ b/lib/pages/library/user_albums.dart @@ -75,7 +75,9 @@ class UserAlbumsPage extends HookConsumerWidget { height: 48, child: TextField( onChanged: (value) => searchText.value = value, - leading: const Icon(SpotubeIcons.filter), + features: const [ + InputFeature.leading(Icon(SpotubeIcons.filter)) + ], placeholder: Text(context.l10n.filter_artist), ), ), diff --git a/lib/pages/library/user_artists.dart b/lib/pages/library/user_artists.dart index 5f304f5e..35577cd7 100644 --- a/lib/pages/library/user_artists.dart +++ b/lib/pages/library/user_artists.dart @@ -80,7 +80,9 @@ class UserArtistsPage extends HookConsumerWidget { height: 48, child: TextField( onChanged: (value) => searchText.value = value, - leading: const Icon(SpotubeIcons.filter), + features: const [ + InputFeature.leading(Icon(SpotubeIcons.filter)), + ], placeholder: Text(context.l10n.filter_artist), ), ), diff --git a/lib/pages/library/user_playlists.dart b/lib/pages/library/user_playlists.dart index 8249726d..8b9e0dc3 100644 --- a/lib/pages/library/user_playlists.dart +++ b/lib/pages/library/user_playlists.dart @@ -99,7 +99,9 @@ class UserPlaylistsPage extends HookConsumerWidget { child: TextField( onChanged: (value) => searchText.value = value, placeholder: Text(context.l10n.filter_playlists), - leading: const Icon(SpotubeIcons.filter), + features: const [ + InputFeature.leading(Icon(SpotubeIcons.filter)), + ], ), ), ), diff --git a/lib/pages/lyrics/lyrics.dart b/lib/pages/lyrics/lyrics.dart index d3e77bf0..1bd58d61 100644 --- a/lib/pages/lyrics/lyrics.dart +++ b/lib/pages/lyrics/lyrics.dart @@ -1,6 +1,6 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; @@ -101,7 +101,7 @@ class LyricsPage extends HookConsumerWidget { borderRadius: BorderRadius.zero, borderWidth: 0, child: ColoredBox( - color: palette.color.withOpacity(.7), + color: palette.color.withValues(alpha: .7), child: SafeArea( child: IndexedStack( index: selectedIndex.value, diff --git a/lib/pages/lyrics/mini_lyrics.dart b/lib/pages/lyrics/mini_lyrics.dart index 3e50987d..4c28eddd 100644 --- a/lib/pages/lyrics/mini_lyrics.dart +++ b/lib/pages/lyrics/mini_lyrics.dart @@ -2,7 +2,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:palette_generator/palette_generator.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotube/collections/routes.gr.dart'; import 'package:spotube/collections/spotube_icons.dart'; @@ -59,7 +59,7 @@ class MiniLyricsPage extends HookConsumerWidget { areaActive.value = false; }, child: Scaffold( - backgroundColor: theme.colorScheme.background.withOpacity(0.4), + backgroundColor: theme.colorScheme.background.withValues(alpha: 0.4), headers: [ Padding( padding: const EdgeInsets.all(8.0), @@ -89,7 +89,8 @@ class MiniLyricsPage extends HookConsumerWidget { const Spacer(), Tooltip( tooltip: - TooltipContainer(child: Text(context.l10n.lyrics)), + TooltipContainer(child: Text(context.l10n.lyrics)) + .call, child: IconButton( variance: showLyrics.value ? ButtonVariance.secondary @@ -115,7 +116,7 @@ class MiniLyricsPage extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.show_hide_ui_on_hover), - ), + ).call, child: IconButton( variance: hoverMode.value ? ButtonVariance.secondary @@ -136,7 +137,7 @@ class MiniLyricsPage extends HookConsumerWidget { return Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.always_on_top), - ), + ).call, child: IconButton( variance: snapshot.data == true ? ButtonVariance.secondary @@ -199,7 +200,7 @@ class MiniLyricsPage extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.queue), - ), + ).call, child: IconButton.ghost( icon: const Icon(SpotubeIcons.queue), onPressed: playlistQueue.activeTrack != null @@ -245,7 +246,8 @@ class MiniLyricsPage extends HookConsumerWidget { const Flexible(child: PlayerControls(compact: true)), Tooltip( tooltip: TooltipContainer( - child: Text(context.l10n.exit_mini_player)), + child: Text(context.l10n.exit_mini_player)) + .call, child: IconButton.ghost( icon: const Icon(SpotubeIcons.maximize), onPressed: () async { @@ -268,7 +270,7 @@ class MiniLyricsPage extends HookConsumerWidget { const Duration(milliseconds: 200)); } finally { if (context.mounted) { - context.navigateTo(LyricsRoute()); + context.navigateTo(const LyricsRoute()); } } }, diff --git a/lib/pages/search/search.dart b/lib/pages/search/search.dart index 3826a0b6..25fb046a 100644 --- a/lib/pages/search/search.dart +++ b/lib/pages/search/search.dart @@ -121,32 +121,47 @@ class SearchPage extends HookConsumerWidget { } }, child: AutoComplete( - suggestions: suggestions, + suggestions: suggestions.length <= 2 + ? [ + ...suggestions, + "Twenty One Pilots", + "Linkin Park", + "d4vd" + ] + : suggestions, + completer: (suggestion) => suggestion, + mode: AutoCompleteMode.replaceAll, child: TextField( autofocus: true, controller: controller, - leading: - const Icon(SpotubeIcons.search), - textInputAction: TextInputAction.search, - placeholder: Text(context.l10n.search), - trailing: AnimatedCrossFade( - duration: - const Duration(milliseconds: 300), - crossFadeState: - controller.text.isNotEmpty + features: [ + const InputFeature.leading( + Icon(SpotubeIcons.search), + ), + InputFeature.trailing( + AnimatedCrossFade( + duration: const Duration( + milliseconds: 300), + crossFadeState: controller + .text.isNotEmpty ? CrossFadeState.showFirst : CrossFadeState.showSecond, - firstChild: IconButton.ghost( - size: ButtonSize.small, - icon: - const Icon(SpotubeIcons.close), - onPressed: () { - controller.clear(); - }, - ), - secondChild: const SizedBox.square( - dimension: 28), - ), + firstChild: IconButton.ghost( + size: ButtonSize.small, + icon: const Icon( + SpotubeIcons.close), + onPressed: () { + controller.clear(); + }, + ), + secondChild: + const SizedBox.square( + dimension: 28), + ), + ) + ], + textInputAction: TextInputAction.search, + placeholder: Text(context.l10n.search), onSubmitted: onSubmitted, ), ), @@ -194,7 +209,7 @@ class SearchPage extends HookConsumerWidget { fontSize: 20, fontWeight: FontWeight.w900, color: theme.colorScheme.foreground - .withOpacity(0.7), + .withValues(alpha: 0.7), ), ), const SizedBox(height: 20), diff --git a/lib/pages/settings/sections/accounts.dart b/lib/pages/settings/sections/accounts.dart index 5e40b9ec..a381dc23 100644 --- a/lib/pages/settings/sections/accounts.dart +++ b/lib/pages/settings/sections/accounts.dart @@ -49,7 +49,7 @@ class SettingsAccountSection extends HookConsumerWidget { ), ), onTap: () { - context.navigateTo(ProfileRoute()); + context.navigateTo(const ProfileRoute()); }, ), if (auth.asData?.value == null) diff --git a/lib/pages/settings/sections/playback.dart b/lib/pages/settings/sections/playback.dart index f3b7d131..6acc70b1 100644 --- a/lib/pages/settings/sections/playback.dart +++ b/lib/pages/settings/sections/playback.dart @@ -4,19 +4,16 @@ import 'package:auto_route/auto_route.dart'; import 'package:collection/collection.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart' show ListTile; -import 'package:flutter_form_builder/flutter_form_builder.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:piped_client/piped_client.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer; import 'package:spotube/collections/routes.gr.dart'; import 'package:spotube/collections/spotube_icons.dart'; -import 'package:spotube/components/form/text_form_field.dart'; -import 'package:spotube/hooks/controllers/use_shadcn_text_editing_controller.dart'; import 'package:spotube/models/database/database.dart'; +import 'package:spotube/modules/settings/playback/edit_connect_port_dialog.dart'; +import 'package:spotube/modules/settings/playback/edit_instance_url_dialog.dart'; import 'package:spotube/modules/settings/section_card_with_heading.dart'; import 'package:spotube/components/adaptive/adaptive_select_tile.dart'; import 'package:spotube/extensions/context.dart'; @@ -106,7 +103,7 @@ class SettingsPlaybackSection extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.add_custom_url), - ), + ).call, child: IconButton.outline( icon: const Icon(SpotubeIcons.edit), size: ButtonSize.small, @@ -114,67 +111,12 @@ class SettingsPlaybackSection extends HookConsumerWidget { showDialog( context: context, barrierColor: Colors.black.withValues(alpha: 0.5), - builder: (context) => HookBuilder( - builder: (context) { - final controller = - useShadcnTextEditingController( - text: preferences.pipedInstance, - ); - final formKey = useMemoized( - () => GlobalKey(), []); - - return Alert( - title: - Text(context.l10n.piped_instance).h4(), - content: FormBuilder( - key: formKey, - child: Column( - children: [ - const Gap(10), - TextFormBuilderField( - name: "url", - controller: controller, - placeholder: Text( - context.l10n.piped_instance), - validator: - FormBuilderValidators.url(), - ), - const Gap(10), - Row( - children: [ - Expanded( - child: Button.secondary( - onPressed: () { - Navigator.of(context).pop(); - }, - child: - Text(context.l10n.cancel), - ), - ), - const Gap(10), - Expanded( - child: Button.primary( - onPressed: () { - if (!formKey.currentState! - .saveAndValidate()) { - return; - } - preferencesNotifier - .setPipedInstance( - controller.text, - ); - Navigator.of(context).pop(); - }, - child: - Text(context.l10n.save), - ), - ), - ], - ) - ], - ), - ), - ); + builder: (context) => + SettingsPlaybackEditInstanceUrlDialog( + title: context.l10n.piped_instance, + initialValue: preferences.pipedInstance, + onSave: (value) { + preferencesNotifier.setPipedInstance(value); }, ), ); @@ -261,7 +203,7 @@ class SettingsPlaybackSection extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.add_custom_url), - ), + ).call, child: IconButton.outline( icon: const Icon(SpotubeIcons.edit), size: ButtonSize.small, @@ -269,67 +211,13 @@ class SettingsPlaybackSection extends HookConsumerWidget { showDialog( context: context, barrierColor: Colors.black.withValues(alpha: 0.5), - builder: (context) => HookBuilder( - builder: (context) { - final controller = - useShadcnTextEditingController( - text: preferences.invidiousInstance, - ); - final formKey = useMemoized( - () => GlobalKey(), []); - - return Alert( - title: Text(context.l10n.invidious_instance) - .h4(), - content: FormBuilder( - key: formKey, - child: Column( - children: [ - const Gap(10), - TextFormBuilderField( - name: "url", - controller: controller, - placeholder: Text(context - .l10n.invidious_instance), - validator: - FormBuilderValidators.url(), - ), - const Gap(10), - Row( - children: [ - Expanded( - child: Button.secondary( - onPressed: () { - Navigator.of(context).pop(); - }, - child: - Text(context.l10n.cancel), - ), - ), - const Gap(10), - Expanded( - child: Button.primary( - onPressed: () { - if (!formKey.currentState! - .saveAndValidate()) { - return; - } - preferencesNotifier - .setInvidiousInstance( - controller.text, - ); - Navigator.of(context).pop(); - }, - child: - Text(context.l10n.save), - ), - ), - ], - ) - ], - ), - ), - ); + builder: (context) => + SettingsPlaybackEditInstanceUrlDialog( + title: context.l10n.invidious_instance, + initialValue: preferences.invidiousInstance, + onSave: (value) { + preferencesNotifier + .setInvidiousInstance(value); }, ), ); @@ -561,9 +449,32 @@ class SettingsPlaybackSection extends HookConsumerWidget { title: Text(context.l10n.enable_connect), subtitle: Text(context.l10n.enable_connect_description), leading: const Icon(SpotubeIcons.connect), - trailing: Switch( - value: preferences.enableConnect, - onChanged: preferencesNotifier.setEnableConnect, + trailing: Row( + mainAxisSize: MainAxisSize.min, + spacing: 10, + children: [ + Tooltip( + tooltip: TooltipContainer( + child: Text(context.l10n.edit_port), + ).call, + child: IconButton.outline( + icon: const Icon(SpotubeIcons.edit), + size: ButtonSize.small, + onPressed: () { + showDialog( + context: context, + barrierColor: Colors.black.withValues(alpha: 0.5), + builder: (context) => + const SettingsPlaybackEditConnectPortDialog(), + ); + }, + ), + ), + Switch( + value: preferences.enableConnect, + onChanged: preferencesNotifier.setEnableConnect, + ), + ], ), ), ], diff --git a/lib/pages/track/track.dart b/lib/pages/track/track.dart index 2918d1d7..8e6df748 100644 --- a/lib/pages/track/track.dart +++ b/lib/pages/track/track.dart @@ -77,7 +77,7 @@ class TrackPage extends HookConsumerWidget { ), fit: BoxFit.cover, colorFilter: ColorFilter.mode( - colorScheme.background.withOpacity(0.5), + colorScheme.background.withValues(alpha: 0.5), BlendMode.srcOver, ), alignment: Alignment.topCenter, @@ -196,7 +196,7 @@ class TrackPage extends HookConsumerWidget { Tooltip( tooltip: TooltipContainer( child: Text(context.l10n.play_next), - ), + ).call, child: IconButton.outline( icon: const Icon( SpotubeIcons.lightning), @@ -214,7 +214,7 @@ class TrackPage extends HookConsumerWidget { ? context.l10n.pause_playback : context.l10n.play, ), - ), + ).call, child: IconButton.primary( shape: ButtonShape.circle, icon: Icon( diff --git a/lib/provider/audio_player/audio_player_streams.dart b/lib/provider/audio_player/audio_player_streams.dart index 54c6d7cd..c221a2b0 100644 --- a/lib/provider/audio_player/audio_player_streams.dart +++ b/lib/provider/audio_player/audio_player_streams.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:spotify/spotify.dart'; import 'package:spotube/models/local_track.dart'; import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/audio_player/state.dart'; @@ -10,6 +11,7 @@ import 'package:spotube/provider/history/history.dart'; import 'package:spotube/provider/skip_segments/skip_segments.dart'; import 'package:spotube/provider/scrobbler/scrobbler.dart'; import 'package:spotube/provider/server/sourced_track.dart'; +import 'package:spotube/provider/spotify/spotify.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_services/audio_services.dart'; @@ -63,7 +65,9 @@ class AudioPlayerStreamListeners { final currentSegments = await ref.read(segmentProvider.future); if (currentSegments?.segments.isNotEmpty != true || - position < const Duration(seconds: 3)) return; + position < const Duration(seconds: 3)) { + return; + } for (final segment in currentSegments!.segments) { final seconds = position.inSeconds; @@ -80,7 +84,7 @@ class AudioPlayerStreamListeners { StreamSubscription subscribeToScrobbleChanged() { String? lastScrobbled; - return audioPlayer.positionStream.listen((position) { + return audioPlayer.positionStream.listen((position) async { try { final uid = audioPlayerState.activeTrack is LocalTrack ? (audioPlayerState.activeTrack as LocalTrack).path @@ -93,8 +97,23 @@ class AudioPlayerStreamListeners { } scrobbler.scrobble(audioPlayerState.activeTrack!); - history.addTrack(audioPlayerState.activeTrack!); lastScrobbled = uid; + + /// The [Track] from Playlist.getTracks doesn't contain artist images + /// so we need to fetch them from the API + final activeTrack = + Track.fromJson(audioPlayerState.activeTrack!.toJson()); + if (audioPlayerState.activeTrack!.artists + ?.any((a) => a.images == null) ?? + false) { + activeTrack.artists = + await ref.read(spotifyProvider).api.artists.list([ + for (final artist in audioPlayerState.activeTrack!.artists!) + artist.id!, + ]).then((value) => value.toList()); + } + + await history.addTrack(activeTrack); } catch (e, stack) { AppLogger.reportError(e, stack); } diff --git a/lib/provider/authentication/authentication.dart b/lib/provider/authentication/authentication.dart index 583955b0..497ccf79 100644 --- a/lib/provider/authentication/authentication.dart +++ b/lib/provider/authentication/authentication.dart @@ -61,7 +61,7 @@ class AuthenticationNotifier extends AsyncNotifier { Timer? refreshTimer; - ref.listenSelf((prevData, newData) async { + listenSelf((prevData, newData) async { if (newData.asData?.value == null) return; if (newData.asData!.value!.isExpired) { diff --git a/lib/provider/connect/connect.dart b/lib/provider/connect/connect.dart index 000a28af..93d2fb88 100644 --- a/lib/provider/connect/connect.dart +++ b/lib/provider/connect/connect.dart @@ -1,6 +1,10 @@ import 'dart:convert'; import 'package:media_kit/media_kit.dart' hide Track; +import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:spotube/collections/routes.dart'; +import 'package:spotube/collections/spotube_icons.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/provider/audio_player/state.dart'; import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/logger/logger.dart'; @@ -46,15 +50,17 @@ final volumeProvider = StateProvider( (ref) => 1.0, ); -class ConnectNotifier extends AsyncNotifier { +typedef ConnectState = ({WebSocketChannel channel, Stream stream}); + +class ConnectNotifier extends AsyncNotifier { @override build() async { try { - final connectClients = ref.watch(connectClientsProvider); + final connectClients = await ref.watch(connectClientsProvider.future); - if (connectClients.asData?.value.resolvedService == null) return null; + if (connectClients.resolvedService == null) return null; - final service = connectClients.asData!.value.resolvedService!; + final service = connectClients.resolvedService!; AppLogger.log.t( '♾️ Connecting to ${service.name}: ws://${service.host}:${service.port}/ws', @@ -70,7 +76,9 @@ class ConnectNotifier extends AsyncNotifier { '✅ Connected to ${service.name}: ws://${service.host}:${service.port}/ws', ); - final subscription = channel.stream.listen( + final stream = channel.stream.asBroadcastStream(); + + final subscription = stream.listen( (message) { final event = WebSocketEvent.fromJson(jsonDecode(message), (data) => data); @@ -102,6 +110,38 @@ class ConnectNotifier extends AsyncNotifier { event.onVolume((event) { ref.read(volumeProvider.notifier).state = event.data; }); + + event.onError((event) { + if (event.data == "Connection denied") { + ref.read(connectClientsProvider.notifier).clearResolvedService(); + + if (rootNavigatorKey.currentContext?.mounted == true) { + final theme = Theme.of(rootNavigatorKey.currentContext!); + + showToast( + context: rootNavigatorKey.currentContext!, + location: ToastLocation.topRight, + dismissible: true, + builder: (context, overlay) { + return SurfaceCard( + fillColor: theme.colorScheme.destructive, + filled: true, + child: Basic( + leading: const Icon(SpotubeIcons.error), + title: Text( + context.l10n.connection_request_denied, + style: theme.typography.normal.copyWith( + color: theme.colorScheme.destructiveForeground, + ), + ), + leadingAlignment: Alignment.center, + ), + ); + }, + ); + } + } + }); }, onError: (error) { AppLogger.reportError(error, StackTrace.current); @@ -113,7 +153,7 @@ class ConnectNotifier extends AsyncNotifier { channel.sink.close(status.goingAway); }); - return channel; + return (channel: channel, stream: stream); } catch (e, stack) { AppLogger.reportError(e, stack); rethrow; @@ -122,7 +162,7 @@ class ConnectNotifier extends AsyncNotifier { Future emit(Object message) async { if (state.value == null) return; - state.value?.sink.add( + state.value?.channel.sink.add( message is String ? message : (message as dynamic).toJson(), ); } @@ -184,7 +224,6 @@ class ConnectNotifier extends AsyncNotifier { } } -final connectProvider = - AsyncNotifierProvider( +final connectProvider = AsyncNotifierProvider( () => ConnectNotifier(), ); diff --git a/lib/provider/download_manager_provider.dart b/lib/provider/download_manager_provider.dart index 5e9eda20..1b588399 100644 --- a/lib/provider/download_manager_provider.dart +++ b/lib/provider/download_manager_provider.dart @@ -46,7 +46,9 @@ class DownloadManagerProvider extends ChangeNotifier { //? WebA audiotagging is not supported yet //? Although in future by converting weba to opus & then tagging it //? is possible using vorbis comments - downloadCodec == SourceCodecs.weba) return; + downloadCodec == SourceCodecs.weba) { + return; + } final file = File(request.path); diff --git a/lib/provider/history/history.dart b/lib/provider/history/history.dart index 0c20a9e5..25b722ff 100644 --- a/lib/provider/history/history.dart +++ b/lib/provider/history/history.dart @@ -39,6 +39,11 @@ class PlaybackHistoryActions { } Future addTracks(List tracks) async { + assert( + tracks.every((t) => t.artists?.every((a) => a.images != null) ?? false), + 'Track artists must have images', + ); + await _batchInsertHistoryEntries([ for (final track in tracks) HistoryTableCompanion.insert( @@ -50,6 +55,11 @@ class PlaybackHistoryActions { } Future addTrack(Track track) async { + assert( + track.artists?.every((a) => a.images != null) ?? false, + 'Track artists must have images', + ); + await _db.into(_db.historyTable).insert( HistoryTableCompanion.insert( type: HistoryEntryType.track, diff --git a/lib/provider/history/top/tracks.dart b/lib/provider/history/top/tracks.dart index b737d148..3c057e56 100644 --- a/lib/provider/history/top/tracks.dart +++ b/lib/provider/history/top/tracks.dart @@ -28,7 +28,15 @@ class HistoryTopTracksState extends PaginatedState { return groupBy(artists, (artist) => artist.id!) .entries .map((entry) { - return (count: entry.value.length, artist: entry.value.first); + return ( + count: entry.value.length, + + /// Previously, due to a bug, artist images were not being saved. + /// Now it's fixed, but we need to handle the case where images are null. + /// So we take the first artist with images if available, otherwise the first one. + artist: entry.value.firstWhereOrNull((a) => a.images != null) ?? + entry.value.first, + ); }) .sorted((a, b) => b.count.compareTo(a.count)) .toList(); @@ -85,11 +93,58 @@ class HistoryTopTracksNotifier extends FamilyPaginatedAsyncNotifier< ); } + Future fixImageNotLoadingForArtistIssue( + List entries, + ) async { + final nonImageArtistTracks = + entries.where((e) => e.track!.artists!.any((a) => a.images == null)); + + if (nonImageArtistTracks.isEmpty) return; + + final artistIds = nonImageArtistTracks + .map((e) => e.track!.artists!.map((a) => a.id!)) + .expand((e) => e) + .toSet() + .toList(); + + if (artistIds.isEmpty) return; + + final artists = await ref.read(spotifyProvider).api.artists.list(artistIds); + + final imagedArtistTracks = nonImageArtistTracks.map((e) { + final track = e.track!; + final includedArtists = track.artists! + .map((a) => artists.firstWhereOrNull((artist) => artist.id == a.id)) + .nonNulls + .toList(); + + track.artists = includedArtists; + + return e.copyWith(data: track.toJson()); + }); + + assert( + imagedArtistTracks + .every((e) => e.track!.artists!.every((a) => a.images != null)), + 'Tracks artists should have images', + ); + + final database = ref.read(databaseProvider); + await database.batch((batch) { + batch.insertAllOnConflictUpdate( + database.historyTable, + imagedArtistTracks, + ); + }); + } + @override fetch(arg, offset, limit) async { final tracksQuery = createTracksQuery()..limit(limit, offset: offset); - final items = getTracksWithCount(await tracksQuery.get()); + final entries = await tracksQuery.get(); + + final items = getTracksWithCount(entries); return ( items: items, @@ -123,13 +178,26 @@ class HistoryTopTracksNotifier extends FamilyPaginatedAsyncNotifier< } List getTracksWithCount(List tracks) { + fixImageNotLoadingForArtistIssue(tracks); + return groupBy( tracks, (track) => track.track!.id!, ) .entries .map((entry) { - return (count: entry.value.length, track: entry.value.first.track!); + return ( + count: entry.value.length, + + /// Previously, due to a bug, artist images were not being saved. + /// Now it's fixed, but we need to handle the case where images are null. + /// So we take the first artist with images if available, otherwise the first one. + track: entry.value + .firstWhereOrNull( + (t) => t.track!.artists!.every((a) => a.images != null)) + ?.track! ?? + entry.value.first.track!, + ); }) .sorted((a, b) => b.count.compareTo(a.count)) .toList(); diff --git a/lib/provider/local_tracks/local_tracks_provider.dart b/lib/provider/local_tracks/local_tracks_provider.dart index b33fd7f6..c69d3169 100644 --- a/lib/provider/local_tracks/local_tracks_provider.dart +++ b/lib/provider/local_tracks/local_tracks_provider.dart @@ -15,6 +15,7 @@ import 'package:spotube/models/local_track.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; // ignore: depend_on_referenced_packages import 'package:flutter_rust_bridge/flutter_rust_bridge.dart' show FrbException; +import 'package:spotube/utils/service_utils.dart'; const supportedAudioTypes = [ "audio/webm", @@ -90,12 +91,15 @@ final localTracksProvider = try { final metadata = await MetadataGod.readMetadata(file: file.path); - final imageFile = File(join( - (await getTemporaryDirectory()).path, - "spotube", - basenameWithoutExtension(file.path) + - imgMimeToExt[metadata.picture?.mimeType ?? "image/jpeg"]!, - )); + final imageFile = File( + join( + (await getTemporaryDirectory()).path, + "spotube", + ServiceUtils.sanitizeFilename( + basenameWithoutExtension(file.path)) + + imgMimeToExt[metadata.picture?.mimeType ?? "image/jpeg"]!, + ), + ); if (!await imageFile.exists() && metadata.picture != null) { await imageFile.create(recursive: true); await imageFile.writeAsBytes( diff --git a/lib/provider/server/routes/connect.dart b/lib/provider/server/routes/connect.dart index 0d35b473..6c4d8ce0 100644 --- a/lib/provider/server/routes/connect.dart +++ b/lib/provider/server/routes/connect.dart @@ -3,9 +3,12 @@ import 'dart:convert'; import 'dart:io'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:shelf/shelf.dart'; import 'package:shelf_web_socket/shelf_web_socket.dart'; import 'package:spotify/spotify.dart'; +import 'package:spotube/collections/routes.dart'; +import 'package:spotube/extensions/context.dart'; import 'package:spotube/models/connect/connect.dart'; import 'package:spotube/provider/history/history.dart'; @@ -43,6 +46,8 @@ class ServerConnectRoutes { Stream get connectClientStream => _connectClientStreamController.stream; + final List _allowedConnections = []; + FutureOr websocket(Request req) { return webSocketHandler( ( @@ -54,6 +59,47 @@ class ServerConnectRoutes { final origin = "${context?.remoteAddress.host}:${context?.remotePort}"; _connectClientStreamController.add(origin); + // Confirm whether user allows to connect + if (rootNavigatorKey.currentContext?.mounted == true && + _allowedConnections.contains(origin) == false) { + final confirmed = await showDialog( + context: rootNavigatorKey.currentContext!, + builder: (context) { + return AlertDialog( + title: Text(context.l10n.connect), + content: Text( + context.l10n.connect_request(origin), + ), + actions: [ + Button.secondary( + onPressed: () { + Navigator.of(context).pop(false); + }, + child: Text(context.l10n.decline), + ), + Button.primary( + onPressed: () { + Navigator.of(context).pop(true); + }, + child: Text(context.l10n.accept), + ), + ], + ); + }, + ) ?? + false; + + if (confirmed) { + _allowedConnections.add(origin); + } else { + channel.sink.addEvent( + WebSocketErrorEvent("Connection denied"), + ); + await channel.sink.close(); + return; + } + } + ref.listen( audioPlayerProvider, (previous, next) { @@ -106,7 +152,7 @@ class ServerConnectRoutes { }, ), channel.stream.listen( - (message) { + (message) async { try { final event = WebSocketEvent.fromJson( jsonDecode(message), diff --git a/lib/provider/server/routes/playback.dart b/lib/provider/server/routes/playback.dart index 1c7d0de7..ccbeb7ab 100644 --- a/lib/provider/server/routes/playback.dart +++ b/lib/provider/server/routes/playback.dart @@ -54,7 +54,9 @@ class ServerPlaybackRoutes { final trackCacheFile = File( join( await UserPreferencesNotifier.getMusicCacheDir(), - '${track.name} - ${track.artists?.asString()} (${track.sourceInfo.id}).${track.codec.name}', + ServiceUtils.sanitizeFilename( + '${track.name} - ${track.artists?.asString()} (${track.sourceInfo.id}).${track.codec.name}', + ), ), ); final trackPartialCacheFile = File("${trackCacheFile.path}.part"); @@ -128,7 +130,10 @@ class ServerPlaybackRoutes { .read(sourcedTrackProvider(SpotubeMedia(track)).notifier) .refreshStreamingUrl(); - ref.read(activeSourcedTrackProvider.notifier).update(sourcedTrack); + if (playlist.activeTrack?.id == sourcedTrack?.id && + sourcedTrack != null) { + ref.read(activeSourcedTrackProvider.notifier).update(sourcedTrack); + } return await dio.get( sourcedTrack!.url, @@ -199,7 +204,10 @@ class ServerPlaybackRoutes { ? activeSourcedTrack : await ref.read(sourcedTrackProvider(SpotubeMedia(track)).future); - ref.read(activeSourcedTrackProvider.notifier).update(sourcedTrack); + if (playlist.activeTrack?.id == sourcedTrack?.id && + sourcedTrack != null) { + ref.read(activeSourcedTrackProvider.notifier).update(sourcedTrack); + } final (bytes: audioBytes, response: res) = await streamTrack(sourcedTrack!, request.headers); diff --git a/lib/provider/server/server.dart b/lib/provider/server/server.dart index 131f1ea4..d10815bf 100644 --- a/lib/provider/server/server.dart +++ b/lib/provider/server/server.dart @@ -5,30 +5,51 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shelf/shelf_io.dart'; import 'package:spotube/provider/server/pipeline.dart'; import 'package:spotube/provider/server/router.dart'; +import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/logger/logger.dart'; final serverProvider = FutureProvider( (ref) async { + final enabledRemoteConnect = ref.watch( + userPreferencesProvider.select((value) => value.enableConnect), + ); + final connectPort = ref.watch( + userPreferencesProvider.select((value) => value.connectPort), + ); final pipeline = ref.watch(pipelineProvider); final router = ref.watch(serverRouterProvider); - final port = Random().nextInt(17500) + 5000; - SpotubeMedia.serverPort = port; + // When connect port is -1, we need to generate a random port + // but we shouldn't reset it if it's already been set (caused by a state change) + if (connectPort == -1) { + if (SpotubeMedia.serverPort == 0) { + final port = Random().nextInt(17500) + 5000; + SpotubeMedia.serverPort = port; + } + } else { + SpotubeMedia.serverPort = connectPort; + } final server = await serve( pipeline.addHandler(router.call), - InternetAddress.anyIPv4, - port, + enabledRemoteConnect + ? InternetAddress.anyIPv4 + : InternetAddress.loopbackIPv4, + SpotubeMedia.serverPort, ); - AppLogger.log - .t('Playback server at http://${server.address.host}:${server.port}'); + AppLogger.log.t( + 'Playback server at http://${server.address.host}:${server.port}', + ); ref.onDispose(() { server.close(); }); - return (server: server, port: port); + return ( + server: server, + port: SpotubeMedia.serverPort, + ); }, ); diff --git a/lib/provider/spotify/album/tracks.dart b/lib/provider/spotify/album/tracks.dart index d886d180..13c48886 100644 --- a/lib/provider/spotify/album/tracks.dart +++ b/lib/provider/spotify/album/tracks.dart @@ -33,7 +33,7 @@ class AlbumTracksNotifier extends AutoDisposeFamilyPaginatedAsyncNotifier api.albums.tracks(arg.id!).getPage(limit, offset), ); - final items = tracks.items?.map((e) => e.asTrack(arg)).toList() ?? []; + final items = await tracks.items!.asTracks(arg, ref); return ( items: items, diff --git a/lib/provider/user_preferences/user_preferences_provider.dart b/lib/provider/user_preferences/user_preferences_provider.dart index 75234241..30ee8b3f 100644 --- a/lib/provider/user_preferences/user_preferences_provider.dart +++ b/lib/provider/user_preferences/user_preferences_provider.dart @@ -90,9 +90,9 @@ class UserPreferencesNotifier extends Notifier { Future reset() async { final db = ref.read(databaseProvider); - final query = db.update(db.preferencesTable)..where((t) => t.id.equals(0)); + final query = db.update(db.preferencesTable); - await query.replace(PreferencesTableCompanion.insert()); + await query.replace(PreferencesTableCompanion.insert(id: const Value(0))); } static Future getMusicCacheDir() async { @@ -240,6 +240,14 @@ class UserPreferencesNotifier extends Notifier { setData(PreferencesTableCompanion(enableConnect: Value(enable))); } + void setConnectPort(int port) { + assert( + port >= -1 && port <= 65535, + "Port must be between -1 and 65535, got $port", + ); + setData(PreferencesTableCompanion(connectPort: Value(port))); + } + void setCacheMusic(bool cache) { setData(PreferencesTableCompanion(cacheMusic: Value(cache))); } diff --git a/lib/services/sourced_track/sources/youtube.dart b/lib/services/sourced_track/sources/youtube.dart index c4881051..193bdc0d 100644 --- a/lib/services/sourced_track/sources/youtube.dart +++ b/lib/services/sourced_track/sources/youtube.dart @@ -236,32 +236,75 @@ class YoutubeSourcedTrack extends SourcedTrack { .toList(); } + static Future> fetchFromIsrc({ + required Track track, + required Ref ref, + }) async { + final isrcResults = []; + final isrc = track.externalIds?.isrc; + if (isrc != null && isrc.isNotEmpty) { + final searchedVideos = + await ref.read(youtubeEngineProvider).searchVideos(isrc.toString()); + if (searchedVideos.isNotEmpty) { + isrcResults.addAll(searchedVideos + .map(YoutubeVideoInfo.fromVideo) + .map((YoutubeVideoInfo videoInfo) { + final ytWords = videoInfo.title + .toLowerCase() + .replaceAll(RegExp(r'[^\p{L}\p{N}\p{Z}]+', unicode: true), '') + .split(RegExp(r'\p{Z}+', unicode: true)) + .where((item) => item.isNotEmpty); + final spWords = track.name! + .toLowerCase() + .replaceAll(RegExp(r'[^\p{L}\p{N}\p{Z}]+', unicode: true), '') + .split(RegExp(r'\p{Z}+', unicode: true)) + .where((item) => item.isNotEmpty); + // Single word and duration match with 3 second tolerance + if (ytWords.any((word) => spWords.contains(word)) && + (videoInfo.duration - track.duration!) + .abs().inMilliseconds <= 3000) { + return videoInfo; + } + return null; + }) + .whereType() + .toList()); + } + } + return isrcResults; + } + static Future> fetchSiblings({ required Track track, required Ref ref, }) async { - final links = await SongLinkService.links(track.id!); - final ytLink = links.firstWhereOrNull((link) => link.platform == "youtube"); + final videoResults = []; - if (ytLink?.url != null - // allows to fetch siblings more results for already sourced track - && - track is! SourcedTrack) { - try { - return [ - await toSiblingType( - 0, - YoutubeVideoInfo.fromVideo( - await ref.read(youtubeEngineProvider).getVideo( - Uri.parse(ytLink!.url!).queryParameters["v"]!, - ), - ), - ref, - ) - ]; - } on VideoUnplayableException catch (e, stack) { - // Ignore this error and continue with the search - AppLogger.reportError(e, stack); + if (track is! SourcedTrack) { + final isrcResults = await fetchFromIsrc( + track: track, + ref: ref, + ); + + videoResults.addAll(isrcResults); + + if (isrcResults.isEmpty) { + final links = await SongLinkService.links(track.id!); + final ytLink = links.firstWhereOrNull( + (link) => link.platform == "youtube", + ); + if (ytLink?.url != null) { + try { + videoResults.add( + YoutubeVideoInfo.fromVideo(await ref + .read(youtubeEngineProvider) + .getVideo(Uri.parse(ytLink!.url!).queryParameters["v"]!)), + ); + } on VideoUnplayableException catch (e, stack) { + // Ignore this error and continue with the search + AppLogger.reportError(e, stack); + } + } } } @@ -271,20 +314,27 @@ class YoutubeSourcedTrack extends SourcedTrack { await ref.read(youtubeEngineProvider).searchVideos(query); if (ServiceUtils.onlyContainsEnglish(query)) { - return await Future.wait(searchResults - .map(YoutubeVideoInfo.fromVideo) - .mapIndexed((index, info) => toSiblingType(index, info, ref))); + videoResults + .addAll(searchResults.map(YoutubeVideoInfo.fromVideo).toList()); + } else { + videoResults.addAll(rankResults( + searchResults.map(YoutubeVideoInfo.fromVideo).toList(), + track, + )); } - final rankedSiblings = rankResults( - searchResults.map(YoutubeVideoInfo.fromVideo).toList(), - track, - ); - + final seenIds = {}; + int index = 0; return await Future.wait( - rankedSiblings - .mapIndexed((index, info) => toSiblingType(index, info, ref)), - ); + videoResults.map((videoResult) async { + // Deduplicate results + if (!seenIds.contains(videoResult.id)) { + seenIds.add(videoResult.id); + return await toSiblingType(index++, videoResult, ref); + } + return null; + }), + ).then((s) => s.whereType().toList()); } @override diff --git a/lib/utils/service_utils.dart b/lib/utils/service_utils.dart index f0eeff05..72a98a0b 100644 --- a/lib/utils/service_utils.dart +++ b/lib/utils/service_utils.dart @@ -434,4 +434,37 @@ abstract class ServiceUtils { return "Mozilla/5.0 (Linux; Android ${randomNumber(8, 13)}) AppleWebKit/${randomNumber(530, 537)}.${randomNumber(30, 36)} (KHTML, like Gecko) Chrome/${randomNumber(101, 116)}.0.${randomNumber(3000, 6000)}.${randomNumber(60, 125)} Mobile Safari/${randomNumber(530, 537)}.${randomNumber(30, 36)}"; } } + + static String sanitizeFilename(String input, {String replacement = ''}) { + final result = input + // illegalRe + .replaceAll( + RegExp(r'[\/\?<>\\:\*\|"]'), + replacement, + ) + // controlRe + .replaceAll( + RegExp( + r'[\x00-\x1f\x80-\x9f]', + ), + replacement, + ) + // reservedRe + .replaceFirst( + RegExp(r'^\.+$'), + replacement, + ) + // windowsReservedRe + .replaceFirst( + RegExp( + r'^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$', + caseSensitive: false, + ), + replacement, + ) + // windowsTrailingRe + .replaceFirst(RegExp(r'[\. ]+$'), replacement); + + return result.length > 255 ? result.substring(0, 255) : result; + } } diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 8f100774..194ef566 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -32,6 +32,7 @@ function(APPLY_STANDARD_SETTINGS TARGET) target_compile_options(${TARGET} PRIVATE -Wall -Werror) target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") + target_compile_options(${TARGET} PRIVATE -Wno-error=deprecated-declarations) endfunction() set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") diff --git a/linux/com.github.KRTirtho.Spotube.appdata.xml b/linux/com.github.KRTirtho.Spotube.appdata.xml index f30d360b..ad63e4b0 100644 --- a/linux/com.github.KRTirtho.Spotube.appdata.xml +++ b/linux/com.github.KRTirtho.Spotube.appdata.xml @@ -17,11 +17,12 @@ https://spotube.krtirtho.dev https://opencollective.com/spotube -

Open source Spotify client that doesn't require Premium nor uses Electron! Available for +

Open source music client that doesn't require Premium nor uses Electron! Available for both desktop & mobile!

Following are the features that currently spotube offers:

    -
  • 🚫 No ads, thanks to the use of public & free Spotify and YT Music APIs¹
  • +
  • 🚫 No ads, thanks to the use of public & free music metadata providers and YT Music + APIs¹
  • ⬇️ Downloadable tracks
  • 🖥️ 📱 Cross-platform support
  • 🪶 Small size & less data usage
  • diff --git a/linux/packaging/appimage/make_config.yaml b/linux/packaging/appimage/make_config.yaml index c7332ea2..94fc5dd9 100644 --- a/linux/packaging/appimage/make_config.yaml +++ b/linux/packaging/appimage/make_config.yaml @@ -3,7 +3,6 @@ icon: assets/spotube-logo.png keywords: - Music - - Spotify - Media - Streaming - YouTube diff --git a/linux/packaging/deb/make_config.yaml b/linux/packaging/deb/make_config.yaml index 4528a136..8a7d4672 100644 --- a/linux/packaging/deb/make_config.yaml +++ b/linux/packaging/deb/make_config.yaml @@ -34,7 +34,6 @@ icon: assets/spotube-logo.png keywords: - Music - - Spotify - Media - Streaming - YouTube diff --git a/linux/packaging/rpm/make_config.yaml b/linux/packaging/rpm/make_config.yaml index 3d4a3b7e..57eaae54 100644 --- a/linux/packaging/rpm/make_config.yaml +++ b/linux/packaging/rpm/make_config.yaml @@ -1,5 +1,5 @@ icon: assets/spotube-logo.png -summary: Lightweight cross-platform Spotify desktop client +summary: Lightweight cross-platform music client group: Applications/Multimedia vendor: Kingkor Roy Tirtho packager: Kingkor Roy Tirtho @@ -23,7 +23,6 @@ display_name: Spotube keywords: - Music - - Spotify - Media - Streaming - YouTube diff --git a/linux/spotube.desktop b/linux/spotube.desktop index 53f381e1..61fdee50 100644 --- a/linux/spotube.desktop +++ b/linux/spotube.desktop @@ -3,7 +3,7 @@ Type=Application Name=Spotube Exec=/usr/bin/spotube Icon=/usr/share/icons/spotube/spotube-logo.png -Comment=A music streaming app combining the power of Spotify & YouTube +Comment=A music streaming app combining the power of music metadata providers & YouTube Terminal=false Categories=Audio;Music;Player;AudioVideo; MimeType=x-scheme-handler/spotify; \ No newline at end of file diff --git a/macos/Podfile.lock b/macos/Podfile.lock index 95feb26d..b3bbbb0b 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -168,7 +168,7 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - app_links: 9028728e32c83a0831d9db8cf91c526d16cc5468 + app_links: afe860c55c7ef176cea7fb630a2b7d7736de591d audio_service: 0d9e4e25347bb3efb768f3b9f005911a81e587a7 audio_session: 48ab6500f7a5e7c64363e206565a5dfe5a0c1441 bonsoir_darwin: 29c7ccf356646118844721f36e1de4b61f6cbd0e diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png index ce03848f..87d35152 100644 Binary files a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png index 9988ac22..951e2199 100644 Binary files a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png index c23f1e0c..8fc26ab9 100644 Binary files a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png index de5236c1..136e59bf 100644 Binary files a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png index 85449d04..cb3042ee 100644 Binary files a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png index e93200f0..5a8f2b83 100644 Binary files a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png index 4be23237..4fe48af6 100644 Binary files a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/metadata/en-US/full_description.txt b/metadata/en-US/full_description.txt index a30d10c7..94f32a38 100644 --- a/metadata/en-US/full_description.txt +++ b/metadata/en-US/full_description.txt @@ -1,8 +1,8 @@ -Open source Spotify client that doesn't require Premium nor uses Electron! Available for both desktop & mobile! +Open source music client that doesn't require Premium nor uses Electron! Available for both desktop & mobile! Features: -* No ads, thanks to the use of public & free Spotify and YT Music APIs¹ +* No ads, thanks to the use of public & free music metadata providers and YT Music APIs¹ * Downloadable tracks * Cross-platform support * Small size & less data usage diff --git a/metadata/en-US/images/phoneScreenshots/android-4.jpg b/metadata/en-US/images/phoneScreenshots/android-4.jpg index 3057c69a..278aae21 100644 Binary files a/metadata/en-US/images/phoneScreenshots/android-4.jpg and b/metadata/en-US/images/phoneScreenshots/android-4.jpg differ diff --git a/metadata/en-US/short_description.txt b/metadata/en-US/short_description.txt index bd37f2d9..df3c2916 100644 --- a/metadata/en-US/short_description.txt +++ b/metadata/en-US/short_description.txt @@ -1 +1 @@ -Lightweight & resource friendly spotify client without requiring Spotify Premium \ No newline at end of file +Lightweight & resource friendly music client \ No newline at end of file diff --git a/metadata/tr/full_description.txt b/metadata/tr/full_description.txt index 8b8b814c..4e56ce17 100644 --- a/metadata/tr/full_description.txt +++ b/metadata/tr/full_description.txt @@ -1,8 +1,8 @@ -Premium gerektirmeyen ve Electron kullanmayan açık kaynaklı Spotify istemcisi! Hem masaüstü hem de mobil için kullanılabilir! +Premium gerektirmeyen ve Electron kullanmayan açık kaynaklı müzik istemcisi! Hem masaüstü hem de mobil için kullanılabilir! Özellikler: -* Herkese açık ve ücretsiz Spotify ve YT Music API'lerinin kullanımı sayesinde reklam yok¹ +* Herkese açık ve ücretsiz müzik meta veri sağlayıcısı ve YT Music API'lerinin kullanımı sayesinde reklam yok¹ * İndirilebilir parçalar * Çapraz platform desteği * Küçük boyut ve daha az veri kullanımı diff --git a/metadata/tr/images/phoneScreenshots/android-4.jpg b/metadata/tr/images/phoneScreenshots/android-4.jpg index 3057c69a..278aae21 100644 Binary files a/metadata/tr/images/phoneScreenshots/android-4.jpg and b/metadata/tr/images/phoneScreenshots/android-4.jpg differ diff --git a/metadata/tr/short_description.txt b/metadata/tr/short_description.txt index 2a0d24cd..1481155e 100644 --- a/metadata/tr/short_description.txt +++ b/metadata/tr/short_description.txt @@ -1 +1 @@ -Spotify Premium gerektirmeyen hafif ve kaynak dostu spotify istemcisi \ No newline at end of file +Hafif ve kaynak dostu müzik istemcisi \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 8a9de0d0..db9cdb80 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -74,18 +74,18 @@ packages: dependency: transitive description: name: archive - sha256: "08064924cbf0ab88280a0c3f60db9dd24fec693927e725ecb176f16c629d1cb8" + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "4.0.7" args: dependency: "direct main" description: name: args - sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 url: "https://pub.dev" source: hosted - version: "2.6.0" + version: "2.7.0" asn1lib: dependency: transitive description: @@ -642,6 +642,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.7" + expressions: + dependency: transitive + description: + name: expressions + sha256: "308a621b602923dd8a0cf3072793b24850d06453eb49c6b698cbda41a282e904" + url: "https://pub.dev" + source: hosted + version: "0.2.5+2" fake_async: dependency: transitive description: @@ -926,16 +934,16 @@ packages: dependency: "direct main" description: name: flutter_native_splash - sha256: "1152ab0067ca5a2ebeb862fe0a762057202cceb22b7e62692dcbabf6483891bb" + sha256: "8321a6d11a8d13977fa780c89de8d257cce3d841eecfb7a4cadffcc4f12d82dc" url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.6" flutter_new_pipe_extractor: dependency: "direct main" description: path: "." ref: HEAD - resolved-ref: "157930289f49d9c2b5016a3df6f771ebfdf2b1e7" + resolved-ref: "385a3c8906351d811a9df5a94bf118e791a51d45" url: "https://github.com/KRTirtho/flutter_new_pipe_extractor.git" source: git version: "0.1.0" @@ -1230,10 +1238,10 @@ packages: dependency: transitive description: name: image - sha256: "599d08e369969bdf83138f5b4e0a7e823d3f992f23b8a64dd626877c37013533" + sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" url: "https://pub.dev" source: hosted - version: "4.4.0" + version: "4.5.4" image_picker: dependency: "direct main" description: @@ -1875,10 +1883,10 @@ packages: dependency: transitive description: name: posix - sha256: a0117dc2167805aa9125b82eee515cc891819bac2f538c83646d355b16f58b9a + sha256: f0d7856b6ca1887cfa6d1d394056a296ae33489db914e365e2044fdada449e62 url: "https://pub.dev" source: hosted - version: "6.0.1" + version: "6.0.2" process: dependency: transitive description: @@ -1919,6 +1927,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + quiver: + dependency: transitive + description: + name: quiver + sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 + url: "https://pub.dev" + source: hosted + version: "3.2.2" recase: dependency: transitive description: @@ -2012,10 +2028,10 @@ packages: dependency: "direct main" description: name: shadcn_flutter - sha256: "1e5f40484a42217a69af254952168783d1305025d56dabc45ab16396dba84d5e" + sha256: "8635e8e0cd2e0fba0a3093a53fbe3bdd37d90d038c4c66d761728d7cfcf23ce3" url: "https://pub.dev" source: hosted - version: "0.0.26" + version: "0.0.34" shared_preferences: dependency: "direct main" description: @@ -2449,10 +2465,10 @@ packages: dependency: "direct main" description: name: tray_manager - sha256: f231031c5c0eb4ad514e18ddaab27a912ddbe50335c594bc28fb0f9972ab6a84 + sha256: c2da0f0f1ddb455e721cf68d05d1281fec75cf5df0a1d3cb67b6ca0bdfd5709d url: "https://pub.dev" source: hosted - version: "0.3.1" + version: "0.4.0" type_plus: dependency: transitive description: @@ -2737,10 +2753,10 @@ packages: dependency: transitive description: name: yaml - sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.1.3" youtube_explode_dart: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index fd2cf9f6..f3be4108 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,7 +60,7 @@ dependencies: flutter_inappwebview: ^6.1.3 flutter_localizations: sdk: flutter - flutter_native_splash: ^2.4.0 + flutter_native_splash: ^2.4.6 flutter_riverpod: ^2.5.1 flutter_secure_storage: ^9.0.0 flutter_sharing_intent: ^1.1.0 @@ -102,7 +102,7 @@ dependencies: ref: dart-3-support url: https://github.com/KRTirtho/scrobblenaut.git scroll_to_index: ^3.0.1 - shadcn_flutter: ^0.0.26 + shadcn_flutter: ^0.0.34 shared_preferences: ^2.2.3 shelf: ^1.4.1 shelf_router: ^1.1.4 @@ -120,7 +120,7 @@ dependencies: test: ^1.25.7 timezone: ^0.10.0 titlebar_buttons: ^1.0.0 - tray_manager: ^0.3.0 + tray_manager: ^0.4.0 url_launcher: ^6.2.6 uuid: ^4.4.0 version: ^3.0.2 @@ -200,6 +200,11 @@ flutter: - family: BootstrapIcons fonts: - asset: packages/shadcn_flutter/icons/BootstrapIcons.otf + - family: Cookie + fonts: + - asset: assets/fonts/Cookie-Regular.ttf + style: normal + weight: 500 flutter_gen: output: lib/collections diff --git a/test/drift/app_db/generated/schema.dart b/test/drift/app_db/generated/schema.dart index bdaebe8f..2ab213a2 100644 --- a/test/drift/app_db/generated/schema.dart +++ b/test/drift/app_db/generated/schema.dart @@ -3,27 +3,33 @@ // ignore_for_file: type=lint import 'package:drift/drift.dart'; import 'package:drift/internal/migrations.dart'; -import 'schema_v4.dart' as v4; import 'schema_v3.dart' as v3; -import 'schema_v2.dart' as v2; +import 'schema_v5.dart' as v5; +import 'schema_v6.dart' as v6; import 'schema_v1.dart' as v1; +import 'schema_v2.dart' as v2; +import 'schema_v4.dart' as v4; class GeneratedHelper implements SchemaInstantiationHelper { @override GeneratedDatabase databaseForVersion(QueryExecutor db, int version) { switch (version) { - case 4: - return v4.DatabaseAtV4(db); case 3: return v3.DatabaseAtV3(db); - case 2: - return v2.DatabaseAtV2(db); + case 5: + return v5.DatabaseAtV5(db); + case 6: + return v6.DatabaseAtV6(db); case 1: return v1.DatabaseAtV1(db); + case 2: + return v2.DatabaseAtV2(db); + case 4: + return v4.DatabaseAtV4(db); default: throw MissingSchemaException(version, versions); } } - static const versions = const [1, 2, 3, 4]; + static const versions = const [1, 2, 3, 4, 5, 6]; } diff --git a/test/drift/app_db/generated/schema_v5.dart b/test/drift/app_db/generated/schema_v5.dart new file mode 100644 index 00000000..4283aa98 --- /dev/null +++ b/test/drift/app_db/generated/schema_v5.dart @@ -0,0 +1,3433 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class AuthenticationTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AuthenticationTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn cookie = GeneratedColumn( + 'cookie', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn accessToken = GeneratedColumn( + 'access_token', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn expiration = GeneratedColumn( + 'expiration', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [id, cookie, accessToken, expiration]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'authentication_table'; + @override + Set get $primaryKey => {id}; + @override + AuthenticationTableData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AuthenticationTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + cookie: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}cookie'])!, + accessToken: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}access_token'])!, + expiration: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}expiration'])!, + ); + } + + @override + AuthenticationTable createAlias(String alias) { + return AuthenticationTable(attachedDatabase, alias); + } +} + +class AuthenticationTableData extends DataClass + implements Insertable { + final int id; + final String cookie; + final String accessToken; + final DateTime expiration; + const AuthenticationTableData( + {required this.id, + required this.cookie, + required this.accessToken, + required this.expiration}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['cookie'] = Variable(cookie); + map['access_token'] = Variable(accessToken); + map['expiration'] = Variable(expiration); + return map; + } + + AuthenticationTableCompanion toCompanion(bool nullToAbsent) { + return AuthenticationTableCompanion( + id: Value(id), + cookie: Value(cookie), + accessToken: Value(accessToken), + expiration: Value(expiration), + ); + } + + factory AuthenticationTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AuthenticationTableData( + id: serializer.fromJson(json['id']), + cookie: serializer.fromJson(json['cookie']), + accessToken: serializer.fromJson(json['accessToken']), + expiration: serializer.fromJson(json['expiration']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'cookie': serializer.toJson(cookie), + 'accessToken': serializer.toJson(accessToken), + 'expiration': serializer.toJson(expiration), + }; + } + + AuthenticationTableData copyWith( + {int? id, + String? cookie, + String? accessToken, + DateTime? expiration}) => + AuthenticationTableData( + id: id ?? this.id, + cookie: cookie ?? this.cookie, + accessToken: accessToken ?? this.accessToken, + expiration: expiration ?? this.expiration, + ); + AuthenticationTableData copyWithCompanion(AuthenticationTableCompanion data) { + return AuthenticationTableData( + id: data.id.present ? data.id.value : this.id, + cookie: data.cookie.present ? data.cookie.value : this.cookie, + accessToken: + data.accessToken.present ? data.accessToken.value : this.accessToken, + expiration: + data.expiration.present ? data.expiration.value : this.expiration, + ); + } + + @override + String toString() { + return (StringBuffer('AuthenticationTableData(') + ..write('id: $id, ') + ..write('cookie: $cookie, ') + ..write('accessToken: $accessToken, ') + ..write('expiration: $expiration') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, cookie, accessToken, expiration); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AuthenticationTableData && + other.id == this.id && + other.cookie == this.cookie && + other.accessToken == this.accessToken && + other.expiration == this.expiration); +} + +class AuthenticationTableCompanion + extends UpdateCompanion { + final Value id; + final Value cookie; + final Value accessToken; + final Value expiration; + const AuthenticationTableCompanion({ + this.id = const Value.absent(), + this.cookie = const Value.absent(), + this.accessToken = const Value.absent(), + this.expiration = const Value.absent(), + }); + AuthenticationTableCompanion.insert({ + this.id = const Value.absent(), + required String cookie, + required String accessToken, + required DateTime expiration, + }) : cookie = Value(cookie), + accessToken = Value(accessToken), + expiration = Value(expiration); + static Insertable custom({ + Expression? id, + Expression? cookie, + Expression? accessToken, + Expression? expiration, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (cookie != null) 'cookie': cookie, + if (accessToken != null) 'access_token': accessToken, + if (expiration != null) 'expiration': expiration, + }); + } + + AuthenticationTableCompanion copyWith( + {Value? id, + Value? cookie, + Value? accessToken, + Value? expiration}) { + return AuthenticationTableCompanion( + id: id ?? this.id, + cookie: cookie ?? this.cookie, + accessToken: accessToken ?? this.accessToken, + expiration: expiration ?? this.expiration, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (cookie.present) { + map['cookie'] = Variable(cookie.value); + } + if (accessToken.present) { + map['access_token'] = Variable(accessToken.value); + } + if (expiration.present) { + map['expiration'] = Variable(expiration.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthenticationTableCompanion(') + ..write('id: $id, ') + ..write('cookie: $cookie, ') + ..write('accessToken: $accessToken, ') + ..write('expiration: $expiration') + ..write(')')) + .toString(); + } +} + +class BlacklistTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + BlacklistTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn elementType = GeneratedColumn( + 'element_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn elementId = GeneratedColumn( + 'element_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, name, elementType, elementId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'blacklist_table'; + @override + Set get $primaryKey => {id}; + @override + BlacklistTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return BlacklistTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + elementType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}element_type'])!, + elementId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}element_id'])!, + ); + } + + @override + BlacklistTable createAlias(String alias) { + return BlacklistTable(attachedDatabase, alias); + } +} + +class BlacklistTableData extends DataClass + implements Insertable { + final int id; + final String name; + final String elementType; + final String elementId; + const BlacklistTableData( + {required this.id, + required this.name, + required this.elementType, + required this.elementId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['element_type'] = Variable(elementType); + map['element_id'] = Variable(elementId); + return map; + } + + BlacklistTableCompanion toCompanion(bool nullToAbsent) { + return BlacklistTableCompanion( + id: Value(id), + name: Value(name), + elementType: Value(elementType), + elementId: Value(elementId), + ); + } + + factory BlacklistTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return BlacklistTableData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + elementType: serializer.fromJson(json['elementType']), + elementId: serializer.fromJson(json['elementId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'elementType': serializer.toJson(elementType), + 'elementId': serializer.toJson(elementId), + }; + } + + BlacklistTableData copyWith( + {int? id, String? name, String? elementType, String? elementId}) => + BlacklistTableData( + id: id ?? this.id, + name: name ?? this.name, + elementType: elementType ?? this.elementType, + elementId: elementId ?? this.elementId, + ); + BlacklistTableData copyWithCompanion(BlacklistTableCompanion data) { + return BlacklistTableData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + elementType: + data.elementType.present ? data.elementType.value : this.elementType, + elementId: data.elementId.present ? data.elementId.value : this.elementId, + ); + } + + @override + String toString() { + return (StringBuffer('BlacklistTableData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('elementType: $elementType, ') + ..write('elementId: $elementId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, elementType, elementId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is BlacklistTableData && + other.id == this.id && + other.name == this.name && + other.elementType == this.elementType && + other.elementId == this.elementId); +} + +class BlacklistTableCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value elementType; + final Value elementId; + const BlacklistTableCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.elementType = const Value.absent(), + this.elementId = const Value.absent(), + }); + BlacklistTableCompanion.insert({ + this.id = const Value.absent(), + required String name, + required String elementType, + required String elementId, + }) : name = Value(name), + elementType = Value(elementType), + elementId = Value(elementId); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? elementType, + Expression? elementId, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (elementType != null) 'element_type': elementType, + if (elementId != null) 'element_id': elementId, + }); + } + + BlacklistTableCompanion copyWith( + {Value? id, + Value? name, + Value? elementType, + Value? elementId}) { + return BlacklistTableCompanion( + id: id ?? this.id, + name: name ?? this.name, + elementType: elementType ?? this.elementType, + elementId: elementId ?? this.elementId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (elementType.present) { + map['element_type'] = Variable(elementType.value); + } + if (elementId.present) { + map['element_id'] = Variable(elementId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BlacklistTableCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('elementType: $elementType, ') + ..write('elementId: $elementId') + ..write(')')) + .toString(); + } +} + +class PreferencesTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PreferencesTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn audioQuality = GeneratedColumn( + 'audio_quality', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceQualities.high.name)); + late final GeneratedColumn albumColorSync = GeneratedColumn( + 'album_color_sync', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("album_color_sync" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn amoledDarkTheme = GeneratedColumn( + 'amoled_dark_theme', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("amoled_dark_theme" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn checkUpdate = GeneratedColumn( + 'check_update', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("check_update" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn normalizeAudio = GeneratedColumn( + 'normalize_audio', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("normalize_audio" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn showSystemTrayIcon = GeneratedColumn( + 'show_system_tray_icon', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("show_system_tray_icon" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn systemTitleBar = GeneratedColumn( + 'system_title_bar', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("system_title_bar" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn skipNonMusic = GeneratedColumn( + 'skip_non_music', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("skip_non_music" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn closeBehavior = GeneratedColumn( + 'close_behavior', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(CloseBehavior.close.name)); + late final GeneratedColumn accentColorScheme = + GeneratedColumn('accent_color_scheme', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("Orange:0xFFf97315")); + late final GeneratedColumn layoutMode = GeneratedColumn( + 'layout_mode', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(LayoutMode.adaptive.name)); + late final GeneratedColumn locale = GeneratedColumn( + 'locale', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: + const Constant('{"languageCode":"system","countryCode":"system"}')); + late final GeneratedColumn market = GeneratedColumn( + 'market', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(Market.US.name)); + late final GeneratedColumn searchMode = GeneratedColumn( + 'search_mode', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SearchMode.youtube.name)); + late final GeneratedColumn downloadLocation = GeneratedColumn( + 'download_location', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("")); + late final GeneratedColumn localLibraryLocation = + GeneratedColumn('local_library_location', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("")); + late final GeneratedColumn pipedInstance = GeneratedColumn( + 'piped_instance', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("https://pipedapi.kavin.rocks")); + late final GeneratedColumn invidiousInstance = + GeneratedColumn('invidious_instance', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("https://inv.nadeko.net")); + late final GeneratedColumn themeMode = GeneratedColumn( + 'theme_mode', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(ThemeMode.system.name)); + late final GeneratedColumn audioSource = GeneratedColumn( + 'audio_source', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(AudioSource.youtube.name)); + late final GeneratedColumn youtubeClientEngine = + GeneratedColumn('youtube_client_engine', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(YoutubeClientEngine.youtubeExplode.name)); + late final GeneratedColumn streamMusicCodec = GeneratedColumn( + 'stream_music_codec', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceCodecs.weba.name)); + late final GeneratedColumn downloadMusicCodec = + GeneratedColumn('download_music_codec', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceCodecs.m4a.name)); + late final GeneratedColumn discordPresence = GeneratedColumn( + 'discord_presence', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("discord_presence" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn endlessPlayback = GeneratedColumn( + 'endless_playback', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("endless_playback" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn enableConnect = GeneratedColumn( + 'enable_connect', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("enable_connect" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn cacheMusic = GeneratedColumn( + 'cache_music', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("cache_music" IN (0, 1))'), + defaultValue: const Constant(true)); + @override + List get $columns => [ + id, + audioQuality, + albumColorSync, + amoledDarkTheme, + checkUpdate, + normalizeAudio, + showSystemTrayIcon, + systemTitleBar, + skipNonMusic, + closeBehavior, + accentColorScheme, + layoutMode, + locale, + market, + searchMode, + downloadLocation, + localLibraryLocation, + pipedInstance, + invidiousInstance, + themeMode, + audioSource, + youtubeClientEngine, + streamMusicCodec, + downloadMusicCodec, + discordPresence, + endlessPlayback, + enableConnect, + cacheMusic + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'preferences_table'; + @override + Set get $primaryKey => {id}; + @override + PreferencesTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PreferencesTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + audioQuality: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}audio_quality'])!, + albumColorSync: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}album_color_sync'])!, + amoledDarkTheme: attachedDatabase.typeMapping.read( + DriftSqlType.bool, data['${effectivePrefix}amoled_dark_theme'])!, + checkUpdate: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}check_update'])!, + normalizeAudio: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}normalize_audio'])!, + showSystemTrayIcon: attachedDatabase.typeMapping.read( + DriftSqlType.bool, data['${effectivePrefix}show_system_tray_icon'])!, + systemTitleBar: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}system_title_bar'])!, + skipNonMusic: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}skip_non_music'])!, + closeBehavior: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}close_behavior'])!, + accentColorScheme: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}accent_color_scheme'])!, + layoutMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}layout_mode'])!, + locale: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}locale'])!, + market: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}market'])!, + searchMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}search_mode'])!, + downloadLocation: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}download_location'])!, + localLibraryLocation: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}local_library_location'])!, + pipedInstance: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}piped_instance'])!, + invidiousInstance: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}invidious_instance'])!, + themeMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}theme_mode'])!, + audioSource: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}audio_source'])!, + youtubeClientEngine: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}youtube_client_engine'])!, + streamMusicCodec: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}stream_music_codec'])!, + downloadMusicCodec: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}download_music_codec'])!, + discordPresence: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}discord_presence'])!, + endlessPlayback: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}endless_playback'])!, + enableConnect: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}enable_connect'])!, + cacheMusic: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}cache_music'])!, + ); + } + + @override + PreferencesTable createAlias(String alias) { + return PreferencesTable(attachedDatabase, alias); + } +} + +class PreferencesTableData extends DataClass + implements Insertable { + final int id; + final String audioQuality; + final bool albumColorSync; + final bool amoledDarkTheme; + final bool checkUpdate; + final bool normalizeAudio; + final bool showSystemTrayIcon; + final bool systemTitleBar; + final bool skipNonMusic; + final String closeBehavior; + final String accentColorScheme; + final String layoutMode; + final String locale; + final String market; + final String searchMode; + final String downloadLocation; + final String localLibraryLocation; + final String pipedInstance; + final String invidiousInstance; + final String themeMode; + final String audioSource; + final String youtubeClientEngine; + final String streamMusicCodec; + final String downloadMusicCodec; + final bool discordPresence; + final bool endlessPlayback; + final bool enableConnect; + final bool cacheMusic; + const PreferencesTableData( + {required this.id, + required this.audioQuality, + required this.albumColorSync, + required this.amoledDarkTheme, + required this.checkUpdate, + required this.normalizeAudio, + required this.showSystemTrayIcon, + required this.systemTitleBar, + required this.skipNonMusic, + required this.closeBehavior, + required this.accentColorScheme, + required this.layoutMode, + required this.locale, + required this.market, + required this.searchMode, + required this.downloadLocation, + required this.localLibraryLocation, + required this.pipedInstance, + required this.invidiousInstance, + required this.themeMode, + required this.audioSource, + required this.youtubeClientEngine, + required this.streamMusicCodec, + required this.downloadMusicCodec, + required this.discordPresence, + required this.endlessPlayback, + required this.enableConnect, + required this.cacheMusic}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['audio_quality'] = Variable(audioQuality); + map['album_color_sync'] = Variable(albumColorSync); + map['amoled_dark_theme'] = Variable(amoledDarkTheme); + map['check_update'] = Variable(checkUpdate); + map['normalize_audio'] = Variable(normalizeAudio); + map['show_system_tray_icon'] = Variable(showSystemTrayIcon); + map['system_title_bar'] = Variable(systemTitleBar); + map['skip_non_music'] = Variable(skipNonMusic); + map['close_behavior'] = Variable(closeBehavior); + map['accent_color_scheme'] = Variable(accentColorScheme); + map['layout_mode'] = Variable(layoutMode); + map['locale'] = Variable(locale); + map['market'] = Variable(market); + map['search_mode'] = Variable(searchMode); + map['download_location'] = Variable(downloadLocation); + map['local_library_location'] = Variable(localLibraryLocation); + map['piped_instance'] = Variable(pipedInstance); + map['invidious_instance'] = Variable(invidiousInstance); + map['theme_mode'] = Variable(themeMode); + map['audio_source'] = Variable(audioSource); + map['youtube_client_engine'] = Variable(youtubeClientEngine); + map['stream_music_codec'] = Variable(streamMusicCodec); + map['download_music_codec'] = Variable(downloadMusicCodec); + map['discord_presence'] = Variable(discordPresence); + map['endless_playback'] = Variable(endlessPlayback); + map['enable_connect'] = Variable(enableConnect); + map['cache_music'] = Variable(cacheMusic); + return map; + } + + PreferencesTableCompanion toCompanion(bool nullToAbsent) { + return PreferencesTableCompanion( + id: Value(id), + audioQuality: Value(audioQuality), + albumColorSync: Value(albumColorSync), + amoledDarkTheme: Value(amoledDarkTheme), + checkUpdate: Value(checkUpdate), + normalizeAudio: Value(normalizeAudio), + showSystemTrayIcon: Value(showSystemTrayIcon), + systemTitleBar: Value(systemTitleBar), + skipNonMusic: Value(skipNonMusic), + closeBehavior: Value(closeBehavior), + accentColorScheme: Value(accentColorScheme), + layoutMode: Value(layoutMode), + locale: Value(locale), + market: Value(market), + searchMode: Value(searchMode), + downloadLocation: Value(downloadLocation), + localLibraryLocation: Value(localLibraryLocation), + pipedInstance: Value(pipedInstance), + invidiousInstance: Value(invidiousInstance), + themeMode: Value(themeMode), + audioSource: Value(audioSource), + youtubeClientEngine: Value(youtubeClientEngine), + streamMusicCodec: Value(streamMusicCodec), + downloadMusicCodec: Value(downloadMusicCodec), + discordPresence: Value(discordPresence), + endlessPlayback: Value(endlessPlayback), + enableConnect: Value(enableConnect), + cacheMusic: Value(cacheMusic), + ); + } + + factory PreferencesTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PreferencesTableData( + id: serializer.fromJson(json['id']), + audioQuality: serializer.fromJson(json['audioQuality']), + albumColorSync: serializer.fromJson(json['albumColorSync']), + amoledDarkTheme: serializer.fromJson(json['amoledDarkTheme']), + checkUpdate: serializer.fromJson(json['checkUpdate']), + normalizeAudio: serializer.fromJson(json['normalizeAudio']), + showSystemTrayIcon: serializer.fromJson(json['showSystemTrayIcon']), + systemTitleBar: serializer.fromJson(json['systemTitleBar']), + skipNonMusic: serializer.fromJson(json['skipNonMusic']), + closeBehavior: serializer.fromJson(json['closeBehavior']), + accentColorScheme: serializer.fromJson(json['accentColorScheme']), + layoutMode: serializer.fromJson(json['layoutMode']), + locale: serializer.fromJson(json['locale']), + market: serializer.fromJson(json['market']), + searchMode: serializer.fromJson(json['searchMode']), + downloadLocation: serializer.fromJson(json['downloadLocation']), + localLibraryLocation: + serializer.fromJson(json['localLibraryLocation']), + pipedInstance: serializer.fromJson(json['pipedInstance']), + invidiousInstance: serializer.fromJson(json['invidiousInstance']), + themeMode: serializer.fromJson(json['themeMode']), + audioSource: serializer.fromJson(json['audioSource']), + youtubeClientEngine: + serializer.fromJson(json['youtubeClientEngine']), + streamMusicCodec: serializer.fromJson(json['streamMusicCodec']), + downloadMusicCodec: + serializer.fromJson(json['downloadMusicCodec']), + discordPresence: serializer.fromJson(json['discordPresence']), + endlessPlayback: serializer.fromJson(json['endlessPlayback']), + enableConnect: serializer.fromJson(json['enableConnect']), + cacheMusic: serializer.fromJson(json['cacheMusic']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'audioQuality': serializer.toJson(audioQuality), + 'albumColorSync': serializer.toJson(albumColorSync), + 'amoledDarkTheme': serializer.toJson(amoledDarkTheme), + 'checkUpdate': serializer.toJson(checkUpdate), + 'normalizeAudio': serializer.toJson(normalizeAudio), + 'showSystemTrayIcon': serializer.toJson(showSystemTrayIcon), + 'systemTitleBar': serializer.toJson(systemTitleBar), + 'skipNonMusic': serializer.toJson(skipNonMusic), + 'closeBehavior': serializer.toJson(closeBehavior), + 'accentColorScheme': serializer.toJson(accentColorScheme), + 'layoutMode': serializer.toJson(layoutMode), + 'locale': serializer.toJson(locale), + 'market': serializer.toJson(market), + 'searchMode': serializer.toJson(searchMode), + 'downloadLocation': serializer.toJson(downloadLocation), + 'localLibraryLocation': serializer.toJson(localLibraryLocation), + 'pipedInstance': serializer.toJson(pipedInstance), + 'invidiousInstance': serializer.toJson(invidiousInstance), + 'themeMode': serializer.toJson(themeMode), + 'audioSource': serializer.toJson(audioSource), + 'youtubeClientEngine': serializer.toJson(youtubeClientEngine), + 'streamMusicCodec': serializer.toJson(streamMusicCodec), + 'downloadMusicCodec': serializer.toJson(downloadMusicCodec), + 'discordPresence': serializer.toJson(discordPresence), + 'endlessPlayback': serializer.toJson(endlessPlayback), + 'enableConnect': serializer.toJson(enableConnect), + 'cacheMusic': serializer.toJson(cacheMusic), + }; + } + + PreferencesTableData copyWith( + {int? id, + String? audioQuality, + bool? albumColorSync, + bool? amoledDarkTheme, + bool? checkUpdate, + bool? normalizeAudio, + bool? showSystemTrayIcon, + bool? systemTitleBar, + bool? skipNonMusic, + String? closeBehavior, + String? accentColorScheme, + String? layoutMode, + String? locale, + String? market, + String? searchMode, + String? downloadLocation, + String? localLibraryLocation, + String? pipedInstance, + String? invidiousInstance, + String? themeMode, + String? audioSource, + String? youtubeClientEngine, + String? streamMusicCodec, + String? downloadMusicCodec, + bool? discordPresence, + bool? endlessPlayback, + bool? enableConnect, + bool? cacheMusic}) => + PreferencesTableData( + id: id ?? this.id, + audioQuality: audioQuality ?? this.audioQuality, + albumColorSync: albumColorSync ?? this.albumColorSync, + amoledDarkTheme: amoledDarkTheme ?? this.amoledDarkTheme, + checkUpdate: checkUpdate ?? this.checkUpdate, + normalizeAudio: normalizeAudio ?? this.normalizeAudio, + showSystemTrayIcon: showSystemTrayIcon ?? this.showSystemTrayIcon, + systemTitleBar: systemTitleBar ?? this.systemTitleBar, + skipNonMusic: skipNonMusic ?? this.skipNonMusic, + closeBehavior: closeBehavior ?? this.closeBehavior, + accentColorScheme: accentColorScheme ?? this.accentColorScheme, + layoutMode: layoutMode ?? this.layoutMode, + locale: locale ?? this.locale, + market: market ?? this.market, + searchMode: searchMode ?? this.searchMode, + downloadLocation: downloadLocation ?? this.downloadLocation, + localLibraryLocation: localLibraryLocation ?? this.localLibraryLocation, + pipedInstance: pipedInstance ?? this.pipedInstance, + invidiousInstance: invidiousInstance ?? this.invidiousInstance, + themeMode: themeMode ?? this.themeMode, + audioSource: audioSource ?? this.audioSource, + youtubeClientEngine: youtubeClientEngine ?? this.youtubeClientEngine, + streamMusicCodec: streamMusicCodec ?? this.streamMusicCodec, + downloadMusicCodec: downloadMusicCodec ?? this.downloadMusicCodec, + discordPresence: discordPresence ?? this.discordPresence, + endlessPlayback: endlessPlayback ?? this.endlessPlayback, + enableConnect: enableConnect ?? this.enableConnect, + cacheMusic: cacheMusic ?? this.cacheMusic, + ); + PreferencesTableData copyWithCompanion(PreferencesTableCompanion data) { + return PreferencesTableData( + id: data.id.present ? data.id.value : this.id, + audioQuality: data.audioQuality.present + ? data.audioQuality.value + : this.audioQuality, + albumColorSync: data.albumColorSync.present + ? data.albumColorSync.value + : this.albumColorSync, + amoledDarkTheme: data.amoledDarkTheme.present + ? data.amoledDarkTheme.value + : this.amoledDarkTheme, + checkUpdate: + data.checkUpdate.present ? data.checkUpdate.value : this.checkUpdate, + normalizeAudio: data.normalizeAudio.present + ? data.normalizeAudio.value + : this.normalizeAudio, + showSystemTrayIcon: data.showSystemTrayIcon.present + ? data.showSystemTrayIcon.value + : this.showSystemTrayIcon, + systemTitleBar: data.systemTitleBar.present + ? data.systemTitleBar.value + : this.systemTitleBar, + skipNonMusic: data.skipNonMusic.present + ? data.skipNonMusic.value + : this.skipNonMusic, + closeBehavior: data.closeBehavior.present + ? data.closeBehavior.value + : this.closeBehavior, + accentColorScheme: data.accentColorScheme.present + ? data.accentColorScheme.value + : this.accentColorScheme, + layoutMode: + data.layoutMode.present ? data.layoutMode.value : this.layoutMode, + locale: data.locale.present ? data.locale.value : this.locale, + market: data.market.present ? data.market.value : this.market, + searchMode: + data.searchMode.present ? data.searchMode.value : this.searchMode, + downloadLocation: data.downloadLocation.present + ? data.downloadLocation.value + : this.downloadLocation, + localLibraryLocation: data.localLibraryLocation.present + ? data.localLibraryLocation.value + : this.localLibraryLocation, + pipedInstance: data.pipedInstance.present + ? data.pipedInstance.value + : this.pipedInstance, + invidiousInstance: data.invidiousInstance.present + ? data.invidiousInstance.value + : this.invidiousInstance, + themeMode: data.themeMode.present ? data.themeMode.value : this.themeMode, + audioSource: + data.audioSource.present ? data.audioSource.value : this.audioSource, + youtubeClientEngine: data.youtubeClientEngine.present + ? data.youtubeClientEngine.value + : this.youtubeClientEngine, + streamMusicCodec: data.streamMusicCodec.present + ? data.streamMusicCodec.value + : this.streamMusicCodec, + downloadMusicCodec: data.downloadMusicCodec.present + ? data.downloadMusicCodec.value + : this.downloadMusicCodec, + discordPresence: data.discordPresence.present + ? data.discordPresence.value + : this.discordPresence, + endlessPlayback: data.endlessPlayback.present + ? data.endlessPlayback.value + : this.endlessPlayback, + enableConnect: data.enableConnect.present + ? data.enableConnect.value + : this.enableConnect, + cacheMusic: + data.cacheMusic.present ? data.cacheMusic.value : this.cacheMusic, + ); + } + + @override + String toString() { + return (StringBuffer('PreferencesTableData(') + ..write('id: $id, ') + ..write('audioQuality: $audioQuality, ') + ..write('albumColorSync: $albumColorSync, ') + ..write('amoledDarkTheme: $amoledDarkTheme, ') + ..write('checkUpdate: $checkUpdate, ') + ..write('normalizeAudio: $normalizeAudio, ') + ..write('showSystemTrayIcon: $showSystemTrayIcon, ') + ..write('systemTitleBar: $systemTitleBar, ') + ..write('skipNonMusic: $skipNonMusic, ') + ..write('closeBehavior: $closeBehavior, ') + ..write('accentColorScheme: $accentColorScheme, ') + ..write('layoutMode: $layoutMode, ') + ..write('locale: $locale, ') + ..write('market: $market, ') + ..write('searchMode: $searchMode, ') + ..write('downloadLocation: $downloadLocation, ') + ..write('localLibraryLocation: $localLibraryLocation, ') + ..write('pipedInstance: $pipedInstance, ') + ..write('invidiousInstance: $invidiousInstance, ') + ..write('themeMode: $themeMode, ') + ..write('audioSource: $audioSource, ') + ..write('youtubeClientEngine: $youtubeClientEngine, ') + ..write('streamMusicCodec: $streamMusicCodec, ') + ..write('downloadMusicCodec: $downloadMusicCodec, ') + ..write('discordPresence: $discordPresence, ') + ..write('endlessPlayback: $endlessPlayback, ') + ..write('enableConnect: $enableConnect, ') + ..write('cacheMusic: $cacheMusic') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + id, + audioQuality, + albumColorSync, + amoledDarkTheme, + checkUpdate, + normalizeAudio, + showSystemTrayIcon, + systemTitleBar, + skipNonMusic, + closeBehavior, + accentColorScheme, + layoutMode, + locale, + market, + searchMode, + downloadLocation, + localLibraryLocation, + pipedInstance, + invidiousInstance, + themeMode, + audioSource, + youtubeClientEngine, + streamMusicCodec, + downloadMusicCodec, + discordPresence, + endlessPlayback, + enableConnect, + cacheMusic + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PreferencesTableData && + other.id == this.id && + other.audioQuality == this.audioQuality && + other.albumColorSync == this.albumColorSync && + other.amoledDarkTheme == this.amoledDarkTheme && + other.checkUpdate == this.checkUpdate && + other.normalizeAudio == this.normalizeAudio && + other.showSystemTrayIcon == this.showSystemTrayIcon && + other.systemTitleBar == this.systemTitleBar && + other.skipNonMusic == this.skipNonMusic && + other.closeBehavior == this.closeBehavior && + other.accentColorScheme == this.accentColorScheme && + other.layoutMode == this.layoutMode && + other.locale == this.locale && + other.market == this.market && + other.searchMode == this.searchMode && + other.downloadLocation == this.downloadLocation && + other.localLibraryLocation == this.localLibraryLocation && + other.pipedInstance == this.pipedInstance && + other.invidiousInstance == this.invidiousInstance && + other.themeMode == this.themeMode && + other.audioSource == this.audioSource && + other.youtubeClientEngine == this.youtubeClientEngine && + other.streamMusicCodec == this.streamMusicCodec && + other.downloadMusicCodec == this.downloadMusicCodec && + other.discordPresence == this.discordPresence && + other.endlessPlayback == this.endlessPlayback && + other.enableConnect == this.enableConnect && + other.cacheMusic == this.cacheMusic); +} + +class PreferencesTableCompanion extends UpdateCompanion { + final Value id; + final Value audioQuality; + final Value albumColorSync; + final Value amoledDarkTheme; + final Value checkUpdate; + final Value normalizeAudio; + final Value showSystemTrayIcon; + final Value systemTitleBar; + final Value skipNonMusic; + final Value closeBehavior; + final Value accentColorScheme; + final Value layoutMode; + final Value locale; + final Value market; + final Value searchMode; + final Value downloadLocation; + final Value localLibraryLocation; + final Value pipedInstance; + final Value invidiousInstance; + final Value themeMode; + final Value audioSource; + final Value youtubeClientEngine; + final Value streamMusicCodec; + final Value downloadMusicCodec; + final Value discordPresence; + final Value endlessPlayback; + final Value enableConnect; + final Value cacheMusic; + const PreferencesTableCompanion({ + this.id = const Value.absent(), + this.audioQuality = const Value.absent(), + this.albumColorSync = const Value.absent(), + this.amoledDarkTheme = const Value.absent(), + this.checkUpdate = const Value.absent(), + this.normalizeAudio = const Value.absent(), + this.showSystemTrayIcon = const Value.absent(), + this.systemTitleBar = const Value.absent(), + this.skipNonMusic = const Value.absent(), + this.closeBehavior = const Value.absent(), + this.accentColorScheme = const Value.absent(), + this.layoutMode = const Value.absent(), + this.locale = const Value.absent(), + this.market = const Value.absent(), + this.searchMode = const Value.absent(), + this.downloadLocation = const Value.absent(), + this.localLibraryLocation = const Value.absent(), + this.pipedInstance = const Value.absent(), + this.invidiousInstance = const Value.absent(), + this.themeMode = const Value.absent(), + this.audioSource = const Value.absent(), + this.youtubeClientEngine = const Value.absent(), + this.streamMusicCodec = const Value.absent(), + this.downloadMusicCodec = const Value.absent(), + this.discordPresence = const Value.absent(), + this.endlessPlayback = const Value.absent(), + this.enableConnect = const Value.absent(), + this.cacheMusic = const Value.absent(), + }); + PreferencesTableCompanion.insert({ + this.id = const Value.absent(), + this.audioQuality = const Value.absent(), + this.albumColorSync = const Value.absent(), + this.amoledDarkTheme = const Value.absent(), + this.checkUpdate = const Value.absent(), + this.normalizeAudio = const Value.absent(), + this.showSystemTrayIcon = const Value.absent(), + this.systemTitleBar = const Value.absent(), + this.skipNonMusic = const Value.absent(), + this.closeBehavior = const Value.absent(), + this.accentColorScheme = const Value.absent(), + this.layoutMode = const Value.absent(), + this.locale = const Value.absent(), + this.market = const Value.absent(), + this.searchMode = const Value.absent(), + this.downloadLocation = const Value.absent(), + this.localLibraryLocation = const Value.absent(), + this.pipedInstance = const Value.absent(), + this.invidiousInstance = const Value.absent(), + this.themeMode = const Value.absent(), + this.audioSource = const Value.absent(), + this.youtubeClientEngine = const Value.absent(), + this.streamMusicCodec = const Value.absent(), + this.downloadMusicCodec = const Value.absent(), + this.discordPresence = const Value.absent(), + this.endlessPlayback = const Value.absent(), + this.enableConnect = const Value.absent(), + this.cacheMusic = const Value.absent(), + }); + static Insertable custom({ + Expression? id, + Expression? audioQuality, + Expression? albumColorSync, + Expression? amoledDarkTheme, + Expression? checkUpdate, + Expression? normalizeAudio, + Expression? showSystemTrayIcon, + Expression? systemTitleBar, + Expression? skipNonMusic, + Expression? closeBehavior, + Expression? accentColorScheme, + Expression? layoutMode, + Expression? locale, + Expression? market, + Expression? searchMode, + Expression? downloadLocation, + Expression? localLibraryLocation, + Expression? pipedInstance, + Expression? invidiousInstance, + Expression? themeMode, + Expression? audioSource, + Expression? youtubeClientEngine, + Expression? streamMusicCodec, + Expression? downloadMusicCodec, + Expression? discordPresence, + Expression? endlessPlayback, + Expression? enableConnect, + Expression? cacheMusic, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (audioQuality != null) 'audio_quality': audioQuality, + if (albumColorSync != null) 'album_color_sync': albumColorSync, + if (amoledDarkTheme != null) 'amoled_dark_theme': amoledDarkTheme, + if (checkUpdate != null) 'check_update': checkUpdate, + if (normalizeAudio != null) 'normalize_audio': normalizeAudio, + if (showSystemTrayIcon != null) + 'show_system_tray_icon': showSystemTrayIcon, + if (systemTitleBar != null) 'system_title_bar': systemTitleBar, + if (skipNonMusic != null) 'skip_non_music': skipNonMusic, + if (closeBehavior != null) 'close_behavior': closeBehavior, + if (accentColorScheme != null) 'accent_color_scheme': accentColorScheme, + if (layoutMode != null) 'layout_mode': layoutMode, + if (locale != null) 'locale': locale, + if (market != null) 'market': market, + if (searchMode != null) 'search_mode': searchMode, + if (downloadLocation != null) 'download_location': downloadLocation, + if (localLibraryLocation != null) + 'local_library_location': localLibraryLocation, + if (pipedInstance != null) 'piped_instance': pipedInstance, + if (invidiousInstance != null) 'invidious_instance': invidiousInstance, + if (themeMode != null) 'theme_mode': themeMode, + if (audioSource != null) 'audio_source': audioSource, + if (youtubeClientEngine != null) + 'youtube_client_engine': youtubeClientEngine, + if (streamMusicCodec != null) 'stream_music_codec': streamMusicCodec, + if (downloadMusicCodec != null) + 'download_music_codec': downloadMusicCodec, + if (discordPresence != null) 'discord_presence': discordPresence, + if (endlessPlayback != null) 'endless_playback': endlessPlayback, + if (enableConnect != null) 'enable_connect': enableConnect, + if (cacheMusic != null) 'cache_music': cacheMusic, + }); + } + + PreferencesTableCompanion copyWith( + {Value? id, + Value? audioQuality, + Value? albumColorSync, + Value? amoledDarkTheme, + Value? checkUpdate, + Value? normalizeAudio, + Value? showSystemTrayIcon, + Value? systemTitleBar, + Value? skipNonMusic, + Value? closeBehavior, + Value? accentColorScheme, + Value? layoutMode, + Value? locale, + Value? market, + Value? searchMode, + Value? downloadLocation, + Value? localLibraryLocation, + Value? pipedInstance, + Value? invidiousInstance, + Value? themeMode, + Value? audioSource, + Value? youtubeClientEngine, + Value? streamMusicCodec, + Value? downloadMusicCodec, + Value? discordPresence, + Value? endlessPlayback, + Value? enableConnect, + Value? cacheMusic}) { + return PreferencesTableCompanion( + id: id ?? this.id, + audioQuality: audioQuality ?? this.audioQuality, + albumColorSync: albumColorSync ?? this.albumColorSync, + amoledDarkTheme: amoledDarkTheme ?? this.amoledDarkTheme, + checkUpdate: checkUpdate ?? this.checkUpdate, + normalizeAudio: normalizeAudio ?? this.normalizeAudio, + showSystemTrayIcon: showSystemTrayIcon ?? this.showSystemTrayIcon, + systemTitleBar: systemTitleBar ?? this.systemTitleBar, + skipNonMusic: skipNonMusic ?? this.skipNonMusic, + closeBehavior: closeBehavior ?? this.closeBehavior, + accentColorScheme: accentColorScheme ?? this.accentColorScheme, + layoutMode: layoutMode ?? this.layoutMode, + locale: locale ?? this.locale, + market: market ?? this.market, + searchMode: searchMode ?? this.searchMode, + downloadLocation: downloadLocation ?? this.downloadLocation, + localLibraryLocation: localLibraryLocation ?? this.localLibraryLocation, + pipedInstance: pipedInstance ?? this.pipedInstance, + invidiousInstance: invidiousInstance ?? this.invidiousInstance, + themeMode: themeMode ?? this.themeMode, + audioSource: audioSource ?? this.audioSource, + youtubeClientEngine: youtubeClientEngine ?? this.youtubeClientEngine, + streamMusicCodec: streamMusicCodec ?? this.streamMusicCodec, + downloadMusicCodec: downloadMusicCodec ?? this.downloadMusicCodec, + discordPresence: discordPresence ?? this.discordPresence, + endlessPlayback: endlessPlayback ?? this.endlessPlayback, + enableConnect: enableConnect ?? this.enableConnect, + cacheMusic: cacheMusic ?? this.cacheMusic, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (audioQuality.present) { + map['audio_quality'] = Variable(audioQuality.value); + } + if (albumColorSync.present) { + map['album_color_sync'] = Variable(albumColorSync.value); + } + if (amoledDarkTheme.present) { + map['amoled_dark_theme'] = Variable(amoledDarkTheme.value); + } + if (checkUpdate.present) { + map['check_update'] = Variable(checkUpdate.value); + } + if (normalizeAudio.present) { + map['normalize_audio'] = Variable(normalizeAudio.value); + } + if (showSystemTrayIcon.present) { + map['show_system_tray_icon'] = Variable(showSystemTrayIcon.value); + } + if (systemTitleBar.present) { + map['system_title_bar'] = Variable(systemTitleBar.value); + } + if (skipNonMusic.present) { + map['skip_non_music'] = Variable(skipNonMusic.value); + } + if (closeBehavior.present) { + map['close_behavior'] = Variable(closeBehavior.value); + } + if (accentColorScheme.present) { + map['accent_color_scheme'] = Variable(accentColorScheme.value); + } + if (layoutMode.present) { + map['layout_mode'] = Variable(layoutMode.value); + } + if (locale.present) { + map['locale'] = Variable(locale.value); + } + if (market.present) { + map['market'] = Variable(market.value); + } + if (searchMode.present) { + map['search_mode'] = Variable(searchMode.value); + } + if (downloadLocation.present) { + map['download_location'] = Variable(downloadLocation.value); + } + if (localLibraryLocation.present) { + map['local_library_location'] = + Variable(localLibraryLocation.value); + } + if (pipedInstance.present) { + map['piped_instance'] = Variable(pipedInstance.value); + } + if (invidiousInstance.present) { + map['invidious_instance'] = Variable(invidiousInstance.value); + } + if (themeMode.present) { + map['theme_mode'] = Variable(themeMode.value); + } + if (audioSource.present) { + map['audio_source'] = Variable(audioSource.value); + } + if (youtubeClientEngine.present) { + map['youtube_client_engine'] = + Variable(youtubeClientEngine.value); + } + if (streamMusicCodec.present) { + map['stream_music_codec'] = Variable(streamMusicCodec.value); + } + if (downloadMusicCodec.present) { + map['download_music_codec'] = Variable(downloadMusicCodec.value); + } + if (discordPresence.present) { + map['discord_presence'] = Variable(discordPresence.value); + } + if (endlessPlayback.present) { + map['endless_playback'] = Variable(endlessPlayback.value); + } + if (enableConnect.present) { + map['enable_connect'] = Variable(enableConnect.value); + } + if (cacheMusic.present) { + map['cache_music'] = Variable(cacheMusic.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PreferencesTableCompanion(') + ..write('id: $id, ') + ..write('audioQuality: $audioQuality, ') + ..write('albumColorSync: $albumColorSync, ') + ..write('amoledDarkTheme: $amoledDarkTheme, ') + ..write('checkUpdate: $checkUpdate, ') + ..write('normalizeAudio: $normalizeAudio, ') + ..write('showSystemTrayIcon: $showSystemTrayIcon, ') + ..write('systemTitleBar: $systemTitleBar, ') + ..write('skipNonMusic: $skipNonMusic, ') + ..write('closeBehavior: $closeBehavior, ') + ..write('accentColorScheme: $accentColorScheme, ') + ..write('layoutMode: $layoutMode, ') + ..write('locale: $locale, ') + ..write('market: $market, ') + ..write('searchMode: $searchMode, ') + ..write('downloadLocation: $downloadLocation, ') + ..write('localLibraryLocation: $localLibraryLocation, ') + ..write('pipedInstance: $pipedInstance, ') + ..write('invidiousInstance: $invidiousInstance, ') + ..write('themeMode: $themeMode, ') + ..write('audioSource: $audioSource, ') + ..write('youtubeClientEngine: $youtubeClientEngine, ') + ..write('streamMusicCodec: $streamMusicCodec, ') + ..write('downloadMusicCodec: $downloadMusicCodec, ') + ..write('discordPresence: $discordPresence, ') + ..write('endlessPlayback: $endlessPlayback, ') + ..write('enableConnect: $enableConnect, ') + ..write('cacheMusic: $cacheMusic') + ..write(')')) + .toString(); + } +} + +class ScrobblerTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + ScrobblerTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + late final GeneratedColumn username = GeneratedColumn( + 'username', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn passwordHash = GeneratedColumn( + 'password_hash', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, createdAt, username, passwordHash]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'scrobbler_table'; + @override + Set get $primaryKey => {id}; + @override + ScrobblerTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return ScrobblerTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + username: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}username'])!, + passwordHash: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}password_hash'])!, + ); + } + + @override + ScrobblerTable createAlias(String alias) { + return ScrobblerTable(attachedDatabase, alias); + } +} + +class ScrobblerTableData extends DataClass + implements Insertable { + final int id; + final DateTime createdAt; + final String username; + final String passwordHash; + const ScrobblerTableData( + {required this.id, + required this.createdAt, + required this.username, + required this.passwordHash}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['username'] = Variable(username); + map['password_hash'] = Variable(passwordHash); + return map; + } + + ScrobblerTableCompanion toCompanion(bool nullToAbsent) { + return ScrobblerTableCompanion( + id: Value(id), + createdAt: Value(createdAt), + username: Value(username), + passwordHash: Value(passwordHash), + ); + } + + factory ScrobblerTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return ScrobblerTableData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + username: serializer.fromJson(json['username']), + passwordHash: serializer.fromJson(json['passwordHash']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'username': serializer.toJson(username), + 'passwordHash': serializer.toJson(passwordHash), + }; + } + + ScrobblerTableData copyWith( + {int? id, + DateTime? createdAt, + String? username, + String? passwordHash}) => + ScrobblerTableData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + username: username ?? this.username, + passwordHash: passwordHash ?? this.passwordHash, + ); + ScrobblerTableData copyWithCompanion(ScrobblerTableCompanion data) { + return ScrobblerTableData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + username: data.username.present ? data.username.value : this.username, + passwordHash: data.passwordHash.present + ? data.passwordHash.value + : this.passwordHash, + ); + } + + @override + String toString() { + return (StringBuffer('ScrobblerTableData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('username: $username, ') + ..write('passwordHash: $passwordHash') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, createdAt, username, passwordHash); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is ScrobblerTableData && + other.id == this.id && + other.createdAt == this.createdAt && + other.username == this.username && + other.passwordHash == this.passwordHash); +} + +class ScrobblerTableCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value username; + final Value passwordHash; + const ScrobblerTableCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.username = const Value.absent(), + this.passwordHash = const Value.absent(), + }); + ScrobblerTableCompanion.insert({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + required String username, + required String passwordHash, + }) : username = Value(username), + passwordHash = Value(passwordHash); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? username, + Expression? passwordHash, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (username != null) 'username': username, + if (passwordHash != null) 'password_hash': passwordHash, + }); + } + + ScrobblerTableCompanion copyWith( + {Value? id, + Value? createdAt, + Value? username, + Value? passwordHash}) { + return ScrobblerTableCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + username: username ?? this.username, + passwordHash: passwordHash ?? this.passwordHash, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (username.present) { + map['username'] = Variable(username.value); + } + if (passwordHash.present) { + map['password_hash'] = Variable(passwordHash.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ScrobblerTableCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('username: $username, ') + ..write('passwordHash: $passwordHash') + ..write(')')) + .toString(); + } +} + +class SkipSegmentTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + SkipSegmentTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn start = GeneratedColumn( + 'start', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + late final GeneratedColumn end = GeneratedColumn( + 'end', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => [id, start, end, trackId, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'skip_segment_table'; + @override + Set get $primaryKey => {id}; + @override + SkipSegmentTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SkipSegmentTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + start: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}start'])!, + end: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}end'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + SkipSegmentTable createAlias(String alias) { + return SkipSegmentTable(attachedDatabase, alias); + } +} + +class SkipSegmentTableData extends DataClass + implements Insertable { + final int id; + final int start; + final int end; + final String trackId; + final DateTime createdAt; + const SkipSegmentTableData( + {required this.id, + required this.start, + required this.end, + required this.trackId, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['start'] = Variable(start); + map['end'] = Variable(end); + map['track_id'] = Variable(trackId); + map['created_at'] = Variable(createdAt); + return map; + } + + SkipSegmentTableCompanion toCompanion(bool nullToAbsent) { + return SkipSegmentTableCompanion( + id: Value(id), + start: Value(start), + end: Value(end), + trackId: Value(trackId), + createdAt: Value(createdAt), + ); + } + + factory SkipSegmentTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SkipSegmentTableData( + id: serializer.fromJson(json['id']), + start: serializer.fromJson(json['start']), + end: serializer.fromJson(json['end']), + trackId: serializer.fromJson(json['trackId']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'start': serializer.toJson(start), + 'end': serializer.toJson(end), + 'trackId': serializer.toJson(trackId), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SkipSegmentTableData copyWith( + {int? id, + int? start, + int? end, + String? trackId, + DateTime? createdAt}) => + SkipSegmentTableData( + id: id ?? this.id, + start: start ?? this.start, + end: end ?? this.end, + trackId: trackId ?? this.trackId, + createdAt: createdAt ?? this.createdAt, + ); + SkipSegmentTableData copyWithCompanion(SkipSegmentTableCompanion data) { + return SkipSegmentTableData( + id: data.id.present ? data.id.value : this.id, + start: data.start.present ? data.start.value : this.start, + end: data.end.present ? data.end.value : this.end, + trackId: data.trackId.present ? data.trackId.value : this.trackId, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('SkipSegmentTableData(') + ..write('id: $id, ') + ..write('start: $start, ') + ..write('end: $end, ') + ..write('trackId: $trackId, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, start, end, trackId, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SkipSegmentTableData && + other.id == this.id && + other.start == this.start && + other.end == this.end && + other.trackId == this.trackId && + other.createdAt == this.createdAt); +} + +class SkipSegmentTableCompanion extends UpdateCompanion { + final Value id; + final Value start; + final Value end; + final Value trackId; + final Value createdAt; + const SkipSegmentTableCompanion({ + this.id = const Value.absent(), + this.start = const Value.absent(), + this.end = const Value.absent(), + this.trackId = const Value.absent(), + this.createdAt = const Value.absent(), + }); + SkipSegmentTableCompanion.insert({ + this.id = const Value.absent(), + required int start, + required int end, + required String trackId, + this.createdAt = const Value.absent(), + }) : start = Value(start), + end = Value(end), + trackId = Value(trackId); + static Insertable custom({ + Expression? id, + Expression? start, + Expression? end, + Expression? trackId, + Expression? createdAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (start != null) 'start': start, + if (end != null) 'end': end, + if (trackId != null) 'track_id': trackId, + if (createdAt != null) 'created_at': createdAt, + }); + } + + SkipSegmentTableCompanion copyWith( + {Value? id, + Value? start, + Value? end, + Value? trackId, + Value? createdAt}) { + return SkipSegmentTableCompanion( + id: id ?? this.id, + start: start ?? this.start, + end: end ?? this.end, + trackId: trackId ?? this.trackId, + createdAt: createdAt ?? this.createdAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (start.present) { + map['start'] = Variable(start.value); + } + if (end.present) { + map['end'] = Variable(end.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SkipSegmentTableCompanion(') + ..write('id: $id, ') + ..write('start: $start, ') + ..write('end: $end, ') + ..write('trackId: $trackId, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } +} + +class SourceMatchTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + SourceMatchTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn sourceId = GeneratedColumn( + 'source_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn sourceType = GeneratedColumn( + 'source_type', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceType.youtube.name)); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => + [id, trackId, sourceId, sourceType, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'source_match_table'; + @override + Set get $primaryKey => {id}; + @override + SourceMatchTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SourceMatchTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + sourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}source_id'])!, + sourceType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}source_type'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + SourceMatchTable createAlias(String alias) { + return SourceMatchTable(attachedDatabase, alias); + } +} + +class SourceMatchTableData extends DataClass + implements Insertable { + final int id; + final String trackId; + final String sourceId; + final String sourceType; + final DateTime createdAt; + const SourceMatchTableData( + {required this.id, + required this.trackId, + required this.sourceId, + required this.sourceType, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['track_id'] = Variable(trackId); + map['source_id'] = Variable(sourceId); + map['source_type'] = Variable(sourceType); + map['created_at'] = Variable(createdAt); + return map; + } + + SourceMatchTableCompanion toCompanion(bool nullToAbsent) { + return SourceMatchTableCompanion( + id: Value(id), + trackId: Value(trackId), + sourceId: Value(sourceId), + sourceType: Value(sourceType), + createdAt: Value(createdAt), + ); + } + + factory SourceMatchTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SourceMatchTableData( + id: serializer.fromJson(json['id']), + trackId: serializer.fromJson(json['trackId']), + sourceId: serializer.fromJson(json['sourceId']), + sourceType: serializer.fromJson(json['sourceType']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'trackId': serializer.toJson(trackId), + 'sourceId': serializer.toJson(sourceId), + 'sourceType': serializer.toJson(sourceType), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SourceMatchTableData copyWith( + {int? id, + String? trackId, + String? sourceId, + String? sourceType, + DateTime? createdAt}) => + SourceMatchTableData( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + sourceId: sourceId ?? this.sourceId, + sourceType: sourceType ?? this.sourceType, + createdAt: createdAt ?? this.createdAt, + ); + SourceMatchTableData copyWithCompanion(SourceMatchTableCompanion data) { + return SourceMatchTableData( + id: data.id.present ? data.id.value : this.id, + trackId: data.trackId.present ? data.trackId.value : this.trackId, + sourceId: data.sourceId.present ? data.sourceId.value : this.sourceId, + sourceType: + data.sourceType.present ? data.sourceType.value : this.sourceType, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('SourceMatchTableData(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('sourceId: $sourceId, ') + ..write('sourceType: $sourceType, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, trackId, sourceId, sourceType, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SourceMatchTableData && + other.id == this.id && + other.trackId == this.trackId && + other.sourceId == this.sourceId && + other.sourceType == this.sourceType && + other.createdAt == this.createdAt); +} + +class SourceMatchTableCompanion extends UpdateCompanion { + final Value id; + final Value trackId; + final Value sourceId; + final Value sourceType; + final Value createdAt; + const SourceMatchTableCompanion({ + this.id = const Value.absent(), + this.trackId = const Value.absent(), + this.sourceId = const Value.absent(), + this.sourceType = const Value.absent(), + this.createdAt = const Value.absent(), + }); + SourceMatchTableCompanion.insert({ + this.id = const Value.absent(), + required String trackId, + required String sourceId, + this.sourceType = const Value.absent(), + this.createdAt = const Value.absent(), + }) : trackId = Value(trackId), + sourceId = Value(sourceId); + static Insertable custom({ + Expression? id, + Expression? trackId, + Expression? sourceId, + Expression? sourceType, + Expression? createdAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (trackId != null) 'track_id': trackId, + if (sourceId != null) 'source_id': sourceId, + if (sourceType != null) 'source_type': sourceType, + if (createdAt != null) 'created_at': createdAt, + }); + } + + SourceMatchTableCompanion copyWith( + {Value? id, + Value? trackId, + Value? sourceId, + Value? sourceType, + Value? createdAt}) { + return SourceMatchTableCompanion( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + sourceId: sourceId ?? this.sourceId, + sourceType: sourceType ?? this.sourceType, + createdAt: createdAt ?? this.createdAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (sourceId.present) { + map['source_id'] = Variable(sourceId.value); + } + if (sourceType.present) { + map['source_type'] = Variable(sourceType.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SourceMatchTableCompanion(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('sourceId: $sourceId, ') + ..write('sourceType: $sourceType, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } +} + +class AudioPlayerStateTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AudioPlayerStateTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn playing = GeneratedColumn( + 'playing', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("playing" IN (0, 1))')); + late final GeneratedColumn loopMode = GeneratedColumn( + 'loop_mode', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn shuffled = GeneratedColumn( + 'shuffled', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("shuffled" IN (0, 1))')); + late final GeneratedColumn collections = GeneratedColumn( + 'collections', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => + [id, playing, loopMode, shuffled, collections]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'audio_player_state_table'; + @override + Set get $primaryKey => {id}; + @override + AudioPlayerStateTableData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AudioPlayerStateTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + playing: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}playing'])!, + loopMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}loop_mode'])!, + shuffled: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}shuffled'])!, + collections: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}collections'])!, + ); + } + + @override + AudioPlayerStateTable createAlias(String alias) { + return AudioPlayerStateTable(attachedDatabase, alias); + } +} + +class AudioPlayerStateTableData extends DataClass + implements Insertable { + final int id; + final bool playing; + final String loopMode; + final bool shuffled; + final String collections; + const AudioPlayerStateTableData( + {required this.id, + required this.playing, + required this.loopMode, + required this.shuffled, + required this.collections}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['playing'] = Variable(playing); + map['loop_mode'] = Variable(loopMode); + map['shuffled'] = Variable(shuffled); + map['collections'] = Variable(collections); + return map; + } + + AudioPlayerStateTableCompanion toCompanion(bool nullToAbsent) { + return AudioPlayerStateTableCompanion( + id: Value(id), + playing: Value(playing), + loopMode: Value(loopMode), + shuffled: Value(shuffled), + collections: Value(collections), + ); + } + + factory AudioPlayerStateTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AudioPlayerStateTableData( + id: serializer.fromJson(json['id']), + playing: serializer.fromJson(json['playing']), + loopMode: serializer.fromJson(json['loopMode']), + shuffled: serializer.fromJson(json['shuffled']), + collections: serializer.fromJson(json['collections']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'playing': serializer.toJson(playing), + 'loopMode': serializer.toJson(loopMode), + 'shuffled': serializer.toJson(shuffled), + 'collections': serializer.toJson(collections), + }; + } + + AudioPlayerStateTableData copyWith( + {int? id, + bool? playing, + String? loopMode, + bool? shuffled, + String? collections}) => + AudioPlayerStateTableData( + id: id ?? this.id, + playing: playing ?? this.playing, + loopMode: loopMode ?? this.loopMode, + shuffled: shuffled ?? this.shuffled, + collections: collections ?? this.collections, + ); + AudioPlayerStateTableData copyWithCompanion( + AudioPlayerStateTableCompanion data) { + return AudioPlayerStateTableData( + id: data.id.present ? data.id.value : this.id, + playing: data.playing.present ? data.playing.value : this.playing, + loopMode: data.loopMode.present ? data.loopMode.value : this.loopMode, + shuffled: data.shuffled.present ? data.shuffled.value : this.shuffled, + collections: + data.collections.present ? data.collections.value : this.collections, + ); + } + + @override + String toString() { + return (StringBuffer('AudioPlayerStateTableData(') + ..write('id: $id, ') + ..write('playing: $playing, ') + ..write('loopMode: $loopMode, ') + ..write('shuffled: $shuffled, ') + ..write('collections: $collections') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, playing, loopMode, shuffled, collections); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AudioPlayerStateTableData && + other.id == this.id && + other.playing == this.playing && + other.loopMode == this.loopMode && + other.shuffled == this.shuffled && + other.collections == this.collections); +} + +class AudioPlayerStateTableCompanion + extends UpdateCompanion { + final Value id; + final Value playing; + final Value loopMode; + final Value shuffled; + final Value collections; + const AudioPlayerStateTableCompanion({ + this.id = const Value.absent(), + this.playing = const Value.absent(), + this.loopMode = const Value.absent(), + this.shuffled = const Value.absent(), + this.collections = const Value.absent(), + }); + AudioPlayerStateTableCompanion.insert({ + this.id = const Value.absent(), + required bool playing, + required String loopMode, + required bool shuffled, + required String collections, + }) : playing = Value(playing), + loopMode = Value(loopMode), + shuffled = Value(shuffled), + collections = Value(collections); + static Insertable custom({ + Expression? id, + Expression? playing, + Expression? loopMode, + Expression? shuffled, + Expression? collections, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (playing != null) 'playing': playing, + if (loopMode != null) 'loop_mode': loopMode, + if (shuffled != null) 'shuffled': shuffled, + if (collections != null) 'collections': collections, + }); + } + + AudioPlayerStateTableCompanion copyWith( + {Value? id, + Value? playing, + Value? loopMode, + Value? shuffled, + Value? collections}) { + return AudioPlayerStateTableCompanion( + id: id ?? this.id, + playing: playing ?? this.playing, + loopMode: loopMode ?? this.loopMode, + shuffled: shuffled ?? this.shuffled, + collections: collections ?? this.collections, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (playing.present) { + map['playing'] = Variable(playing.value); + } + if (loopMode.present) { + map['loop_mode'] = Variable(loopMode.value); + } + if (shuffled.present) { + map['shuffled'] = Variable(shuffled.value); + } + if (collections.present) { + map['collections'] = Variable(collections.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AudioPlayerStateTableCompanion(') + ..write('id: $id, ') + ..write('playing: $playing, ') + ..write('loopMode: $loopMode, ') + ..write('shuffled: $shuffled, ') + ..write('collections: $collections') + ..write(')')) + .toString(); + } +} + +class PlaylistTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PlaylistTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn audioPlayerStateId = GeneratedColumn( + 'audio_player_state_id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES audio_player_state_table (id)')); + late final GeneratedColumn index = GeneratedColumn( + 'index', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + @override + List get $columns => [id, audioPlayerStateId, index]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'playlist_table'; + @override + Set get $primaryKey => {id}; + @override + PlaylistTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PlaylistTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + audioPlayerStateId: attachedDatabase.typeMapping.read( + DriftSqlType.int, data['${effectivePrefix}audio_player_state_id'])!, + index: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}index'])!, + ); + } + + @override + PlaylistTable createAlias(String alias) { + return PlaylistTable(attachedDatabase, alias); + } +} + +class PlaylistTableData extends DataClass + implements Insertable { + final int id; + final int audioPlayerStateId; + final int index; + const PlaylistTableData( + {required this.id, + required this.audioPlayerStateId, + required this.index}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['audio_player_state_id'] = Variable(audioPlayerStateId); + map['index'] = Variable(index); + return map; + } + + PlaylistTableCompanion toCompanion(bool nullToAbsent) { + return PlaylistTableCompanion( + id: Value(id), + audioPlayerStateId: Value(audioPlayerStateId), + index: Value(index), + ); + } + + factory PlaylistTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PlaylistTableData( + id: serializer.fromJson(json['id']), + audioPlayerStateId: serializer.fromJson(json['audioPlayerStateId']), + index: serializer.fromJson(json['index']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'audioPlayerStateId': serializer.toJson(audioPlayerStateId), + 'index': serializer.toJson(index), + }; + } + + PlaylistTableData copyWith({int? id, int? audioPlayerStateId, int? index}) => + PlaylistTableData( + id: id ?? this.id, + audioPlayerStateId: audioPlayerStateId ?? this.audioPlayerStateId, + index: index ?? this.index, + ); + PlaylistTableData copyWithCompanion(PlaylistTableCompanion data) { + return PlaylistTableData( + id: data.id.present ? data.id.value : this.id, + audioPlayerStateId: data.audioPlayerStateId.present + ? data.audioPlayerStateId.value + : this.audioPlayerStateId, + index: data.index.present ? data.index.value : this.index, + ); + } + + @override + String toString() { + return (StringBuffer('PlaylistTableData(') + ..write('id: $id, ') + ..write('audioPlayerStateId: $audioPlayerStateId, ') + ..write('index: $index') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, audioPlayerStateId, index); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PlaylistTableData && + other.id == this.id && + other.audioPlayerStateId == this.audioPlayerStateId && + other.index == this.index); +} + +class PlaylistTableCompanion extends UpdateCompanion { + final Value id; + final Value audioPlayerStateId; + final Value index; + const PlaylistTableCompanion({ + this.id = const Value.absent(), + this.audioPlayerStateId = const Value.absent(), + this.index = const Value.absent(), + }); + PlaylistTableCompanion.insert({ + this.id = const Value.absent(), + required int audioPlayerStateId, + required int index, + }) : audioPlayerStateId = Value(audioPlayerStateId), + index = Value(index); + static Insertable custom({ + Expression? id, + Expression? audioPlayerStateId, + Expression? index, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (audioPlayerStateId != null) + 'audio_player_state_id': audioPlayerStateId, + if (index != null) 'index': index, + }); + } + + PlaylistTableCompanion copyWith( + {Value? id, Value? audioPlayerStateId, Value? index}) { + return PlaylistTableCompanion( + id: id ?? this.id, + audioPlayerStateId: audioPlayerStateId ?? this.audioPlayerStateId, + index: index ?? this.index, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (audioPlayerStateId.present) { + map['audio_player_state_id'] = Variable(audioPlayerStateId.value); + } + if (index.present) { + map['index'] = Variable(index.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PlaylistTableCompanion(') + ..write('id: $id, ') + ..write('audioPlayerStateId: $audioPlayerStateId, ') + ..write('index: $index') + ..write(')')) + .toString(); + } +} + +class PlaylistMediaTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PlaylistMediaTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn playlistId = GeneratedColumn( + 'playlist_id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES playlist_table (id)')); + late final GeneratedColumn uri = GeneratedColumn( + 'uri', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn extras = GeneratedColumn( + 'extras', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn httpHeaders = GeneratedColumn( + 'http_headers', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => + [id, playlistId, uri, extras, httpHeaders]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'playlist_media_table'; + @override + Set get $primaryKey => {id}; + @override + PlaylistMediaTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PlaylistMediaTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + playlistId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}playlist_id'])!, + uri: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}uri'])!, + extras: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extras']), + httpHeaders: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}http_headers']), + ); + } + + @override + PlaylistMediaTable createAlias(String alias) { + return PlaylistMediaTable(attachedDatabase, alias); + } +} + +class PlaylistMediaTableData extends DataClass + implements Insertable { + final int id; + final int playlistId; + final String uri; + final String? extras; + final String? httpHeaders; + const PlaylistMediaTableData( + {required this.id, + required this.playlistId, + required this.uri, + this.extras, + this.httpHeaders}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['playlist_id'] = Variable(playlistId); + map['uri'] = Variable(uri); + if (!nullToAbsent || extras != null) { + map['extras'] = Variable(extras); + } + if (!nullToAbsent || httpHeaders != null) { + map['http_headers'] = Variable(httpHeaders); + } + return map; + } + + PlaylistMediaTableCompanion toCompanion(bool nullToAbsent) { + return PlaylistMediaTableCompanion( + id: Value(id), + playlistId: Value(playlistId), + uri: Value(uri), + extras: + extras == null && nullToAbsent ? const Value.absent() : Value(extras), + httpHeaders: httpHeaders == null && nullToAbsent + ? const Value.absent() + : Value(httpHeaders), + ); + } + + factory PlaylistMediaTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PlaylistMediaTableData( + id: serializer.fromJson(json['id']), + playlistId: serializer.fromJson(json['playlistId']), + uri: serializer.fromJson(json['uri']), + extras: serializer.fromJson(json['extras']), + httpHeaders: serializer.fromJson(json['httpHeaders']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'playlistId': serializer.toJson(playlistId), + 'uri': serializer.toJson(uri), + 'extras': serializer.toJson(extras), + 'httpHeaders': serializer.toJson(httpHeaders), + }; + } + + PlaylistMediaTableData copyWith( + {int? id, + int? playlistId, + String? uri, + Value extras = const Value.absent(), + Value httpHeaders = const Value.absent()}) => + PlaylistMediaTableData( + id: id ?? this.id, + playlistId: playlistId ?? this.playlistId, + uri: uri ?? this.uri, + extras: extras.present ? extras.value : this.extras, + httpHeaders: httpHeaders.present ? httpHeaders.value : this.httpHeaders, + ); + PlaylistMediaTableData copyWithCompanion(PlaylistMediaTableCompanion data) { + return PlaylistMediaTableData( + id: data.id.present ? data.id.value : this.id, + playlistId: + data.playlistId.present ? data.playlistId.value : this.playlistId, + uri: data.uri.present ? data.uri.value : this.uri, + extras: data.extras.present ? data.extras.value : this.extras, + httpHeaders: + data.httpHeaders.present ? data.httpHeaders.value : this.httpHeaders, + ); + } + + @override + String toString() { + return (StringBuffer('PlaylistMediaTableData(') + ..write('id: $id, ') + ..write('playlistId: $playlistId, ') + ..write('uri: $uri, ') + ..write('extras: $extras, ') + ..write('httpHeaders: $httpHeaders') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, playlistId, uri, extras, httpHeaders); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PlaylistMediaTableData && + other.id == this.id && + other.playlistId == this.playlistId && + other.uri == this.uri && + other.extras == this.extras && + other.httpHeaders == this.httpHeaders); +} + +class PlaylistMediaTableCompanion + extends UpdateCompanion { + final Value id; + final Value playlistId; + final Value uri; + final Value extras; + final Value httpHeaders; + const PlaylistMediaTableCompanion({ + this.id = const Value.absent(), + this.playlistId = const Value.absent(), + this.uri = const Value.absent(), + this.extras = const Value.absent(), + this.httpHeaders = const Value.absent(), + }); + PlaylistMediaTableCompanion.insert({ + this.id = const Value.absent(), + required int playlistId, + required String uri, + this.extras = const Value.absent(), + this.httpHeaders = const Value.absent(), + }) : playlistId = Value(playlistId), + uri = Value(uri); + static Insertable custom({ + Expression? id, + Expression? playlistId, + Expression? uri, + Expression? extras, + Expression? httpHeaders, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (playlistId != null) 'playlist_id': playlistId, + if (uri != null) 'uri': uri, + if (extras != null) 'extras': extras, + if (httpHeaders != null) 'http_headers': httpHeaders, + }); + } + + PlaylistMediaTableCompanion copyWith( + {Value? id, + Value? playlistId, + Value? uri, + Value? extras, + Value? httpHeaders}) { + return PlaylistMediaTableCompanion( + id: id ?? this.id, + playlistId: playlistId ?? this.playlistId, + uri: uri ?? this.uri, + extras: extras ?? this.extras, + httpHeaders: httpHeaders ?? this.httpHeaders, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (playlistId.present) { + map['playlist_id'] = Variable(playlistId.value); + } + if (uri.present) { + map['uri'] = Variable(uri.value); + } + if (extras.present) { + map['extras'] = Variable(extras.value); + } + if (httpHeaders.present) { + map['http_headers'] = Variable(httpHeaders.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PlaylistMediaTableCompanion(') + ..write('id: $id, ') + ..write('playlistId: $playlistId, ') + ..write('uri: $uri, ') + ..write('extras: $extras, ') + ..write('httpHeaders: $httpHeaders') + ..write(')')) + .toString(); + } +} + +class HistoryTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + HistoryTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn itemId = GeneratedColumn( + 'item_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, createdAt, type, itemId, data]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'history_table'; + @override + Set get $primaryKey => {id}; + @override + HistoryTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return HistoryTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + itemId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}item_id'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + ); + } + + @override + HistoryTable createAlias(String alias) { + return HistoryTable(attachedDatabase, alias); + } +} + +class HistoryTableData extends DataClass + implements Insertable { + final int id; + final DateTime createdAt; + final String type; + final String itemId; + final String data; + const HistoryTableData( + {required this.id, + required this.createdAt, + required this.type, + required this.itemId, + required this.data}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['type'] = Variable(type); + map['item_id'] = Variable(itemId); + map['data'] = Variable(data); + return map; + } + + HistoryTableCompanion toCompanion(bool nullToAbsent) { + return HistoryTableCompanion( + id: Value(id), + createdAt: Value(createdAt), + type: Value(type), + itemId: Value(itemId), + data: Value(data), + ); + } + + factory HistoryTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return HistoryTableData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + type: serializer.fromJson(json['type']), + itemId: serializer.fromJson(json['itemId']), + data: serializer.fromJson(json['data']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'type': serializer.toJson(type), + 'itemId': serializer.toJson(itemId), + 'data': serializer.toJson(data), + }; + } + + HistoryTableData copyWith( + {int? id, + DateTime? createdAt, + String? type, + String? itemId, + String? data}) => + HistoryTableData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + type: type ?? this.type, + itemId: itemId ?? this.itemId, + data: data ?? this.data, + ); + HistoryTableData copyWithCompanion(HistoryTableCompanion data) { + return HistoryTableData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + type: data.type.present ? data.type.value : this.type, + itemId: data.itemId.present ? data.itemId.value : this.itemId, + data: data.data.present ? data.data.value : this.data, + ); + } + + @override + String toString() { + return (StringBuffer('HistoryTableData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('type: $type, ') + ..write('itemId: $itemId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, createdAt, type, itemId, data); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is HistoryTableData && + other.id == this.id && + other.createdAt == this.createdAt && + other.type == this.type && + other.itemId == this.itemId && + other.data == this.data); +} + +class HistoryTableCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value type; + final Value itemId; + final Value data; + const HistoryTableCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.type = const Value.absent(), + this.itemId = const Value.absent(), + this.data = const Value.absent(), + }); + HistoryTableCompanion.insert({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + required String type, + required String itemId, + required String data, + }) : type = Value(type), + itemId = Value(itemId), + data = Value(data); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? type, + Expression? itemId, + Expression? data, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (type != null) 'type': type, + if (itemId != null) 'item_id': itemId, + if (data != null) 'data': data, + }); + } + + HistoryTableCompanion copyWith( + {Value? id, + Value? createdAt, + Value? type, + Value? itemId, + Value? data}) { + return HistoryTableCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + type: type ?? this.type, + itemId: itemId ?? this.itemId, + data: data ?? this.data, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (itemId.present) { + map['item_id'] = Variable(itemId.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('HistoryTableCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('type: $type, ') + ..write('itemId: $itemId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } +} + +class LyricsTable extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LyricsTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, trackId, data]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'lyrics_table'; + @override + Set get $primaryKey => {id}; + @override + LyricsTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LyricsTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + ); + } + + @override + LyricsTable createAlias(String alias) { + return LyricsTable(attachedDatabase, alias); + } +} + +class LyricsTableData extends DataClass implements Insertable { + final int id; + final String trackId; + final String data; + const LyricsTableData( + {required this.id, required this.trackId, required this.data}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['track_id'] = Variable(trackId); + map['data'] = Variable(data); + return map; + } + + LyricsTableCompanion toCompanion(bool nullToAbsent) { + return LyricsTableCompanion( + id: Value(id), + trackId: Value(trackId), + data: Value(data), + ); + } + + factory LyricsTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LyricsTableData( + id: serializer.fromJson(json['id']), + trackId: serializer.fromJson(json['trackId']), + data: serializer.fromJson(json['data']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'trackId': serializer.toJson(trackId), + 'data': serializer.toJson(data), + }; + } + + LyricsTableData copyWith({int? id, String? trackId, String? data}) => + LyricsTableData( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + data: data ?? this.data, + ); + LyricsTableData copyWithCompanion(LyricsTableCompanion data) { + return LyricsTableData( + id: data.id.present ? data.id.value : this.id, + trackId: data.trackId.present ? data.trackId.value : this.trackId, + data: data.data.present ? data.data.value : this.data, + ); + } + + @override + String toString() { + return (StringBuffer('LyricsTableData(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, trackId, data); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LyricsTableData && + other.id == this.id && + other.trackId == this.trackId && + other.data == this.data); +} + +class LyricsTableCompanion extends UpdateCompanion { + final Value id; + final Value trackId; + final Value data; + const LyricsTableCompanion({ + this.id = const Value.absent(), + this.trackId = const Value.absent(), + this.data = const Value.absent(), + }); + LyricsTableCompanion.insert({ + this.id = const Value.absent(), + required String trackId, + required String data, + }) : trackId = Value(trackId), + data = Value(data); + static Insertable custom({ + Expression? id, + Expression? trackId, + Expression? data, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (trackId != null) 'track_id': trackId, + if (data != null) 'data': data, + }); + } + + LyricsTableCompanion copyWith( + {Value? id, Value? trackId, Value? data}) { + return LyricsTableCompanion( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + data: data ?? this.data, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LyricsTableCompanion(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV5 extends GeneratedDatabase { + DatabaseAtV5(QueryExecutor e) : super(e); + late final AuthenticationTable authenticationTable = + AuthenticationTable(this); + late final BlacklistTable blacklistTable = BlacklistTable(this); + late final PreferencesTable preferencesTable = PreferencesTable(this); + late final ScrobblerTable scrobblerTable = ScrobblerTable(this); + late final SkipSegmentTable skipSegmentTable = SkipSegmentTable(this); + late final SourceMatchTable sourceMatchTable = SourceMatchTable(this); + late final AudioPlayerStateTable audioPlayerStateTable = + AudioPlayerStateTable(this); + late final PlaylistTable playlistTable = PlaylistTable(this); + late final PlaylistMediaTable playlistMediaTable = PlaylistMediaTable(this); + late final HistoryTable historyTable = HistoryTable(this); + late final LyricsTable lyricsTable = LyricsTable(this); + late final Index uniqueBlacklist = Index('unique_blacklist', + 'CREATE UNIQUE INDEX unique_blacklist ON blacklist_table (element_type, element_id)'); + late final Index uniqTrackMatch = Index('uniq_track_match', + 'CREATE UNIQUE INDEX uniq_track_match ON source_match_table (track_id, source_id, source_type)'); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + authenticationTable, + blacklistTable, + preferencesTable, + scrobblerTable, + skipSegmentTable, + sourceMatchTable, + audioPlayerStateTable, + playlistTable, + playlistMediaTable, + historyTable, + lyricsTable, + uniqueBlacklist, + uniqTrackMatch + ]; + @override + int get schemaVersion => 5; +} diff --git a/test/drift/app_db/generated/schema_v6.dart b/test/drift/app_db/generated/schema_v6.dart new file mode 100644 index 00000000..c0ef0442 --- /dev/null +++ b/test/drift/app_db/generated/schema_v6.dart @@ -0,0 +1,3465 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class AuthenticationTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AuthenticationTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn cookie = GeneratedColumn( + 'cookie', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn accessToken = GeneratedColumn( + 'access_token', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn expiration = GeneratedColumn( + 'expiration', aliasedName, false, + type: DriftSqlType.dateTime, requiredDuringInsert: true); + @override + List get $columns => [id, cookie, accessToken, expiration]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'authentication_table'; + @override + Set get $primaryKey => {id}; + @override + AuthenticationTableData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AuthenticationTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + cookie: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}cookie'])!, + accessToken: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}access_token'])!, + expiration: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}expiration'])!, + ); + } + + @override + AuthenticationTable createAlias(String alias) { + return AuthenticationTable(attachedDatabase, alias); + } +} + +class AuthenticationTableData extends DataClass + implements Insertable { + final int id; + final String cookie; + final String accessToken; + final DateTime expiration; + const AuthenticationTableData( + {required this.id, + required this.cookie, + required this.accessToken, + required this.expiration}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['cookie'] = Variable(cookie); + map['access_token'] = Variable(accessToken); + map['expiration'] = Variable(expiration); + return map; + } + + AuthenticationTableCompanion toCompanion(bool nullToAbsent) { + return AuthenticationTableCompanion( + id: Value(id), + cookie: Value(cookie), + accessToken: Value(accessToken), + expiration: Value(expiration), + ); + } + + factory AuthenticationTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AuthenticationTableData( + id: serializer.fromJson(json['id']), + cookie: serializer.fromJson(json['cookie']), + accessToken: serializer.fromJson(json['accessToken']), + expiration: serializer.fromJson(json['expiration']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'cookie': serializer.toJson(cookie), + 'accessToken': serializer.toJson(accessToken), + 'expiration': serializer.toJson(expiration), + }; + } + + AuthenticationTableData copyWith( + {int? id, + String? cookie, + String? accessToken, + DateTime? expiration}) => + AuthenticationTableData( + id: id ?? this.id, + cookie: cookie ?? this.cookie, + accessToken: accessToken ?? this.accessToken, + expiration: expiration ?? this.expiration, + ); + AuthenticationTableData copyWithCompanion(AuthenticationTableCompanion data) { + return AuthenticationTableData( + id: data.id.present ? data.id.value : this.id, + cookie: data.cookie.present ? data.cookie.value : this.cookie, + accessToken: + data.accessToken.present ? data.accessToken.value : this.accessToken, + expiration: + data.expiration.present ? data.expiration.value : this.expiration, + ); + } + + @override + String toString() { + return (StringBuffer('AuthenticationTableData(') + ..write('id: $id, ') + ..write('cookie: $cookie, ') + ..write('accessToken: $accessToken, ') + ..write('expiration: $expiration') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, cookie, accessToken, expiration); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AuthenticationTableData && + other.id == this.id && + other.cookie == this.cookie && + other.accessToken == this.accessToken && + other.expiration == this.expiration); +} + +class AuthenticationTableCompanion + extends UpdateCompanion { + final Value id; + final Value cookie; + final Value accessToken; + final Value expiration; + const AuthenticationTableCompanion({ + this.id = const Value.absent(), + this.cookie = const Value.absent(), + this.accessToken = const Value.absent(), + this.expiration = const Value.absent(), + }); + AuthenticationTableCompanion.insert({ + this.id = const Value.absent(), + required String cookie, + required String accessToken, + required DateTime expiration, + }) : cookie = Value(cookie), + accessToken = Value(accessToken), + expiration = Value(expiration); + static Insertable custom({ + Expression? id, + Expression? cookie, + Expression? accessToken, + Expression? expiration, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (cookie != null) 'cookie': cookie, + if (accessToken != null) 'access_token': accessToken, + if (expiration != null) 'expiration': expiration, + }); + } + + AuthenticationTableCompanion copyWith( + {Value? id, + Value? cookie, + Value? accessToken, + Value? expiration}) { + return AuthenticationTableCompanion( + id: id ?? this.id, + cookie: cookie ?? this.cookie, + accessToken: accessToken ?? this.accessToken, + expiration: expiration ?? this.expiration, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (cookie.present) { + map['cookie'] = Variable(cookie.value); + } + if (accessToken.present) { + map['access_token'] = Variable(accessToken.value); + } + if (expiration.present) { + map['expiration'] = Variable(expiration.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthenticationTableCompanion(') + ..write('id: $id, ') + ..write('cookie: $cookie, ') + ..write('accessToken: $accessToken, ') + ..write('expiration: $expiration') + ..write(')')) + .toString(); + } +} + +class BlacklistTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + BlacklistTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn name = GeneratedColumn( + 'name', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn elementType = GeneratedColumn( + 'element_type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn elementId = GeneratedColumn( + 'element_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, name, elementType, elementId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'blacklist_table'; + @override + Set get $primaryKey => {id}; + @override + BlacklistTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return BlacklistTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + name: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}name'])!, + elementType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}element_type'])!, + elementId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}element_id'])!, + ); + } + + @override + BlacklistTable createAlias(String alias) { + return BlacklistTable(attachedDatabase, alias); + } +} + +class BlacklistTableData extends DataClass + implements Insertable { + final int id; + final String name; + final String elementType; + final String elementId; + const BlacklistTableData( + {required this.id, + required this.name, + required this.elementType, + required this.elementId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['element_type'] = Variable(elementType); + map['element_id'] = Variable(elementId); + return map; + } + + BlacklistTableCompanion toCompanion(bool nullToAbsent) { + return BlacklistTableCompanion( + id: Value(id), + name: Value(name), + elementType: Value(elementType), + elementId: Value(elementId), + ); + } + + factory BlacklistTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return BlacklistTableData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + elementType: serializer.fromJson(json['elementType']), + elementId: serializer.fromJson(json['elementId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'elementType': serializer.toJson(elementType), + 'elementId': serializer.toJson(elementId), + }; + } + + BlacklistTableData copyWith( + {int? id, String? name, String? elementType, String? elementId}) => + BlacklistTableData( + id: id ?? this.id, + name: name ?? this.name, + elementType: elementType ?? this.elementType, + elementId: elementId ?? this.elementId, + ); + BlacklistTableData copyWithCompanion(BlacklistTableCompanion data) { + return BlacklistTableData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + elementType: + data.elementType.present ? data.elementType.value : this.elementType, + elementId: data.elementId.present ? data.elementId.value : this.elementId, + ); + } + + @override + String toString() { + return (StringBuffer('BlacklistTableData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('elementType: $elementType, ') + ..write('elementId: $elementId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, elementType, elementId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is BlacklistTableData && + other.id == this.id && + other.name == this.name && + other.elementType == this.elementType && + other.elementId == this.elementId); +} + +class BlacklistTableCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value elementType; + final Value elementId; + const BlacklistTableCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.elementType = const Value.absent(), + this.elementId = const Value.absent(), + }); + BlacklistTableCompanion.insert({ + this.id = const Value.absent(), + required String name, + required String elementType, + required String elementId, + }) : name = Value(name), + elementType = Value(elementType), + elementId = Value(elementId); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? elementType, + Expression? elementId, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (elementType != null) 'element_type': elementType, + if (elementId != null) 'element_id': elementId, + }); + } + + BlacklistTableCompanion copyWith( + {Value? id, + Value? name, + Value? elementType, + Value? elementId}) { + return BlacklistTableCompanion( + id: id ?? this.id, + name: name ?? this.name, + elementType: elementType ?? this.elementType, + elementId: elementId ?? this.elementId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (elementType.present) { + map['element_type'] = Variable(elementType.value); + } + if (elementId.present) { + map['element_id'] = Variable(elementId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('BlacklistTableCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('elementType: $elementType, ') + ..write('elementId: $elementId') + ..write(')')) + .toString(); + } +} + +class PreferencesTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PreferencesTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn audioQuality = GeneratedColumn( + 'audio_quality', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceQualities.high.name)); + late final GeneratedColumn albumColorSync = GeneratedColumn( + 'album_color_sync', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("album_color_sync" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn amoledDarkTheme = GeneratedColumn( + 'amoled_dark_theme', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("amoled_dark_theme" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn checkUpdate = GeneratedColumn( + 'check_update', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("check_update" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn normalizeAudio = GeneratedColumn( + 'normalize_audio', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("normalize_audio" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn showSystemTrayIcon = GeneratedColumn( + 'show_system_tray_icon', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("show_system_tray_icon" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn systemTitleBar = GeneratedColumn( + 'system_title_bar', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("system_title_bar" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn skipNonMusic = GeneratedColumn( + 'skip_non_music', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("skip_non_music" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn closeBehavior = GeneratedColumn( + 'close_behavior', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(CloseBehavior.close.name)); + late final GeneratedColumn accentColorScheme = + GeneratedColumn('accent_color_scheme', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("Orange:0xFFf97315")); + late final GeneratedColumn layoutMode = GeneratedColumn( + 'layout_mode', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(LayoutMode.adaptive.name)); + late final GeneratedColumn locale = GeneratedColumn( + 'locale', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: + const Constant('{"languageCode":"system","countryCode":"system"}')); + late final GeneratedColumn market = GeneratedColumn( + 'market', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(Market.US.name)); + late final GeneratedColumn searchMode = GeneratedColumn( + 'search_mode', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SearchMode.youtube.name)); + late final GeneratedColumn downloadLocation = GeneratedColumn( + 'download_location', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("")); + late final GeneratedColumn localLibraryLocation = + GeneratedColumn('local_library_location', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("")); + late final GeneratedColumn pipedInstance = GeneratedColumn( + 'piped_instance', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("https://pipedapi.kavin.rocks")); + late final GeneratedColumn invidiousInstance = + GeneratedColumn('invidious_instance', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant("https://inv.nadeko.net")); + late final GeneratedColumn themeMode = GeneratedColumn( + 'theme_mode', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(ThemeMode.system.name)); + late final GeneratedColumn audioSource = GeneratedColumn( + 'audio_source', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(AudioSource.youtube.name)); + late final GeneratedColumn youtubeClientEngine = + GeneratedColumn('youtube_client_engine', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(YoutubeClientEngine.youtubeExplode.name)); + late final GeneratedColumn streamMusicCodec = GeneratedColumn( + 'stream_music_codec', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceCodecs.weba.name)); + late final GeneratedColumn downloadMusicCodec = + GeneratedColumn('download_music_codec', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceCodecs.m4a.name)); + late final GeneratedColumn discordPresence = GeneratedColumn( + 'discord_presence', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("discord_presence" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn endlessPlayback = GeneratedColumn( + 'endless_playback', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("endless_playback" IN (0, 1))'), + defaultValue: const Constant(true)); + late final GeneratedColumn enableConnect = GeneratedColumn( + 'enable_connect', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("enable_connect" IN (0, 1))'), + defaultValue: const Constant(false)); + late final GeneratedColumn connectPort = GeneratedColumn( + 'connect_port', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const Constant(-1)); + late final GeneratedColumn cacheMusic = GeneratedColumn( + 'cache_music', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("cache_music" IN (0, 1))'), + defaultValue: const Constant(true)); + @override + List get $columns => [ + id, + audioQuality, + albumColorSync, + amoledDarkTheme, + checkUpdate, + normalizeAudio, + showSystemTrayIcon, + systemTitleBar, + skipNonMusic, + closeBehavior, + accentColorScheme, + layoutMode, + locale, + market, + searchMode, + downloadLocation, + localLibraryLocation, + pipedInstance, + invidiousInstance, + themeMode, + audioSource, + youtubeClientEngine, + streamMusicCodec, + downloadMusicCodec, + discordPresence, + endlessPlayback, + enableConnect, + connectPort, + cacheMusic + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'preferences_table'; + @override + Set get $primaryKey => {id}; + @override + PreferencesTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PreferencesTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + audioQuality: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}audio_quality'])!, + albumColorSync: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}album_color_sync'])!, + amoledDarkTheme: attachedDatabase.typeMapping.read( + DriftSqlType.bool, data['${effectivePrefix}amoled_dark_theme'])!, + checkUpdate: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}check_update'])!, + normalizeAudio: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}normalize_audio'])!, + showSystemTrayIcon: attachedDatabase.typeMapping.read( + DriftSqlType.bool, data['${effectivePrefix}show_system_tray_icon'])!, + systemTitleBar: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}system_title_bar'])!, + skipNonMusic: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}skip_non_music'])!, + closeBehavior: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}close_behavior'])!, + accentColorScheme: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}accent_color_scheme'])!, + layoutMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}layout_mode'])!, + locale: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}locale'])!, + market: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}market'])!, + searchMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}search_mode'])!, + downloadLocation: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}download_location'])!, + localLibraryLocation: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}local_library_location'])!, + pipedInstance: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}piped_instance'])!, + invidiousInstance: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}invidious_instance'])!, + themeMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}theme_mode'])!, + audioSource: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}audio_source'])!, + youtubeClientEngine: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}youtube_client_engine'])!, + streamMusicCodec: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}stream_music_codec'])!, + downloadMusicCodec: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}download_music_codec'])!, + discordPresence: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}discord_presence'])!, + endlessPlayback: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}endless_playback'])!, + enableConnect: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}enable_connect'])!, + connectPort: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}connect_port'])!, + cacheMusic: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}cache_music'])!, + ); + } + + @override + PreferencesTable createAlias(String alias) { + return PreferencesTable(attachedDatabase, alias); + } +} + +class PreferencesTableData extends DataClass + implements Insertable { + final int id; + final String audioQuality; + final bool albumColorSync; + final bool amoledDarkTheme; + final bool checkUpdate; + final bool normalizeAudio; + final bool showSystemTrayIcon; + final bool systemTitleBar; + final bool skipNonMusic; + final String closeBehavior; + final String accentColorScheme; + final String layoutMode; + final String locale; + final String market; + final String searchMode; + final String downloadLocation; + final String localLibraryLocation; + final String pipedInstance; + final String invidiousInstance; + final String themeMode; + final String audioSource; + final String youtubeClientEngine; + final String streamMusicCodec; + final String downloadMusicCodec; + final bool discordPresence; + final bool endlessPlayback; + final bool enableConnect; + final int connectPort; + final bool cacheMusic; + const PreferencesTableData( + {required this.id, + required this.audioQuality, + required this.albumColorSync, + required this.amoledDarkTheme, + required this.checkUpdate, + required this.normalizeAudio, + required this.showSystemTrayIcon, + required this.systemTitleBar, + required this.skipNonMusic, + required this.closeBehavior, + required this.accentColorScheme, + required this.layoutMode, + required this.locale, + required this.market, + required this.searchMode, + required this.downloadLocation, + required this.localLibraryLocation, + required this.pipedInstance, + required this.invidiousInstance, + required this.themeMode, + required this.audioSource, + required this.youtubeClientEngine, + required this.streamMusicCodec, + required this.downloadMusicCodec, + required this.discordPresence, + required this.endlessPlayback, + required this.enableConnect, + required this.connectPort, + required this.cacheMusic}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['audio_quality'] = Variable(audioQuality); + map['album_color_sync'] = Variable(albumColorSync); + map['amoled_dark_theme'] = Variable(amoledDarkTheme); + map['check_update'] = Variable(checkUpdate); + map['normalize_audio'] = Variable(normalizeAudio); + map['show_system_tray_icon'] = Variable(showSystemTrayIcon); + map['system_title_bar'] = Variable(systemTitleBar); + map['skip_non_music'] = Variable(skipNonMusic); + map['close_behavior'] = Variable(closeBehavior); + map['accent_color_scheme'] = Variable(accentColorScheme); + map['layout_mode'] = Variable(layoutMode); + map['locale'] = Variable(locale); + map['market'] = Variable(market); + map['search_mode'] = Variable(searchMode); + map['download_location'] = Variable(downloadLocation); + map['local_library_location'] = Variable(localLibraryLocation); + map['piped_instance'] = Variable(pipedInstance); + map['invidious_instance'] = Variable(invidiousInstance); + map['theme_mode'] = Variable(themeMode); + map['audio_source'] = Variable(audioSource); + map['youtube_client_engine'] = Variable(youtubeClientEngine); + map['stream_music_codec'] = Variable(streamMusicCodec); + map['download_music_codec'] = Variable(downloadMusicCodec); + map['discord_presence'] = Variable(discordPresence); + map['endless_playback'] = Variable(endlessPlayback); + map['enable_connect'] = Variable(enableConnect); + map['connect_port'] = Variable(connectPort); + map['cache_music'] = Variable(cacheMusic); + return map; + } + + PreferencesTableCompanion toCompanion(bool nullToAbsent) { + return PreferencesTableCompanion( + id: Value(id), + audioQuality: Value(audioQuality), + albumColorSync: Value(albumColorSync), + amoledDarkTheme: Value(amoledDarkTheme), + checkUpdate: Value(checkUpdate), + normalizeAudio: Value(normalizeAudio), + showSystemTrayIcon: Value(showSystemTrayIcon), + systemTitleBar: Value(systemTitleBar), + skipNonMusic: Value(skipNonMusic), + closeBehavior: Value(closeBehavior), + accentColorScheme: Value(accentColorScheme), + layoutMode: Value(layoutMode), + locale: Value(locale), + market: Value(market), + searchMode: Value(searchMode), + downloadLocation: Value(downloadLocation), + localLibraryLocation: Value(localLibraryLocation), + pipedInstance: Value(pipedInstance), + invidiousInstance: Value(invidiousInstance), + themeMode: Value(themeMode), + audioSource: Value(audioSource), + youtubeClientEngine: Value(youtubeClientEngine), + streamMusicCodec: Value(streamMusicCodec), + downloadMusicCodec: Value(downloadMusicCodec), + discordPresence: Value(discordPresence), + endlessPlayback: Value(endlessPlayback), + enableConnect: Value(enableConnect), + connectPort: Value(connectPort), + cacheMusic: Value(cacheMusic), + ); + } + + factory PreferencesTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PreferencesTableData( + id: serializer.fromJson(json['id']), + audioQuality: serializer.fromJson(json['audioQuality']), + albumColorSync: serializer.fromJson(json['albumColorSync']), + amoledDarkTheme: serializer.fromJson(json['amoledDarkTheme']), + checkUpdate: serializer.fromJson(json['checkUpdate']), + normalizeAudio: serializer.fromJson(json['normalizeAudio']), + showSystemTrayIcon: serializer.fromJson(json['showSystemTrayIcon']), + systemTitleBar: serializer.fromJson(json['systemTitleBar']), + skipNonMusic: serializer.fromJson(json['skipNonMusic']), + closeBehavior: serializer.fromJson(json['closeBehavior']), + accentColorScheme: serializer.fromJson(json['accentColorScheme']), + layoutMode: serializer.fromJson(json['layoutMode']), + locale: serializer.fromJson(json['locale']), + market: serializer.fromJson(json['market']), + searchMode: serializer.fromJson(json['searchMode']), + downloadLocation: serializer.fromJson(json['downloadLocation']), + localLibraryLocation: + serializer.fromJson(json['localLibraryLocation']), + pipedInstance: serializer.fromJson(json['pipedInstance']), + invidiousInstance: serializer.fromJson(json['invidiousInstance']), + themeMode: serializer.fromJson(json['themeMode']), + audioSource: serializer.fromJson(json['audioSource']), + youtubeClientEngine: + serializer.fromJson(json['youtubeClientEngine']), + streamMusicCodec: serializer.fromJson(json['streamMusicCodec']), + downloadMusicCodec: + serializer.fromJson(json['downloadMusicCodec']), + discordPresence: serializer.fromJson(json['discordPresence']), + endlessPlayback: serializer.fromJson(json['endlessPlayback']), + enableConnect: serializer.fromJson(json['enableConnect']), + connectPort: serializer.fromJson(json['connectPort']), + cacheMusic: serializer.fromJson(json['cacheMusic']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'audioQuality': serializer.toJson(audioQuality), + 'albumColorSync': serializer.toJson(albumColorSync), + 'amoledDarkTheme': serializer.toJson(amoledDarkTheme), + 'checkUpdate': serializer.toJson(checkUpdate), + 'normalizeAudio': serializer.toJson(normalizeAudio), + 'showSystemTrayIcon': serializer.toJson(showSystemTrayIcon), + 'systemTitleBar': serializer.toJson(systemTitleBar), + 'skipNonMusic': serializer.toJson(skipNonMusic), + 'closeBehavior': serializer.toJson(closeBehavior), + 'accentColorScheme': serializer.toJson(accentColorScheme), + 'layoutMode': serializer.toJson(layoutMode), + 'locale': serializer.toJson(locale), + 'market': serializer.toJson(market), + 'searchMode': serializer.toJson(searchMode), + 'downloadLocation': serializer.toJson(downloadLocation), + 'localLibraryLocation': serializer.toJson(localLibraryLocation), + 'pipedInstance': serializer.toJson(pipedInstance), + 'invidiousInstance': serializer.toJson(invidiousInstance), + 'themeMode': serializer.toJson(themeMode), + 'audioSource': serializer.toJson(audioSource), + 'youtubeClientEngine': serializer.toJson(youtubeClientEngine), + 'streamMusicCodec': serializer.toJson(streamMusicCodec), + 'downloadMusicCodec': serializer.toJson(downloadMusicCodec), + 'discordPresence': serializer.toJson(discordPresence), + 'endlessPlayback': serializer.toJson(endlessPlayback), + 'enableConnect': serializer.toJson(enableConnect), + 'connectPort': serializer.toJson(connectPort), + 'cacheMusic': serializer.toJson(cacheMusic), + }; + } + + PreferencesTableData copyWith( + {int? id, + String? audioQuality, + bool? albumColorSync, + bool? amoledDarkTheme, + bool? checkUpdate, + bool? normalizeAudio, + bool? showSystemTrayIcon, + bool? systemTitleBar, + bool? skipNonMusic, + String? closeBehavior, + String? accentColorScheme, + String? layoutMode, + String? locale, + String? market, + String? searchMode, + String? downloadLocation, + String? localLibraryLocation, + String? pipedInstance, + String? invidiousInstance, + String? themeMode, + String? audioSource, + String? youtubeClientEngine, + String? streamMusicCodec, + String? downloadMusicCodec, + bool? discordPresence, + bool? endlessPlayback, + bool? enableConnect, + int? connectPort, + bool? cacheMusic}) => + PreferencesTableData( + id: id ?? this.id, + audioQuality: audioQuality ?? this.audioQuality, + albumColorSync: albumColorSync ?? this.albumColorSync, + amoledDarkTheme: amoledDarkTheme ?? this.amoledDarkTheme, + checkUpdate: checkUpdate ?? this.checkUpdate, + normalizeAudio: normalizeAudio ?? this.normalizeAudio, + showSystemTrayIcon: showSystemTrayIcon ?? this.showSystemTrayIcon, + systemTitleBar: systemTitleBar ?? this.systemTitleBar, + skipNonMusic: skipNonMusic ?? this.skipNonMusic, + closeBehavior: closeBehavior ?? this.closeBehavior, + accentColorScheme: accentColorScheme ?? this.accentColorScheme, + layoutMode: layoutMode ?? this.layoutMode, + locale: locale ?? this.locale, + market: market ?? this.market, + searchMode: searchMode ?? this.searchMode, + downloadLocation: downloadLocation ?? this.downloadLocation, + localLibraryLocation: localLibraryLocation ?? this.localLibraryLocation, + pipedInstance: pipedInstance ?? this.pipedInstance, + invidiousInstance: invidiousInstance ?? this.invidiousInstance, + themeMode: themeMode ?? this.themeMode, + audioSource: audioSource ?? this.audioSource, + youtubeClientEngine: youtubeClientEngine ?? this.youtubeClientEngine, + streamMusicCodec: streamMusicCodec ?? this.streamMusicCodec, + downloadMusicCodec: downloadMusicCodec ?? this.downloadMusicCodec, + discordPresence: discordPresence ?? this.discordPresence, + endlessPlayback: endlessPlayback ?? this.endlessPlayback, + enableConnect: enableConnect ?? this.enableConnect, + connectPort: connectPort ?? this.connectPort, + cacheMusic: cacheMusic ?? this.cacheMusic, + ); + PreferencesTableData copyWithCompanion(PreferencesTableCompanion data) { + return PreferencesTableData( + id: data.id.present ? data.id.value : this.id, + audioQuality: data.audioQuality.present + ? data.audioQuality.value + : this.audioQuality, + albumColorSync: data.albumColorSync.present + ? data.albumColorSync.value + : this.albumColorSync, + amoledDarkTheme: data.amoledDarkTheme.present + ? data.amoledDarkTheme.value + : this.amoledDarkTheme, + checkUpdate: + data.checkUpdate.present ? data.checkUpdate.value : this.checkUpdate, + normalizeAudio: data.normalizeAudio.present + ? data.normalizeAudio.value + : this.normalizeAudio, + showSystemTrayIcon: data.showSystemTrayIcon.present + ? data.showSystemTrayIcon.value + : this.showSystemTrayIcon, + systemTitleBar: data.systemTitleBar.present + ? data.systemTitleBar.value + : this.systemTitleBar, + skipNonMusic: data.skipNonMusic.present + ? data.skipNonMusic.value + : this.skipNonMusic, + closeBehavior: data.closeBehavior.present + ? data.closeBehavior.value + : this.closeBehavior, + accentColorScheme: data.accentColorScheme.present + ? data.accentColorScheme.value + : this.accentColorScheme, + layoutMode: + data.layoutMode.present ? data.layoutMode.value : this.layoutMode, + locale: data.locale.present ? data.locale.value : this.locale, + market: data.market.present ? data.market.value : this.market, + searchMode: + data.searchMode.present ? data.searchMode.value : this.searchMode, + downloadLocation: data.downloadLocation.present + ? data.downloadLocation.value + : this.downloadLocation, + localLibraryLocation: data.localLibraryLocation.present + ? data.localLibraryLocation.value + : this.localLibraryLocation, + pipedInstance: data.pipedInstance.present + ? data.pipedInstance.value + : this.pipedInstance, + invidiousInstance: data.invidiousInstance.present + ? data.invidiousInstance.value + : this.invidiousInstance, + themeMode: data.themeMode.present ? data.themeMode.value : this.themeMode, + audioSource: + data.audioSource.present ? data.audioSource.value : this.audioSource, + youtubeClientEngine: data.youtubeClientEngine.present + ? data.youtubeClientEngine.value + : this.youtubeClientEngine, + streamMusicCodec: data.streamMusicCodec.present + ? data.streamMusicCodec.value + : this.streamMusicCodec, + downloadMusicCodec: data.downloadMusicCodec.present + ? data.downloadMusicCodec.value + : this.downloadMusicCodec, + discordPresence: data.discordPresence.present + ? data.discordPresence.value + : this.discordPresence, + endlessPlayback: data.endlessPlayback.present + ? data.endlessPlayback.value + : this.endlessPlayback, + enableConnect: data.enableConnect.present + ? data.enableConnect.value + : this.enableConnect, + connectPort: + data.connectPort.present ? data.connectPort.value : this.connectPort, + cacheMusic: + data.cacheMusic.present ? data.cacheMusic.value : this.cacheMusic, + ); + } + + @override + String toString() { + return (StringBuffer('PreferencesTableData(') + ..write('id: $id, ') + ..write('audioQuality: $audioQuality, ') + ..write('albumColorSync: $albumColorSync, ') + ..write('amoledDarkTheme: $amoledDarkTheme, ') + ..write('checkUpdate: $checkUpdate, ') + ..write('normalizeAudio: $normalizeAudio, ') + ..write('showSystemTrayIcon: $showSystemTrayIcon, ') + ..write('systemTitleBar: $systemTitleBar, ') + ..write('skipNonMusic: $skipNonMusic, ') + ..write('closeBehavior: $closeBehavior, ') + ..write('accentColorScheme: $accentColorScheme, ') + ..write('layoutMode: $layoutMode, ') + ..write('locale: $locale, ') + ..write('market: $market, ') + ..write('searchMode: $searchMode, ') + ..write('downloadLocation: $downloadLocation, ') + ..write('localLibraryLocation: $localLibraryLocation, ') + ..write('pipedInstance: $pipedInstance, ') + ..write('invidiousInstance: $invidiousInstance, ') + ..write('themeMode: $themeMode, ') + ..write('audioSource: $audioSource, ') + ..write('youtubeClientEngine: $youtubeClientEngine, ') + ..write('streamMusicCodec: $streamMusicCodec, ') + ..write('downloadMusicCodec: $downloadMusicCodec, ') + ..write('discordPresence: $discordPresence, ') + ..write('endlessPlayback: $endlessPlayback, ') + ..write('enableConnect: $enableConnect, ') + ..write('connectPort: $connectPort, ') + ..write('cacheMusic: $cacheMusic') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + id, + audioQuality, + albumColorSync, + amoledDarkTheme, + checkUpdate, + normalizeAudio, + showSystemTrayIcon, + systemTitleBar, + skipNonMusic, + closeBehavior, + accentColorScheme, + layoutMode, + locale, + market, + searchMode, + downloadLocation, + localLibraryLocation, + pipedInstance, + invidiousInstance, + themeMode, + audioSource, + youtubeClientEngine, + streamMusicCodec, + downloadMusicCodec, + discordPresence, + endlessPlayback, + enableConnect, + connectPort, + cacheMusic + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PreferencesTableData && + other.id == this.id && + other.audioQuality == this.audioQuality && + other.albumColorSync == this.albumColorSync && + other.amoledDarkTheme == this.amoledDarkTheme && + other.checkUpdate == this.checkUpdate && + other.normalizeAudio == this.normalizeAudio && + other.showSystemTrayIcon == this.showSystemTrayIcon && + other.systemTitleBar == this.systemTitleBar && + other.skipNonMusic == this.skipNonMusic && + other.closeBehavior == this.closeBehavior && + other.accentColorScheme == this.accentColorScheme && + other.layoutMode == this.layoutMode && + other.locale == this.locale && + other.market == this.market && + other.searchMode == this.searchMode && + other.downloadLocation == this.downloadLocation && + other.localLibraryLocation == this.localLibraryLocation && + other.pipedInstance == this.pipedInstance && + other.invidiousInstance == this.invidiousInstance && + other.themeMode == this.themeMode && + other.audioSource == this.audioSource && + other.youtubeClientEngine == this.youtubeClientEngine && + other.streamMusicCodec == this.streamMusicCodec && + other.downloadMusicCodec == this.downloadMusicCodec && + other.discordPresence == this.discordPresence && + other.endlessPlayback == this.endlessPlayback && + other.enableConnect == this.enableConnect && + other.connectPort == this.connectPort && + other.cacheMusic == this.cacheMusic); +} + +class PreferencesTableCompanion extends UpdateCompanion { + final Value id; + final Value audioQuality; + final Value albumColorSync; + final Value amoledDarkTheme; + final Value checkUpdate; + final Value normalizeAudio; + final Value showSystemTrayIcon; + final Value systemTitleBar; + final Value skipNonMusic; + final Value closeBehavior; + final Value accentColorScheme; + final Value layoutMode; + final Value locale; + final Value market; + final Value searchMode; + final Value downloadLocation; + final Value localLibraryLocation; + final Value pipedInstance; + final Value invidiousInstance; + final Value themeMode; + final Value audioSource; + final Value youtubeClientEngine; + final Value streamMusicCodec; + final Value downloadMusicCodec; + final Value discordPresence; + final Value endlessPlayback; + final Value enableConnect; + final Value connectPort; + final Value cacheMusic; + const PreferencesTableCompanion({ + this.id = const Value.absent(), + this.audioQuality = const Value.absent(), + this.albumColorSync = const Value.absent(), + this.amoledDarkTheme = const Value.absent(), + this.checkUpdate = const Value.absent(), + this.normalizeAudio = const Value.absent(), + this.showSystemTrayIcon = const Value.absent(), + this.systemTitleBar = const Value.absent(), + this.skipNonMusic = const Value.absent(), + this.closeBehavior = const Value.absent(), + this.accentColorScheme = const Value.absent(), + this.layoutMode = const Value.absent(), + this.locale = const Value.absent(), + this.market = const Value.absent(), + this.searchMode = const Value.absent(), + this.downloadLocation = const Value.absent(), + this.localLibraryLocation = const Value.absent(), + this.pipedInstance = const Value.absent(), + this.invidiousInstance = const Value.absent(), + this.themeMode = const Value.absent(), + this.audioSource = const Value.absent(), + this.youtubeClientEngine = const Value.absent(), + this.streamMusicCodec = const Value.absent(), + this.downloadMusicCodec = const Value.absent(), + this.discordPresence = const Value.absent(), + this.endlessPlayback = const Value.absent(), + this.enableConnect = const Value.absent(), + this.connectPort = const Value.absent(), + this.cacheMusic = const Value.absent(), + }); + PreferencesTableCompanion.insert({ + this.id = const Value.absent(), + this.audioQuality = const Value.absent(), + this.albumColorSync = const Value.absent(), + this.amoledDarkTheme = const Value.absent(), + this.checkUpdate = const Value.absent(), + this.normalizeAudio = const Value.absent(), + this.showSystemTrayIcon = const Value.absent(), + this.systemTitleBar = const Value.absent(), + this.skipNonMusic = const Value.absent(), + this.closeBehavior = const Value.absent(), + this.accentColorScheme = const Value.absent(), + this.layoutMode = const Value.absent(), + this.locale = const Value.absent(), + this.market = const Value.absent(), + this.searchMode = const Value.absent(), + this.downloadLocation = const Value.absent(), + this.localLibraryLocation = const Value.absent(), + this.pipedInstance = const Value.absent(), + this.invidiousInstance = const Value.absent(), + this.themeMode = const Value.absent(), + this.audioSource = const Value.absent(), + this.youtubeClientEngine = const Value.absent(), + this.streamMusicCodec = const Value.absent(), + this.downloadMusicCodec = const Value.absent(), + this.discordPresence = const Value.absent(), + this.endlessPlayback = const Value.absent(), + this.enableConnect = const Value.absent(), + this.connectPort = const Value.absent(), + this.cacheMusic = const Value.absent(), + }); + static Insertable custom({ + Expression? id, + Expression? audioQuality, + Expression? albumColorSync, + Expression? amoledDarkTheme, + Expression? checkUpdate, + Expression? normalizeAudio, + Expression? showSystemTrayIcon, + Expression? systemTitleBar, + Expression? skipNonMusic, + Expression? closeBehavior, + Expression? accentColorScheme, + Expression? layoutMode, + Expression? locale, + Expression? market, + Expression? searchMode, + Expression? downloadLocation, + Expression? localLibraryLocation, + Expression? pipedInstance, + Expression? invidiousInstance, + Expression? themeMode, + Expression? audioSource, + Expression? youtubeClientEngine, + Expression? streamMusicCodec, + Expression? downloadMusicCodec, + Expression? discordPresence, + Expression? endlessPlayback, + Expression? enableConnect, + Expression? connectPort, + Expression? cacheMusic, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (audioQuality != null) 'audio_quality': audioQuality, + if (albumColorSync != null) 'album_color_sync': albumColorSync, + if (amoledDarkTheme != null) 'amoled_dark_theme': amoledDarkTheme, + if (checkUpdate != null) 'check_update': checkUpdate, + if (normalizeAudio != null) 'normalize_audio': normalizeAudio, + if (showSystemTrayIcon != null) + 'show_system_tray_icon': showSystemTrayIcon, + if (systemTitleBar != null) 'system_title_bar': systemTitleBar, + if (skipNonMusic != null) 'skip_non_music': skipNonMusic, + if (closeBehavior != null) 'close_behavior': closeBehavior, + if (accentColorScheme != null) 'accent_color_scheme': accentColorScheme, + if (layoutMode != null) 'layout_mode': layoutMode, + if (locale != null) 'locale': locale, + if (market != null) 'market': market, + if (searchMode != null) 'search_mode': searchMode, + if (downloadLocation != null) 'download_location': downloadLocation, + if (localLibraryLocation != null) + 'local_library_location': localLibraryLocation, + if (pipedInstance != null) 'piped_instance': pipedInstance, + if (invidiousInstance != null) 'invidious_instance': invidiousInstance, + if (themeMode != null) 'theme_mode': themeMode, + if (audioSource != null) 'audio_source': audioSource, + if (youtubeClientEngine != null) + 'youtube_client_engine': youtubeClientEngine, + if (streamMusicCodec != null) 'stream_music_codec': streamMusicCodec, + if (downloadMusicCodec != null) + 'download_music_codec': downloadMusicCodec, + if (discordPresence != null) 'discord_presence': discordPresence, + if (endlessPlayback != null) 'endless_playback': endlessPlayback, + if (enableConnect != null) 'enable_connect': enableConnect, + if (connectPort != null) 'connect_port': connectPort, + if (cacheMusic != null) 'cache_music': cacheMusic, + }); + } + + PreferencesTableCompanion copyWith( + {Value? id, + Value? audioQuality, + Value? albumColorSync, + Value? amoledDarkTheme, + Value? checkUpdate, + Value? normalizeAudio, + Value? showSystemTrayIcon, + Value? systemTitleBar, + Value? skipNonMusic, + Value? closeBehavior, + Value? accentColorScheme, + Value? layoutMode, + Value? locale, + Value? market, + Value? searchMode, + Value? downloadLocation, + Value? localLibraryLocation, + Value? pipedInstance, + Value? invidiousInstance, + Value? themeMode, + Value? audioSource, + Value? youtubeClientEngine, + Value? streamMusicCodec, + Value? downloadMusicCodec, + Value? discordPresence, + Value? endlessPlayback, + Value? enableConnect, + Value? connectPort, + Value? cacheMusic}) { + return PreferencesTableCompanion( + id: id ?? this.id, + audioQuality: audioQuality ?? this.audioQuality, + albumColorSync: albumColorSync ?? this.albumColorSync, + amoledDarkTheme: amoledDarkTheme ?? this.amoledDarkTheme, + checkUpdate: checkUpdate ?? this.checkUpdate, + normalizeAudio: normalizeAudio ?? this.normalizeAudio, + showSystemTrayIcon: showSystemTrayIcon ?? this.showSystemTrayIcon, + systemTitleBar: systemTitleBar ?? this.systemTitleBar, + skipNonMusic: skipNonMusic ?? this.skipNonMusic, + closeBehavior: closeBehavior ?? this.closeBehavior, + accentColorScheme: accentColorScheme ?? this.accentColorScheme, + layoutMode: layoutMode ?? this.layoutMode, + locale: locale ?? this.locale, + market: market ?? this.market, + searchMode: searchMode ?? this.searchMode, + downloadLocation: downloadLocation ?? this.downloadLocation, + localLibraryLocation: localLibraryLocation ?? this.localLibraryLocation, + pipedInstance: pipedInstance ?? this.pipedInstance, + invidiousInstance: invidiousInstance ?? this.invidiousInstance, + themeMode: themeMode ?? this.themeMode, + audioSource: audioSource ?? this.audioSource, + youtubeClientEngine: youtubeClientEngine ?? this.youtubeClientEngine, + streamMusicCodec: streamMusicCodec ?? this.streamMusicCodec, + downloadMusicCodec: downloadMusicCodec ?? this.downloadMusicCodec, + discordPresence: discordPresence ?? this.discordPresence, + endlessPlayback: endlessPlayback ?? this.endlessPlayback, + enableConnect: enableConnect ?? this.enableConnect, + connectPort: connectPort ?? this.connectPort, + cacheMusic: cacheMusic ?? this.cacheMusic, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (audioQuality.present) { + map['audio_quality'] = Variable(audioQuality.value); + } + if (albumColorSync.present) { + map['album_color_sync'] = Variable(albumColorSync.value); + } + if (amoledDarkTheme.present) { + map['amoled_dark_theme'] = Variable(amoledDarkTheme.value); + } + if (checkUpdate.present) { + map['check_update'] = Variable(checkUpdate.value); + } + if (normalizeAudio.present) { + map['normalize_audio'] = Variable(normalizeAudio.value); + } + if (showSystemTrayIcon.present) { + map['show_system_tray_icon'] = Variable(showSystemTrayIcon.value); + } + if (systemTitleBar.present) { + map['system_title_bar'] = Variable(systemTitleBar.value); + } + if (skipNonMusic.present) { + map['skip_non_music'] = Variable(skipNonMusic.value); + } + if (closeBehavior.present) { + map['close_behavior'] = Variable(closeBehavior.value); + } + if (accentColorScheme.present) { + map['accent_color_scheme'] = Variable(accentColorScheme.value); + } + if (layoutMode.present) { + map['layout_mode'] = Variable(layoutMode.value); + } + if (locale.present) { + map['locale'] = Variable(locale.value); + } + if (market.present) { + map['market'] = Variable(market.value); + } + if (searchMode.present) { + map['search_mode'] = Variable(searchMode.value); + } + if (downloadLocation.present) { + map['download_location'] = Variable(downloadLocation.value); + } + if (localLibraryLocation.present) { + map['local_library_location'] = + Variable(localLibraryLocation.value); + } + if (pipedInstance.present) { + map['piped_instance'] = Variable(pipedInstance.value); + } + if (invidiousInstance.present) { + map['invidious_instance'] = Variable(invidiousInstance.value); + } + if (themeMode.present) { + map['theme_mode'] = Variable(themeMode.value); + } + if (audioSource.present) { + map['audio_source'] = Variable(audioSource.value); + } + if (youtubeClientEngine.present) { + map['youtube_client_engine'] = + Variable(youtubeClientEngine.value); + } + if (streamMusicCodec.present) { + map['stream_music_codec'] = Variable(streamMusicCodec.value); + } + if (downloadMusicCodec.present) { + map['download_music_codec'] = Variable(downloadMusicCodec.value); + } + if (discordPresence.present) { + map['discord_presence'] = Variable(discordPresence.value); + } + if (endlessPlayback.present) { + map['endless_playback'] = Variable(endlessPlayback.value); + } + if (enableConnect.present) { + map['enable_connect'] = Variable(enableConnect.value); + } + if (connectPort.present) { + map['connect_port'] = Variable(connectPort.value); + } + if (cacheMusic.present) { + map['cache_music'] = Variable(cacheMusic.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PreferencesTableCompanion(') + ..write('id: $id, ') + ..write('audioQuality: $audioQuality, ') + ..write('albumColorSync: $albumColorSync, ') + ..write('amoledDarkTheme: $amoledDarkTheme, ') + ..write('checkUpdate: $checkUpdate, ') + ..write('normalizeAudio: $normalizeAudio, ') + ..write('showSystemTrayIcon: $showSystemTrayIcon, ') + ..write('systemTitleBar: $systemTitleBar, ') + ..write('skipNonMusic: $skipNonMusic, ') + ..write('closeBehavior: $closeBehavior, ') + ..write('accentColorScheme: $accentColorScheme, ') + ..write('layoutMode: $layoutMode, ') + ..write('locale: $locale, ') + ..write('market: $market, ') + ..write('searchMode: $searchMode, ') + ..write('downloadLocation: $downloadLocation, ') + ..write('localLibraryLocation: $localLibraryLocation, ') + ..write('pipedInstance: $pipedInstance, ') + ..write('invidiousInstance: $invidiousInstance, ') + ..write('themeMode: $themeMode, ') + ..write('audioSource: $audioSource, ') + ..write('youtubeClientEngine: $youtubeClientEngine, ') + ..write('streamMusicCodec: $streamMusicCodec, ') + ..write('downloadMusicCodec: $downloadMusicCodec, ') + ..write('discordPresence: $discordPresence, ') + ..write('endlessPlayback: $endlessPlayback, ') + ..write('enableConnect: $enableConnect, ') + ..write('connectPort: $connectPort, ') + ..write('cacheMusic: $cacheMusic') + ..write(')')) + .toString(); + } +} + +class ScrobblerTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + ScrobblerTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + late final GeneratedColumn username = GeneratedColumn( + 'username', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn passwordHash = GeneratedColumn( + 'password_hash', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, createdAt, username, passwordHash]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'scrobbler_table'; + @override + Set get $primaryKey => {id}; + @override + ScrobblerTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return ScrobblerTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + username: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}username'])!, + passwordHash: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}password_hash'])!, + ); + } + + @override + ScrobblerTable createAlias(String alias) { + return ScrobblerTable(attachedDatabase, alias); + } +} + +class ScrobblerTableData extends DataClass + implements Insertable { + final int id; + final DateTime createdAt; + final String username; + final String passwordHash; + const ScrobblerTableData( + {required this.id, + required this.createdAt, + required this.username, + required this.passwordHash}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['username'] = Variable(username); + map['password_hash'] = Variable(passwordHash); + return map; + } + + ScrobblerTableCompanion toCompanion(bool nullToAbsent) { + return ScrobblerTableCompanion( + id: Value(id), + createdAt: Value(createdAt), + username: Value(username), + passwordHash: Value(passwordHash), + ); + } + + factory ScrobblerTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return ScrobblerTableData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + username: serializer.fromJson(json['username']), + passwordHash: serializer.fromJson(json['passwordHash']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'username': serializer.toJson(username), + 'passwordHash': serializer.toJson(passwordHash), + }; + } + + ScrobblerTableData copyWith( + {int? id, + DateTime? createdAt, + String? username, + String? passwordHash}) => + ScrobblerTableData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + username: username ?? this.username, + passwordHash: passwordHash ?? this.passwordHash, + ); + ScrobblerTableData copyWithCompanion(ScrobblerTableCompanion data) { + return ScrobblerTableData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + username: data.username.present ? data.username.value : this.username, + passwordHash: data.passwordHash.present + ? data.passwordHash.value + : this.passwordHash, + ); + } + + @override + String toString() { + return (StringBuffer('ScrobblerTableData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('username: $username, ') + ..write('passwordHash: $passwordHash') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, createdAt, username, passwordHash); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is ScrobblerTableData && + other.id == this.id && + other.createdAt == this.createdAt && + other.username == this.username && + other.passwordHash == this.passwordHash); +} + +class ScrobblerTableCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value username; + final Value passwordHash; + const ScrobblerTableCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.username = const Value.absent(), + this.passwordHash = const Value.absent(), + }); + ScrobblerTableCompanion.insert({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + required String username, + required String passwordHash, + }) : username = Value(username), + passwordHash = Value(passwordHash); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? username, + Expression? passwordHash, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (username != null) 'username': username, + if (passwordHash != null) 'password_hash': passwordHash, + }); + } + + ScrobblerTableCompanion copyWith( + {Value? id, + Value? createdAt, + Value? username, + Value? passwordHash}) { + return ScrobblerTableCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + username: username ?? this.username, + passwordHash: passwordHash ?? this.passwordHash, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (username.present) { + map['username'] = Variable(username.value); + } + if (passwordHash.present) { + map['password_hash'] = Variable(passwordHash.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('ScrobblerTableCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('username: $username, ') + ..write('passwordHash: $passwordHash') + ..write(')')) + .toString(); + } +} + +class SkipSegmentTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + SkipSegmentTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn start = GeneratedColumn( + 'start', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + late final GeneratedColumn end = GeneratedColumn( + 'end', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => [id, start, end, trackId, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'skip_segment_table'; + @override + Set get $primaryKey => {id}; + @override + SkipSegmentTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SkipSegmentTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + start: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}start'])!, + end: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}end'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + SkipSegmentTable createAlias(String alias) { + return SkipSegmentTable(attachedDatabase, alias); + } +} + +class SkipSegmentTableData extends DataClass + implements Insertable { + final int id; + final int start; + final int end; + final String trackId; + final DateTime createdAt; + const SkipSegmentTableData( + {required this.id, + required this.start, + required this.end, + required this.trackId, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['start'] = Variable(start); + map['end'] = Variable(end); + map['track_id'] = Variable(trackId); + map['created_at'] = Variable(createdAt); + return map; + } + + SkipSegmentTableCompanion toCompanion(bool nullToAbsent) { + return SkipSegmentTableCompanion( + id: Value(id), + start: Value(start), + end: Value(end), + trackId: Value(trackId), + createdAt: Value(createdAt), + ); + } + + factory SkipSegmentTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SkipSegmentTableData( + id: serializer.fromJson(json['id']), + start: serializer.fromJson(json['start']), + end: serializer.fromJson(json['end']), + trackId: serializer.fromJson(json['trackId']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'start': serializer.toJson(start), + 'end': serializer.toJson(end), + 'trackId': serializer.toJson(trackId), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SkipSegmentTableData copyWith( + {int? id, + int? start, + int? end, + String? trackId, + DateTime? createdAt}) => + SkipSegmentTableData( + id: id ?? this.id, + start: start ?? this.start, + end: end ?? this.end, + trackId: trackId ?? this.trackId, + createdAt: createdAt ?? this.createdAt, + ); + SkipSegmentTableData copyWithCompanion(SkipSegmentTableCompanion data) { + return SkipSegmentTableData( + id: data.id.present ? data.id.value : this.id, + start: data.start.present ? data.start.value : this.start, + end: data.end.present ? data.end.value : this.end, + trackId: data.trackId.present ? data.trackId.value : this.trackId, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('SkipSegmentTableData(') + ..write('id: $id, ') + ..write('start: $start, ') + ..write('end: $end, ') + ..write('trackId: $trackId, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, start, end, trackId, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SkipSegmentTableData && + other.id == this.id && + other.start == this.start && + other.end == this.end && + other.trackId == this.trackId && + other.createdAt == this.createdAt); +} + +class SkipSegmentTableCompanion extends UpdateCompanion { + final Value id; + final Value start; + final Value end; + final Value trackId; + final Value createdAt; + const SkipSegmentTableCompanion({ + this.id = const Value.absent(), + this.start = const Value.absent(), + this.end = const Value.absent(), + this.trackId = const Value.absent(), + this.createdAt = const Value.absent(), + }); + SkipSegmentTableCompanion.insert({ + this.id = const Value.absent(), + required int start, + required int end, + required String trackId, + this.createdAt = const Value.absent(), + }) : start = Value(start), + end = Value(end), + trackId = Value(trackId); + static Insertable custom({ + Expression? id, + Expression? start, + Expression? end, + Expression? trackId, + Expression? createdAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (start != null) 'start': start, + if (end != null) 'end': end, + if (trackId != null) 'track_id': trackId, + if (createdAt != null) 'created_at': createdAt, + }); + } + + SkipSegmentTableCompanion copyWith( + {Value? id, + Value? start, + Value? end, + Value? trackId, + Value? createdAt}) { + return SkipSegmentTableCompanion( + id: id ?? this.id, + start: start ?? this.start, + end: end ?? this.end, + trackId: trackId ?? this.trackId, + createdAt: createdAt ?? this.createdAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (start.present) { + map['start'] = Variable(start.value); + } + if (end.present) { + map['end'] = Variable(end.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SkipSegmentTableCompanion(') + ..write('id: $id, ') + ..write('start: $start, ') + ..write('end: $end, ') + ..write('trackId: $trackId, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } +} + +class SourceMatchTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + SourceMatchTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn sourceId = GeneratedColumn( + 'source_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn sourceType = GeneratedColumn( + 'source_type', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: Constant(SourceType.youtube.name)); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => + [id, trackId, sourceId, sourceType, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'source_match_table'; + @override + Set get $primaryKey => {id}; + @override + SourceMatchTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return SourceMatchTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + sourceId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}source_id'])!, + sourceType: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}source_type'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + SourceMatchTable createAlias(String alias) { + return SourceMatchTable(attachedDatabase, alias); + } +} + +class SourceMatchTableData extends DataClass + implements Insertable { + final int id; + final String trackId; + final String sourceId; + final String sourceType; + final DateTime createdAt; + const SourceMatchTableData( + {required this.id, + required this.trackId, + required this.sourceId, + required this.sourceType, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['track_id'] = Variable(trackId); + map['source_id'] = Variable(sourceId); + map['source_type'] = Variable(sourceType); + map['created_at'] = Variable(createdAt); + return map; + } + + SourceMatchTableCompanion toCompanion(bool nullToAbsent) { + return SourceMatchTableCompanion( + id: Value(id), + trackId: Value(trackId), + sourceId: Value(sourceId), + sourceType: Value(sourceType), + createdAt: Value(createdAt), + ); + } + + factory SourceMatchTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return SourceMatchTableData( + id: serializer.fromJson(json['id']), + trackId: serializer.fromJson(json['trackId']), + sourceId: serializer.fromJson(json['sourceId']), + sourceType: serializer.fromJson(json['sourceType']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'trackId': serializer.toJson(trackId), + 'sourceId': serializer.toJson(sourceId), + 'sourceType': serializer.toJson(sourceType), + 'createdAt': serializer.toJson(createdAt), + }; + } + + SourceMatchTableData copyWith( + {int? id, + String? trackId, + String? sourceId, + String? sourceType, + DateTime? createdAt}) => + SourceMatchTableData( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + sourceId: sourceId ?? this.sourceId, + sourceType: sourceType ?? this.sourceType, + createdAt: createdAt ?? this.createdAt, + ); + SourceMatchTableData copyWithCompanion(SourceMatchTableCompanion data) { + return SourceMatchTableData( + id: data.id.present ? data.id.value : this.id, + trackId: data.trackId.present ? data.trackId.value : this.trackId, + sourceId: data.sourceId.present ? data.sourceId.value : this.sourceId, + sourceType: + data.sourceType.present ? data.sourceType.value : this.sourceType, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('SourceMatchTableData(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('sourceId: $sourceId, ') + ..write('sourceType: $sourceType, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, trackId, sourceId, sourceType, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is SourceMatchTableData && + other.id == this.id && + other.trackId == this.trackId && + other.sourceId == this.sourceId && + other.sourceType == this.sourceType && + other.createdAt == this.createdAt); +} + +class SourceMatchTableCompanion extends UpdateCompanion { + final Value id; + final Value trackId; + final Value sourceId; + final Value sourceType; + final Value createdAt; + const SourceMatchTableCompanion({ + this.id = const Value.absent(), + this.trackId = const Value.absent(), + this.sourceId = const Value.absent(), + this.sourceType = const Value.absent(), + this.createdAt = const Value.absent(), + }); + SourceMatchTableCompanion.insert({ + this.id = const Value.absent(), + required String trackId, + required String sourceId, + this.sourceType = const Value.absent(), + this.createdAt = const Value.absent(), + }) : trackId = Value(trackId), + sourceId = Value(sourceId); + static Insertable custom({ + Expression? id, + Expression? trackId, + Expression? sourceId, + Expression? sourceType, + Expression? createdAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (trackId != null) 'track_id': trackId, + if (sourceId != null) 'source_id': sourceId, + if (sourceType != null) 'source_type': sourceType, + if (createdAt != null) 'created_at': createdAt, + }); + } + + SourceMatchTableCompanion copyWith( + {Value? id, + Value? trackId, + Value? sourceId, + Value? sourceType, + Value? createdAt}) { + return SourceMatchTableCompanion( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + sourceId: sourceId ?? this.sourceId, + sourceType: sourceType ?? this.sourceType, + createdAt: createdAt ?? this.createdAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (sourceId.present) { + map['source_id'] = Variable(sourceId.value); + } + if (sourceType.present) { + map['source_type'] = Variable(sourceType.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('SourceMatchTableCompanion(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('sourceId: $sourceId, ') + ..write('sourceType: $sourceType, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } +} + +class AudioPlayerStateTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AudioPlayerStateTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn playing = GeneratedColumn( + 'playing', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("playing" IN (0, 1))')); + late final GeneratedColumn loopMode = GeneratedColumn( + 'loop_mode', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn shuffled = GeneratedColumn( + 'shuffled', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("shuffled" IN (0, 1))')); + late final GeneratedColumn collections = GeneratedColumn( + 'collections', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => + [id, playing, loopMode, shuffled, collections]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'audio_player_state_table'; + @override + Set get $primaryKey => {id}; + @override + AudioPlayerStateTableData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AudioPlayerStateTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + playing: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}playing'])!, + loopMode: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}loop_mode'])!, + shuffled: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}shuffled'])!, + collections: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}collections'])!, + ); + } + + @override + AudioPlayerStateTable createAlias(String alias) { + return AudioPlayerStateTable(attachedDatabase, alias); + } +} + +class AudioPlayerStateTableData extends DataClass + implements Insertable { + final int id; + final bool playing; + final String loopMode; + final bool shuffled; + final String collections; + const AudioPlayerStateTableData( + {required this.id, + required this.playing, + required this.loopMode, + required this.shuffled, + required this.collections}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['playing'] = Variable(playing); + map['loop_mode'] = Variable(loopMode); + map['shuffled'] = Variable(shuffled); + map['collections'] = Variable(collections); + return map; + } + + AudioPlayerStateTableCompanion toCompanion(bool nullToAbsent) { + return AudioPlayerStateTableCompanion( + id: Value(id), + playing: Value(playing), + loopMode: Value(loopMode), + shuffled: Value(shuffled), + collections: Value(collections), + ); + } + + factory AudioPlayerStateTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AudioPlayerStateTableData( + id: serializer.fromJson(json['id']), + playing: serializer.fromJson(json['playing']), + loopMode: serializer.fromJson(json['loopMode']), + shuffled: serializer.fromJson(json['shuffled']), + collections: serializer.fromJson(json['collections']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'playing': serializer.toJson(playing), + 'loopMode': serializer.toJson(loopMode), + 'shuffled': serializer.toJson(shuffled), + 'collections': serializer.toJson(collections), + }; + } + + AudioPlayerStateTableData copyWith( + {int? id, + bool? playing, + String? loopMode, + bool? shuffled, + String? collections}) => + AudioPlayerStateTableData( + id: id ?? this.id, + playing: playing ?? this.playing, + loopMode: loopMode ?? this.loopMode, + shuffled: shuffled ?? this.shuffled, + collections: collections ?? this.collections, + ); + AudioPlayerStateTableData copyWithCompanion( + AudioPlayerStateTableCompanion data) { + return AudioPlayerStateTableData( + id: data.id.present ? data.id.value : this.id, + playing: data.playing.present ? data.playing.value : this.playing, + loopMode: data.loopMode.present ? data.loopMode.value : this.loopMode, + shuffled: data.shuffled.present ? data.shuffled.value : this.shuffled, + collections: + data.collections.present ? data.collections.value : this.collections, + ); + } + + @override + String toString() { + return (StringBuffer('AudioPlayerStateTableData(') + ..write('id: $id, ') + ..write('playing: $playing, ') + ..write('loopMode: $loopMode, ') + ..write('shuffled: $shuffled, ') + ..write('collections: $collections') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, playing, loopMode, shuffled, collections); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AudioPlayerStateTableData && + other.id == this.id && + other.playing == this.playing && + other.loopMode == this.loopMode && + other.shuffled == this.shuffled && + other.collections == this.collections); +} + +class AudioPlayerStateTableCompanion + extends UpdateCompanion { + final Value id; + final Value playing; + final Value loopMode; + final Value shuffled; + final Value collections; + const AudioPlayerStateTableCompanion({ + this.id = const Value.absent(), + this.playing = const Value.absent(), + this.loopMode = const Value.absent(), + this.shuffled = const Value.absent(), + this.collections = const Value.absent(), + }); + AudioPlayerStateTableCompanion.insert({ + this.id = const Value.absent(), + required bool playing, + required String loopMode, + required bool shuffled, + required String collections, + }) : playing = Value(playing), + loopMode = Value(loopMode), + shuffled = Value(shuffled), + collections = Value(collections); + static Insertable custom({ + Expression? id, + Expression? playing, + Expression? loopMode, + Expression? shuffled, + Expression? collections, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (playing != null) 'playing': playing, + if (loopMode != null) 'loop_mode': loopMode, + if (shuffled != null) 'shuffled': shuffled, + if (collections != null) 'collections': collections, + }); + } + + AudioPlayerStateTableCompanion copyWith( + {Value? id, + Value? playing, + Value? loopMode, + Value? shuffled, + Value? collections}) { + return AudioPlayerStateTableCompanion( + id: id ?? this.id, + playing: playing ?? this.playing, + loopMode: loopMode ?? this.loopMode, + shuffled: shuffled ?? this.shuffled, + collections: collections ?? this.collections, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (playing.present) { + map['playing'] = Variable(playing.value); + } + if (loopMode.present) { + map['loop_mode'] = Variable(loopMode.value); + } + if (shuffled.present) { + map['shuffled'] = Variable(shuffled.value); + } + if (collections.present) { + map['collections'] = Variable(collections.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AudioPlayerStateTableCompanion(') + ..write('id: $id, ') + ..write('playing: $playing, ') + ..write('loopMode: $loopMode, ') + ..write('shuffled: $shuffled, ') + ..write('collections: $collections') + ..write(')')) + .toString(); + } +} + +class PlaylistTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PlaylistTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn audioPlayerStateId = GeneratedColumn( + 'audio_player_state_id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES audio_player_state_table (id)')); + late final GeneratedColumn index = GeneratedColumn( + 'index', aliasedName, false, + type: DriftSqlType.int, requiredDuringInsert: true); + @override + List get $columns => [id, audioPlayerStateId, index]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'playlist_table'; + @override + Set get $primaryKey => {id}; + @override + PlaylistTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PlaylistTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + audioPlayerStateId: attachedDatabase.typeMapping.read( + DriftSqlType.int, data['${effectivePrefix}audio_player_state_id'])!, + index: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}index'])!, + ); + } + + @override + PlaylistTable createAlias(String alias) { + return PlaylistTable(attachedDatabase, alias); + } +} + +class PlaylistTableData extends DataClass + implements Insertable { + final int id; + final int audioPlayerStateId; + final int index; + const PlaylistTableData( + {required this.id, + required this.audioPlayerStateId, + required this.index}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['audio_player_state_id'] = Variable(audioPlayerStateId); + map['index'] = Variable(index); + return map; + } + + PlaylistTableCompanion toCompanion(bool nullToAbsent) { + return PlaylistTableCompanion( + id: Value(id), + audioPlayerStateId: Value(audioPlayerStateId), + index: Value(index), + ); + } + + factory PlaylistTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PlaylistTableData( + id: serializer.fromJson(json['id']), + audioPlayerStateId: serializer.fromJson(json['audioPlayerStateId']), + index: serializer.fromJson(json['index']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'audioPlayerStateId': serializer.toJson(audioPlayerStateId), + 'index': serializer.toJson(index), + }; + } + + PlaylistTableData copyWith({int? id, int? audioPlayerStateId, int? index}) => + PlaylistTableData( + id: id ?? this.id, + audioPlayerStateId: audioPlayerStateId ?? this.audioPlayerStateId, + index: index ?? this.index, + ); + PlaylistTableData copyWithCompanion(PlaylistTableCompanion data) { + return PlaylistTableData( + id: data.id.present ? data.id.value : this.id, + audioPlayerStateId: data.audioPlayerStateId.present + ? data.audioPlayerStateId.value + : this.audioPlayerStateId, + index: data.index.present ? data.index.value : this.index, + ); + } + + @override + String toString() { + return (StringBuffer('PlaylistTableData(') + ..write('id: $id, ') + ..write('audioPlayerStateId: $audioPlayerStateId, ') + ..write('index: $index') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, audioPlayerStateId, index); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PlaylistTableData && + other.id == this.id && + other.audioPlayerStateId == this.audioPlayerStateId && + other.index == this.index); +} + +class PlaylistTableCompanion extends UpdateCompanion { + final Value id; + final Value audioPlayerStateId; + final Value index; + const PlaylistTableCompanion({ + this.id = const Value.absent(), + this.audioPlayerStateId = const Value.absent(), + this.index = const Value.absent(), + }); + PlaylistTableCompanion.insert({ + this.id = const Value.absent(), + required int audioPlayerStateId, + required int index, + }) : audioPlayerStateId = Value(audioPlayerStateId), + index = Value(index); + static Insertable custom({ + Expression? id, + Expression? audioPlayerStateId, + Expression? index, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (audioPlayerStateId != null) + 'audio_player_state_id': audioPlayerStateId, + if (index != null) 'index': index, + }); + } + + PlaylistTableCompanion copyWith( + {Value? id, Value? audioPlayerStateId, Value? index}) { + return PlaylistTableCompanion( + id: id ?? this.id, + audioPlayerStateId: audioPlayerStateId ?? this.audioPlayerStateId, + index: index ?? this.index, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (audioPlayerStateId.present) { + map['audio_player_state_id'] = Variable(audioPlayerStateId.value); + } + if (index.present) { + map['index'] = Variable(index.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PlaylistTableCompanion(') + ..write('id: $id, ') + ..write('audioPlayerStateId: $audioPlayerStateId, ') + ..write('index: $index') + ..write(')')) + .toString(); + } +} + +class PlaylistMediaTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PlaylistMediaTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn playlistId = GeneratedColumn( + 'playlist_id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES playlist_table (id)')); + late final GeneratedColumn uri = GeneratedColumn( + 'uri', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn extras = GeneratedColumn( + 'extras', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + late final GeneratedColumn httpHeaders = GeneratedColumn( + 'http_headers', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false); + @override + List get $columns => + [id, playlistId, uri, extras, httpHeaders]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'playlist_media_table'; + @override + Set get $primaryKey => {id}; + @override + PlaylistMediaTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PlaylistMediaTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + playlistId: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}playlist_id'])!, + uri: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}uri'])!, + extras: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extras']), + httpHeaders: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}http_headers']), + ); + } + + @override + PlaylistMediaTable createAlias(String alias) { + return PlaylistMediaTable(attachedDatabase, alias); + } +} + +class PlaylistMediaTableData extends DataClass + implements Insertable { + final int id; + final int playlistId; + final String uri; + final String? extras; + final String? httpHeaders; + const PlaylistMediaTableData( + {required this.id, + required this.playlistId, + required this.uri, + this.extras, + this.httpHeaders}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['playlist_id'] = Variable(playlistId); + map['uri'] = Variable(uri); + if (!nullToAbsent || extras != null) { + map['extras'] = Variable(extras); + } + if (!nullToAbsent || httpHeaders != null) { + map['http_headers'] = Variable(httpHeaders); + } + return map; + } + + PlaylistMediaTableCompanion toCompanion(bool nullToAbsent) { + return PlaylistMediaTableCompanion( + id: Value(id), + playlistId: Value(playlistId), + uri: Value(uri), + extras: + extras == null && nullToAbsent ? const Value.absent() : Value(extras), + httpHeaders: httpHeaders == null && nullToAbsent + ? const Value.absent() + : Value(httpHeaders), + ); + } + + factory PlaylistMediaTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PlaylistMediaTableData( + id: serializer.fromJson(json['id']), + playlistId: serializer.fromJson(json['playlistId']), + uri: serializer.fromJson(json['uri']), + extras: serializer.fromJson(json['extras']), + httpHeaders: serializer.fromJson(json['httpHeaders']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'playlistId': serializer.toJson(playlistId), + 'uri': serializer.toJson(uri), + 'extras': serializer.toJson(extras), + 'httpHeaders': serializer.toJson(httpHeaders), + }; + } + + PlaylistMediaTableData copyWith( + {int? id, + int? playlistId, + String? uri, + Value extras = const Value.absent(), + Value httpHeaders = const Value.absent()}) => + PlaylistMediaTableData( + id: id ?? this.id, + playlistId: playlistId ?? this.playlistId, + uri: uri ?? this.uri, + extras: extras.present ? extras.value : this.extras, + httpHeaders: httpHeaders.present ? httpHeaders.value : this.httpHeaders, + ); + PlaylistMediaTableData copyWithCompanion(PlaylistMediaTableCompanion data) { + return PlaylistMediaTableData( + id: data.id.present ? data.id.value : this.id, + playlistId: + data.playlistId.present ? data.playlistId.value : this.playlistId, + uri: data.uri.present ? data.uri.value : this.uri, + extras: data.extras.present ? data.extras.value : this.extras, + httpHeaders: + data.httpHeaders.present ? data.httpHeaders.value : this.httpHeaders, + ); + } + + @override + String toString() { + return (StringBuffer('PlaylistMediaTableData(') + ..write('id: $id, ') + ..write('playlistId: $playlistId, ') + ..write('uri: $uri, ') + ..write('extras: $extras, ') + ..write('httpHeaders: $httpHeaders') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, playlistId, uri, extras, httpHeaders); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PlaylistMediaTableData && + other.id == this.id && + other.playlistId == this.playlistId && + other.uri == this.uri && + other.extras == this.extras && + other.httpHeaders == this.httpHeaders); +} + +class PlaylistMediaTableCompanion + extends UpdateCompanion { + final Value id; + final Value playlistId; + final Value uri; + final Value extras; + final Value httpHeaders; + const PlaylistMediaTableCompanion({ + this.id = const Value.absent(), + this.playlistId = const Value.absent(), + this.uri = const Value.absent(), + this.extras = const Value.absent(), + this.httpHeaders = const Value.absent(), + }); + PlaylistMediaTableCompanion.insert({ + this.id = const Value.absent(), + required int playlistId, + required String uri, + this.extras = const Value.absent(), + this.httpHeaders = const Value.absent(), + }) : playlistId = Value(playlistId), + uri = Value(uri); + static Insertable custom({ + Expression? id, + Expression? playlistId, + Expression? uri, + Expression? extras, + Expression? httpHeaders, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (playlistId != null) 'playlist_id': playlistId, + if (uri != null) 'uri': uri, + if (extras != null) 'extras': extras, + if (httpHeaders != null) 'http_headers': httpHeaders, + }); + } + + PlaylistMediaTableCompanion copyWith( + {Value? id, + Value? playlistId, + Value? uri, + Value? extras, + Value? httpHeaders}) { + return PlaylistMediaTableCompanion( + id: id ?? this.id, + playlistId: playlistId ?? this.playlistId, + uri: uri ?? this.uri, + extras: extras ?? this.extras, + httpHeaders: httpHeaders ?? this.httpHeaders, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (playlistId.present) { + map['playlist_id'] = Variable(playlistId.value); + } + if (uri.present) { + map['uri'] = Variable(uri.value); + } + if (extras.present) { + map['extras'] = Variable(extras.value); + } + if (httpHeaders.present) { + map['http_headers'] = Variable(httpHeaders.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PlaylistMediaTableCompanion(') + ..write('id: $id, ') + ..write('playlistId: $playlistId, ') + ..write('uri: $uri, ') + ..write('extras: $extras, ') + ..write('httpHeaders: $httpHeaders') + ..write(')')) + .toString(); + } +} + +class HistoryTable extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + HistoryTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + late final GeneratedColumn type = GeneratedColumn( + 'type', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn itemId = GeneratedColumn( + 'item_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, createdAt, type, itemId, data]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'history_table'; + @override + Set get $primaryKey => {id}; + @override + HistoryTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return HistoryTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + type: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}type'])!, + itemId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}item_id'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + ); + } + + @override + HistoryTable createAlias(String alias) { + return HistoryTable(attachedDatabase, alias); + } +} + +class HistoryTableData extends DataClass + implements Insertable { + final int id; + final DateTime createdAt; + final String type; + final String itemId; + final String data; + const HistoryTableData( + {required this.id, + required this.createdAt, + required this.type, + required this.itemId, + required this.data}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['type'] = Variable(type); + map['item_id'] = Variable(itemId); + map['data'] = Variable(data); + return map; + } + + HistoryTableCompanion toCompanion(bool nullToAbsent) { + return HistoryTableCompanion( + id: Value(id), + createdAt: Value(createdAt), + type: Value(type), + itemId: Value(itemId), + data: Value(data), + ); + } + + factory HistoryTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return HistoryTableData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + type: serializer.fromJson(json['type']), + itemId: serializer.fromJson(json['itemId']), + data: serializer.fromJson(json['data']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'type': serializer.toJson(type), + 'itemId': serializer.toJson(itemId), + 'data': serializer.toJson(data), + }; + } + + HistoryTableData copyWith( + {int? id, + DateTime? createdAt, + String? type, + String? itemId, + String? data}) => + HistoryTableData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + type: type ?? this.type, + itemId: itemId ?? this.itemId, + data: data ?? this.data, + ); + HistoryTableData copyWithCompanion(HistoryTableCompanion data) { + return HistoryTableData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + type: data.type.present ? data.type.value : this.type, + itemId: data.itemId.present ? data.itemId.value : this.itemId, + data: data.data.present ? data.data.value : this.data, + ); + } + + @override + String toString() { + return (StringBuffer('HistoryTableData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('type: $type, ') + ..write('itemId: $itemId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, createdAt, type, itemId, data); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is HistoryTableData && + other.id == this.id && + other.createdAt == this.createdAt && + other.type == this.type && + other.itemId == this.itemId && + other.data == this.data); +} + +class HistoryTableCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value type; + final Value itemId; + final Value data; + const HistoryTableCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.type = const Value.absent(), + this.itemId = const Value.absent(), + this.data = const Value.absent(), + }); + HistoryTableCompanion.insert({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + required String type, + required String itemId, + required String data, + }) : type = Value(type), + itemId = Value(itemId), + data = Value(data); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? type, + Expression? itemId, + Expression? data, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (type != null) 'type': type, + if (itemId != null) 'item_id': itemId, + if (data != null) 'data': data, + }); + } + + HistoryTableCompanion copyWith( + {Value? id, + Value? createdAt, + Value? type, + Value? itemId, + Value? data}) { + return HistoryTableCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + type: type ?? this.type, + itemId: itemId ?? this.itemId, + data: data ?? this.data, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (itemId.present) { + map['item_id'] = Variable(itemId.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('HistoryTableCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('type: $type, ') + ..write('itemId: $itemId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } +} + +class LyricsTable extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LyricsTable(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + late final GeneratedColumn trackId = GeneratedColumn( + 'track_id', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + late final GeneratedColumn data = GeneratedColumn( + 'data', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + @override + List get $columns => [id, trackId, data]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'lyrics_table'; + @override + Set get $primaryKey => {id}; + @override + LyricsTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LyricsTableData( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + trackId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}track_id'])!, + data: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}data'])!, + ); + } + + @override + LyricsTable createAlias(String alias) { + return LyricsTable(attachedDatabase, alias); + } +} + +class LyricsTableData extends DataClass implements Insertable { + final int id; + final String trackId; + final String data; + const LyricsTableData( + {required this.id, required this.trackId, required this.data}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['track_id'] = Variable(trackId); + map['data'] = Variable(data); + return map; + } + + LyricsTableCompanion toCompanion(bool nullToAbsent) { + return LyricsTableCompanion( + id: Value(id), + trackId: Value(trackId), + data: Value(data), + ); + } + + factory LyricsTableData.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LyricsTableData( + id: serializer.fromJson(json['id']), + trackId: serializer.fromJson(json['trackId']), + data: serializer.fromJson(json['data']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'trackId': serializer.toJson(trackId), + 'data': serializer.toJson(data), + }; + } + + LyricsTableData copyWith({int? id, String? trackId, String? data}) => + LyricsTableData( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + data: data ?? this.data, + ); + LyricsTableData copyWithCompanion(LyricsTableCompanion data) { + return LyricsTableData( + id: data.id.present ? data.id.value : this.id, + trackId: data.trackId.present ? data.trackId.value : this.trackId, + data: data.data.present ? data.data.value : this.data, + ); + } + + @override + String toString() { + return (StringBuffer('LyricsTableData(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, trackId, data); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LyricsTableData && + other.id == this.id && + other.trackId == this.trackId && + other.data == this.data); +} + +class LyricsTableCompanion extends UpdateCompanion { + final Value id; + final Value trackId; + final Value data; + const LyricsTableCompanion({ + this.id = const Value.absent(), + this.trackId = const Value.absent(), + this.data = const Value.absent(), + }); + LyricsTableCompanion.insert({ + this.id = const Value.absent(), + required String trackId, + required String data, + }) : trackId = Value(trackId), + data = Value(data); + static Insertable custom({ + Expression? id, + Expression? trackId, + Expression? data, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (trackId != null) 'track_id': trackId, + if (data != null) 'data': data, + }); + } + + LyricsTableCompanion copyWith( + {Value? id, Value? trackId, Value? data}) { + return LyricsTableCompanion( + id: id ?? this.id, + trackId: trackId ?? this.trackId, + data: data ?? this.data, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (trackId.present) { + map['track_id'] = Variable(trackId.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LyricsTableCompanion(') + ..write('id: $id, ') + ..write('trackId: $trackId, ') + ..write('data: $data') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV6 extends GeneratedDatabase { + DatabaseAtV6(QueryExecutor e) : super(e); + late final AuthenticationTable authenticationTable = + AuthenticationTable(this); + late final BlacklistTable blacklistTable = BlacklistTable(this); + late final PreferencesTable preferencesTable = PreferencesTable(this); + late final ScrobblerTable scrobblerTable = ScrobblerTable(this); + late final SkipSegmentTable skipSegmentTable = SkipSegmentTable(this); + late final SourceMatchTable sourceMatchTable = SourceMatchTable(this); + late final AudioPlayerStateTable audioPlayerStateTable = + AudioPlayerStateTable(this); + late final PlaylistTable playlistTable = PlaylistTable(this); + late final PlaylistMediaTable playlistMediaTable = PlaylistMediaTable(this); + late final HistoryTable historyTable = HistoryTable(this); + late final LyricsTable lyricsTable = LyricsTable(this); + late final Index uniqueBlacklist = Index('unique_blacklist', + 'CREATE UNIQUE INDEX unique_blacklist ON blacklist_table (element_type, element_id)'); + late final Index uniqTrackMatch = Index('uniq_track_match', + 'CREATE UNIQUE INDEX uniq_track_match ON source_match_table (track_id, source_id, source_type)'); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + authenticationTable, + blacklistTable, + preferencesTable, + scrobblerTable, + skipSegmentTable, + sourceMatchTable, + audioPlayerStateTable, + playlistTable, + playlistMediaTable, + historyTable, + lyricsTable, + uniqueBlacklist, + uniqTrackMatch + ]; + @override + int get schemaVersion => 6; +} diff --git a/untranslated_messages.json b/untranslated_messages.json index 9e26dfee..7c1927da 100644 --- a/untranslated_messages.json +++ b/untranslated_messages.json @@ -1 +1,5 @@ -{} \ No newline at end of file +{ + "fr": [ + "connection_request_denied" + ] +} diff --git a/web/index.html b/web/index.html index 59b9a339..09232aa5 100644 --- a/web/index.html +++ b/web/index.html @@ -32,6 +32,12 @@ + + + + + +