mirror of
https://github.com/yattee/yattee.git
synced 2026-08-06 15:21:29 +00:00
Adds a "Load subtitle from file…" row to the Subtitles section on iOS (document picker) and macOS (open panel), available when playing files from local folder, SMB, or WebDAV sources. The picked file is copied into the per-video temp subtitle directory, registered as a selectable Caption (displayed by filename), and activated through the existing loadCaption flow. The Subtitles tab and captions control button now also appear for media-source files without any subtitles.
78 lines
2.3 KiB
Swift
78 lines
2.3 KiB
Swift
//
|
|
// Caption.swift
|
|
// Yattee
|
|
//
|
|
// Model representing a video caption/subtitle track.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/// Represents a caption/subtitle track for a video.
|
|
struct Caption: Identifiable, Codable, Hashable, Sendable {
|
|
/// The display label (e.g., "English", "English (auto-generated)")
|
|
let label: String
|
|
|
|
/// The language code (e.g., "en", "de-DE", "es-419")
|
|
let languageCode: String
|
|
|
|
/// The URL to fetch the caption content
|
|
let url: URL
|
|
|
|
/// Original filename of a user-picked external subtitle file.
|
|
/// When set, it is used as the display name so two picked files with the
|
|
/// same language remain distinguishable from API captions and each other.
|
|
var pickedFileName: String? = nil
|
|
|
|
/// Whether this is an auto-generated caption
|
|
var isAutoGenerated: Bool {
|
|
label.contains("auto-generated")
|
|
}
|
|
|
|
/// The base language code without region (e.g., "en" from "en-US")
|
|
var baseLanguageCode: String {
|
|
if let hyphenIndex = languageCode.firstIndex(of: "-") {
|
|
return String(languageCode[..<hyphenIndex])
|
|
}
|
|
return languageCode
|
|
}
|
|
|
|
var id: String {
|
|
"\(languageCode):\(label)"
|
|
}
|
|
|
|
/// Formatted display name for the caption
|
|
var displayName: String {
|
|
if let pickedFileName {
|
|
return pickedFileName
|
|
}
|
|
// Try to get localized language name (AUTO badge shown separately in UI)
|
|
if let localizedName = Locale.current.localizedString(forLanguageCode: baseLanguageCode) {
|
|
return localizedName
|
|
}
|
|
// Strip "(auto-generated)" from label if present
|
|
return label.replacingOccurrences(of: " (auto-generated)", with: "")
|
|
}
|
|
}
|
|
|
|
// MARK: - Preview Data
|
|
|
|
extension Caption {
|
|
/// A sample English caption for SwiftUI previews.
|
|
static var preview: Caption {
|
|
Caption(
|
|
label: "English",
|
|
languageCode: "en",
|
|
url: URL(string: "https://example.com/captions/en.vtt")!
|
|
)
|
|
}
|
|
|
|
/// A sample auto-generated caption for SwiftUI previews.
|
|
static var autoGeneratedPreview: Caption {
|
|
Caption(
|
|
label: "English (auto-generated)",
|
|
languageCode: "en",
|
|
url: URL(string: "https://example.com/captions/en-auto.vtt")!
|
|
)
|
|
}
|
|
}
|