mirror of
https://github.com/yattee/yattee.git
synced 2026-02-20 01:39:46 +00:00
265 lines
8.5 KiB
Swift
265 lines
8.5 KiB
Swift
//
|
|
// SubtitlesSettingsView.swift
|
|
// Yattee
|
|
//
|
|
// Settings view for configuring subtitle appearance in MPV player.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct SubtitlesSettingsView: View {
|
|
@Environment(\.appEnvironment) private var appEnvironment
|
|
@State private var settings: SubtitleSettings = .default
|
|
|
|
var body: some View {
|
|
Form {
|
|
fontSection
|
|
colorsSection
|
|
styleSection
|
|
positionSection
|
|
resetSection
|
|
}
|
|
#if os(iOS)
|
|
.scrollDismissesKeyboard(.interactively)
|
|
#endif
|
|
.navigationTitle(String(localized: "settings.subtitles.title"))
|
|
#if os(iOS)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
#endif
|
|
.onAppear {
|
|
if let settingsManager = appEnvironment?.settingsManager {
|
|
settings = settingsManager.subtitleSettings
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Font Section
|
|
|
|
private var fontSection: some View {
|
|
Section {
|
|
Picker(
|
|
String(localized: "settings.subtitles.font"),
|
|
selection: $settings.font
|
|
) {
|
|
ForEach(SubtitleFont.allCases, id: \.self) { font in
|
|
Text(font.displayName).tag(font)
|
|
}
|
|
}
|
|
.onChange(of: settings.font) { _, _ in saveSettings() }
|
|
|
|
#if os(tvOS)
|
|
// tvOS uses Picker instead of Slider (Slider unavailable)
|
|
Picker(String(localized: "settings.subtitles.fontSize"), selection: $settings.fontSize) {
|
|
ForEach([20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100], id: \.self) { size in
|
|
Text("settings.subtitles.fontSize \(size)").tag(size)
|
|
}
|
|
}
|
|
.onChange(of: settings.fontSize) { _, _ in saveSettings() }
|
|
#else
|
|
VStack(alignment: .leading) {
|
|
Text(String(localized: "settings.subtitles.fontSize"))
|
|
HStack {
|
|
Slider(
|
|
value: Binding(
|
|
get: { Double(settings.fontSize) },
|
|
set: { settings.fontSize = Int($0) }
|
|
),
|
|
in: 20...100,
|
|
step: 1
|
|
)
|
|
.onChange(of: settings.fontSize) { _, _ in saveSettings() }
|
|
TextField("", value: $settings.fontSize, format: .number)
|
|
.textFieldStyle(.roundedBorder)
|
|
.frame(width: 60)
|
|
.multilineTextAlignment(.center)
|
|
.onChange(of: settings.fontSize) { _, _ in saveSettings() }
|
|
Text(String(localized: "common.unit.points"))
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// MARK: - Colors Section
|
|
|
|
private var colorsSection: some View {
|
|
Section {
|
|
#if os(tvOS)
|
|
HStack {
|
|
Text(String(localized: "settings.subtitles.textColor"))
|
|
Spacer()
|
|
Circle()
|
|
.fill(settings.textColor.color)
|
|
.frame(width: 24, height: 24)
|
|
}
|
|
|
|
HStack {
|
|
Text(String(localized: "settings.subtitles.borderColor"))
|
|
Spacer()
|
|
Circle()
|
|
.fill(settings.borderColor.color)
|
|
.frame(width: 24, height: 24)
|
|
}
|
|
|
|
LabeledContent(
|
|
String(localized: "settings.subtitles.borderSize"),
|
|
value: String(format: "%.1f", settings.borderSize)
|
|
)
|
|
#else
|
|
ColorPicker(
|
|
String(localized: "settings.subtitles.textColor"),
|
|
selection: Binding(
|
|
get: { settings.textColor.color },
|
|
set: {
|
|
settings.textColor = CodableColor($0)
|
|
saveSettings()
|
|
}
|
|
),
|
|
supportsOpacity: false
|
|
)
|
|
|
|
ColorPicker(
|
|
String(localized: "settings.subtitles.borderColor"),
|
|
selection: Binding(
|
|
get: { settings.borderColor.color },
|
|
set: {
|
|
settings.borderColor = CodableColor($0)
|
|
saveSettings()
|
|
}
|
|
),
|
|
supportsOpacity: false
|
|
)
|
|
|
|
VStack(alignment: .leading) {
|
|
Text(String(localized: "settings.subtitles.borderSize"))
|
|
HStack {
|
|
Slider(value: $settings.borderSize, in: 0...5, step: 0.5)
|
|
.onChange(of: settings.borderSize) { _, _ in saveSettings() }
|
|
Text(String(format: "%.1f", settings.borderSize))
|
|
.foregroundStyle(.secondary)
|
|
.monospacedDigit()
|
|
.frame(width: 30)
|
|
}
|
|
}
|
|
#endif
|
|
|
|
Toggle(
|
|
String(localized: "settings.subtitles.showBackground"),
|
|
isOn: $settings.showBackground
|
|
)
|
|
.onChange(of: settings.showBackground) { _, _ in saveSettings() }
|
|
|
|
#if os(tvOS)
|
|
if settings.showBackground {
|
|
HStack {
|
|
Text(String(localized: "settings.subtitles.backgroundColor"))
|
|
Spacer()
|
|
Circle()
|
|
.fill(settings.backgroundColor.color)
|
|
.frame(width: 24, height: 24)
|
|
}
|
|
}
|
|
#else
|
|
if settings.showBackground {
|
|
ColorPicker(
|
|
String(localized: "settings.subtitles.backgroundColor"),
|
|
selection: Binding(
|
|
get: { settings.backgroundColor.color },
|
|
set: {
|
|
settings.backgroundColor = CodableColor($0)
|
|
saveSettings()
|
|
}
|
|
),
|
|
supportsOpacity: true
|
|
)
|
|
}
|
|
#endif
|
|
} header: {
|
|
Text(String(localized: "settings.subtitles.colorsSection"))
|
|
}
|
|
}
|
|
|
|
// MARK: - Style Section
|
|
|
|
private var styleSection: some View {
|
|
Section {
|
|
Toggle(
|
|
String(localized: "settings.subtitles.bold"),
|
|
isOn: $settings.isBold
|
|
)
|
|
.onChange(of: settings.isBold) { _, _ in saveSettings() }
|
|
|
|
Toggle(
|
|
String(localized: "settings.subtitles.italic"),
|
|
isOn: $settings.isItalic
|
|
)
|
|
.onChange(of: settings.isItalic) { _, _ in saveSettings() }
|
|
} header: {
|
|
Text(String(localized: "settings.subtitles.styleSection"))
|
|
}
|
|
}
|
|
|
|
// MARK: - Position Section
|
|
|
|
private var positionSection: some View {
|
|
Section {
|
|
#if os(tvOS)
|
|
LabeledContent(
|
|
String(localized: "settings.subtitles.positionSection"),
|
|
value: "\(settings.bottomMargin)"
|
|
)
|
|
#else
|
|
Stepper(
|
|
String(localized: "settings.subtitles.bottomMargin \(settings.bottomMargin)"),
|
|
value: $settings.bottomMargin,
|
|
in: 0...50,
|
|
step: 5
|
|
)
|
|
.onChange(of: settings.bottomMargin) { _, _ in saveSettings() }
|
|
#endif
|
|
} header: {
|
|
Text(String(localized: "settings.subtitles.positionSection"))
|
|
} footer: {
|
|
Text(String(localized: "settings.subtitles.positionFooter"))
|
|
}
|
|
}
|
|
|
|
// MARK: - Reset Section
|
|
|
|
private var resetSection: some View {
|
|
Section {
|
|
Button(role: .destructive) {
|
|
settings = .default
|
|
saveSettings()
|
|
} label: {
|
|
HStack {
|
|
Spacer()
|
|
Text(String(localized: "settings.subtitles.resetToDefaults"))
|
|
Spacer()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private func saveSettings() {
|
|
appEnvironment?.settingsManager.subtitleSettings = settings
|
|
|
|
// Apply changes to active MPV player immediately
|
|
if let mpvBackend = appEnvironment?.playerService.currentBackend as? MPVBackend {
|
|
mpvBackend.updateSubtitleSettings()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Preview
|
|
|
|
#Preview {
|
|
NavigationStack {
|
|
SubtitlesSettingsView()
|
|
}
|
|
.appEnvironment(.preview)
|
|
}
|