Add "Download All in ZIP" feature for session downloads
Introduce automatic ZIP file creation and management for session-based downloads. - Server: Add endpoints to serve and provide info about session ZIPs; VideoService now updates ZIP after each MP3 download with user-friendly filenames. - Client: Add "Download All in ZIP" button with loading state and ZIP info; trigger browser download via JS interop; responsive and styled UI. - API: Extend service interfaces for ZIP download/info; add SessionZipInfo model. - Docs: Update SESSION_MANAGEMENT.md with ZIP workflow, endpoints, and UX details. - Robust error handling and logging throughout.
This commit is contained in:
@@ -128,6 +128,31 @@
|
||||
{
|
||||
<div class="download-links-section">
|
||||
<h3 class="downloads-title">📥 Your Downloads</h3>
|
||||
|
||||
@* Download All in ZIP Button *@
|
||||
@if (!string.IsNullOrWhiteSpace(currentSessionId) && downloadLinks.Count > 1)
|
||||
{
|
||||
<div class="download-all-container">
|
||||
<button class="download-all-btn @(isLoadingZip ? "loading" : "")"
|
||||
@onclick="DownloadAllInZip"
|
||||
disabled="@isLoadingZip">
|
||||
<span class="download-all-icon">📦</span>
|
||||
@if (isLoadingZip)
|
||||
{
|
||||
<span>Preparing ZIP...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Download All in ZIP</span>
|
||||
}
|
||||
@if (sessionZipInfo != null)
|
||||
{
|
||||
<span class="zip-info">(@sessionZipInfo.Mp3FilesCount files, @sessionZipInfo.FileSize)</span>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="download-links">
|
||||
@foreach (var download in downloadLinks.AsEnumerable().Reverse())
|
||||
{
|
||||
@@ -168,11 +193,13 @@
|
||||
private string outputMessage = "";
|
||||
private string apiErrorMessage = "";
|
||||
private bool isProcessing = false;
|
||||
private bool isLoadingZip = false;
|
||||
private int progressPercentage = 0;
|
||||
private string progressMessage = "";
|
||||
private List<DownloadItem> downloadLinks = new();
|
||||
private YouTubeVideoDetails? currentVideoDetails = null;
|
||||
private string currentSessionId = "";
|
||||
private SessionZipInfo? sessionZipInfo = null;
|
||||
|
||||
public class DownloadItem
|
||||
{
|
||||
@@ -189,6 +216,10 @@
|
||||
// Initialize session on component load
|
||||
currentSessionId = await SessionService.GetCurrentSessionIdAsync();
|
||||
Logger.LogInformation("Initialized with session: {SessionId}", currentSessionId);
|
||||
|
||||
// Load session ZIP info if available
|
||||
await LoadSessionZipInfoAsync();
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -198,6 +229,58 @@
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadSessionZipInfoAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(currentSessionId))
|
||||
{
|
||||
sessionZipInfo = await ApiService.GetSessionZipInfoAsync(currentSessionId);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error loading session ZIP info");
|
||||
// Don't block the UI if ZIP info loading fails
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadAllInZip()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(currentSessionId))
|
||||
{
|
||||
apiErrorMessage = "Session not available for ZIP download";
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
isLoadingZip = true;
|
||||
StateHasChanged();
|
||||
|
||||
Logger.LogInformation("Downloading session ZIP for session: {SessionId}", currentSessionId);
|
||||
|
||||
// Create the download URL for the ZIP file
|
||||
var zipDownloadUrl = $"https://localhost:7160/api/download/zip/{currentSessionId}";
|
||||
|
||||
// Use browser to download the ZIP file
|
||||
await JSRuntime.InvokeVoidAsync("open", zipDownloadUrl, "_blank");
|
||||
|
||||
Logger.LogInformation("Successfully initiated ZIP download for session: {SessionId}", currentSessionId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error downloading session ZIP for session: {SessionId}", currentSessionId);
|
||||
apiErrorMessage = $"Error downloading ZIP file: {ex.Message}";
|
||||
StateHasChanged();
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoadingZip = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadMp3()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(youtubeUrl))
|
||||
@@ -377,6 +460,9 @@
|
||||
progressPercentage = 100;
|
||||
progressMessage = "Complete!";
|
||||
|
||||
// Reload session ZIP info after successful download
|
||||
await LoadSessionZipInfoAsync();
|
||||
|
||||
// Small delay to show completion
|
||||
await Task.Delay(500);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user