diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index edac498..fdde745 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,10 +1,14 @@ - + + + + + + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" + /> - - + + + + + + + + + + + + + + + - - + + - + \ No newline at end of file diff --git a/android/app/src/main/ic_launcher-playstore.png b/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..f3ae518 Binary files /dev/null and b/android/app/src/main/ic_launcher-playstore.png differ diff --git a/android/app/src/main/res/drawable-anydpi/ic_stat_name.xml b/android/app/src/main/res/drawable-anydpi/ic_stat_name.xml new file mode 100644 index 0000000..9d76126 --- /dev/null +++ b/android/app/src/main/res/drawable-anydpi/ic_stat_name.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/android/app/src/main/res/drawable-hdpi/ic_stat_name.png b/android/app/src/main/res/drawable-hdpi/ic_stat_name.png new file mode 100644 index 0000000..fb2a3f4 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/ic_stat_name.png differ diff --git a/android/app/src/main/res/drawable-mdpi/ic_stat_name.png b/android/app/src/main/res/drawable-mdpi/ic_stat_name.png new file mode 100644 index 0000000..a4abbef Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/ic_stat_name.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/ic_stat_name.png b/android/app/src/main/res/drawable-xhdpi/ic_stat_name.png new file mode 100644 index 0000000..19c9ddc Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/ic_stat_name.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_stat_name.png b/android/app/src/main/res/drawable-xxhdpi/ic_stat_name.png new file mode 100644 index 0000000..f58aa1f Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/ic_stat_name.png differ diff --git a/android/app/src/main/res/drawable/ic_launcher_background.xml b/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..ca3826a --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..ffcb604 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,14 @@ + + + + + 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 new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..7353dbd --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4..0000000 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..7bd6309 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..3698920 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..fea0421 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000..dac978b Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/launcher_icon.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 deleted file mode 100644 index 17987b7..0000000 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..f1a7bbf Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..8885078 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..e4210b5 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png new file mode 100644 index 0000000..0e0a3dd Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/launcher_icon.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 deleted file mode 100644 index 09d4391..0000000 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..27446b5 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..56d116d Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b4491d Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png new file mode 100644 index 0000000..98458eb Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.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 deleted file mode 100644 index d5f1c8d..0000000 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..ec97d1a Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..3bfe3c8 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..f2815cc Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png new file mode 100644 index 0000000..245a0f0 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.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 deleted file mode 100644 index 4d6372e..0000000 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..176143f Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000..9f6628d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..c257b68 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png new file mode 100644 index 0000000..0539fd5 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..cad15c8 --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #BD7F44 + \ No newline at end of file diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000..ada9129 Binary files /dev/null and b/assets/icon.png differ diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 884d190..33a5f5c 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -540,7 +540,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -597,7 +597,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; 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 index dc9ada4..aefff76 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png 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 index 7353c41..ea0a97a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png 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 index 797d452..1a60071 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png 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 index 6ed2d93..26f6e91 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png 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 index 4cd7b00..eac57e9 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png 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 index fe73094..8b47f53 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png 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 index 321773c..e90b6ef 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png 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 index 797d452..1a60071 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png 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 index 502f463..530b01c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png 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 index 0ec3034..ae65a03 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png 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 0000000..971149c 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 0000000..1d2bcf7 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 0000000..dd27983 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 0000000..0813fb9 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 index 0ec3034..ae65a03 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png 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 index e9f5fea..16ff1d1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png 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 0000000..e2a75b4 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 0000000..a3b4614 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 index 84ac32a..125ddee 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png 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 index 8953cba..1e6583a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png 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 index 0467bf1..6ecee5a 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/lib/providers/audio_player.dart b/lib/providers/audio_player.dart index 8356432..553dee8 100644 --- a/lib/providers/audio_player.dart +++ b/lib/providers/audio_player.dart @@ -1,19 +1,16 @@ import 'dart:async'; -import 'dart:convert'; import 'dart:math'; -import 'package:get/get.dart'; +import 'package:drift/drift.dart'; +import 'package:get/get.dart' hide Value; import 'package:media_kit/media_kit.dart' hide Track; +import 'package:rhythm_box/providers/database.dart'; import 'package:rhythm_box/services/audio_player/state.dart'; -import 'package:rhythm_box/services/local_track.dart'; -import 'package:rhythm_box/services/server/sourced_track.dart'; +import 'package:rhythm_box/services/database/database.dart'; import 'package:spotify/spotify.dart' hide Playlist; import 'package:rhythm_box/services/audio_player/audio_player.dart'; -import 'package:shared_preferences/shared_preferences.dart'; class AudioPlayerProvider extends GetxController { - late final SharedPreferences _prefs; - RxBool isPlaying = false.obs; Rx state = Rx(AudioPlayerState( @@ -28,41 +25,39 @@ class AudioPlayerProvider extends GetxController { @override void onInit() { - SharedPreferences.getInstance().then((ins) async { - _prefs = ins; - final res = await _readSavedState(); - if (res != null) { - state.value = res; - } else { - state.value = AudioPlayerState( - loopMode: audioPlayer.loopMode, - playing: audioPlayer.isPlaying, - playlist: audioPlayer.playlist, - shuffled: audioPlayer.isShuffled, - collections: [], - ); - } - }); - _subscriptions = [ audioPlayer.playingStream.listen((playing) async { state.value = state.value.copyWith(playing: playing); - await _updateSavedState(); + await _updatePlayerState( + AudioPlayerStateTableCompanion( + playing: Value(playing), + ), + ); }), audioPlayer.loopModeStream.listen((loopMode) async { state.value = state.value.copyWith(loopMode: loopMode); - await _updateSavedState(); + await _updatePlayerState( + AudioPlayerStateTableCompanion( + loopMode: Value(loopMode), + ), + ); }), audioPlayer.shuffledStream.listen((shuffled) async { state.value = state.value.copyWith(shuffled: shuffled); - await _updateSavedState(); + await _updatePlayerState( + AudioPlayerStateTableCompanion( + shuffled: Value(shuffled), + ), + ); }), audioPlayer.playlistStream.listen((playlist) async { state.value = state.value.copyWith(playlist: playlist); - await _updateSavedState(); + await _updatePlaylist(playlist); }), ]; + _readSavedState(); + audioPlayer.playingStream.listen((playing) { isPlaying.value = playing; }); @@ -80,16 +75,124 @@ class AudioPlayerProvider extends GetxController { super.dispose(); } - Future _readSavedState() async { - final data = _prefs.getString('player_state'); - if (data == null) return null; + Future _readSavedState() async { + final database = Get.find().database; - return AudioPlayerState.fromJson(jsonDecode(data)); + var playerState = + await database.select(database.audioPlayerStateTable).getSingleOrNull(); + + if (playerState == null) { + await database.into(database.audioPlayerStateTable).insert( + AudioPlayerStateTableCompanion.insert( + playing: audioPlayer.isPlaying, + loopMode: audioPlayer.loopMode, + shuffled: audioPlayer.isShuffled, + collections: [], + id: const Value(0), + ), + ); + + playerState = + await database.select(database.audioPlayerStateTable).getSingle(); + } else { + await audioPlayer.setLoopMode(playerState.loopMode); + await audioPlayer.setShuffle(playerState.shuffled); + } + + var playlist = + await database.select(database.playlistTable).getSingleOrNull(); + var medias = await database.select(database.playlistMediaTable).get(); + + if (playlist == null) { + await database.into(database.playlistTable).insert( + PlaylistTableCompanion.insert( + audioPlayerStateId: 0, + index: audioPlayer.playlist.index, + id: const Value(0), + ), + ); + + playlist = await database.select(database.playlistTable).getSingle(); + } + + if (medias.isEmpty && audioPlayer.playlist.medias.isNotEmpty) { + await database.batch((batch) { + batch.insertAll( + database.playlistMediaTable, + [ + for (final media in audioPlayer.playlist.medias) + PlaylistMediaTableCompanion.insert( + playlistId: playlist!.id, + uri: media.uri, + extras: Value(media.extras), + httpHeaders: Value(media.httpHeaders), + ), + ], + ); + }); + } else if (medias.isNotEmpty) { + await audioPlayer.openPlaylist( + medias + .map( + (media) => RhythmMedia.fromMedia( + Media( + media.uri, + extras: media.extras, + httpHeaders: media.httpHeaders, + ), + ), + ) + .toList(), + initialIndex: playlist.index, + autoPlay: false, + ); + } + + if (playerState.collections.isNotEmpty) { + state.value = state.value.copyWith( + collections: playerState.collections, + ); + } } - Future _updateSavedState() async { - final out = jsonEncode(state.value.toJson()); - await _prefs.setString('player_state', out); + Future _updatePlayerState( + AudioPlayerStateTableCompanion companion, + ) async { + final database = Get.find().database; + + await (database.update(database.audioPlayerStateTable) + ..where((tb) => tb.id.equals(0))) + .write(companion); + } + + Future _updatePlaylist( + Playlist playlist, + ) async { + final database = Get.find().database; + + await database.batch((batch) { + batch.update( + database.playlistTable, + PlaylistTableCompanion(index: Value(playlist.index)), + where: (tb) => tb.id.equals(0), + ); + + batch.deleteAll(database.playlistMediaTable); + + if (playlist.medias.isEmpty) return; + batch.insertAll( + database.playlistMediaTable, + [ + for (final media in playlist.medias) + PlaylistMediaTableCompanion.insert( + playlistId: 0, + uri: media.uri, + extras: Value(media.extras), + httpHeaders: Value(media.httpHeaders), + ), + ], + ); + }); } Future addCollections(List collectionIds) async { @@ -98,7 +201,11 @@ class AudioPlayerProvider extends GetxController { ...collectionIds, ]); - await _updateSavedState(); + await _updatePlayerState( + AudioPlayerStateTableCompanion( + collections: Value(state.value.collections), + ), + ); } Future addCollection(String collectionId) async { @@ -112,7 +219,11 @@ class AudioPlayerProvider extends GetxController { .toList(), ); - await _updateSavedState(); + await _updatePlayerState( + AudioPlayerStateTableCompanion( + collections: Value(state.value.collections), + ), + ); } Future removeCollection(String collectionId) async { diff --git a/lib/providers/audio_player_stream.dart b/lib/providers/audio_player_stream.dart index 0fe9ac5..cb7eb7d 100644 --- a/lib/providers/audio_player_stream.dart +++ b/lib/providers/audio_player_stream.dart @@ -21,9 +21,16 @@ class AudioPlayerStreamProvider extends GetxController { List? _subscriptions; AudioPlayerStreamProvider() { - AudioServices.create().then( - (value) => notificationService = value, - ); + _initNotificationService(); + } + + Future _initNotificationService() async { + try { + final res = await AudioServices.create(); + notificationService = res; + } catch (err) { + log('[AudioService] Unable to init audio service: $err'); + } } @override @@ -50,7 +57,7 @@ class AudioPlayerStreamProvider extends GetxController { } Future updatePalette() async { - if (!Get.find().albumColorSync) { + if (!Get.find().state.value.albumColorSync) { if (palette.value != null) { palette.value = null; } diff --git a/lib/screens/player/view.dart b/lib/screens/player/view.dart index dd109c0..bcfd40c 100644 --- a/lib/screens/player/view.dart +++ b/lib/screens/player/view.dart @@ -155,7 +155,10 @@ class _PlayerScreenState extends State { ), child: Slider( value: _draggingValue ?? - _durationCurrent.inMilliseconds.toDouble(), + (_durationCurrent.inMilliseconds <= + _durationTotal.inMilliseconds + ? _durationCurrent.inMilliseconds.toDouble() + : 0), min: 0, max: _durationTotal.inMilliseconds.toDouble(), onChanged: (value) { diff --git a/lib/services/audio_services/audio_services.dart b/lib/services/audio_services/audio_services.dart index 0e43e84..e49019e 100755 --- a/lib/services/audio_services/audio_services.dart +++ b/lib/services/audio_services/audio_services.dart @@ -27,7 +27,7 @@ class AudioServices with WidgetsBindingObserver { : 'dev.solsynth.rhythmBox', androidNotificationChannelName: 'RhythmBox', androidNotificationOngoing: false, - androidNotificationIcon: 'drawable/ic_launcher_monochrome', + androidNotificationIcon: 'drawable/ic_stat_name', androidStopForegroundOnPause: false, androidNotificationChannelDescription: 'RhythmBox Music', ), diff --git a/lib/services/database/database.dart b/lib/services/database/database.dart index dce8791..fc2fffc 100755 --- a/lib/services/database/database.dart +++ b/lib/services/database/database.dart @@ -5,6 +5,7 @@ import 'dart:io'; import 'package:drift/drift.dart'; import 'package:encrypt/encrypt.dart'; +import 'package:media_kit/media_kit.dart' hide Track; import 'package:path/path.dart'; import 'package:path_provider/path_provider.dart'; import 'package:rhythm_box/services/color.dart'; @@ -27,6 +28,7 @@ part 'tables/skip_segment.dart'; part 'tables/source_match.dart'; part 'tables/history.dart'; part 'tables/lyrics.dart'; +part 'tables/audio_player_state.dart'; part 'typeconverters/color.dart'; part 'typeconverters/locale.dart'; @@ -44,6 +46,9 @@ part 'typeconverters/subtitle.dart'; SourceMatchTable, HistoryTable, LyricsTable, + AudioPlayerStateTable, + PlaylistTable, + PlaylistMediaTable, ], ) class AppDatabase extends _$AppDatabase { diff --git a/lib/services/database/database.g.dart b/lib/services/database/database.g.dart index ea94029..a61f9ac 100644 --- a/lib/services/database/database.g.dart +++ b/lib/services/database/database.g.dart @@ -2951,6 +2951,879 @@ class LyricsTableCompanion extends UpdateCompanion { } } +class $AudioPlayerStateTableTable extends AudioPlayerStateTable + with TableInfo<$AudioPlayerStateTableTable, AudioPlayerStateTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $AudioPlayerStateTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + static const VerificationMeta _playingMeta = + const VerificationMeta('playing'); + @override + late final GeneratedColumn playing = GeneratedColumn( + 'playing', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("playing" IN (0, 1))')); + static const VerificationMeta _loopModeMeta = + const VerificationMeta('loopMode'); + @override + late final GeneratedColumnWithTypeConverter loopMode = + GeneratedColumn('loop_mode', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter( + $AudioPlayerStateTableTable.$converterloopMode); + static const VerificationMeta _shuffledMeta = + const VerificationMeta('shuffled'); + @override + late final GeneratedColumn shuffled = GeneratedColumn( + 'shuffled', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("shuffled" IN (0, 1))')); + static const VerificationMeta _collectionsMeta = + const VerificationMeta('collections'); + @override + late final GeneratedColumnWithTypeConverter, String> + collections = GeneratedColumn('collections', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true) + .withConverter>( + $AudioPlayerStateTableTable.$convertercollections); + @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 + VerificationContext validateIntegrity( + Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } + if (data.containsKey('playing')) { + context.handle(_playingMeta, + playing.isAcceptableOrUnknown(data['playing']!, _playingMeta)); + } else if (isInserting) { + context.missing(_playingMeta); + } + context.handle(_loopModeMeta, const VerificationResult.success()); + if (data.containsKey('shuffled')) { + context.handle(_shuffledMeta, + shuffled.isAcceptableOrUnknown(data['shuffled']!, _shuffledMeta)); + } else if (isInserting) { + context.missing(_shuffledMeta); + } + context.handle(_collectionsMeta, const VerificationResult.success()); + return context; + } + + @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: $AudioPlayerStateTableTable.$converterloopMode.fromSql( + attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}loop_mode'])!), + shuffled: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}shuffled'])!, + collections: $AudioPlayerStateTableTable.$convertercollections.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}collections'])!), + ); + } + + @override + $AudioPlayerStateTableTable createAlias(String alias) { + return $AudioPlayerStateTableTable(attachedDatabase, alias); + } + + static JsonTypeConverter2 $converterloopMode = + const EnumNameConverter(PlaylistMode.values); + static TypeConverter, String> $convertercollections = + const StringListConverter(); +} + +class AudioPlayerStateTableData extends DataClass + implements Insertable { + final int id; + final bool playing; + final PlaylistMode loopMode; + final bool shuffled; + final List 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( + $AudioPlayerStateTableTable.$converterloopMode.toSql(loopMode)); + } + map['shuffled'] = Variable(shuffled); + { + map['collections'] = Variable( + $AudioPlayerStateTableTable.$convertercollections.toSql(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: $AudioPlayerStateTableTable.$converterloopMode + .fromJson(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( + $AudioPlayerStateTableTable.$converterloopMode.toJson(loopMode)), + 'shuffled': serializer.toJson(shuffled), + 'collections': serializer.toJson>(collections), + }; + } + + AudioPlayerStateTableData copyWith( + {int? id, + bool? playing, + PlaylistMode? loopMode, + bool? shuffled, + List? 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 PlaylistMode loopMode, + required bool shuffled, + required List 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( + $AudioPlayerStateTableTable.$converterloopMode.toSql(loopMode.value)); + } + if (shuffled.present) { + map['shuffled'] = Variable(shuffled.value); + } + if (collections.present) { + map['collections'] = Variable($AudioPlayerStateTableTable + .$convertercollections + .toSql(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 $PlaylistTableTable extends PlaylistTable + with TableInfo<$PlaylistTableTable, PlaylistTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $PlaylistTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + static const VerificationMeta _audioPlayerStateIdMeta = + const VerificationMeta('audioPlayerStateId'); + @override + 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)')); + static const VerificationMeta _indexMeta = const VerificationMeta('index'); + @override + 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 + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } + if (data.containsKey('audio_player_state_id')) { + context.handle( + _audioPlayerStateIdMeta, + audioPlayerStateId.isAcceptableOrUnknown( + data['audio_player_state_id']!, _audioPlayerStateIdMeta)); + } else if (isInserting) { + context.missing(_audioPlayerStateIdMeta); + } + if (data.containsKey('index')) { + context.handle( + _indexMeta, index.isAcceptableOrUnknown(data['index']!, _indexMeta)); + } else if (isInserting) { + context.missing(_indexMeta); + } + return context; + } + + @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 + $PlaylistTableTable createAlias(String alias) { + return $PlaylistTableTable(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 $PlaylistMediaTableTable extends PlaylistMediaTable + with TableInfo<$PlaylistMediaTableTable, PlaylistMediaTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $PlaylistMediaTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + static const VerificationMeta _playlistIdMeta = + const VerificationMeta('playlistId'); + @override + late final GeneratedColumn playlistId = GeneratedColumn( + 'playlist_id', aliasedName, false, + type: DriftSqlType.int, + requiredDuringInsert: true, + defaultConstraints: + GeneratedColumn.constraintIsAlways('REFERENCES playlist_table (id)')); + static const VerificationMeta _uriMeta = const VerificationMeta('uri'); + @override + late final GeneratedColumn uri = GeneratedColumn( + 'uri', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _extrasMeta = const VerificationMeta('extras'); + @override + late final GeneratedColumnWithTypeConverter?, String> + extras = GeneratedColumn('extras', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $PlaylistMediaTableTable.$converterextrasn); + static const VerificationMeta _httpHeadersMeta = + const VerificationMeta('httpHeaders'); + @override + late final GeneratedColumnWithTypeConverter?, String> + httpHeaders = GeneratedColumn('http_headers', aliasedName, true, + type: DriftSqlType.string, requiredDuringInsert: false) + .withConverter?>( + $PlaylistMediaTableTable.$converterhttpHeadersn); + @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 + VerificationContext validateIntegrity( + Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } + if (data.containsKey('playlist_id')) { + context.handle( + _playlistIdMeta, + playlistId.isAcceptableOrUnknown( + data['playlist_id']!, _playlistIdMeta)); + } else if (isInserting) { + context.missing(_playlistIdMeta); + } + if (data.containsKey('uri')) { + context.handle( + _uriMeta, uri.isAcceptableOrUnknown(data['uri']!, _uriMeta)); + } else if (isInserting) { + context.missing(_uriMeta); + } + context.handle(_extrasMeta, const VerificationResult.success()); + context.handle(_httpHeadersMeta, const VerificationResult.success()); + return context; + } + + @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: $PlaylistMediaTableTable.$converterextrasn.fromSql( + attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}extras'])), + httpHeaders: $PlaylistMediaTableTable.$converterhttpHeadersn.fromSql( + attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}http_headers'])), + ); + } + + @override + $PlaylistMediaTableTable createAlias(String alias) { + return $PlaylistMediaTableTable(attachedDatabase, alias); + } + + static TypeConverter, String> $converterextras = + const MapTypeConverter(); + static TypeConverter?, String?> $converterextrasn = + NullAwareTypeConverter.wrap($converterextras); + static TypeConverter, String> $converterhttpHeaders = + const MapTypeConverter(); + static TypeConverter?, String?> $converterhttpHeadersn = + NullAwareTypeConverter.wrap($converterhttpHeaders); +} + +class PlaylistMediaTableData extends DataClass + implements Insertable { + final int id; + final int playlistId; + final String uri; + final Map? extras; + final Map? 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( + $PlaylistMediaTableTable.$converterextrasn.toSql(extras)); + } + if (!nullToAbsent || httpHeaders != null) { + map['http_headers'] = Variable( + $PlaylistMediaTableTable.$converterhttpHeadersn.toSql(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( + $PlaylistMediaTableTable.$converterextrasn.toSql(extras.value)); + } + if (httpHeaders.present) { + map['http_headers'] = Variable($PlaylistMediaTableTable + .$converterhttpHeadersn + .toSql(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(); + } +} + abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); $AppDatabaseManager get managers => $AppDatabaseManager(this); @@ -2965,6 +3838,11 @@ abstract class _$AppDatabase extends GeneratedDatabase { $SourceMatchTableTable(this); late final $HistoryTableTable historyTable = $HistoryTableTable(this); late final $LyricsTableTable lyricsTable = $LyricsTableTable(this); + late final $AudioPlayerStateTableTable audioPlayerStateTable = + $AudioPlayerStateTableTable(this); + late final $PlaylistTableTable playlistTable = $PlaylistTableTable(this); + late final $PlaylistMediaTableTable playlistMediaTable = + $PlaylistMediaTableTable(this); 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 @@ -2979,6 +3857,9 @@ abstract class _$AppDatabase extends GeneratedDatabase { sourceMatchTable, historyTable, lyricsTable, + audioPlayerStateTable, + playlistTable, + playlistMediaTable, uniqTrackMatch ]; } @@ -4313,6 +5194,675 @@ typedef $$LyricsTableTableProcessedTableManager = ProcessedTableManager< ), LyricsTableData, PrefetchHooks Function()>; +typedef $$AudioPlayerStateTableTableCreateCompanionBuilder + = AudioPlayerStateTableCompanion Function({ + Value id, + required bool playing, + required PlaylistMode loopMode, + required bool shuffled, + required List collections, +}); +typedef $$AudioPlayerStateTableTableUpdateCompanionBuilder + = AudioPlayerStateTableCompanion Function({ + Value id, + Value playing, + Value loopMode, + Value shuffled, + Value> collections, +}); + +final class $$AudioPlayerStateTableTableReferences extends BaseReferences< + _$AppDatabase, $AudioPlayerStateTableTable, AudioPlayerStateTableData> { + $$AudioPlayerStateTableTableReferences( + super.$_db, super.$_table, super.$_typedResult); + + static MultiTypedResultKey<$PlaylistTableTable, List> + _playlistTableRefsTable(_$AppDatabase db) => + MultiTypedResultKey.fromTable(db.playlistTable, + aliasName: $_aliasNameGenerator(db.audioPlayerStateTable.id, + db.playlistTable.audioPlayerStateId)); + + $$PlaylistTableTableProcessedTableManager get playlistTableRefs { + final manager = $$PlaylistTableTableTableManager($_db, $_db.playlistTable) + .filter((f) => f.audioPlayerStateId.id($_item.id)); + + final cache = $_typedResult.readTableOrNull(_playlistTableRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } +} + +class $$AudioPlayerStateTableTableFilterComposer + extends FilterComposer<_$AppDatabase, $AudioPlayerStateTableTable> { + $$AudioPlayerStateTableTableFilterComposer(super.$state); + ColumnFilters get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get playing => $state.composableBuilder( + column: $state.table.playing, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters + get loopMode => $state.composableBuilder( + column: $state.table.loopMode, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + ColumnFilters get shuffled => $state.composableBuilder( + column: $state.table.shuffled, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters, List, String> + get collections => $state.composableBuilder( + column: $state.table.collections, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + ComposableFilter playlistTableRefs( + ComposableFilter Function($$PlaylistTableTableFilterComposer f) f) { + final $$PlaylistTableTableFilterComposer composer = $state.composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $state.db.playlistTable, + getReferencedColumn: (t) => t.audioPlayerStateId, + builder: (joinBuilder, parentComposers) => + $$PlaylistTableTableFilterComposer(ComposerState($state.db, + $state.db.playlistTable, joinBuilder, parentComposers))); + return f(composer); + } +} + +class $$AudioPlayerStateTableTableOrderingComposer + extends OrderingComposer<_$AppDatabase, $AudioPlayerStateTableTable> { + $$AudioPlayerStateTableTableOrderingComposer(super.$state); + ColumnOrderings get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get playing => $state.composableBuilder( + column: $state.table.playing, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get loopMode => $state.composableBuilder( + column: $state.table.loopMode, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get shuffled => $state.composableBuilder( + column: $state.table.shuffled, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get collections => $state.composableBuilder( + column: $state.table.collections, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); +} + +class $$AudioPlayerStateTableTableTableManager extends RootTableManager< + _$AppDatabase, + $AudioPlayerStateTableTable, + AudioPlayerStateTableData, + $$AudioPlayerStateTableTableFilterComposer, + $$AudioPlayerStateTableTableOrderingComposer, + $$AudioPlayerStateTableTableCreateCompanionBuilder, + $$AudioPlayerStateTableTableUpdateCompanionBuilder, + (AudioPlayerStateTableData, $$AudioPlayerStateTableTableReferences), + AudioPlayerStateTableData, + PrefetchHooks Function({bool playlistTableRefs})> { + $$AudioPlayerStateTableTableTableManager( + _$AppDatabase db, $AudioPlayerStateTableTable table) + : super(TableManagerState( + db: db, + table: table, + filteringComposer: $$AudioPlayerStateTableTableFilterComposer( + ComposerState(db, table)), + orderingComposer: $$AudioPlayerStateTableTableOrderingComposer( + ComposerState(db, table)), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value playing = const Value.absent(), + Value loopMode = const Value.absent(), + Value shuffled = const Value.absent(), + Value> collections = const Value.absent(), + }) => + AudioPlayerStateTableCompanion( + id: id, + playing: playing, + loopMode: loopMode, + shuffled: shuffled, + collections: collections, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required bool playing, + required PlaylistMode loopMode, + required bool shuffled, + required List collections, + }) => + AudioPlayerStateTableCompanion.insert( + id: id, + playing: playing, + loopMode: loopMode, + shuffled: shuffled, + collections: collections, + ), + withReferenceMapper: (p0) => p0 + .map((e) => ( + e.readTable(table), + $$AudioPlayerStateTableTableReferences(db, table, e) + )) + .toList(), + prefetchHooksCallback: ({playlistTableRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [ + if (playlistTableRefs) db.playlistTable + ], + addJoins: null, + getPrefetchedDataCallback: (items) async { + return [ + if (playlistTableRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: $$AudioPlayerStateTableTableReferences + ._playlistTableRefsTable(db), + managerFromTypedResult: (p0) => + $$AudioPlayerStateTableTableReferences( + db, table, p0) + .playlistTableRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.audioPlayerStateId == item.id), + typedResults: items) + ]; + }, + ); + }, + )); +} + +typedef $$AudioPlayerStateTableTableProcessedTableManager + = ProcessedTableManager< + _$AppDatabase, + $AudioPlayerStateTableTable, + AudioPlayerStateTableData, + $$AudioPlayerStateTableTableFilterComposer, + $$AudioPlayerStateTableTableOrderingComposer, + $$AudioPlayerStateTableTableCreateCompanionBuilder, + $$AudioPlayerStateTableTableUpdateCompanionBuilder, + (AudioPlayerStateTableData, $$AudioPlayerStateTableTableReferences), + AudioPlayerStateTableData, + PrefetchHooks Function({bool playlistTableRefs})>; +typedef $$PlaylistTableTableCreateCompanionBuilder = PlaylistTableCompanion + Function({ + Value id, + required int audioPlayerStateId, + required int index, +}); +typedef $$PlaylistTableTableUpdateCompanionBuilder = PlaylistTableCompanion + Function({ + Value id, + Value audioPlayerStateId, + Value index, +}); + +final class $$PlaylistTableTableReferences extends BaseReferences<_$AppDatabase, + $PlaylistTableTable, PlaylistTableData> { + $$PlaylistTableTableReferences( + super.$_db, super.$_table, super.$_typedResult); + + static $AudioPlayerStateTableTable _audioPlayerStateIdTable( + _$AppDatabase db) => + db.audioPlayerStateTable.createAlias($_aliasNameGenerator( + db.playlistTable.audioPlayerStateId, db.audioPlayerStateTable.id)); + + $$AudioPlayerStateTableTableProcessedTableManager? get audioPlayerStateId { + if ($_item.audioPlayerStateId == null) return null; + final manager = $$AudioPlayerStateTableTableTableManager( + $_db, $_db.audioPlayerStateTable) + .filter((f) => f.id($_item.audioPlayerStateId!)); + final item = $_typedResult.readTableOrNull(_audioPlayerStateIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } + + static MultiTypedResultKey<$PlaylistMediaTableTable, + List> _playlistMediaTableRefsTable( + _$AppDatabase db) => + MultiTypedResultKey.fromTable(db.playlistMediaTable, + aliasName: $_aliasNameGenerator( + db.playlistTable.id, db.playlistMediaTable.playlistId)); + + $$PlaylistMediaTableTableProcessedTableManager get playlistMediaTableRefs { + final manager = + $$PlaylistMediaTableTableTableManager($_db, $_db.playlistMediaTable) + .filter((f) => f.playlistId.id($_item.id)); + + final cache = + $_typedResult.readTableOrNull(_playlistMediaTableRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } +} + +class $$PlaylistTableTableFilterComposer + extends FilterComposer<_$AppDatabase, $PlaylistTableTable> { + $$PlaylistTableTableFilterComposer(super.$state); + ColumnFilters get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get index => $state.composableBuilder( + column: $state.table.index, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + $$AudioPlayerStateTableTableFilterComposer get audioPlayerStateId { + final $$AudioPlayerStateTableTableFilterComposer composer = + $state.composerBuilder( + composer: this, + getCurrentColumn: (t) => t.audioPlayerStateId, + referencedTable: $state.db.audioPlayerStateTable, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, parentComposers) => + $$AudioPlayerStateTableTableFilterComposer(ComposerState( + $state.db, + $state.db.audioPlayerStateTable, + joinBuilder, + parentComposers))); + return composer; + } + + ComposableFilter playlistMediaTableRefs( + ComposableFilter Function($$PlaylistMediaTableTableFilterComposer f) f) { + final $$PlaylistMediaTableTableFilterComposer composer = $state + .composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $state.db.playlistMediaTable, + getReferencedColumn: (t) => t.playlistId, + builder: (joinBuilder, parentComposers) => + $$PlaylistMediaTableTableFilterComposer(ComposerState( + $state.db, + $state.db.playlistMediaTable, + joinBuilder, + parentComposers))); + return f(composer); + } +} + +class $$PlaylistTableTableOrderingComposer + extends OrderingComposer<_$AppDatabase, $PlaylistTableTable> { + $$PlaylistTableTableOrderingComposer(super.$state); + ColumnOrderings get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get index => $state.composableBuilder( + column: $state.table.index, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + $$AudioPlayerStateTableTableOrderingComposer get audioPlayerStateId { + final $$AudioPlayerStateTableTableOrderingComposer composer = + $state.composerBuilder( + composer: this, + getCurrentColumn: (t) => t.audioPlayerStateId, + referencedTable: $state.db.audioPlayerStateTable, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, parentComposers) => + $$AudioPlayerStateTableTableOrderingComposer(ComposerState( + $state.db, + $state.db.audioPlayerStateTable, + joinBuilder, + parentComposers))); + return composer; + } +} + +class $$PlaylistTableTableTableManager extends RootTableManager< + _$AppDatabase, + $PlaylistTableTable, + PlaylistTableData, + $$PlaylistTableTableFilterComposer, + $$PlaylistTableTableOrderingComposer, + $$PlaylistTableTableCreateCompanionBuilder, + $$PlaylistTableTableUpdateCompanionBuilder, + (PlaylistTableData, $$PlaylistTableTableReferences), + PlaylistTableData, + PrefetchHooks Function( + {bool audioPlayerStateId, bool playlistMediaTableRefs})> { + $$PlaylistTableTableTableManager(_$AppDatabase db, $PlaylistTableTable table) + : super(TableManagerState( + db: db, + table: table, + filteringComposer: + $$PlaylistTableTableFilterComposer(ComposerState(db, table)), + orderingComposer: + $$PlaylistTableTableOrderingComposer(ComposerState(db, table)), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value audioPlayerStateId = const Value.absent(), + Value index = const Value.absent(), + }) => + PlaylistTableCompanion( + id: id, + audioPlayerStateId: audioPlayerStateId, + index: index, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required int audioPlayerStateId, + required int index, + }) => + PlaylistTableCompanion.insert( + id: id, + audioPlayerStateId: audioPlayerStateId, + index: index, + ), + withReferenceMapper: (p0) => p0 + .map((e) => ( + e.readTable(table), + $$PlaylistTableTableReferences(db, table, e) + )) + .toList(), + prefetchHooksCallback: ( + {audioPlayerStateId = false, playlistMediaTableRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [ + if (playlistMediaTableRefs) db.playlistMediaTable + ], + addJoins: < + T extends TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic>>(state) { + if (audioPlayerStateId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.audioPlayerStateId, + referencedTable: $$PlaylistTableTableReferences + ._audioPlayerStateIdTable(db), + referencedColumn: $$PlaylistTableTableReferences + ._audioPlayerStateIdTable(db) + .id, + ) as T; + } + + return state; + }, + getPrefetchedDataCallback: (items) async { + return [ + if (playlistMediaTableRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: $$PlaylistTableTableReferences + ._playlistMediaTableRefsTable(db), + managerFromTypedResult: (p0) => + $$PlaylistTableTableReferences(db, table, p0) + .playlistMediaTableRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.playlistId == item.id), + typedResults: items) + ]; + }, + ); + }, + )); +} + +typedef $$PlaylistTableTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $PlaylistTableTable, + PlaylistTableData, + $$PlaylistTableTableFilterComposer, + $$PlaylistTableTableOrderingComposer, + $$PlaylistTableTableCreateCompanionBuilder, + $$PlaylistTableTableUpdateCompanionBuilder, + (PlaylistTableData, $$PlaylistTableTableReferences), + PlaylistTableData, + PrefetchHooks Function( + {bool audioPlayerStateId, bool playlistMediaTableRefs})>; +typedef $$PlaylistMediaTableTableCreateCompanionBuilder + = PlaylistMediaTableCompanion Function({ + Value id, + required int playlistId, + required String uri, + Value?> extras, + Value?> httpHeaders, +}); +typedef $$PlaylistMediaTableTableUpdateCompanionBuilder + = PlaylistMediaTableCompanion Function({ + Value id, + Value playlistId, + Value uri, + Value?> extras, + Value?> httpHeaders, +}); + +final class $$PlaylistMediaTableTableReferences extends BaseReferences< + _$AppDatabase, $PlaylistMediaTableTable, PlaylistMediaTableData> { + $$PlaylistMediaTableTableReferences( + super.$_db, super.$_table, super.$_typedResult); + + static $PlaylistTableTable _playlistIdTable(_$AppDatabase db) => + db.playlistTable.createAlias($_aliasNameGenerator( + db.playlistMediaTable.playlistId, db.playlistTable.id)); + + $$PlaylistTableTableProcessedTableManager? get playlistId { + if ($_item.playlistId == null) return null; + final manager = $$PlaylistTableTableTableManager($_db, $_db.playlistTable) + .filter((f) => f.id($_item.playlistId!)); + final item = $_typedResult.readTableOrNull(_playlistIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } +} + +class $$PlaylistMediaTableTableFilterComposer + extends FilterComposer<_$AppDatabase, $PlaylistMediaTableTable> { + $$PlaylistMediaTableTableFilterComposer(super.$state); + ColumnFilters get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnFilters get uri => $state.composableBuilder( + column: $state.table.uri, + builder: (column, joinBuilders) => + ColumnFilters(column, joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters?, Map, + String> + get extras => $state.composableBuilder( + column: $state.table.extras, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + ColumnWithTypeConverterFilters?, Map, + String> + get httpHeaders => $state.composableBuilder( + column: $state.table.httpHeaders, + builder: (column, joinBuilders) => ColumnWithTypeConverterFilters( + column, + joinBuilders: joinBuilders)); + + $$PlaylistTableTableFilterComposer get playlistId { + final $$PlaylistTableTableFilterComposer composer = $state.composerBuilder( + composer: this, + getCurrentColumn: (t) => t.playlistId, + referencedTable: $state.db.playlistTable, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, parentComposers) => + $$PlaylistTableTableFilterComposer(ComposerState($state.db, + $state.db.playlistTable, joinBuilder, parentComposers))); + return composer; + } +} + +class $$PlaylistMediaTableTableOrderingComposer + extends OrderingComposer<_$AppDatabase, $PlaylistMediaTableTable> { + $$PlaylistMediaTableTableOrderingComposer(super.$state); + ColumnOrderings get id => $state.composableBuilder( + column: $state.table.id, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get uri => $state.composableBuilder( + column: $state.table.uri, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get extras => $state.composableBuilder( + column: $state.table.extras, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + ColumnOrderings get httpHeaders => $state.composableBuilder( + column: $state.table.httpHeaders, + builder: (column, joinBuilders) => + ColumnOrderings(column, joinBuilders: joinBuilders)); + + $$PlaylistTableTableOrderingComposer get playlistId { + final $$PlaylistTableTableOrderingComposer composer = + $state.composerBuilder( + composer: this, + getCurrentColumn: (t) => t.playlistId, + referencedTable: $state.db.playlistTable, + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, parentComposers) => + $$PlaylistTableTableOrderingComposer(ComposerState($state.db, + $state.db.playlistTable, joinBuilder, parentComposers))); + return composer; + } +} + +class $$PlaylistMediaTableTableTableManager extends RootTableManager< + _$AppDatabase, + $PlaylistMediaTableTable, + PlaylistMediaTableData, + $$PlaylistMediaTableTableFilterComposer, + $$PlaylistMediaTableTableOrderingComposer, + $$PlaylistMediaTableTableCreateCompanionBuilder, + $$PlaylistMediaTableTableUpdateCompanionBuilder, + (PlaylistMediaTableData, $$PlaylistMediaTableTableReferences), + PlaylistMediaTableData, + PrefetchHooks Function({bool playlistId})> { + $$PlaylistMediaTableTableTableManager( + _$AppDatabase db, $PlaylistMediaTableTable table) + : super(TableManagerState( + db: db, + table: table, + filteringComposer: + $$PlaylistMediaTableTableFilterComposer(ComposerState(db, table)), + orderingComposer: $$PlaylistMediaTableTableOrderingComposer( + ComposerState(db, table)), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value playlistId = const Value.absent(), + Value uri = const Value.absent(), + Value?> extras = const Value.absent(), + Value?> httpHeaders = const Value.absent(), + }) => + PlaylistMediaTableCompanion( + id: id, + playlistId: playlistId, + uri: uri, + extras: extras, + httpHeaders: httpHeaders, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required int playlistId, + required String uri, + Value?> extras = const Value.absent(), + Value?> httpHeaders = const Value.absent(), + }) => + PlaylistMediaTableCompanion.insert( + id: id, + playlistId: playlistId, + uri: uri, + extras: extras, + httpHeaders: httpHeaders, + ), + withReferenceMapper: (p0) => p0 + .map((e) => ( + e.readTable(table), + $$PlaylistMediaTableTableReferences(db, table, e) + )) + .toList(), + prefetchHooksCallback: ({playlistId = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [], + addJoins: < + T extends TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic>>(state) { + if (playlistId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.playlistId, + referencedTable: $$PlaylistMediaTableTableReferences + ._playlistIdTable(db), + referencedColumn: $$PlaylistMediaTableTableReferences + ._playlistIdTable(db) + .id, + ) as T; + } + + return state; + }, + getPrefetchedDataCallback: (items) async { + return []; + }, + ); + }, + )); +} + +typedef $$PlaylistMediaTableTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $PlaylistMediaTableTable, + PlaylistMediaTableData, + $$PlaylistMediaTableTableFilterComposer, + $$PlaylistMediaTableTableOrderingComposer, + $$PlaylistMediaTableTableCreateCompanionBuilder, + $$PlaylistMediaTableTableUpdateCompanionBuilder, + (PlaylistMediaTableData, $$PlaylistMediaTableTableReferences), + PlaylistMediaTableData, + PrefetchHooks Function({bool playlistId})>; class $AppDatabaseManager { final _$AppDatabase _db; @@ -4331,4 +5881,10 @@ class $AppDatabaseManager { $$HistoryTableTableTableManager(_db, _db.historyTable); $$LyricsTableTableTableManager get lyricsTable => $$LyricsTableTableTableManager(_db, _db.lyricsTable); + $$AudioPlayerStateTableTableTableManager get audioPlayerStateTable => + $$AudioPlayerStateTableTableTableManager(_db, _db.audioPlayerStateTable); + $$PlaylistTableTableTableManager get playlistTable => + $$PlaylistTableTableTableManager(_db, _db.playlistTable); + $$PlaylistMediaTableTableTableManager get playlistMediaTable => + $$PlaylistMediaTableTableTableManager(_db, _db.playlistMediaTable); } diff --git a/lib/services/database/tables/audio_player_state.dart b/lib/services/database/tables/audio_player_state.dart new file mode 100755 index 0000000..3e49cf6 --- /dev/null +++ b/lib/services/database/tables/audio_player_state.dart @@ -0,0 +1,27 @@ +part of '../database.dart'; + +class AudioPlayerStateTable extends Table { + IntColumn get id => integer().autoIncrement()(); + BoolColumn get playing => boolean()(); + TextColumn get loopMode => textEnum()(); + BoolColumn get shuffled => boolean()(); + TextColumn get collections => text().map(const StringListConverter())(); +} + +class PlaylistTable extends Table { + IntColumn get id => integer().autoIncrement()(); + IntColumn get audioPlayerStateId => + integer().references(AudioPlayerStateTable, #id)(); + IntColumn get index => integer()(); +} + +class PlaylistMediaTable extends Table { + IntColumn get id => integer().autoIncrement()(); + IntColumn get playlistId => integer().references(PlaylistTable, #id)(); + + TextColumn get uri => text()(); + TextColumn get extras => + text().nullable().map(const MapTypeConverter())(); + TextColumn get httpHeaders => + text().nullable().map(const MapTypeConverter())(); +} diff --git a/lib/services/kv_store/kv_store.dart b/lib/services/kv_store/kv_store.dart index b174a07..9eb656b 100755 --- a/lib/services/kv_store/kv_store.dart +++ b/lib/services/kv_store/kv_store.dart @@ -13,24 +13,18 @@ abstract class KVStoreService { _sharedPreferences = await SharedPreferences.getInstance(); } - static bool get doneGettingStarted => - sharedPreferences.getBool('doneGettingStarted') ?? false; - static Future setDoneGettingStarted(bool value) async => - await sharedPreferences.setBool('doneGettingStarted', value); - static bool get askedForBatteryOptimization => - sharedPreferences.getBool('askedForBatteryOptimization') ?? false; + sharedPreferences.getBool('asked_for_battery_optimization') ?? false; static Future setAskedForBatteryOptimization(bool value) async => - await sharedPreferences.setBool('askedForBatteryOptimization', value); + await sharedPreferences.setBool('asked_for_battery_optimization', value); static List get recentSearches => - sharedPreferences.getStringList('recentSearches') ?? []; - + sharedPreferences.getStringList('recent_searches') ?? []; static Future setRecentSearches(List value) async => - await sharedPreferences.setStringList('recentSearches', value); + await sharedPreferences.setStringList('recent_searches', value); static WindowSize? get windowSize { - final raw = sharedPreferences.getString('windowSize'); + final raw = sharedPreferences.getString('window_size'); if (raw == null) { return null; @@ -40,7 +34,7 @@ abstract class KVStoreService { static Future setWindowSize(WindowSize value) async => await sharedPreferences.setString( - 'windowSize', + 'window_size', jsonEncode( value.toJson(), ), @@ -82,9 +76,4 @@ abstract class KVStoreService { static double get volume => sharedPreferences.getDouble('volume') ?? 1.0; static Future setVolume(double value) async => await sharedPreferences.setDouble('volume', value); - - static bool get hasMigratedToDrift => - sharedPreferences.getBool('hasMigratedToDrift') ?? false; - static Future setHasMigratedToDrift(bool value) async => - await sharedPreferences.setBool('hasMigratedToDrift', value); } diff --git a/lib/widgets/tracks/playlist_track_list.dart b/lib/widgets/tracks/playlist_track_list.dart index 9c6cb24..8391a6b 100644 --- a/lib/widgets/tracks/playlist_track_list.dart +++ b/lib/widgets/tracks/playlist_track_list.dart @@ -70,7 +70,11 @@ class _PlaylistTrackListState extends State { ), onTap: () { if (item == null) return; - Get.find().load([item], autoPlay: true); + Get.find().load( + _tracks!, + initialIndex: idx, + autoPlay: true, + ); }, ); }, diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f..96d3fee 100644 --- a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "info": { + "version": 1, + "author": "xcode" }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} + "images": [ + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" + }, + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" + } + ] +} \ No newline at end of file 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 82b6f9d..aefff76 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 13b35eb..f94fc53 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 0a3f5fa..11170e1 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 bdb5722..009600d 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 f083318..d84105d 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 326c0e7..9ed4d01 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 2f1632c..3514b9a 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/pubspec.lock b/pubspec.lock index 61bc072..13011e0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -419,6 +419,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.4.1" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" flutter_lints: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index 11b8fe7..4bdbfce 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -56,7 +56,6 @@ dependencies: piped_client: ^0.1.1 flutter_broadcasts: ^0.4.0 audio_session: ^0.1.21 - shared_preferences: ^2.3.2 audio_service: ^0.18.15 smtc_windows: ^0.1.3 win32_registry: ^1.1.4 @@ -82,6 +81,7 @@ dependencies: url: https://github.com/KRTirtho/scrobblenaut.git ref: dart-3-support dismissible_page: ^1.0.2 + shared_preferences: ^2.3.2 dev_dependencies: flutter_test: @@ -95,6 +95,7 @@ dev_dependencies: flutter_lints: ^4.0.0 drift_dev: ^2.20.1 build_runner: ^2.4.12 + flutter_launcher_icons: ^0.13.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -137,3 +138,19 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/to/font-from-package + +flutter_launcher_icons: + android: false + ios: true + image_path: "assets/icon.png" + min_sdk_android: 21 # android min sdk min:16, default 21 + web: + generate: true + image_path: "assets/icon.png" + windows: + generate: true + image_path: "assets/icon.png" + icon_size: 256 + macos: + generate: true + image_path: "assets/icon.png" \ No newline at end of file diff --git a/web/favicon.png b/web/favicon.png index 8aaa46a..11170e1 100644 Binary files a/web/favicon.png and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png index b749bfe..11f83e4 100644 Binary files a/web/icons/Icon-192.png and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png index 88cfd48..9ed4d01 100644 Binary files a/web/icons/Icon-512.png and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png index eb9b4d7..11f83e4 100644 Binary files a/web/icons/Icon-maskable-192.png and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png index d69c566..9ed4d01 100644 Binary files a/web/icons/Icon-maskable-512.png and b/web/icons/Icon-maskable-512.png differ diff --git a/web/manifest.json b/web/manifest.json index 97001e0..b50aeab 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -32,4 +32,4 @@ "purpose": "maskable" } ] -} +} \ No newline at end of file diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20c..e0f78cd 100644 Binary files a/windows/runner/resources/app_icon.ico and b/windows/runner/resources/app_icon.ico differ