Yattee v2 rewrite

This commit is contained in:
Arkadiusz Fal
2026-02-08 18:31:16 +01:00
parent 20d0cfc0c7
commit 05f921d605
1043 changed files with 163875 additions and 68430 deletions

View File

@@ -0,0 +1,165 @@
//
// TVSettingsButtonStyles.swift
// Yattee
//
// Button styles for tvOS settings forms - removes native glow effect.
//
#if os(tvOS)
import SwiftUI
// MARK: - Custom Picker for tvOS
/// Custom picker for tvOS that avoids the native focus glow effect
struct TVSettingsPicker<SelectionValue: Hashable, Content: View>: View {
let title: String
@Binding var selection: SelectionValue
let content: () -> Content
@State private var isExpanded = false
var body: some View {
Button {
isExpanded.toggle()
} label: {
HStack {
Text(title)
Spacer()
Image(systemName: isExpanded ? "chevron.up" : "chevron.down")
.foregroundStyle(.secondary)
}
}
.buttonStyle(TVFormRowButtonStyle())
if isExpanded {
content()
}
}
}
// MARK: - Custom TextField for tvOS
/// Custom text field for tvOS that avoids the native focus glow effect
/// Uses a Button that shows an alert for text input
struct TVSettingsTextField: View {
let title: String
@Binding var text: String
var isSecure: Bool = false
@State private var isEditing = false
@State private var editText = ""
var body: some View {
Button {
editText = text
isEditing = true
} label: {
HStack {
if text.isEmpty {
Text(title)
.foregroundStyle(.secondary)
} else if isSecure {
Text(String(repeating: "", count: min(text.count, 12)))
.foregroundStyle(.primary)
} else {
Text(text)
.foregroundStyle(.primary)
}
Spacer()
}
}
.buttonStyle(TVFormRowButtonStyle())
.alert(title, isPresented: $isEditing) {
if isSecure {
SecureField(title, text: $editText)
} else {
TextField(title, text: $editText)
}
Button("OK") {
text = editText
}
Button("Cancel", role: .cancel) { }
}
}
}
// MARK: - Button Styles
/// Button style for settings forms - subtle focus effect without glow
struct TVSettingsButtonStyle: ButtonStyle {
@Environment(\.isFocused) private var isFocused
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(.horizontal, 20)
.padding(.vertical, 12)
.background(
RoundedRectangle(cornerRadius: 10)
.fill(isFocused ? .white.opacity(0.2) : .clear)
)
.scaleEffect(configuration.isPressed ? 0.97 : (isFocused ? 1.02 : 1.0))
.animation(.easeInOut(duration: 0.15), value: isFocused)
.animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
}
}
/// Button style for toolbar Done/Cancel buttons - pill shaped like tvOS standard
struct TVToolbarButtonStyle: ButtonStyle {
@Environment(\.isFocused) private var isFocused
func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(.callout)
.fontWeight(.medium)
.foregroundStyle(isFocused ? .white : .secondary)
.padding(.horizontal, 24)
.padding(.vertical, 12)
.background(
Capsule()
.fill(isFocused ? Color.white.opacity(0.3) : Color.white.opacity(0.1))
)
.scaleEffect(configuration.isPressed ? 0.95 : (isFocused ? 1.05 : 1.0))
.animation(.easeInOut(duration: 0.15), value: isFocused)
.animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
}
}
/// Custom toggle view for tvOS that replaces native Toggle to avoid glow effect
struct TVSettingsToggle: View {
let title: String
@Binding var isOn: Bool
var body: some View {
Button {
isOn.toggle()
} label: {
HStack {
Text(title)
Spacer()
Text(isOn ? "On" : "Off")
.foregroundStyle(.secondary)
}
}
.buttonStyle(TVFormRowButtonStyle())
}
}
/// Button style for form rows (toggles, pickers) - matches form appearance
struct TVFormRowButtonStyle: ButtonStyle {
@Environment(\.isFocused) private var isFocused
func makeBody(configuration: Configuration) -> some View {
configuration.label
.padding(.horizontal, 20)
.padding(.vertical, 16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(
RoundedRectangle(cornerRadius: 12)
.fill(isFocused ? .white.opacity(0.15) : .clear)
)
.scaleEffect(configuration.isPressed ? 0.98 : (isFocused ? 1.01 : 1.0))
.animation(.easeInOut(duration: 0.15), value: isFocused)
.animation(.easeInOut(duration: 0.1), value: configuration.isPressed)
}
}
#endif