Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
3cbba21a00
19 changed files with 66 additions and 112 deletions
|
@ -193,7 +193,7 @@ class DynamicQueue implements ManagedQueueInfo {
|
|||
void removeQueueIndices(List<int> indices, bool permanent) {
|
||||
_log.d('removeQueueIndices');
|
||||
|
||||
for (final index in indices..sort(((a, b) => -a.compareTo(b)))) {
|
||||
for (final index in indices..sort((a, b) => -a.compareTo(b))) {
|
||||
final queueItem = _queue[index];
|
||||
|
||||
if (permanent) {
|
||||
|
@ -316,9 +316,9 @@ class DynamicQueue implements ManagedQueueInfo {
|
|||
newSongs = await _shufflePlusQueue(filteredAvailableSongs, songsToQueue);
|
||||
}
|
||||
|
||||
newSongs.forEach((qi) {
|
||||
for (final qi in newSongs) {
|
||||
qi.isAvailable = false;
|
||||
});
|
||||
}
|
||||
_queue.addAll(newSongs);
|
||||
_queueSubject.add(_queue);
|
||||
_availableSongsSubject.add(_availableSongs);
|
||||
|
@ -475,9 +475,9 @@ class DynamicQueue implements ManagedQueueInfo {
|
|||
}
|
||||
|
||||
// these qi are the same objects as in _availableSongs -> marks them to not be queued (again)
|
||||
queue.forEach((qi) {
|
||||
for (final qi in queue) {
|
||||
qi.isAvailable = false;
|
||||
});
|
||||
}
|
||||
_queue = queue.cast();
|
||||
_queueSubject.add(_queue);
|
||||
return 0;
|
||||
|
@ -494,7 +494,9 @@ class DynamicQueue implements ManagedQueueInfo {
|
|||
final linkedSong = await getQueueItemWithLinks(locallyAvailableSongs[index], queueItems);
|
||||
queue.addAll(linkedSong);
|
||||
if (linkedSong.length > 1) {
|
||||
linkedSong.forEach((q) => locallyAvailableSongs.removeWhere((e) => e.song == q.song));
|
||||
for (final q in linkedSong) {
|
||||
locallyAvailableSongs.removeWhere((e) => e.song == q.song);
|
||||
}
|
||||
} else {
|
||||
locallyAvailableSongs.removeAt(index);
|
||||
}
|
||||
|
|
|
@ -86,11 +86,11 @@ class HomeSettingsPage extends StatelessWidget {
|
|||
background: Container(
|
||||
width: double.infinity,
|
||||
color: RED,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
children: [
|
||||
Icon(
|
||||
Icons.delete_forever_rounded,
|
||||
color: Colors.white,
|
||||
|
|
|
@ -2,14 +2,10 @@
|
|||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import '../state/import_store.dart';
|
||||
import '../state/navigation_store.dart';
|
||||
import '../theming.dart';
|
||||
import '../widgets/settings_section.dart';
|
||||
|
||||
class ImportPage extends StatefulWidget {
|
||||
const ImportPage({Key? key, required this.importPath}) : super(key: key);
|
||||
|
@ -21,12 +17,10 @@ class ImportPage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _ImportPageState extends State<ImportPage> {
|
||||
late final ImportStore _importStore;
|
||||
late final NavigationStore _navStore;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_importStore = GetIt.I<ImportStore>(param1: widget.importPath);
|
||||
_navStore = GetIt.I<NavigationStore>();
|
||||
|
||||
super.initState();
|
||||
|
@ -36,7 +30,7 @@ class _ImportPageState extends State<ImportPage> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
title: const Text(
|
||||
'Import Data',
|
||||
style: TEXT_HEADER,
|
||||
),
|
||||
|
@ -53,7 +47,7 @@ class _ImportPageState extends State<ImportPage> {
|
|||
centerTitle: true,
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
children: const [
|
||||
// Observer(builder: (context) {
|
||||
// final dataInfo = _importStore.appData;
|
||||
// if (dataInfo == null) {
|
||||
|
|
|
@ -81,9 +81,9 @@ class _InitWorkflowState extends State<InitWorkflow> {
|
|||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: FilledButton(
|
||||
child: Row(
|
||||
child: const Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: const [
|
||||
children: [
|
||||
Icon(Icons.chevron_left_rounded),
|
||||
Text('Back'),
|
||||
SizedBox(width: 10),
|
||||
|
|
|
@ -5,10 +5,8 @@ import 'package:get_it/get_it.dart';
|
|||
import 'package:reorderables/reorderables.dart';
|
||||
|
||||
import '../../domain/entities/playlist.dart';
|
||||
import '../../domain/entities/shuffle_mode.dart';
|
||||
import '../../domain/entities/song.dart';
|
||||
import '../l10n_utils.dart';
|
||||
import '../mucke_icons.dart';
|
||||
import '../state/audio_store.dart';
|
||||
import '../state/music_data_store.dart';
|
||||
import '../state/navigation_store.dart';
|
||||
|
@ -67,20 +65,6 @@ class _PlaylistPageState extends State<PlaylistPage> {
|
|||
(Duration d, s) => d + s.duration,
|
||||
);
|
||||
|
||||
IconData playIcon = Icons.play_arrow_rounded;
|
||||
switch (playlist.shuffleMode) {
|
||||
case ShuffleMode.standard:
|
||||
playIcon = Icons.shuffle_rounded;
|
||||
break;
|
||||
case ShuffleMode.plus:
|
||||
playIcon = MuckeIcons.shuffle_heart;
|
||||
break;
|
||||
case ShuffleMode.none:
|
||||
playIcon = MuckeIcons.shuffle_none;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return Scrollbar(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
|
@ -207,13 +191,13 @@ class _PlaylistPageState extends State<PlaylistPage> {
|
|||
background: Container(
|
||||
width: double.infinity,
|
||||
color: RED,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: HORIZONTAL_PADDING,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
children: [
|
||||
Icon(
|
||||
Icons.playlist_remove_rounded,
|
||||
color: Colors.white,
|
||||
|
|
|
@ -179,11 +179,11 @@ class QueuePage extends StatelessWidget {
|
|||
background: Container(
|
||||
width: double.infinity,
|
||||
color: RED,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: HORIZONTAL_PADDING),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const [
|
||||
children: [
|
||||
Icon(
|
||||
Icons.playlist_remove_rounded,
|
||||
color: Colors.white,
|
||||
|
|
|
@ -3,11 +3,9 @@ import 'package:flutter_gen/gen_l10n/localizations.dart';
|
|||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import '../../domain/entities/shuffle_mode.dart';
|
||||
import '../../domain/entities/smart_list.dart';
|
||||
import '../../domain/entities/song.dart';
|
||||
import '../l10n_utils.dart';
|
||||
import '../mucke_icons.dart';
|
||||
import '../state/audio_store.dart';
|
||||
import '../state/music_data_store.dart';
|
||||
import '../state/navigation_store.dart';
|
||||
|
@ -63,20 +61,6 @@ class _SmartListPageState extends State<SmartListPage> {
|
|||
(Duration d, s) => d + s.duration,
|
||||
);
|
||||
|
||||
IconData playIcon = Icons.play_arrow_rounded;
|
||||
switch (smartList.shuffleMode) {
|
||||
case ShuffleMode.standard:
|
||||
playIcon = Icons.shuffle_rounded;
|
||||
break;
|
||||
case ShuffleMode.plus:
|
||||
playIcon = MuckeIcons.shuffle_heart;
|
||||
break;
|
||||
case ShuffleMode.none:
|
||||
playIcon = MuckeIcons.shuffle_none;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return Scrollbar(
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
|
|
|
@ -61,9 +61,9 @@ class _SongsPageState extends State<SongsPage> with AutomaticKeepAliveClientMixi
|
|||
);
|
||||
case StreamStatus.waiting:
|
||||
case StreamStatus.done:
|
||||
return Column(
|
||||
return const Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const <Widget>[
|
||||
children: <Widget>[
|
||||
CircularProgressIndicator(),
|
||||
Text('Loading items...'),
|
||||
],
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:fimber/fimber.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
|
@ -11,8 +10,6 @@ import 'album_art.dart';
|
|||
class AlbumArtSwipe extends StatefulWidget {
|
||||
const AlbumArtSwipe({Key? key}) : super(key: key);
|
||||
|
||||
static final _log = FimberLog('AlbumArtSwipe');
|
||||
|
||||
@override
|
||||
State<AlbumArtSwipe> createState() => _AlbumArtSwipeState();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
|
|
@ -9,8 +9,8 @@ class CurrentlyPlayingControl extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: const [
|
||||
return const Column(
|
||||
children: [
|
||||
SizedBox(height: 10.0),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 12.0 + 2.0),
|
||||
|
|
|
@ -11,8 +11,8 @@ class PlaybackControl extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: const [
|
||||
return const Row(
|
||||
children: [
|
||||
LoopButton(iconSize: 24.0),
|
||||
PreviousButton(iconSize: 48.0),
|
||||
PlayPauseButton(
|
||||
|
|
|
@ -55,9 +55,9 @@ class HistoryDao extends DatabaseAccessor<MainDatabase>
|
|||
}
|
||||
|
||||
final historyStream = query.watch();
|
||||
final slArtistStream = (select(smartListArtists).join(
|
||||
final slArtistStream = select(smartListArtists).join(
|
||||
[innerJoin(artists, artists.name.equalsExp(smartListArtists.artistName))],
|
||||
)).watch();
|
||||
).watch();
|
||||
|
||||
return Rx.combineLatest2<List<TypedResult>, List<TypedResult>, List<HistoryEntryModel>>(
|
||||
historyStream,
|
||||
|
@ -80,9 +80,9 @@ class HistoryDao extends DatabaseAccessor<MainDatabase>
|
|||
playable = PlaylistModel.fromDrift(e.readTable(playlists));
|
||||
break;
|
||||
case PlayableType.smartlist:
|
||||
final driftArtists = (slArtists.where((element) =>
|
||||
final driftArtists = slArtists.where((element) =>
|
||||
element.readTable(smartListArtists).smartListId ==
|
||||
int.parse(entry.identifier))).map((e) => e.readTable(artists)).toList();
|
||||
int.parse(entry.identifier)).map((e) => e.readTable(artists)).toList();
|
||||
playable = SmartListModel.fromDrift(e.readTable(smartLists), driftArtists);
|
||||
break;
|
||||
case PlayableType.search:
|
||||
|
|
|
@ -192,9 +192,9 @@ class PersistentStateDao extends DatabaseAccessor<MainDatabase>
|
|||
result = null;
|
||||
else {
|
||||
final slArtists =
|
||||
await ((select(smartListArtists)..where((tbl) => tbl.smartListId.equals(slId))).join(
|
||||
await (select(smartListArtists)..where((tbl) => tbl.smartListId.equals(slId))).join(
|
||||
[innerJoin(artists, artists.name.equalsExp(smartListArtists.artistName))],
|
||||
)).map((p0) => p0.readTable(artists)).get();
|
||||
).map((p0) => p0.readTable(artists)).get();
|
||||
|
||||
result = SmartListModel.fromDrift(sl, slArtists);
|
||||
}
|
||||
|
|
|
@ -89,12 +89,12 @@ class PlaylistDao extends DatabaseAccessor<MainDatabase>
|
|||
|
||||
@override
|
||||
Stream<List<SongModel>> getPlaylistSongStream(PlaylistModel playlist) {
|
||||
return ((select(playlistEntries)
|
||||
return (select(playlistEntries)
|
||||
..where((tbl) => tbl.playlistId.equals(playlist.id))
|
||||
..orderBy([(t) => OrderingTerm.asc(t.position)]))
|
||||
.join(
|
||||
[innerJoin(songs, songs.path.equalsExp(playlistEntries.songPath))],
|
||||
)).watch().map((driftSongList) =>
|
||||
).watch().map((driftSongList) =>
|
||||
driftSongList.map((driftSong) => SongModel.fromDrift(driftSong.readTable(songs))).toList());
|
||||
}
|
||||
|
||||
|
@ -221,9 +221,9 @@ class PlaylistDao extends DatabaseAccessor<MainDatabase>
|
|||
Stream<List<SmartListModel>> get smartListsStream {
|
||||
final slStream = select(smartLists).watch();
|
||||
|
||||
final slArtistStream = (select(smartListArtists).join(
|
||||
final slArtistStream = select(smartListArtists).join(
|
||||
[innerJoin(artists, artists.name.equalsExp(smartListArtists.artistName))],
|
||||
)).watch();
|
||||
).watch();
|
||||
|
||||
return Rx.combineLatest2<List<DriftSmartList>, List<TypedResult>, List<SmartListModel>>(
|
||||
slStream,
|
||||
|
@ -231,7 +231,7 @@ class PlaylistDao extends DatabaseAccessor<MainDatabase>
|
|||
(a, b) {
|
||||
return a.map((sl) {
|
||||
final driftArtists =
|
||||
(b.where((element) => element.readTable(smartListArtists).smartListId == sl.id))
|
||||
b.where((element) => element.readTable(smartListArtists).smartListId == sl.id)
|
||||
.map((e) => e.readTable(artists))
|
||||
.toList();
|
||||
return SmartListModel.fromDrift(sl, driftArtists);
|
||||
|
@ -340,9 +340,9 @@ class PlaylistDao extends DatabaseAccessor<MainDatabase>
|
|||
|
||||
@override
|
||||
Future<List<SmartListModel>> searchSmartLists(String searchText, {int? limit}) async {
|
||||
final slArtists = await (select(smartListArtists).join(
|
||||
final slArtists = await select(smartListArtists).join(
|
||||
[innerJoin(artists, artists.name.equalsExp(smartListArtists.artistName))],
|
||||
)).get();
|
||||
).get();
|
||||
|
||||
final List<SmartListModel> result = await (select(smartLists)
|
||||
..where((tbl) => tbl.name.regexp(searchText, dotAll: true, caseSensitive: false)))
|
||||
|
@ -350,8 +350,8 @@ class PlaylistDao extends DatabaseAccessor<MainDatabase>
|
|||
.then(
|
||||
(driftList) {
|
||||
return driftList.map((driftSmartList) {
|
||||
final driftArtists = (slArtists.where((element) =>
|
||||
element.readTable(smartListArtists).smartListId == driftSmartList.id))
|
||||
final driftArtists = slArtists.where((element) =>
|
||||
element.readTable(smartListArtists).smartListId == driftSmartList.id)
|
||||
.map((e) => e.readTable(artists))
|
||||
.toList();
|
||||
return SmartListModel.fromDrift(driftSmartList, driftArtists);
|
||||
|
@ -418,12 +418,12 @@ class PlaylistDao extends DatabaseAccessor<MainDatabase>
|
|||
|
||||
@override
|
||||
Future<List<SongModel>> getPlaylistSongs(PlaylistModel playlist) async {
|
||||
return await ((select(playlistEntries)
|
||||
return await (select(playlistEntries)
|
||||
..where((tbl) => tbl.playlistId.equals(playlist.id))
|
||||
..orderBy([(t) => OrderingTerm.asc(t.position)]))
|
||||
.join(
|
||||
[innerJoin(songs, songs.path.equalsExp(playlistEntries.songPath))],
|
||||
)).get().then((driftSongList) =>
|
||||
).get().then((driftSongList) =>
|
||||
driftSongList.map((driftSong) => SongModel.fromDrift(driftSong.readTable(songs))).toList());
|
||||
}
|
||||
|
||||
|
@ -438,13 +438,13 @@ class PlaylistDao extends DatabaseAccessor<MainDatabase>
|
|||
Future<List<SmartListModel>> getSmartlists() async {
|
||||
final sls = await select(smartLists).get();
|
||||
|
||||
final slArtists = await (select(smartListArtists).join(
|
||||
final slArtists = await select(smartListArtists).join(
|
||||
[innerJoin(artists, artists.name.equalsExp(smartListArtists.artistName))],
|
||||
)).get();
|
||||
).get();
|
||||
|
||||
return sls.map((sl) {
|
||||
final driftArtists =
|
||||
(slArtists.where((element) => element.readTable(smartListArtists).smartListId == sl.id))
|
||||
slArtists.where((element) => element.readTable(smartListArtists).smartListId == sl.id)
|
||||
.map((e) => e.readTable(artists))
|
||||
.toList();
|
||||
return SmartListModel.fromDrift(sl, driftArtists);
|
||||
|
|
|
@ -91,7 +91,7 @@ class LocalMusicFetcherImpl implements LocalMusicFetcher {
|
|||
// => also update, when the file was created later (and wasn't really changed)
|
||||
// this is used as a workaround because android
|
||||
// doesn't seem to return the correct modification time
|
||||
final lastModified = await songFile.lastModified();
|
||||
final lastModified = songFile.lastModifiedSync();
|
||||
final song = await _musicDataSource.getSongByPath(songFile.path);
|
||||
|
||||
int? albumId;
|
||||
|
@ -233,12 +233,12 @@ class LocalMusicFetcherImpl implements LocalMusicFetcher {
|
|||
|
||||
Future<List<File>> getAllFilesRecursively(String path) async {
|
||||
final List<File> files = [];
|
||||
if (await FileSystemEntity.isDirectory(path)) {
|
||||
if (FileSystemEntity.isDirectorySync(path)) {
|
||||
final dir = Directory(path);
|
||||
await for (var entity in dir.list(recursive: true, followLinks: false)) {
|
||||
await for (final entity in dir.list(recursive: true, followLinks: false)) {
|
||||
files.addAll(await getAllFilesRecursively(entity.path));
|
||||
}
|
||||
} else if (await FileSystemEntity.isFile(path)) {
|
||||
} else if (FileSystemEntity.isFileSync(path)) {
|
||||
files.add(File(path));
|
||||
}
|
||||
return files;
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'package:metadata_god/metadata_god.dart';
|
|||
|
||||
import '../../domain/entities/album.dart';
|
||||
import '../datasources/drift_database.dart';
|
||||
import '../utils.dart';
|
||||
import 'default_values.dart';
|
||||
|
||||
class AlbumModel extends Album {
|
||||
|
|
|
@ -2,25 +2,21 @@ import 'package:audio_service/audio_service.dart';
|
|||
|
||||
import '../../domain/entities/playback_state.dart' as entity;
|
||||
|
||||
class PlaybackStateModel {
|
||||
|
||||
static entity.PlaybackState? fromASPlaybackState(PlaybackState? playbackState) {
|
||||
if (playbackState == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (playbackState.playing) {
|
||||
return entity.PlaybackState.playing;
|
||||
} else if (playbackState.processingState == AudioProcessingState.ready) {
|
||||
return entity.PlaybackState.paused;
|
||||
}
|
||||
|
||||
switch (playbackState.processingState) {
|
||||
case AudioProcessingState.completed:
|
||||
return entity.PlaybackState.stopped;
|
||||
default:
|
||||
return entity.PlaybackState.none;
|
||||
}
|
||||
entity.PlaybackState? fromASPlaybackState(PlaybackState? playbackState) {
|
||||
if (playbackState == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (playbackState.playing) {
|
||||
return entity.PlaybackState.playing;
|
||||
} else if (playbackState.processingState == AudioProcessingState.ready) {
|
||||
return entity.PlaybackState.paused;
|
||||
}
|
||||
|
||||
switch (playbackState.processingState) {
|
||||
case AudioProcessingState.completed:
|
||||
return entity.PlaybackState.stopped;
|
||||
default:
|
||||
return entity.PlaybackState.none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,6 @@ class AudioPlayerRepositoryImpl implements AudioPlayerRepository {
|
|||
_queueSubject.add(_dynamicQueue.queue);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> dispose() async {
|
||||
_audioPlayerDataSource.dispose();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue