Files
yattee/Yattee/Views/Settings/SponsorBlockSettingsView.swift
Arkadiusz Fal f173dd1c39 Convert YouTube Enhancements settings to macOS-native helpers
Includes SponsorBlock, Return YouTube Dislike, and DeArrow sub-screens.
Extend SettingsNavigationRow with an optional trailing content slot so
rows can show enabled/disabled status next to the chevron.
2026-04-21 00:31:04 +02:00

182 lines
5.5 KiB
Swift

//
// SponsorBlockSettingsView.swift
// Yattee
//
// SponsorBlock settings with category selection.
//
import SwiftUI
struct SponsorBlockSettingsView: View {
@Environment(\.appEnvironment) private var appEnvironment
var body: some View {
SettingsFormContainer {
if let settings = appEnvironment?.settingsManager {
// Enable/Disable toggle
EnableSection(settings: settings)
// Categories section
if settings.sponsorBlockEnabled {
CategoriesSection(settings: settings)
}
// Advanced section
AdvancedSection(settings: settings)
// About section
AboutSection()
}
}
#if os(iOS)
.scrollDismissesKeyboard(.interactively)
#endif
.navigationTitle(String(localized: "settings.sponsorBlock.title"))
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
#endif
}
}
// MARK: - Enable Section
private struct EnableSection: View {
@Bindable var settings: SettingsManager
var body: some View {
SettingsFormSection(footer: "settings.sponsorBlock.footer") {
Toggle(
String(localized: "settings.sponsorBlock.enabled"),
isOn: $settings.sponsorBlockEnabled
)
}
}
}
// MARK: - Categories Section
private struct CategoriesSection: View {
@Bindable var settings: SettingsManager
var body: some View {
SettingsFormSection("settings.sponsorBlock.categories.header", footer: "settings.sponsorBlock.categories.footer") {
ForEach(SponsorBlockCategory.allCases, id: \.self) { category in
CategoryToggleRow(
category: category,
isEnabled: settings.sponsorBlockCategories.contains(category),
onToggle: { enabled in
var categories = settings.sponsorBlockCategories
if enabled {
categories.insert(category)
} else {
categories.remove(category)
}
settings.sponsorBlockCategories = categories
}
)
}
}
}
}
// MARK: - Advanced Section
private struct AdvancedSection: View {
@Bindable var settings: SettingsManager
@State private var apiURLText: String = ""
var body: some View {
SettingsFormSection("settings.sponsorBlock.advanced.header", footer: "settings.sponsorBlock.apiURL.footer") {
TextField(
String(localized: "settings.sponsorBlock.apiURL"),
text: $apiURLText,
prompt: Text(SettingsManager.defaultSponsorBlockAPIURL)
)
#if os(iOS)
.textInputAutocapitalization(.never)
.keyboardType(.URL)
#endif
.autocorrectionDisabled()
.onChange(of: apiURLText) { _, newValue in
let trimmed = newValue.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty {
settings.sponsorBlockAPIURL = SettingsManager.defaultSponsorBlockAPIURL
} else {
settings.sponsorBlockAPIURL = trimmed
}
}
if settings.sponsorBlockAPIURL != SettingsManager.defaultSponsorBlockAPIURL {
Button(String(localized: "settings.sponsorBlock.apiURL.reset")) {
apiURLText = ""
settings.sponsorBlockAPIURL = SettingsManager.defaultSponsorBlockAPIURL
}
}
}
.onAppear {
let currentURL = settings.sponsorBlockAPIURL
if currentURL != SettingsManager.defaultSponsorBlockAPIURL {
apiURLText = currentURL
}
}
}
}
// MARK: - About Section
private struct AboutSection: View {
var body: some View {
SettingsFormSection("settings.sponsorBlock.about.header") {
VStack(alignment: .leading, spacing: 8) {
Text(String(localized: "settings.sponsorBlock.about.description"))
.font(.callout)
.foregroundStyle(.secondary)
Link(destination: URL(string: "https://sponsor.ajay.app")!) {
HStack {
Text(String(localized: "settings.sponsorBlock.about.learnMore"))
Spacer()
Image(systemName: "arrow.up.right")
.font(.caption)
}
}
}
}
}
}
// MARK: - Category Toggle Row
private struct CategoryToggleRow: View {
let category: SponsorBlockCategory
let isEnabled: Bool
let onToggle: (Bool) -> Void
var body: some View {
HStack {
Toggle(isOn: Binding(
get: { isEnabled },
set: { onToggle($0) }
)) {
VStack(alignment: .leading, spacing: 2) {
Text(category.displayName)
.font(.body)
Text(category.localizedDescription)
.font(.caption)
.foregroundStyle(.secondary)
}
}
}
}
}
// MARK: - Preview
#Preview {
NavigationStack {
SponsorBlockSettingsView()
}
.appEnvironment(.preview)
}