import SwiftUI // MARK: - Ejemplo de Integración del Sistema de Descargas // Este archivo muestra cómo integrar el sistema de descargas en tu app /// Ejemplo 1: Agregar DownloadsView a un TabView struct MainTabViewExample: View { @State private var selectedTab = 0 var body: some View { TabView(selection: $selectedTab) { // Home/Library ContentView() .tabItem { Label("Biblioteca", systemImage: "books.vertical") } .tag(0) // Downloads DownloadsView() .tabItem { Label("Descargas", systemImage: "arrow.down.circle") } .tag(1) // Settings SettingsView() .tabItem { Label("Ajustes", systemImage: "gear") } .tag(2) } } } /// Ejemplo 2: Navegación desde MangaDetailView struct MangaDetailViewWithNavigation: View { let manga: Manga var body: some View { MangaDetailView(manga: manga) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Menu { Button { // Navegar a descargas } label: { Label("Ver Descargas", systemImage: "arrow.down.circle") } Button { // Descargar último capítulo } label: { Label("Descargar último", systemImage: "arrow.down.doc") } } label: { Image(systemName: "ellipsis.circle") } } } } } /// Ejemplo 3: Badge en TabView para mostrar descargas activas struct MainTabViewWithBadge: View { @StateObject private var downloadManager = DownloadManager.shared @State private var selectedTab = 0 var body: some View { TabView(selection: $selectedTab) { ContentView() .tabItem { Label("Biblioteca", systemImage: "books.vertical") } .tag(0) DownloadsView() .tabItem { Label("Descargas", systemImage: "arrow.down.circle") } .badge(downloadManager.activeDownloads.count) .tag(1) SettingsView() .tabItem { Label("Ajustes", systemImage: "gear") } .tag(2) } } } /// Ejemplo 4: Sheet para mostrar descargas desde cualquier vista struct DownloadsSheetExample: View { @State private var showingDownloads = false @StateObject private var downloadManager = DownloadManager.shared var body: some View { VStack { Text("Contenido Principal") Button("Ver Descargas") { showingDownloads = true } .disabled(downloadManager.activeDownloads.isEmpty) } .sheet(isPresented: $showingDownloads) { NavigationView { DownloadsView() .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Cerrar") { showingDownloads = false } } } } } } } /// Ejemplo 5: Vista de configuración con opciones de descarga struct SettingsView: View { @StateObject private var storage = StorageService.shared @StateObject private var downloadManager = DownloadManager.shared @State private var showingClearAlert = false var body: some View { Form { Section("Descargas") { HStack { Text("Almacenamiento usado") Spacer() Text(storage.formatFileSize(storage.getStorageSize())) .foregroundColor(.secondary) } Button(role: .destructive) { showingClearAlert = true } label: { Label("Limpiar todas las descargas", systemImage: "trash") } .disabled(storage.getStorageSize() == 0) } Section("Estadísticas") { HStack { Text("Descargas activas") Spacer() Text("\(downloadManager.activeDownloads.count)") .foregroundColor(.secondary) } HStack { Text("Completadas") Spacer() Text("\(downloadManager.completedDownloads.count)") .foregroundColor(.secondary) } HStack { Text("Fallidas") Spacer() Text("\(downloadManager.failedDownloads.count)") .foregroundColor(.secondary) } } Section("Preferencias") { Toggle("Descargar solo en Wi-Fi", isOn: .constant(true)) Toggle("Notificar descargas completadas", isOn: .constant(true)) } } .navigationTitle("Ajustes") .alert("Limpiar descargas", isPresented: $showingClearAlert) { Button("Cancelar", role: .cancel) { } Button("Limpiar", role: .destructive) { storage.clearAllDownloads() downloadManager.clearCompletedHistory() downloadManager.clearFailedHistory() } } message: { Text("Esta acción eliminará todos los capítulos descargados. ¿Estás seguro?") } } } /// Ejemplo 6: Widget de descargas activas en home struct ActiveDownloadsWidget: View { @ObservedObject var downloadManager = DownloadManager.shared var body: some View { VStack(alignment: .leading, spacing: 12) { Text("Descargas Activas") .font(.headline) if downloadManager.activeDownloads.isEmpty { Text("No hay descargas activas") .font(.caption) .foregroundColor(.secondary) } else { ForEach(downloadManager.activeDownloads.prefix(3)) { task in HStack { VStack(alignment: .leading) { Text(task.mangaTitle) .font(.subheadline) .lineLimit(1) Text("Cap. \(task.chapterNumber)") .font(.caption) .foregroundColor(.secondary) } Spacer() ProgressView(value: task.progress) .frame(width: 50) } } if downloadManager.activeDownloads.count > 3 { Text("+\(downloadManager.activeDownloads.count - 3) más") .font(.caption) .foregroundColor(.secondary) } Button("Ver todas") { // Navegar a DownloadsView } .buttonStyle(.bordered) } } .padding() .background( RoundedRectangle(cornerRadius: 12) .fill(Color(.systemGray6)) ) } } /// Ejemplo 7: Modificador para mostrar banner de descargas activas struct ActiveDownloadsBannerModifier: ViewModifier { @ObservedObject var downloadManager = DownloadManager.shared @State private var isVisible = false func body(content: Content) -> some View { ZStack(alignment: .top) { content if downloadManager.hasActiveDownloads && isVisible { HStack { Image(systemName: "arrow.down.circle.fill") .foregroundColor(.blue) Text("\(downloadManager.activeDownloads.count) descarga(s) en progreso") .font(.caption) Spacer() Button("Ver") { // Navegar a DownloadsView } .font(.caption) } .padding() .background( RoundedRectangle(cornerRadius: 10) .fill(.blue) .shadow(color: .black.opacity(0.2), radius: 5, x: 0, y: 2) ) .foregroundColor(.white) .padding(.horizontal) .padding(.top, 50) .transition(.move(edge: .top).combined(with: .opacity)) } } .onAppear { if downloadManager.hasActiveDownloads { withAnimation(.spring()) { isVisible = true } } } .onChange(of: downloadManager.hasActiveDownloads) { hasActive in withAnimation(.spring()) { isVisible = hasActive } } } } extension View { func activeDownloadsBanner() -> some View { modifier(ActiveDownloadsBannerModifier()) } } // MARK: - Preview #Preview { MainTabViewWithBadge() } #Preview("Downloads Widget") { ActiveDownloadsWidget() .padding() } #Preview("Settings") { NavigationView { SettingsView() } }