feat(queue): tap a failed download to view its error details

Tapping a failed download tile (grid or list) now opens a dialog showing the full error message with retry and remove actions.
This commit is contained in:
zarzet
2026-06-14 05:26:30 +07:00
parent 7b22bbf25f
commit 983be8b37a
2 changed files with 74 additions and 8 deletions
+4 -6
View File
@@ -388,8 +388,6 @@ jobs:
### Installation
**Android**: Enable "Install from unknown sources" and install the APK
**iOS**: Use AltStore, Sideloadly, or similar tools to sideload the IPA
![arm64](https://img.shields.io/github/downloads/${REPO_OWNER}/${REPO_NAME}/${VERSION}/SpotiFLAC-${VERSION}-arm64.apk?style=flat-square&logo=android&label=arm64&color=3DDC84) ![arm32](https://img.shields.io/github/downloads/${REPO_OWNER}/${REPO_NAME}/${VERSION}/SpotiFLAC-${VERSION}-arm32.apk?style=flat-square&logo=android&label=arm32&color=3DDC84) ![iOS](https://img.shields.io/github/downloads/${REPO_OWNER}/${REPO_NAME}/${VERSION}/SpotiFLAC-${VERSION}-ios-unsigned.ipa?style=flat-square&logo=apple&label=iOS&color=0078D6)
FOOTER
echo "Release body:"
@@ -399,7 +397,7 @@ jobs:
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.get-version.outputs.version }}
name: SpotiFLAC ${{ needs.get-version.outputs.version }}
name: SpotiFLAC-Mobile ${{ needs.get-version.outputs.version }}
body_path: /tmp/release_body.txt
files: ./release/*
draft: false
@@ -565,7 +563,7 @@ jobs:
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \
-F chat_id="${TELEGRAM_CHANNEL_ID}" \
-F document=@"${ARM64_APK}" \
-F caption="SpotiFLAC ${VERSION} - arm64 (recommended)"
-F caption="SpotiFLAC Mobile ${VERSION} - arm64 (recommended)"
fi
# Upload arm32 APK to channel
@@ -574,7 +572,7 @@ jobs:
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \
-F chat_id="${TELEGRAM_CHANNEL_ID}" \
-F document=@"${ARM32_APK}" \
-F caption="SpotiFLAC ${VERSION} - arm32"
-F caption="SpotiFLAC Mobile ${VERSION} - arm32"
fi
# Upload iOS IPA to channel
@@ -584,7 +582,7 @@ jobs:
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendDocument" \
-F chat_id="${TELEGRAM_CHANNEL_ID}" \
-F document=@"${IOS_IPA}" \
-F caption="SpotiFLAC ${VERSION} - iOS (unsigned, sideload required)"
-F caption="SpotiFLAC Mobile ${VERSION} - iOS (unsigned, sideload required)"
fi
echo "Telegram notification sent!"
+70 -2
View File
@@ -3200,6 +3200,68 @@ class _QueueTabState extends ConsumerState<QueueTab> {
}
}
Future<void> _showDownloadErrorDialog(
BuildContext context,
DownloadItem item,
) async {
final colorScheme = Theme.of(context).colorScheme;
final isRateLimit = item.errorType == DownloadErrorType.rateLimit;
final title = isRateLimit
? context.l10n.queueRateLimitTitle
: context.l10n.updateDownloadFailed;
final message = isRateLimit
? context.l10n.queueRateLimitMessage
: (item.errorMessage.trim().isNotEmpty
? item.errorMessage
: context.l10n.updateDownloadFailed);
final action = await showDialog<String>(
context: context,
builder: (ctx) => AlertDialog(
title: Text(title),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
item.track.name,
style: Theme.of(
ctx,
).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600),
),
const SizedBox(height: 10),
SelectableText(
message,
style: Theme.of(ctx).textTheme.bodyMedium,
),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(ctx).pop('remove'),
style: TextButton.styleFrom(foregroundColor: colorScheme.error),
child: Text(context.l10n.dialogRemove),
),
TextButton(
onPressed: () => Navigator.of(ctx).pop(),
child: Text(context.l10n.dialogCancel),
),
FilledButton(
onPressed: () => Navigator.of(ctx).pop('retry'),
child: Text(context.l10n.dialogRetry),
),
],
),
);
if (!mounted) return;
if (action == 'retry') {
ref.read(downloadQueueProvider.notifier).retryItem(item.id);
} else if (action == 'remove') {
ref.read(downloadQueueProvider.notifier).removeItem(item.id);
}
}
Widget _buildDownloadGridItem(
BuildContext context,
DownloadItem item,
@@ -3227,7 +3289,9 @@ class _QueueTabState extends ConsumerState<QueueTab> {
child: Icon(Icons.music_note, color: colorScheme.onSurfaceVariant),
);
final onTap = isFailed || item.status == DownloadStatus.skipped
final onTap = isFailed
? () => _showDownloadErrorDialog(context, item)
: item.status == DownloadStatus.skipped
? () => ref.read(downloadQueueProvider.notifier).removeItem(item.id)
: () => _confirmCancelDownload(context, item);
@@ -6068,7 +6132,11 @@ class _QueueTabState extends ConsumerState<QueueTab> {
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: isCompleted ? () => _navigateToMetadataScreen(item) : null,
onTap: isCompleted
? () => _navigateToMetadataScreen(item)
: item.status == DownloadStatus.failed
? () => _showDownloadErrorDialog(context, item)
: null,
borderRadius: BorderRadius.circular(12),
child: Stack(
children: [