mirror of
https://github.com/yattee/yattee.git
synced 2026-10-23 21:22:53 +00:00
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.
100 lines
2.5 KiB
Swift
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: {}
|
|
)
|
|
}
|