♻️ Moved player state from shared_prefs to drift
🍱 Update icons
@ -1,10 +1,14 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="rhythm_box"
|
android:label="RhythmBox"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name="com.ryanheise.audioservice.AudioServiceActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:taskAffinity=""
|
android:taskAffinity=""
|
||||||
@ -17,14 +21,30 @@
|
|||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI. -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
/>
|
/>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service android:name="com.ryanheise.audioservice.AudioService"
|
||||||
|
android:foregroundServiceType="mediaPlayback"
|
||||||
|
android:exported="true" tools:ignore="Instantiatable">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.media.browse.MediaBrowserService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<receiver android:name="com.ryanheise.audioservice.MediaButtonReceiver"
|
||||||
|
android:exported="true" tools:ignore="Instantiatable">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
<meta-data
|
<meta-data
|
||||||
@ -38,8 +58,8 @@
|
|||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT" />
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain" />
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
BIN
android/app/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
15
android/app/src/main/res/drawable-anydpi/ic_stat_name.xml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#FFFFFF">
|
||||||
|
<group android:scaleX="1.127451"
|
||||||
|
android:scaleY="1.127451"
|
||||||
|
android:translateX="-1.5294118"
|
||||||
|
android:translateY="-1.5294118">
|
||||||
|
<path
|
||||||
|
android:pathData="M16,9H13V14.5A2.5,2.5 0,0 1,10.5 17A2.5,2.5 0,0 1,8 14.5A2.5,2.5 0,0 1,10.5 12C11.07,12 11.58,12.19 12,12.5V7H16M19,3H5A2,2 0,0 0,3 5V19A2,2 0,0 0,5 21H19A2,2 0,0 0,21 19V5A2,2 0,0 0,19 3Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
BIN
android/app/src/main/res/drawable-hdpi/ic_stat_name.png
Normal file
After Width: | Height: | Size: 337 B |
BIN
android/app/src/main/res/drawable-mdpi/ic_stat_name.png
Normal file
After Width: | Height: | Size: 240 B |
BIN
android/app/src/main/res/drawable-xhdpi/ic_stat_name.png
Normal file
After Width: | Height: | Size: 461 B |
BIN
android/app/src/main/res/drawable-xxhdpi/ic_stat_name.png
Normal file
After Width: | Height: | Size: 656 B |
74
android/app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector
|
||||||
|
android:height="108dp"
|
||||||
|
android:width="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#3DDC84"
|
||||||
|
android:pathData="M0,0h108v108h-108z"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
</vector>
|
14
android/app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<group android:scaleX="0.88536584"
|
||||||
|
android:scaleY="0.88536584"
|
||||||
|
android:translateX="1.3756098"
|
||||||
|
android:translateY="1.3756098">
|
||||||
|
<path
|
||||||
|
android:pathData="M16,9H13V14.5A2.5,2.5 0,0 1,10.5 17A2.5,2.5 0,0 1,8 14.5A2.5,2.5 0,0 1,10.5 12C11.07,12 11.58,12.19 12,12.5V7H16M19,3H5A2,2 0,0 0,3 5V19A2,2 0,0 0,5 21H19A2,2 0,0 0,21 19V5A2,2 0,0 0,19 3Z"
|
||||||
|
android:fillColor="#fff"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
Before Width: | Height: | Size: 544 B |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 774 B |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 442 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 672 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp
Normal file
After Width: | Height: | Size: 888 B |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 985 B |
Before Width: | Height: | Size: 721 B |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.8 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.0 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 3.1 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 1.4 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 4.7 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="ic_launcher_background">#BD7F44</color>
|
||||||
|
</resources>
|
BIN
assets/icon.png
Normal file
After Width: | Height: | Size: 62 KiB |
@ -540,7 +540,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
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_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
@ -597,7 +597,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
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_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 395 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 788 B |
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 588 B |
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 788 B |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 1009 B |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 4.6 KiB |
@ -1,19 +1,16 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:math';
|
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: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/audio_player/state.dart';
|
||||||
import 'package:rhythm_box/services/local_track.dart';
|
import 'package:rhythm_box/services/database/database.dart';
|
||||||
import 'package:rhythm_box/services/server/sourced_track.dart';
|
|
||||||
import 'package:spotify/spotify.dart' hide Playlist;
|
import 'package:spotify/spotify.dart' hide Playlist;
|
||||||
import 'package:rhythm_box/services/audio_player/audio_player.dart';
|
import 'package:rhythm_box/services/audio_player/audio_player.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
class AudioPlayerProvider extends GetxController {
|
class AudioPlayerProvider extends GetxController {
|
||||||
late final SharedPreferences _prefs;
|
|
||||||
|
|
||||||
RxBool isPlaying = false.obs;
|
RxBool isPlaying = false.obs;
|
||||||
|
|
||||||
Rx<AudioPlayerState> state = Rx(AudioPlayerState(
|
Rx<AudioPlayerState> state = Rx(AudioPlayerState(
|
||||||
@ -28,41 +25,39 @@ class AudioPlayerProvider extends GetxController {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() {
|
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 = [
|
_subscriptions = [
|
||||||
audioPlayer.playingStream.listen((playing) async {
|
audioPlayer.playingStream.listen((playing) async {
|
||||||
state.value = state.value.copyWith(playing: playing);
|
state.value = state.value.copyWith(playing: playing);
|
||||||
await _updateSavedState();
|
await _updatePlayerState(
|
||||||
|
AudioPlayerStateTableCompanion(
|
||||||
|
playing: Value(playing),
|
||||||
|
),
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
audioPlayer.loopModeStream.listen((loopMode) async {
|
audioPlayer.loopModeStream.listen((loopMode) async {
|
||||||
state.value = state.value.copyWith(loopMode: loopMode);
|
state.value = state.value.copyWith(loopMode: loopMode);
|
||||||
await _updateSavedState();
|
await _updatePlayerState(
|
||||||
|
AudioPlayerStateTableCompanion(
|
||||||
|
loopMode: Value(loopMode),
|
||||||
|
),
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
audioPlayer.shuffledStream.listen((shuffled) async {
|
audioPlayer.shuffledStream.listen((shuffled) async {
|
||||||
state.value = state.value.copyWith(shuffled: shuffled);
|
state.value = state.value.copyWith(shuffled: shuffled);
|
||||||
await _updateSavedState();
|
await _updatePlayerState(
|
||||||
|
AudioPlayerStateTableCompanion(
|
||||||
|
shuffled: Value(shuffled),
|
||||||
|
),
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
audioPlayer.playlistStream.listen((playlist) async {
|
audioPlayer.playlistStream.listen((playlist) async {
|
||||||
state.value = state.value.copyWith(playlist: playlist);
|
state.value = state.value.copyWith(playlist: playlist);
|
||||||
await _updateSavedState();
|
await _updatePlaylist(playlist);
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
_readSavedState();
|
||||||
|
|
||||||
audioPlayer.playingStream.listen((playing) {
|
audioPlayer.playingStream.listen((playing) {
|
||||||
isPlaying.value = playing;
|
isPlaying.value = playing;
|
||||||
});
|
});
|
||||||
@ -80,16 +75,124 @@ class AudioPlayerProvider extends GetxController {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<AudioPlayerState?> _readSavedState() async {
|
Future<void> _readSavedState() async {
|
||||||
final data = _prefs.getString('player_state');
|
final database = Get.find<DatabaseProvider>().database;
|
||||||
if (data == null) return null;
|
|
||||||
|
|
||||||
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: <String>[],
|
||||||
|
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<void> _updateSavedState() async {
|
Future<void> _updatePlayerState(
|
||||||
final out = jsonEncode(state.value.toJson());
|
AudioPlayerStateTableCompanion companion,
|
||||||
await _prefs.setString('player_state', out);
|
) async {
|
||||||
|
final database = Get.find<DatabaseProvider>().database;
|
||||||
|
|
||||||
|
await (database.update(database.audioPlayerStateTable)
|
||||||
|
..where((tb) => tb.id.equals(0)))
|
||||||
|
.write(companion);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _updatePlaylist(
|
||||||
|
Playlist playlist,
|
||||||
|
) async {
|
||||||
|
final database = Get.find<DatabaseProvider>().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<void> addCollections(List<String> collectionIds) async {
|
Future<void> addCollections(List<String> collectionIds) async {
|
||||||
@ -98,7 +201,11 @@ class AudioPlayerProvider extends GetxController {
|
|||||||
...collectionIds,
|
...collectionIds,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await _updateSavedState();
|
await _updatePlayerState(
|
||||||
|
AudioPlayerStateTableCompanion(
|
||||||
|
collections: Value(state.value.collections),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addCollection(String collectionId) async {
|
Future<void> addCollection(String collectionId) async {
|
||||||
@ -112,7 +219,11 @@ class AudioPlayerProvider extends GetxController {
|
|||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
await _updateSavedState();
|
await _updatePlayerState(
|
||||||
|
AudioPlayerStateTableCompanion(
|
||||||
|
collections: Value(state.value.collections),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> removeCollection(String collectionId) async {
|
Future<void> removeCollection(String collectionId) async {
|
||||||
|
@ -21,9 +21,16 @@ class AudioPlayerStreamProvider extends GetxController {
|
|||||||
List<StreamSubscription>? _subscriptions;
|
List<StreamSubscription>? _subscriptions;
|
||||||
|
|
||||||
AudioPlayerStreamProvider() {
|
AudioPlayerStreamProvider() {
|
||||||
AudioServices.create().then(
|
_initNotificationService();
|
||||||
(value) => notificationService = value,
|
}
|
||||||
);
|
|
||||||
|
Future<void> _initNotificationService() async {
|
||||||
|
try {
|
||||||
|
final res = await AudioServices.create();
|
||||||
|
notificationService = res;
|
||||||
|
} catch (err) {
|
||||||
|
log('[AudioService] Unable to init audio service: $err');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -50,7 +57,7 @@ class AudioPlayerStreamProvider extends GetxController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updatePalette() async {
|
Future<void> updatePalette() async {
|
||||||
if (!Get.find<UserPreferences>().albumColorSync) {
|
if (!Get.find<UserPreferencesProvider>().state.value.albumColorSync) {
|
||||||
if (palette.value != null) {
|
if (palette.value != null) {
|
||||||
palette.value = null;
|
palette.value = null;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,10 @@ class _PlayerScreenState extends State<PlayerScreen> {
|
|||||||
),
|
),
|
||||||
child: Slider(
|
child: Slider(
|
||||||
value: _draggingValue ??
|
value: _draggingValue ??
|
||||||
_durationCurrent.inMilliseconds.toDouble(),
|
(_durationCurrent.inMilliseconds <=
|
||||||
|
_durationTotal.inMilliseconds
|
||||||
|
? _durationCurrent.inMilliseconds.toDouble()
|
||||||
|
: 0),
|
||||||
min: 0,
|
min: 0,
|
||||||
max: _durationTotal.inMilliseconds.toDouble(),
|
max: _durationTotal.inMilliseconds.toDouble(),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
@ -27,7 +27,7 @@ class AudioServices with WidgetsBindingObserver {
|
|||||||
: 'dev.solsynth.rhythmBox',
|
: 'dev.solsynth.rhythmBox',
|
||||||
androidNotificationChannelName: 'RhythmBox',
|
androidNotificationChannelName: 'RhythmBox',
|
||||||
androidNotificationOngoing: false,
|
androidNotificationOngoing: false,
|
||||||
androidNotificationIcon: 'drawable/ic_launcher_monochrome',
|
androidNotificationIcon: 'drawable/ic_stat_name',
|
||||||
androidStopForegroundOnPause: false,
|
androidStopForegroundOnPause: false,
|
||||||
androidNotificationChannelDescription: 'RhythmBox Music',
|
androidNotificationChannelDescription: 'RhythmBox Music',
|
||||||
),
|
),
|
||||||
|
@ -5,6 +5,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:encrypt/encrypt.dart';
|
import 'package:encrypt/encrypt.dart';
|
||||||
|
import 'package:media_kit/media_kit.dart' hide Track;
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:rhythm_box/services/color.dart';
|
import 'package:rhythm_box/services/color.dart';
|
||||||
@ -27,6 +28,7 @@ part 'tables/skip_segment.dart';
|
|||||||
part 'tables/source_match.dart';
|
part 'tables/source_match.dart';
|
||||||
part 'tables/history.dart';
|
part 'tables/history.dart';
|
||||||
part 'tables/lyrics.dart';
|
part 'tables/lyrics.dart';
|
||||||
|
part 'tables/audio_player_state.dart';
|
||||||
|
|
||||||
part 'typeconverters/color.dart';
|
part 'typeconverters/color.dart';
|
||||||
part 'typeconverters/locale.dart';
|
part 'typeconverters/locale.dart';
|
||||||
@ -44,6 +46,9 @@ part 'typeconverters/subtitle.dart';
|
|||||||
SourceMatchTable,
|
SourceMatchTable,
|
||||||
HistoryTable,
|
HistoryTable,
|
||||||
LyricsTable,
|
LyricsTable,
|
||||||
|
AudioPlayerStateTable,
|
||||||
|
PlaylistTable,
|
||||||
|
PlaylistMediaTable,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class AppDatabase extends _$AppDatabase {
|
class AppDatabase extends _$AppDatabase {
|
||||||
|
27
lib/services/database/tables/audio_player_state.dart
Executable file
@ -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<PlaylistMode>()();
|
||||||
|
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<String, dynamic>())();
|
||||||
|
TextColumn get httpHeaders =>
|
||||||
|
text().nullable().map(const MapTypeConverter<String, String>())();
|
||||||
|
}
|
@ -13,24 +13,18 @@ abstract class KVStoreService {
|
|||||||
_sharedPreferences = await SharedPreferences.getInstance();
|
_sharedPreferences = await SharedPreferences.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get doneGettingStarted =>
|
|
||||||
sharedPreferences.getBool('doneGettingStarted') ?? false;
|
|
||||||
static Future<void> setDoneGettingStarted(bool value) async =>
|
|
||||||
await sharedPreferences.setBool('doneGettingStarted', value);
|
|
||||||
|
|
||||||
static bool get askedForBatteryOptimization =>
|
static bool get askedForBatteryOptimization =>
|
||||||
sharedPreferences.getBool('askedForBatteryOptimization') ?? false;
|
sharedPreferences.getBool('asked_for_battery_optimization') ?? false;
|
||||||
static Future<void> setAskedForBatteryOptimization(bool value) async =>
|
static Future<void> setAskedForBatteryOptimization(bool value) async =>
|
||||||
await sharedPreferences.setBool('askedForBatteryOptimization', value);
|
await sharedPreferences.setBool('asked_for_battery_optimization', value);
|
||||||
|
|
||||||
static List<String> get recentSearches =>
|
static List<String> get recentSearches =>
|
||||||
sharedPreferences.getStringList('recentSearches') ?? [];
|
sharedPreferences.getStringList('recent_searches') ?? [];
|
||||||
|
|
||||||
static Future<void> setRecentSearches(List<String> value) async =>
|
static Future<void> setRecentSearches(List<String> value) async =>
|
||||||
await sharedPreferences.setStringList('recentSearches', value);
|
await sharedPreferences.setStringList('recent_searches', value);
|
||||||
|
|
||||||
static WindowSize? get windowSize {
|
static WindowSize? get windowSize {
|
||||||
final raw = sharedPreferences.getString('windowSize');
|
final raw = sharedPreferences.getString('window_size');
|
||||||
|
|
||||||
if (raw == null) {
|
if (raw == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -40,7 +34,7 @@ abstract class KVStoreService {
|
|||||||
|
|
||||||
static Future<void> setWindowSize(WindowSize value) async =>
|
static Future<void> setWindowSize(WindowSize value) async =>
|
||||||
await sharedPreferences.setString(
|
await sharedPreferences.setString(
|
||||||
'windowSize',
|
'window_size',
|
||||||
jsonEncode(
|
jsonEncode(
|
||||||
value.toJson(),
|
value.toJson(),
|
||||||
),
|
),
|
||||||
@ -82,9 +76,4 @@ abstract class KVStoreService {
|
|||||||
static double get volume => sharedPreferences.getDouble('volume') ?? 1.0;
|
static double get volume => sharedPreferences.getDouble('volume') ?? 1.0;
|
||||||
static Future<void> setVolume(double value) async =>
|
static Future<void> setVolume(double value) async =>
|
||||||
await sharedPreferences.setDouble('volume', value);
|
await sharedPreferences.setDouble('volume', value);
|
||||||
|
|
||||||
static bool get hasMigratedToDrift =>
|
|
||||||
sharedPreferences.getBool('hasMigratedToDrift') ?? false;
|
|
||||||
static Future<void> setHasMigratedToDrift(bool value) async =>
|
|
||||||
await sharedPreferences.setBool('hasMigratedToDrift', value);
|
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,11 @@ class _PlaylistTrackListState extends State<PlaylistTrackList> {
|
|||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (item == null) return;
|
if (item == null) return;
|
||||||
Get.find<AudioPlayerProvider>().load([item], autoPlay: true);
|
Get.find<AudioPlayerProvider>().load(
|
||||||
|
_tracks!,
|
||||||
|
initialIndex: idx,
|
||||||
|
autoPlay: true,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -1,68 +1,68 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"info": {
|
||||||
{
|
"version": 1,
|
||||||
"size" : "16x16",
|
"author": "xcode"
|
||||||
"idiom" : "mac",
|
|
||||||
"filename" : "app_icon_16.png",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
},
|
||||||
{
|
"images": [
|
||||||
"size" : "16x16",
|
{
|
||||||
"idiom" : "mac",
|
"size": "16x16",
|
||||||
"filename" : "app_icon_32.png",
|
"idiom": "mac",
|
||||||
"scale" : "2x"
|
"filename": "app_icon_16.png",
|
||||||
},
|
"scale": "1x"
|
||||||
{
|
},
|
||||||
"size" : "32x32",
|
{
|
||||||
"idiom" : "mac",
|
"size": "16x16",
|
||||||
"filename" : "app_icon_32.png",
|
"idiom": "mac",
|
||||||
"scale" : "1x"
|
"filename": "app_icon_32.png",
|
||||||
},
|
"scale": "2x"
|
||||||
{
|
},
|
||||||
"size" : "32x32",
|
{
|
||||||
"idiom" : "mac",
|
"size": "32x32",
|
||||||
"filename" : "app_icon_64.png",
|
"idiom": "mac",
|
||||||
"scale" : "2x"
|
"filename": "app_icon_32.png",
|
||||||
},
|
"scale": "1x"
|
||||||
{
|
},
|
||||||
"size" : "128x128",
|
{
|
||||||
"idiom" : "mac",
|
"size": "32x32",
|
||||||
"filename" : "app_icon_128.png",
|
"idiom": "mac",
|
||||||
"scale" : "1x"
|
"filename": "app_icon_64.png",
|
||||||
},
|
"scale": "2x"
|
||||||
{
|
},
|
||||||
"size" : "128x128",
|
{
|
||||||
"idiom" : "mac",
|
"size": "128x128",
|
||||||
"filename" : "app_icon_256.png",
|
"idiom": "mac",
|
||||||
"scale" : "2x"
|
"filename": "app_icon_128.png",
|
||||||
},
|
"scale": "1x"
|
||||||
{
|
},
|
||||||
"size" : "256x256",
|
{
|
||||||
"idiom" : "mac",
|
"size": "128x128",
|
||||||
"filename" : "app_icon_256.png",
|
"idiom": "mac",
|
||||||
"scale" : "1x"
|
"filename": "app_icon_256.png",
|
||||||
},
|
"scale": "2x"
|
||||||
{
|
},
|
||||||
"size" : "256x256",
|
{
|
||||||
"idiom" : "mac",
|
"size": "256x256",
|
||||||
"filename" : "app_icon_512.png",
|
"idiom": "mac",
|
||||||
"scale" : "2x"
|
"filename": "app_icon_256.png",
|
||||||
},
|
"scale": "1x"
|
||||||
{
|
},
|
||||||
"size" : "512x512",
|
{
|
||||||
"idiom" : "mac",
|
"size": "256x256",
|
||||||
"filename" : "app_icon_512.png",
|
"idiom": "mac",
|
||||||
"scale" : "1x"
|
"filename": "app_icon_512.png",
|
||||||
},
|
"scale": "2x"
|
||||||
{
|
},
|
||||||
"size" : "512x512",
|
{
|
||||||
"idiom" : "mac",
|
"size": "512x512",
|
||||||
"filename" : "app_icon_1024.png",
|
"idiom": "mac",
|
||||||
"scale" : "2x"
|
"filename": "app_icon_512.png",
|
||||||
}
|
"scale": "1x"
|
||||||
],
|
},
|
||||||
"info" : {
|
{
|
||||||
"version" : 1,
|
"size": "512x512",
|
||||||
"author" : "xcode"
|
"idiom": "mac",
|
||||||
}
|
"filename": "app_icon_1024.png",
|
||||||
|
"scale": "2x"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 621 B |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.4 KiB |
@ -419,6 +419,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.1"
|
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:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
|
19
pubspec.yaml
@ -56,7 +56,6 @@ dependencies:
|
|||||||
piped_client: ^0.1.1
|
piped_client: ^0.1.1
|
||||||
flutter_broadcasts: ^0.4.0
|
flutter_broadcasts: ^0.4.0
|
||||||
audio_session: ^0.1.21
|
audio_session: ^0.1.21
|
||||||
shared_preferences: ^2.3.2
|
|
||||||
audio_service: ^0.18.15
|
audio_service: ^0.18.15
|
||||||
smtc_windows: ^0.1.3
|
smtc_windows: ^0.1.3
|
||||||
win32_registry: ^1.1.4
|
win32_registry: ^1.1.4
|
||||||
@ -82,6 +81,7 @@ dependencies:
|
|||||||
url: https://github.com/KRTirtho/scrobblenaut.git
|
url: https://github.com/KRTirtho/scrobblenaut.git
|
||||||
ref: dart-3-support
|
ref: dart-3-support
|
||||||
dismissible_page: ^1.0.2
|
dismissible_page: ^1.0.2
|
||||||
|
shared_preferences: ^2.3.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@ -95,6 +95,7 @@ dev_dependencies:
|
|||||||
flutter_lints: ^4.0.0
|
flutter_lints: ^4.0.0
|
||||||
drift_dev: ^2.20.1
|
drift_dev: ^2.20.1
|
||||||
build_runner: ^2.4.12
|
build_runner: ^2.4.12
|
||||||
|
flutter_launcher_icons: ^0.13.1
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
@ -137,3 +138,19 @@ flutter:
|
|||||||
#
|
#
|
||||||
# For details regarding fonts from package dependencies,
|
# For details regarding fonts from package dependencies,
|
||||||
# see https://flutter.dev/to/font-from-package
|
# 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"
|
BIN
web/favicon.png
Before Width: | Height: | Size: 917 B After Width: | Height: | Size: 320 B |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 7.9 KiB |