✨ Impl more features (clean up 20+ todo)
⚡ Add query cache
This commit is contained in:
157
lib/providers/audio_player_stream.dart
Normal file
157
lib/providers/audio_player_stream.dart
Normal file
@ -0,0 +1,157 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:palette_generator/palette_generator.dart';
|
||||
import 'package:rhythm_box/providers/audio_player.dart';
|
||||
import 'package:rhythm_box/providers/history.dart';
|
||||
import 'package:rhythm_box/providers/scrobbler.dart';
|
||||
import 'package:rhythm_box/providers/skip_segments.dart';
|
||||
import 'package:rhythm_box/providers/user_preferences.dart';
|
||||
import 'package:rhythm_box/services/audio_player/audio_player.dart';
|
||||
import 'package:rhythm_box/services/audio_services/audio_services.dart';
|
||||
import 'package:rhythm_box/services/audio_services/image.dart';
|
||||
import 'package:rhythm_box/services/local_track.dart';
|
||||
import 'package:rhythm_box/services/server/sourced_track.dart';
|
||||
import 'package:rhythm_box/widgets/auto_cache_image.dart';
|
||||
|
||||
class AudioPlayerStreamProvider extends GetxController {
|
||||
late final AudioServices notificationService;
|
||||
final Rxn<PaletteGenerator?> palette = Rxn<PaletteGenerator?>();
|
||||
|
||||
List<StreamSubscription>? _subscriptions;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
AudioServices.create().then(
|
||||
(value) => notificationService = value,
|
||||
);
|
||||
|
||||
_subscriptions = [
|
||||
subscribeToPlaylist(),
|
||||
subscribeToSkipSponsor(),
|
||||
subscribeToScrobbleChanged(),
|
||||
subscribeToPosition(),
|
||||
subscribeToPlayerError(),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_subscriptions != null) {
|
||||
for (final subscription in _subscriptions!) {
|
||||
subscription.cancel();
|
||||
}
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> updatePalette() async {
|
||||
if (!Get.find<UserPreferences>().albumColorSync) {
|
||||
if (palette.value != null) {
|
||||
palette.value = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final AudioPlayerProvider playback = Get.find();
|
||||
final activeTrack = playback.state.value.activeTrack;
|
||||
if (activeTrack == null) return;
|
||||
|
||||
if (activeTrack.album?.images != null) {
|
||||
final newPalette = await PaletteGenerator.fromImageProvider(
|
||||
AutoCacheImage.provider(
|
||||
(activeTrack.album?.images).asUrlString()!,
|
||||
),
|
||||
);
|
||||
palette.value = newPalette;
|
||||
}
|
||||
}
|
||||
|
||||
StreamSubscription subscribeToPlaylist() {
|
||||
final AudioPlayerProvider playback = Get.find();
|
||||
return audioPlayer.playlistStream.listen((mpvPlaylist) {
|
||||
final activeTrack = playback.state.value.activeTrack;
|
||||
if (activeTrack != null) {
|
||||
notificationService.addTrack(activeTrack);
|
||||
updatePalette();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription subscribeToSkipSponsor() {
|
||||
return audioPlayer.positionStream.listen((position) async {
|
||||
final currentSegments =
|
||||
await Get.find<SegmentsProvider>().fetchSegments();
|
||||
|
||||
if (currentSegments?.segments.isNotEmpty != true ||
|
||||
position < const Duration(seconds: 3)) return;
|
||||
|
||||
for (final segment in currentSegments!.segments) {
|
||||
final seconds = position.inSeconds;
|
||||
|
||||
if (seconds < segment.start || seconds >= segment.end) continue;
|
||||
|
||||
await audioPlayer.seek(Duration(seconds: segment.end + 1));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription subscribeToScrobbleChanged() {
|
||||
String? lastScrobbled;
|
||||
return audioPlayer.positionStream.listen((position) {
|
||||
try {
|
||||
final AudioPlayerProvider playback = Get.find();
|
||||
final uid = playback.state.value.activeTrack is LocalTrack
|
||||
? (playback.state.value.activeTrack as LocalTrack).path
|
||||
: playback.state.value.activeTrack?.id;
|
||||
|
||||
if (playback.state.value.activeTrack == null ||
|
||||
lastScrobbled == uid ||
|
||||
position.inSeconds < 30) {
|
||||
return;
|
||||
}
|
||||
|
||||
Get.find<ScrobblerProvider>()
|
||||
.scrobble(playback.state.value.activeTrack!);
|
||||
Get.find<PlaybackHistoryProvider>()
|
||||
.addTrack(playback.state.value.activeTrack!);
|
||||
lastScrobbled = uid;
|
||||
} catch (e, stack) {
|
||||
log('[Scrobbler] Error: $e; Trace:\n$stack');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription subscribeToPosition() {
|
||||
String lastTrack = ''; // used to prevent multiple calls to the same track
|
||||
final AudioPlayerProvider playback = Get.find();
|
||||
return audioPlayer.positionStream.listen((event) async {
|
||||
if (event < const Duration(seconds: 3) ||
|
||||
audioPlayer.playlist.index == -1 ||
|
||||
audioPlayer.playlist.index ==
|
||||
playback.state.value.tracks.length - 1) {
|
||||
return;
|
||||
}
|
||||
final nextTrack = RhythmMedia.fromMedia(
|
||||
audioPlayer.playlist.medias.elementAt(audioPlayer.playlist.index + 1),
|
||||
);
|
||||
|
||||
if (lastTrack == nextTrack.track.id || nextTrack.track is LocalTrack) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await Get.find<SourcedTrackProvider>().fetch(nextTrack);
|
||||
} finally {
|
||||
lastTrack = nextTrack.track.id!;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription subscribeToPlayerError() {
|
||||
return audioPlayer.errorStream.listen((event) {
|
||||
// Handle player error events here
|
||||
});
|
||||
}
|
||||
}
|
6
lib/providers/database.dart
Normal file
6
lib/providers/database.dart
Normal file
@ -0,0 +1,6 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rhythm_box/services/database/database.dart';
|
||||
|
||||
class DatabaseProvider extends GetxController {
|
||||
late final AppDatabase database = AppDatabase();
|
||||
}
|
62
lib/providers/history.dart
Normal file
62
lib/providers/history.dart
Normal file
@ -0,0 +1,62 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rhythm_box/providers/database.dart';
|
||||
import 'package:rhythm_box/services/database/database.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
|
||||
class PlaybackHistoryProvider extends GetxController {
|
||||
final AppDatabase _db = Get.find<DatabaseProvider>().database;
|
||||
|
||||
Future<void> _batchInsertHistoryEntries(
|
||||
List<HistoryTableCompanion> entries) async {
|
||||
await _db.batch((batch) {
|
||||
batch.insertAll(_db.historyTable, entries);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> addPlaylists(List<PlaylistSimple> playlists) async {
|
||||
await _batchInsertHistoryEntries([
|
||||
for (final playlist in playlists)
|
||||
HistoryTableCompanion.insert(
|
||||
type: HistoryEntryType.playlist,
|
||||
itemId: playlist.id!,
|
||||
data: playlist.toJson(),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> addAlbums(List<AlbumSimple> albums) async {
|
||||
await _batchInsertHistoryEntries([
|
||||
for (final album in albums)
|
||||
HistoryTableCompanion.insert(
|
||||
type: HistoryEntryType.album,
|
||||
itemId: album.id!,
|
||||
data: album.toJson(),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> addTracks(List<Track> tracks) async {
|
||||
await _batchInsertHistoryEntries([
|
||||
for (final track in tracks)
|
||||
HistoryTableCompanion.insert(
|
||||
type: HistoryEntryType.track,
|
||||
itemId: track.id!,
|
||||
data: track.toJson(),
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
Future<void> addTrack(Track track) async {
|
||||
await _db.into(_db.historyTable).insert(
|
||||
HistoryTableCompanion.insert(
|
||||
type: HistoryEntryType.track,
|
||||
itemId: track.id!,
|
||||
data: track.toJson(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> clear() async {
|
||||
await _db.delete(_db.historyTable).go();
|
||||
}
|
||||
}
|
14
lib/providers/palette.dart
Normal file
14
lib/providers/palette.dart
Normal file
@ -0,0 +1,14 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:palette_generator/palette_generator.dart';
|
||||
|
||||
class PaletteProvider extends GetxController {
|
||||
final Rx<PaletteGenerator?> palette = Rx<PaletteGenerator?>(null);
|
||||
|
||||
void updatePalette(PaletteGenerator? newPalette) {
|
||||
palette.value = newPalette;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
palette.value = null;
|
||||
}
|
||||
}
|
140
lib/providers/scrobbler.dart
Normal file
140
lib/providers/scrobbler.dart
Normal file
@ -0,0 +1,140 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:get/get.dart' hide Value;
|
||||
import 'package:rhythm_box/providers/database.dart';
|
||||
import 'package:rhythm_box/services/artist.dart';
|
||||
import 'package:rhythm_box/services/database/database.dart';
|
||||
import 'package:scrobblenaut/scrobblenaut.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
|
||||
class ScrobblerProvider extends GetxController {
|
||||
final StreamController<Track> _scrobbleController =
|
||||
StreamController<Track>.broadcast();
|
||||
final Rxn<Scrobblenaut?> scrobbler = Rxn<Scrobblenaut?>(null);
|
||||
late StreamSubscription _databaseSubscription;
|
||||
late StreamSubscription _scrobbleSubscription;
|
||||
|
||||
static String apiKey = 'd2a75393e1141d0c9486eb77cc7b8892';
|
||||
static String apiSecret = '3ac3a5231a2e8a0dc98577c246101b78';
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
_initialize();
|
||||
}
|
||||
|
||||
Future<void> _initialize() async {
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
|
||||
final loginInfo = await (database.select(database.scrobblerTable)
|
||||
..where((t) => t.id.equals(0)))
|
||||
.getSingleOrNull();
|
||||
|
||||
_databaseSubscription =
|
||||
database.select(database.scrobblerTable).watch().listen((event) async {
|
||||
if (event.isNotEmpty) {
|
||||
try {
|
||||
scrobbler.value = Scrobblenaut(
|
||||
lastFM: await LastFM.authenticateWithPasswordHash(
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
username: event.first.username,
|
||||
passwordHash: event.first.passwordHash.value,
|
||||
),
|
||||
);
|
||||
} catch (e, stack) {
|
||||
log('[Scrobble] Error: $e; Trace:\n$stack');
|
||||
scrobbler.value = null;
|
||||
}
|
||||
} else {
|
||||
scrobbler.value = null;
|
||||
}
|
||||
});
|
||||
|
||||
_scrobbleSubscription = _scrobbleController.stream.listen((track) async {
|
||||
try {
|
||||
await scrobbler.value?.track.scrobble(
|
||||
artist: track.artists!.first.name!,
|
||||
track: track.name!,
|
||||
album: track.album!.name!,
|
||||
chosenByUser: true,
|
||||
duration: track.duration,
|
||||
timestamp: DateTime.now().toUtc(),
|
||||
trackNumber: track.trackNumber,
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
log('[Scrobble] Error: $e; Trace:\n$stackTrace');
|
||||
}
|
||||
});
|
||||
|
||||
if (loginInfo == null) {
|
||||
scrobbler.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
scrobbler.value = Scrobblenaut(
|
||||
lastFM: await LastFM.authenticateWithPasswordHash(
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
username: loginInfo.username,
|
||||
passwordHash: loginInfo.passwordHash.value,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> login(String username, String password) async {
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
|
||||
final lastFm = await LastFM.authenticate(
|
||||
apiKey: apiKey,
|
||||
apiSecret: apiSecret,
|
||||
username: username,
|
||||
password: password,
|
||||
);
|
||||
|
||||
if (!lastFm.isAuth) throw Exception('Invalid credentials');
|
||||
|
||||
await database.into(database.scrobblerTable).insert(
|
||||
ScrobblerTableCompanion.insert(
|
||||
id: const Value(0),
|
||||
username: username,
|
||||
passwordHash: DecryptedText(lastFm.passwordHash!),
|
||||
),
|
||||
);
|
||||
|
||||
scrobbler.value = Scrobblenaut(lastFM: lastFm);
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
scrobbler.value = null;
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
await database.delete(database.scrobblerTable).go();
|
||||
}
|
||||
|
||||
void scrobble(Track track) {
|
||||
_scrobbleController.add(track);
|
||||
}
|
||||
|
||||
Future<void> love(Track track) async {
|
||||
await scrobbler.value?.track.love(
|
||||
artist: track.artists!.asString(),
|
||||
track: track.name!,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> unlove(Track track) async {
|
||||
await scrobbler.value?.track.unLove(
|
||||
artist: track.artists!.asString(),
|
||||
track: track.name!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
_databaseSubscription.cancel();
|
||||
_scrobbleSubscription.cancel();
|
||||
_scrobbleController.close();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
117
lib/providers/skip_segments.dart
Normal file
117
lib/providers/skip_segments.dart
Normal file
@ -0,0 +1,117 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rhythm_box/providers/database.dart';
|
||||
import 'package:rhythm_box/providers/user_preferences.dart';
|
||||
import 'package:rhythm_box/services/database/database.dart';
|
||||
import 'package:rhythm_box/services/server/active_sourced_track.dart';
|
||||
|
||||
class SourcedSegments {
|
||||
final String source;
|
||||
final List<SkipSegmentTableData> segments;
|
||||
|
||||
SourcedSegments({required this.source, required this.segments});
|
||||
}
|
||||
|
||||
Future<List<SkipSegmentTableData>> getAndCacheSkipSegments(String id) async {
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
try {
|
||||
final cached = await (database.select(database.skipSegmentTable)
|
||||
..where((s) => s.trackId.equals(id)))
|
||||
.get();
|
||||
|
||||
if (cached.isNotEmpty) {
|
||||
return cached;
|
||||
}
|
||||
|
||||
final res = await Dio().getUri(
|
||||
Uri(
|
||||
scheme: 'https',
|
||||
host: 'sponsor.ajay.app',
|
||||
path: '/api/skipSegments',
|
||||
queryParameters: {
|
||||
'videoID': id,
|
||||
'category': [
|
||||
'sponsor',
|
||||
'selfpromo',
|
||||
'interaction',
|
||||
'intro',
|
||||
'outro',
|
||||
'music_offtopic'
|
||||
],
|
||||
'actionType': 'skip'
|
||||
},
|
||||
),
|
||||
options: Options(
|
||||
responseType: ResponseType.json,
|
||||
validateStatus: (status) => (status ?? 0) < 500,
|
||||
),
|
||||
);
|
||||
|
||||
if (res.data == 'Not Found') {
|
||||
return List.castFrom<dynamic, SkipSegmentTableData>([]);
|
||||
}
|
||||
|
||||
final data = res.data as List;
|
||||
final segments = data.map((obj) {
|
||||
final start = obj['segment'].first.toInt();
|
||||
final end = obj['segment'].last.toInt();
|
||||
return SkipSegmentTableCompanion.insert(
|
||||
trackId: id,
|
||||
start: start,
|
||||
end: end,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
await database.batch((b) {
|
||||
b.insertAll(database.skipSegmentTable, segments);
|
||||
});
|
||||
|
||||
return await (database.select(database.skipSegmentTable)
|
||||
..where((s) => s.trackId.equals(id)))
|
||||
.get();
|
||||
} catch (e, stack) {
|
||||
log('[SkipSegment] Error: $e; Trace:\n$stack');
|
||||
return List.castFrom<dynamic, SkipSegmentTableData>([]);
|
||||
}
|
||||
}
|
||||
|
||||
class SegmentsProvider extends GetxController {
|
||||
final Rx<SourcedSegments?> segments = Rx<SourcedSegments?>(null);
|
||||
|
||||
Future<SourcedSegments?> fetchSegments() async {
|
||||
final track = Get.find<ActiveSourcedTrackProvider>().state.value;
|
||||
if (track == null) {
|
||||
segments.value = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
final userPreferences = Get.find<UserPreferencesProvider>().state.value;
|
||||
final skipNonMusic = userPreferences.skipNonMusic &&
|
||||
!(userPreferences.audioSource == AudioSource.piped &&
|
||||
userPreferences.searchMode == SearchMode.youtubeMusic);
|
||||
|
||||
if (!skipNonMusic) {
|
||||
segments.value = SourcedSegments(
|
||||
segments: [],
|
||||
source: track.sourceInfo.id,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
final fetchedSegments = await getAndCacheSkipSegments(track.sourceInfo.id);
|
||||
segments.value = SourcedSegments(
|
||||
source: track.sourceInfo.id,
|
||||
segments: fetchedSegments,
|
||||
);
|
||||
|
||||
return segments.value!;
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
fetchSegments(); // Automatically load segments when controller is initialized
|
||||
}
|
||||
}
|
190
lib/providers/user_preferences.dart
Normal file
190
lib/providers/user_preferences.dart
Normal file
@ -0,0 +1,190 @@
|
||||
import 'package:get/get.dart' hide Value;
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:rhythm_box/platform.dart';
|
||||
import 'package:rhythm_box/providers/audio_player_stream.dart';
|
||||
import 'package:rhythm_box/providers/database.dart';
|
||||
import 'package:rhythm_box/providers/palette.dart';
|
||||
import 'package:rhythm_box/services/audio_player/audio_player.dart';
|
||||
import 'package:rhythm_box/services/color.dart';
|
||||
import 'package:rhythm_box/services/database/database.dart';
|
||||
import 'package:rhythm_box/services/sourced_track/enums.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
typedef UserPreferences = PreferencesTableData;
|
||||
|
||||
class UserPreferencesProvider extends GetxController {
|
||||
final Rx<UserPreferences> state = PreferencesTable.defaults().obs;
|
||||
late final AppDatabase db;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
db = Get.find<DatabaseProvider>().database;
|
||||
_initializePreferences();
|
||||
}
|
||||
|
||||
Future<void> _initializePreferences() async {
|
||||
var result = await (db.select(db.preferencesTable)
|
||||
..where((tbl) => tbl.id.equals(0)))
|
||||
.getSingleOrNull();
|
||||
if (result == null) {
|
||||
await db.into(db.preferencesTable).insert(
|
||||
PreferencesTableCompanion.insert(
|
||||
id: const Value(0),
|
||||
downloadLocation: Value(await _getDefaultDownloadDirectory()),
|
||||
),
|
||||
);
|
||||
}
|
||||
state.value = await (db.select(db.preferencesTable)
|
||||
..where((tbl) => tbl.id.equals(0)))
|
||||
.getSingle();
|
||||
|
||||
// Subscribe to updates
|
||||
(db.select(db.preferencesTable)..where((tbl) => tbl.id.equals(0)))
|
||||
.watchSingle()
|
||||
.listen((event) async {
|
||||
state.value = event;
|
||||
|
||||
if (PlatformInfo.isDesktop) {
|
||||
await windowManager.setTitleBarStyle(
|
||||
state.value.systemTitleBar
|
||||
? TitleBarStyle.normal
|
||||
: TitleBarStyle.hidden,
|
||||
);
|
||||
}
|
||||
|
||||
await audioPlayer.setAudioNormalization(state.value.normalizeAudio);
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> _getDefaultDownloadDirectory() async {
|
||||
if (PlatformInfo.isAndroid) return '/storage/emulated/0/Download/RhythmBox';
|
||||
|
||||
if (PlatformInfo.isMacOS) {
|
||||
return join((await getLibraryDirectory()).path, 'Caches');
|
||||
}
|
||||
|
||||
return getDownloadsDirectory().then((dir) {
|
||||
return join(dir!.path, 'RhythmBox');
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> setData(PreferencesTableCompanion data) async {
|
||||
await (db.update(db.preferencesTable)..where((t) => t.id.equals(0)))
|
||||
.write(data);
|
||||
}
|
||||
|
||||
Future<void> reset() async {
|
||||
await (db.update(db.preferencesTable)..where((t) => t.id.equals(0)))
|
||||
.replace(PreferencesTableCompanion.insert());
|
||||
}
|
||||
|
||||
void setStreamMusicCodec(SourceCodecs codec) {
|
||||
setData(PreferencesTableCompanion(streamMusicCodec: Value(codec)));
|
||||
}
|
||||
|
||||
void setDownloadMusicCodec(SourceCodecs codec) {
|
||||
setData(PreferencesTableCompanion(downloadMusicCodec: Value(codec)));
|
||||
}
|
||||
|
||||
void setThemeMode(ThemeMode mode) {
|
||||
setData(PreferencesTableCompanion(themeMode: Value(mode)));
|
||||
}
|
||||
|
||||
void setRecommendationMarket(Market country) {
|
||||
setData(PreferencesTableCompanion(market: Value(country)));
|
||||
}
|
||||
|
||||
void setAccentColorScheme(RhythmColor color) {
|
||||
setData(PreferencesTableCompanion(accentColorScheme: Value(color)));
|
||||
}
|
||||
|
||||
void setAlbumColorSync(bool sync) {
|
||||
setData(PreferencesTableCompanion(albumColorSync: Value(sync)));
|
||||
|
||||
if (!sync) {
|
||||
Get.find<PaletteProvider>().clear();
|
||||
} else {
|
||||
Get.find<AudioPlayerStreamProvider>().updatePalette();
|
||||
}
|
||||
}
|
||||
|
||||
void setCheckUpdate(bool check) {
|
||||
setData(PreferencesTableCompanion(checkUpdate: Value(check)));
|
||||
}
|
||||
|
||||
void setAudioQuality(SourceQualities quality) {
|
||||
setData(PreferencesTableCompanion(audioQuality: Value(quality)));
|
||||
}
|
||||
|
||||
void setDownloadLocation(String downloadDir) {
|
||||
if (downloadDir.isEmpty) return;
|
||||
setData(PreferencesTableCompanion(downloadLocation: Value(downloadDir)));
|
||||
}
|
||||
|
||||
void setLocalLibraryLocation(List<String> localLibraryDirs) {
|
||||
setData(PreferencesTableCompanion(
|
||||
localLibraryLocation: Value(localLibraryDirs)));
|
||||
}
|
||||
|
||||
void setLayoutMode(LayoutMode mode) {
|
||||
setData(PreferencesTableCompanion(layoutMode: Value(mode)));
|
||||
}
|
||||
|
||||
void setCloseBehavior(CloseBehavior behavior) {
|
||||
setData(PreferencesTableCompanion(closeBehavior: Value(behavior)));
|
||||
}
|
||||
|
||||
void setShowSystemTrayIcon(bool show) {
|
||||
setData(PreferencesTableCompanion(showSystemTrayIcon: Value(show)));
|
||||
}
|
||||
|
||||
void setLocale(Locale locale) {
|
||||
setData(PreferencesTableCompanion(locale: Value(locale)));
|
||||
}
|
||||
|
||||
void setPipedInstance(String instance) {
|
||||
setData(PreferencesTableCompanion(pipedInstance: Value(instance)));
|
||||
}
|
||||
|
||||
void setSearchMode(SearchMode mode) {
|
||||
setData(PreferencesTableCompanion(searchMode: Value(mode)));
|
||||
}
|
||||
|
||||
void setSkipNonMusic(bool skip) {
|
||||
setData(PreferencesTableCompanion(skipNonMusic: Value(skip)));
|
||||
}
|
||||
|
||||
void setAudioSource(AudioSource type) {
|
||||
setData(PreferencesTableCompanion(audioSource: Value(type)));
|
||||
}
|
||||
|
||||
void setSystemTitleBar(bool isSystemTitleBar) {
|
||||
setData(PreferencesTableCompanion(systemTitleBar: Value(isSystemTitleBar)));
|
||||
}
|
||||
|
||||
void setDiscordPresence(bool discordPresence) {
|
||||
setData(PreferencesTableCompanion(discordPresence: Value(discordPresence)));
|
||||
}
|
||||
|
||||
void setAmoledDarkTheme(bool isAmoled) {
|
||||
setData(PreferencesTableCompanion(amoledDarkTheme: Value(isAmoled)));
|
||||
}
|
||||
|
||||
void setNormalizeAudio(bool normalize) {
|
||||
setData(PreferencesTableCompanion(normalizeAudio: Value(normalize)));
|
||||
audioPlayer.setAudioNormalization(normalize);
|
||||
}
|
||||
|
||||
void setEndlessPlayback(bool endless) {
|
||||
setData(PreferencesTableCompanion(endlessPlayback: Value(endless)));
|
||||
}
|
||||
|
||||
void setEnableConnect(bool enable) {
|
||||
setData(PreferencesTableCompanion(enableConnect: Value(enable)));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user