yattee/Shared/Settings/SponsorBlockSettings.swift

190 lines
6.5 KiB
Swift
Raw Permalink Normal View History

2022-01-06 15:02:53 +00:00
import Defaults
import SwiftUI
2024-05-16 16:53:47 +00:00
#if canImport(UIKit)
import UIKit
#endif
2022-01-06 15:02:53 +00:00
struct SponsorBlockSettings: View {
@ObservedObject private var settings = SettingsModel.shared
2022-01-06 15:02:53 +00:00
@Default(.sponsorBlockInstance) private var sponsorBlockInstance
@Default(.sponsorBlockCategories) private var sponsorBlockCategories
@Default(.sponsorBlockColors) private var sponsorBlockColors
@Default(.sponsorBlockShowTimeWithSkipsRemoved) private var showTimeWithSkipsRemoved
@Default(.sponsorBlockShowCategoriesInTimeline) private var showCategoriesInTimeline
@Default(.sponsorBlockShowNoticeAfterSkip) private var showNoticeAfterSkip
2022-01-06 15:02:53 +00:00
var body: some View {
Group {
#if os(macOS)
sections
Spacer()
#else
List {
sections
}
#endif
}
#if os(tvOS)
.frame(maxWidth: 1000)
2022-11-11 18:53:52 +00:00
#else
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
2022-01-06 15:02:53 +00:00
#endif
.navigationTitle("SponsorBlock")
}
private var sections: some View {
Group {
Section(header: SettingsHeader(text: "SponsorBlock API")) {
TextField(
"SponsorBlock API Instance",
text: $sponsorBlockInstance
)
.labelsHidden()
#if !os(macOS)
.autocapitalization(.none)
.disableAutocorrection(true)
2022-01-06 15:02:53 +00:00
.keyboardType(.URL)
#endif
}
Section(header: Text("Playback")) {
Toggle("Categories in timeline", isOn: $showCategoriesInTimeline)
Toggle("Post-skip notice", isOn: $showNoticeAfterSkip)
Toggle("Adjusted total time", isOn: $showTimeWithSkipsRemoved)
}
Section(header: SettingsHeader(text: "Categories to Skip".localized())) {
categoryRows
}
2024-05-16 16:53:47 +00:00
#if os(iOS)
colorSection
Button {
settings.presentAlert(
Alert(
title: Text("Restore Default Colors?"),
message: Text("This action will reset all custom colors back to their original defaults. " +
"Any custom color changes you've made will be lost."),
primaryButton: .destructive(Text("Restore")) {
resetColors()
},
secondaryButton: .cancel()
)
)
2024-05-16 16:53:47 +00:00
} label: {
2024-07-06 11:44:02 +00:00
Text("Restore Default Colors…")
2024-05-16 16:53:47 +00:00
.foregroundColor(.red)
}
#endif
Section(footer: categoriesDetails) {
EmptyView()
}
}
}
2024-05-16 16:53:47 +00:00
#if os(iOS)
private var colorSection: some View {
Section(header: SettingsHeader(text: "Colors for Categories")) {
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
LazyVStack(alignment: .leading) {
ColorPicker(
SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
selection: Binding(
get: { getColor(for: category) },
set: { setColor($0, for: category) }
)
)
2024-05-16 16:53:47 +00:00
}
}
}
}
2024-05-16 16:53:47 +00:00
#endif
private var categoryRows: some View {
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
LazyVStack(alignment: .leading) {
MultiselectRow(
title: SponsorBlockAPI.categoryDescription(category) ?? "Unknown",
selected: sponsorBlockCategories.contains(category)
) { value in
toggleCategory(category, value: value)
}
2022-01-06 15:02:53 +00:00
}
}
}
2022-01-07 18:46:47 +00:00
private var categoriesDetails: some View {
VStack(alignment: .leading) {
ForEach(SponsorBlockAPI.categories, id: \.self) { category in
Text(SponsorBlockAPI.categoryDescription(category) ?? "Category")
.fontWeight(.bold)
.padding(.bottom, 0.5)
2022-01-07 18:46:47 +00:00
#if os(tvOS)
.focusable()
#endif
Text(SponsorBlockAPI.categoryDetails(category) ?? "Details")
.padding(.bottom, 10)
2022-01-07 18:46:47 +00:00
.fixedSize(horizontal: false, vertical: true)
}
}
.foregroundColor(.secondary)
}
2022-01-06 15:02:53 +00:00
func toggleCategory(_ category: String, value: Bool) {
if let index = sponsorBlockCategories.firstIndex(where: { $0 == category }), !value {
sponsorBlockCategories.remove(at: index)
} else if value {
sponsorBlockCategories.insert(category)
}
}
private func getColor(for category: String) -> Color {
if let hexString = sponsorBlockColors[category], let rgbValue = Int(hexString.dropFirst(), radix: 16) {
let r = Double((rgbValue >> 16) & 0xFF) / 255.0
let g = Double((rgbValue >> 8) & 0xFF) / 255.0
let b = Double(rgbValue & 0xFF) / 255.0
return Color(red: r, green: g, blue: b)
}
return Color("AppRedColor") // Fallback color if no match found
}
2024-05-16 16:53:47 +00:00
#if canImport(UIKit)
private func setColor(_ color: Color, for category: String) {
let uiColor = UIColor(color)
2024-05-16 16:53:47 +00:00
// swiftlint:disable no_cgfloat
var red: CGFloat = 0
var green: CGFloat = 0
var blue: CGFloat = 0
var alpha: CGFloat = 0
// swiftlint:enable no_cgfloat
2024-05-16 16:53:47 +00:00
uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
2024-05-16 16:53:47 +00:00
let r = Int(red * 255.0)
let g = Int(green * 255.0)
let b = Int(blue * 255.0)
2024-05-16 16:53:47 +00:00
let rgbValue = (r << 16) | (g << 8) | b
sponsorBlockColors[category] = String(format: "#%06x", rgbValue)
}
#endif
private func resetColors() {
sponsorBlockColors = SponsorBlockColors.dictionary
}
2022-01-06 15:02:53 +00:00
}
2022-01-07 18:46:47 +00:00
struct SponsorBlockSettings_Previews: PreviewProvider {
2022-01-06 15:02:53 +00:00
static var previews: some View {
VStack {
SponsorBlockSettings()
}
2022-11-11 18:53:52 +00:00
.frame(maxHeight: 600)
2022-01-06 15:02:53 +00:00
}
}