freezer/lib/ui/queue_screen.dart

144 lines
5.3 KiB
Dart
Raw Normal View History

2023-07-29 02:17:26 +00:00
import 'dart:async';
import 'package:audio_service/audio_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:freezer/api/definitions.dart';
import 'package:freezer/api/player.dart';
import 'package:freezer/translations.i18n.dart';
import 'package:freezer/ui/player_screen.dart';
import 'package:freezer/ui/tiles.dart';
class QueueScreen extends StatefulWidget {
@override
_QueueScreenState createState() => _QueueScreenState();
}
class _QueueScreenState extends State<QueueScreen> {
late StreamSubscription _queueSub;
static const _dismissibleBackground = DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Align(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Icon(Icons.delete)),
alignment: Alignment.centerLeft));
static const _dismissibleSecondaryBackground = DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Align(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Icon(Icons.delete)),
alignment: Alignment.centerRight));
/// Basically a simple list that keeps itself synchronized with [AudioHandler.queue],
/// so that the [ReorderableListView] is updated instanly (as it should be)
List<MediaItem> _queueCache = [];
@override
void initState() {
_queueCache = List.from(audioHandler.queue.value); // avoid shadow-copying
_queueSub = audioHandler.queue.listen((newQueue) {
print('got new queue!');
print(newQueue.map((e) => e.title).toList());
// avoid rebuilding if the cache has got the right update
// if (listEquals(_queueCache, newQueue)) {
// print('avoiding rebuilding queue since they are the same');
// return;
// }
_queueCache = List.from(newQueue);
setState(() {});
});
super.initState();
}
@override
void dispose() {
_queueSub.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Queue'.i18n),
systemOverlayStyle: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.light,
statusBarBrightness: Brightness.light,
systemNavigationBarColor: Theme.of(context).scaffoldBackgroundColor,
systemNavigationBarDividerColor: Color(
Theme.of(context).scaffoldBackgroundColor.value - 0x00111111),
systemNavigationBarIconBrightness: Brightness.light,
),
// actions: <Widget>[
// IconButton(
// icon: Icon(
// Icons.shuffle,
// semanticLabel: "Shuffle".i18n,
// ),
// onPressed: () async {
// await playerHelper.toggleShuffle();
// setState(() {});
// },
// )
// ],
),
body: SafeArea(
child: ReorderableListView.builder(
onReorder: (oldIndex, newIndex) {
if (oldIndex == playerHelper.queueIndex) return;
_queueCache.reorder(oldIndex, newIndex);
playerHelper.reorder(oldIndex, newIndex);
setState(() {});
},
itemCount: _queueCache.length,
itemBuilder: (BuildContext context, int i) {
Track track = Track.fromMediaItem(audioHandler.queue.value[i]);
return Dismissible(
key: ValueKey<String>(track.id),
background: _dismissibleBackground,
secondaryBackground: _dismissibleSecondaryBackground,
onDismissed: (_) {
audioHandler.removeQueueItemAt(i);
setState(() => _queueCache.removeAt(i));
},
confirmDismiss: (_) {
if (i == playerHelper.queueIndex)
return audioHandler.skipToNext().then((value) => true);
return Future.value(true);
// final completer = Completer<bool>();
// ScaffoldMessenger.of(context).clearSnackBars();
// ScaffoldMessenger.of(context)
// .showSnackBar(SnackBar(
// behavior: SnackBarBehavior.floating,
// content: Text('Song deleted from queue'),
// action: SnackBarAction(
// label: 'UNDO',
// onPressed: () => completer.complete(false))))
// .closed
// .then((value) {
// if (value == SnackBarClosedReason.action) return;
// completer.complete(true);
// });
// return completer.future;
},
child: TrackTile(
track,
onTap: () {
pageViewLock = true;
audioHandler.skipToQueueItem(i).then((value) {
Navigator.of(context).pop();
pageViewLock = false;
});
},
key: Key(track.id),
),
);
},
),
),
);
}
}