mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-07-26 05:51:18 +02:00
fix(download): suffix batch filenames with track number when needed
Mark multi-track queue additions as batch downloads and append
{track:02} - {title} when the configured format has no uniqueness
token, instead of relying on playlist position alone.
This commit is contained in:
@@ -38,6 +38,7 @@ class DownloadItem {
|
||||
final String? qualityOverride;
|
||||
final String? playlistName;
|
||||
final int? playlistPosition; // 1-based position in the source playlist
|
||||
final bool fromBatch;
|
||||
|
||||
const DownloadItem({
|
||||
required this.id,
|
||||
@@ -55,6 +56,7 @@ class DownloadItem {
|
||||
this.qualityOverride,
|
||||
this.playlistName,
|
||||
this.playlistPosition,
|
||||
this.fromBatch = false,
|
||||
});
|
||||
|
||||
DownloadItem copyWith({
|
||||
@@ -73,6 +75,7 @@ class DownloadItem {
|
||||
String? qualityOverride,
|
||||
String? playlistName,
|
||||
int? playlistPosition,
|
||||
bool? fromBatch,
|
||||
}) {
|
||||
return DownloadItem(
|
||||
id: id ?? this.id,
|
||||
@@ -90,6 +93,7 @@ class DownloadItem {
|
||||
qualityOverride: qualityOverride ?? this.qualityOverride,
|
||||
playlistName: playlistName ?? this.playlistName,
|
||||
playlistPosition: playlistPosition ?? this.playlistPosition,
|
||||
fromBatch: fromBatch ?? this.fromBatch,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ DownloadItem _$DownloadItemFromJson(Map<String, dynamic> json) => DownloadItem(
|
||||
qualityOverride: json['qualityOverride'] as String?,
|
||||
playlistName: json['playlistName'] as String?,
|
||||
playlistPosition: (json['playlistPosition'] as num?)?.toInt(),
|
||||
fromBatch: json['fromBatch'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$DownloadItemToJson(DownloadItem instance) =>
|
||||
@@ -43,6 +44,7 @@ Map<String, dynamic> _$DownloadItemToJson(DownloadItem instance) =>
|
||||
'qualityOverride': instance.qualityOverride,
|
||||
'playlistName': instance.playlistName,
|
||||
'playlistPosition': instance.playlistPosition,
|
||||
'fromBatch': instance.fromBatch,
|
||||
};
|
||||
|
||||
const _$DownloadStatusEnumMap = {
|
||||
|
||||
@@ -189,6 +189,10 @@ const _defaultOutputFolderName = 'SpotiFLAC';
|
||||
const _defaultAndroidMusicSubpath = 'Music/$_defaultOutputFolderName';
|
||||
const _maxSafFilenameUtf8Bytes = 180;
|
||||
const _maxSafDirSegmentUtf8Bytes = 120;
|
||||
final _batchUniqueFilenameTokenPattern = RegExp(
|
||||
r'\{(?:title|track(?:_raw)?|track:\d+|playlist_position(?:_raw)?|playlist_position:\d+|playlist position|playlistPosition|position(?::\d+)?)\}',
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
class DownloadHistoryItem {
|
||||
final String id;
|
||||
@@ -3863,6 +3867,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final takenIds = state.items.map((item) => item.id).toSet();
|
||||
final shouldAssignPlaylistPositions =
|
||||
playlistName != null && playlistName.trim().isNotEmpty;
|
||||
final fromBatch = tracks.length > 1;
|
||||
final newItems = tracks.asMap().entries.map((entry) {
|
||||
final track = entry.value;
|
||||
final index = entry.key;
|
||||
@@ -3884,6 +3889,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
playlistPosition:
|
||||
explicitPosition ??
|
||||
(shouldAssignPlaylistPositions ? index + 1 : null),
|
||||
fromBatch: fromBatch,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
@@ -3902,19 +3908,17 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
}
|
||||
|
||||
String _filenameFormatForItem(DownloadItem item, String baseFormat) {
|
||||
if (_validPlaylistPosition(item) == 0 ||
|
||||
item.playlistName == null ||
|
||||
item.playlistName!.trim().isEmpty) {
|
||||
if (!item.fromBatch) {
|
||||
return baseFormat;
|
||||
}
|
||||
|
||||
final lower = baseFormat.toLowerCase();
|
||||
if (lower.contains('{playlist_position') ||
|
||||
lower.contains('{playlist position') ||
|
||||
lower.contains('{playlistposition')) {
|
||||
final trimmed = baseFormat.trim();
|
||||
if (trimmed.isEmpty) {
|
||||
return baseFormat;
|
||||
}
|
||||
return '{playlist_position:02} - $baseFormat';
|
||||
if (_batchUniqueFilenameTokenPattern.hasMatch(trimmed)) {
|
||||
return baseFormat;
|
||||
}
|
||||
return '$trimmed - {track:02} - {title}';
|
||||
}
|
||||
|
||||
Map<String, dynamic> _filenameMetadataForTrack(
|
||||
|
||||
Reference in New Issue
Block a user