Files
yattee/Yattee/Views/Components/LoadStateView.swift
Arkadiusz Fal 4770bbe3b9 Remove dead code found by Periphery on all platforms
Delete declarations that Periphery reports unused on every platform that
compiles them (iOS, macOS, tvOS), including nine views used only by their
own previews. Platform-gated code still used on another platform, device-
only MPV render paths, migration models, CloudKit record names, App
Intents metadata and unused parameters are kept.
2026-10-08 23:57:56 +02:00

100 lines
2.5 KiB
Swift

//
// LoadStateView.swift
// Yattee
//
// Reusable components for loading, error, and empty states.
//
import SwiftUI
// MARK: - Loading View
/// A simple loading indicator with optional message and subtext.
struct LoadingView: View {
var message: String? = nil
var subtext: String? = nil
var body: some View {
VStack(spacing: 16) {
ProgressView()
.scaleEffect(1.5)
if let message {
Text(message)
.font(.headline)
}
if let subtext {
Text(subtext)
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(1)
.truncationMode(.middle)
.padding(.horizontal)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
// MARK: - Error State View
/// An error view with icon, message, and action buttons.
struct ErrorStateView: View {
let title: String
let message: String
var onRetry: (() async -> Void)? = nil
var onDismiss: (() -> Void)? = nil
var retryTitle: String = "Try Again"
var dismissTitle: String = "Cancel"
var body: some View {
VStack(spacing: 20) {
Image(systemName: "exclamationmark.triangle.fill")
.font(.system(size: 50))
.foregroundStyle(.yellow)
Text(title)
.font(.headline)
Text(message)
.font(.subheadline)
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
.padding(.horizontal)
VStack(spacing: 12) {
if let onRetry {
Button(retryTitle) {
Task { await onRetry() }
}
.buttonStyle(.borderedProminent)
}
if let onDismiss {
Button(dismissTitle) {
onDismiss()
}
.buttonStyle(.bordered)
}
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
// MARK: - Previews
#Preview("Loading") {
LoadingView(message: "Loading video...", subtext: "youtube.com")
}
#Preview("Error") {
ErrorStateView(
title: "Could not load video",
message: "The video is unavailable or has been removed.",
onRetry: { try? await Task.sleep(for: .seconds(1)) },
onDismiss: {}
)
}