@@ -78,6 +78,7 @@ class MusifyAudioHandler extends BaseAudioHandler {
7878 final List <Map > _historyList = [];
7979 final BehaviorSubject <List <Map >> _queueMapStream =
8080 BehaviorSubject <List <Map >>.seeded ([]);
81+ int _queueEntryCounter = 0 ;
8182 int _currentQueueIndex = 0 ;
8283 int _currentLoadingIndex = - 1 ;
8384 int _currentLoadingTransitionId = - 1 ;
@@ -237,8 +238,40 @@ class MusifyAudioHandler extends BaseAudioHandler {
237238 });
238239 }
239240
240- MediaItem _getMediaItemForQueue (Map song, int index) {
241- return mapToMediaItem (song).copyWith (id: '${song ['ytid' ]}_$index ' );
241+ String _generateQueueEntryId () {
242+ return 'queue-${DateTime .now ().microsecondsSinceEpoch }-${_queueEntryCounter ++}' ;
243+ }
244+
245+ String _ensureQueueEntryId (Map song) {
246+ final existingId = song['queueEntryId' ]? .toString ();
247+ if (existingId != null && existingId.isNotEmpty) {
248+ return existingId;
249+ }
250+
251+ final generatedId = _generateQueueEntryId ();
252+ song['queueEntryId' ] = generatedId;
253+ return generatedId;
254+ }
255+
256+ Map <String , dynamic > _createQueueSong (Map song) {
257+ final queueSong = Map <String , dynamic >.from (song);
258+ queueSong['queueEntryId' ] = _generateQueueEntryId ();
259+ return queueSong;
260+ }
261+
262+ void _ensureQueueEntryIds (Iterable <Map > songs) {
263+ for (final song in songs) {
264+ _ensureQueueEntryId (song);
265+ }
266+ }
267+
268+ void _hydrateQueueEntryIds () {
269+ _ensureQueueEntryIds (_queueList);
270+ _ensureQueueEntryIds (_originalQueueList);
271+ }
272+
273+ MediaItem _getMediaItemForQueue (Map song) {
274+ return mapToMediaItem (song).copyWith (id: _ensureQueueEntryId (song));
242275 }
243276
244277 void _updateCurrentMediaItemWithDuration (Duration duration) {
@@ -256,10 +289,7 @@ class MusifyAudioHandler extends BaseAudioHandler {
256289 }
257290
258291 final currentSong = _queueList[capturedQueueIndex];
259- final currentMediaItem = _getMediaItemForQueue (
260- currentSong,
261- capturedQueueIndex,
262- );
292+ final currentMediaItem = _getMediaItemForQueue (currentSong);
263293 final uniqueId = currentMediaItem.id;
264294 final currentItem = mediaItem.valueOrNull;
265295
@@ -270,16 +300,11 @@ class MusifyAudioHandler extends BaseAudioHandler {
270300 mediaItem.add (currentMediaItem.copyWith (duration: duration));
271301 }
272302
273- List <MediaItem > newQueue;
274- if (queue.hasValue && queue.value.length == _queueList.length) {
275- newQueue = List <MediaItem >.from (queue.value);
276- } else {
277- newQueue = _queueList
278- .asMap ()
279- .entries
280- .map ((entry) => _getMediaItemForQueue (entry.value, entry.key))
281- .toList ();
282- }
303+ final newQueue = _queueList
304+ .asMap ()
305+ .entries
306+ .map ((entry) => _getMediaItemForQueue (entry.value))
307+ .toList ();
283308
284309 if (capturedQueueIndex < newQueue.length) {
285310 newQueue[capturedQueueIndex] = newQueue[capturedQueueIndex].copyWith (
@@ -742,7 +767,7 @@ class MusifyAudioHandler extends BaseAudioHandler {
742767 insertIndex = _queueList.length;
743768 }
744769
745- _queueList.insert (insertIndex, song);
770+ _queueList.insert (insertIndex, _createQueueSong ( song) );
746771
747772 if (_currentQueueIndex < 0 ) {
748773 _currentQueueIndex = 0 ;
@@ -821,14 +846,15 @@ class MusifyAudioHandler extends BaseAudioHandler {
821846 for (var i = 0 ; i < songs.length; i++ ) {
822847 final song = songs[i];
823848 if (song['ytid' ] != null && song['ytid' ].toString ().isNotEmpty) {
824- _queueList.add (song);
849+ _queueList.add (_createQueueSong ( song) );
825850
826851 if (replace && startIndex == i) {
827852 targetQueueIndex = _queueList.length - 1 ;
828853 }
829854 }
830855 }
831856
857+ _hydrateQueueEntryIds ();
832858 _updateQueueMediaItems ();
833859
834860 if (targetQueueIndex != null ) {
@@ -854,11 +880,12 @@ class MusifyAudioHandler extends BaseAudioHandler {
854880 if (index < 0 || index >= _queueList.length) return ;
855881
856882 final removedSong = _queueList[index];
883+ final removedQueueEntryId = _ensureQueueEntryId (removedSong);
857884 _queueList.removeAt (index);
858885
859886 if (shuffleNotifier.value && _originalQueueList.isNotEmpty) {
860887 _originalQueueList.removeWhere (
861- (s) => s[ 'ytid' ] != null && s[ 'ytid' ] == removedSong[ 'ytid' ] ,
888+ (s) => _ensureQueueEntryId (s) == removedQueueEntryId ,
862889 );
863890 }
864891
@@ -877,6 +904,7 @@ class MusifyAudioHandler extends BaseAudioHandler {
877904 await _playFromQueue (_currentQueueIndex);
878905 }
879906
907+ _hydrateQueueEntryIds ();
880908 _updateQueueMediaItems ();
881909 } catch (e, stackTrace) {
882910 logger.log ('Error removing from queue' , error: e, stackTrace: stackTrace);
@@ -885,6 +913,8 @@ class MusifyAudioHandler extends BaseAudioHandler {
885913
886914 Future <void > reorderQueue (int oldIndex, int newIndex) async {
887915 try {
916+ _ensureQueueEntryIds (_queueList);
917+
888918 if (oldIndex < 0 ||
889919 oldIndex >= _queueList.length ||
890920 newIndex < 0 ||
@@ -927,10 +957,12 @@ class MusifyAudioHandler extends BaseAudioHandler {
927957
928958 void _updateQueueMediaItems () {
929959 try {
960+ _ensureQueueEntryIds (_queueList);
961+
930962 final mediaItems = _queueList
931963 .asMap ()
932964 .entries
933- .map ((entry) => _getMediaItemForQueue (entry.value, entry.key ))
965+ .map ((entry) => _getMediaItemForQueue (entry.value))
934966 .toList ();
935967 queue.add (mediaItems);
936968
@@ -1036,10 +1068,7 @@ class MusifyAudioHandler extends BaseAudioHandler {
10361068 _currentQueueIndex = index;
10371069
10381070 final currentSong = _queueList[_currentQueueIndex];
1039- final currentMediaItem = _getMediaItemForQueue (
1040- currentSong,
1041- _currentQueueIndex,
1042- );
1071+ final currentMediaItem = _getMediaItemForQueue (currentSong);
10431072 final uniqueId = currentMediaItem.id;
10441073
10451074 await Future .microtask (() {
@@ -1660,41 +1689,43 @@ class MusifyAudioHandler extends BaseAudioHandler {
16601689 if (_queueList.isEmpty) return ;
16611690
16621691 if (shuffleEnabled && ! wasShuffled) {
1692+ _hydrateQueueEntryIds ();
1693+
16631694 _originalQueueList
16641695 ..clear ()
16651696 ..addAll (_queueList);
16661697
16671698 final currentSong = _queueList[_currentQueueIndex];
1668- final currentYtId = currentSong[ 'ytid' ] ;
1699+ final currentQueueEntryId = _ensureQueueEntryId ( currentSong) ;
16691700
16701701 _queueList.shuffle ();
16711702
1672- if (currentYtId != null ) {
1673- final newCurrentIndex = _queueList.indexWhere (
1674- (song) => song['ytid' ] == currentYtId,
1675- );
1703+ final newCurrentIndex = _queueList.indexWhere (
1704+ (song) => _ensureQueueEntryId (song) == currentQueueEntryId,
1705+ );
16761706
1677- if (newCurrentIndex != - 1 && newCurrentIndex != 0 ) {
1678- _queueList
1679- ..removeAt (newCurrentIndex)
1680- ..insert (0 , currentSong);
1681- }
1707+ if (newCurrentIndex != - 1 && newCurrentIndex != 0 ) {
1708+ _queueList
1709+ ..removeAt (newCurrentIndex)
1710+ ..insert (0 , currentSong);
16821711 }
16831712
16841713 _currentQueueIndex = 0 ;
16851714 _updateQueueMediaItems ();
16861715 } else if (! shuffleEnabled && wasShuffled) {
16871716 if (_originalQueueList.isNotEmpty) {
1717+ _hydrateQueueEntryIds ();
1718+
16881719 final currentSong = _queueList[_currentQueueIndex];
1689- final currentYtId = currentSong[ 'ytid' ] ;
1720+ final currentQueueEntryId = _ensureQueueEntryId ( currentSong) ;
16901721
16911722 _queueList
16921723 ..clear ()
16931724 ..addAll (_originalQueueList);
16941725
1695- _currentQueueIndex = currentYtId != null
1696- ? _queueList. indexWhere (( song) => song[ 'ytid' ] == currentYtId)
1697- : 0 ;
1726+ _currentQueueIndex = _queueList. indexWhere (
1727+ ( song) => _ensureQueueEntryId ( song) == currentQueueEntryId,
1728+ ) ;
16981729
16991730 if (_currentQueueIndex == - 1 ) {
17001731 _currentQueueIndex = 0 ;
0 commit comments