mirror of
https://github.com/yattee/yattee.git
synced 2026-02-20 09:49:46 +00:00
265 lines
9.2 KiB
Swift
265 lines
9.2 KiB
Swift
//
|
|
// DeveloperSettingsView.swift
|
|
// Yattee
|
|
//
|
|
// Developer-focused settings for logging, debugging, and testing.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
struct DeveloperSettingsView: View {
|
|
@Environment(\.appEnvironment) private var appEnvironment
|
|
@Bindable private var loggingService = LoggingService.shared
|
|
@State private var loggingEnabled = LoggingService.shared.isEnabled
|
|
|
|
// Data management state
|
|
@State private var showingDeduplicateConfirmation = false
|
|
@State private var deduplicationResult: DataManager.DeduplicationResult?
|
|
@State private var showingDeduplicationResult = false
|
|
@State private var showingResetiCloudConfirmation = false
|
|
@State private var showingResetiCloudComplete = false
|
|
|
|
var body: some View {
|
|
List {
|
|
loggingSection
|
|
if loggingEnabled {
|
|
verboseLoggingSection
|
|
}
|
|
debugSection
|
|
testingSection
|
|
dataSection
|
|
}
|
|
.navigationTitle(String(localized: "settings.developer.title"))
|
|
#if os(iOS)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
#endif
|
|
.confirmationDialog(
|
|
String(localized: "settings.advanced.data.removeDuplicates.title"),
|
|
isPresented: $showingDeduplicateConfirmation,
|
|
titleVisibility: .visible
|
|
) {
|
|
Button(String(localized: "settings.advanced.data.removeDuplicates.action"), role: .destructive) {
|
|
deduplicateData()
|
|
}
|
|
Button(String(localized: "common.cancel"), role: .cancel) {}
|
|
} message: {
|
|
Text(String(localized: "settings.advanced.data.removeDuplicates.message"))
|
|
}
|
|
.alert(
|
|
String(localized: "settings.advanced.data.deduplicationComplete"),
|
|
isPresented: $showingDeduplicationResult
|
|
) {
|
|
Button(String(localized: "common.ok"), role: .cancel) {}
|
|
} message: {
|
|
if let result = deduplicationResult {
|
|
if result.totalRemoved > 0 {
|
|
Text(result.summary)
|
|
} else {
|
|
Text(String(localized: "settings.advanced.data.noDuplicates"))
|
|
}
|
|
}
|
|
}
|
|
.confirmationDialog(
|
|
String(localized: "settings.advanced.data.resetICloud.title"),
|
|
isPresented: $showingResetiCloudConfirmation,
|
|
titleVisibility: .visible
|
|
) {
|
|
Button(String(localized: "settings.advanced.data.resetICloud.action"), role: .destructive) {
|
|
resetiCloudData()
|
|
}
|
|
Button(String(localized: "common.cancel"), role: .cancel) {}
|
|
} message: {
|
|
Text(String(localized: "settings.advanced.data.resetICloud.message"))
|
|
}
|
|
.alert(
|
|
String(localized: "settings.advanced.data.iCloudReset"),
|
|
isPresented: $showingResetiCloudComplete
|
|
) {
|
|
Button(String(localized: "common.ok"), role: .cancel) {}
|
|
} message: {
|
|
Text(String(localized: "settings.advanced.data.iCloudResetMessage"))
|
|
}
|
|
}
|
|
|
|
// MARK: - Sections
|
|
|
|
@ViewBuilder
|
|
private var loggingSection: some View {
|
|
Section {
|
|
Toggle(isOn: $loggingEnabled) {
|
|
Label(String(localized: "settings.advanced.logging.enable"), systemImage: "doc.text")
|
|
}
|
|
.onChange(of: loggingEnabled) { _, newValue in
|
|
loggingService.isEnabled = newValue
|
|
}
|
|
|
|
if loggingEnabled {
|
|
NavigationLink {
|
|
LogViewerView()
|
|
} label: {
|
|
HStack {
|
|
Label(String(localized: "settings.advanced.logging.viewLogs"), systemImage: "list.bullet.rectangle")
|
|
Spacer()
|
|
Text("\(loggingService.entries.count)")
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
}
|
|
} header: {
|
|
Text(String(localized: "settings.advanced.logging.sectionTitle"))
|
|
} footer: {
|
|
Text(String(localized: "settings.advanced.logging.footer"))
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var verboseLoggingSection: some View {
|
|
if let settingsManager = appEnvironment?.settingsManager {
|
|
Section {
|
|
Toggle(isOn: Binding(
|
|
get: { settingsManager.verboseMPVLogging },
|
|
set: { settingsManager.verboseMPVLogging = $0 }
|
|
)) {
|
|
Label(String(localized: "settings.advanced.debug.verboseMPV"), systemImage: "doc.text.magnifyingglass")
|
|
}
|
|
|
|
Toggle(isOn: Binding(
|
|
get: { settingsManager.verboseRemoteControlLogging },
|
|
set: { settingsManager.verboseRemoteControlLogging = $0 }
|
|
)) {
|
|
Label(String(localized: "settings.advanced.debug.verboseRemote"), systemImage: "antenna.radiowaves.left.and.right")
|
|
}
|
|
} header: {
|
|
Text(String(localized: "settings.advanced.verboseLogging.sectionTitle"))
|
|
}
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var debugSection: some View {
|
|
if let settingsManager = appEnvironment?.settingsManager {
|
|
Section {
|
|
Toggle(isOn: Binding(
|
|
get: { settingsManager.showPlayerAreaDebug },
|
|
set: { settingsManager.showPlayerAreaDebug = $0 }
|
|
)) {
|
|
Label(String(localized: "settings.advanced.debug.playerAreaDebug"), systemImage: "rectangle.dashed")
|
|
}
|
|
|
|
#if os(iOS)
|
|
Toggle(isOn: Binding(
|
|
get: { settingsManager.zoomTransitionsEnabled },
|
|
set: { settingsManager.zoomTransitionsEnabled = $0 }
|
|
)) {
|
|
Label(String(localized: "settings.advanced.debug.zoomTransitions"), systemImage: "arrow.up.left.and.arrow.down.right")
|
|
}
|
|
#endif
|
|
} header: {
|
|
Text(String(localized: "settings.advanced.debug.sectionTitle"))
|
|
}
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var testingSection: some View {
|
|
#if !os(tvOS)
|
|
notificationTestingSection
|
|
#endif
|
|
|
|
Section {
|
|
Button {
|
|
NotificationCenter.default.post(name: .showOnboarding, object: nil)
|
|
appEnvironment?.navigationCoordinator.dismissSettings()
|
|
} label: {
|
|
Label(String(localized: "settings.advanced.showOnboarding"), systemImage: "hand.wave")
|
|
}
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var dataSection: some View {
|
|
Section {
|
|
Button {
|
|
showingDeduplicateConfirmation = true
|
|
} label: {
|
|
Label(String(localized: "settings.advanced.data.removeDuplicates"), systemImage: "doc.on.doc")
|
|
}
|
|
|
|
Button(role: .destructive) {
|
|
showingResetiCloudConfirmation = true
|
|
} label: {
|
|
Label(String(localized: "settings.advanced.data.resetICloud"), systemImage: "icloud.slash")
|
|
}
|
|
} header: {
|
|
Text(String(localized: "settings.advanced.data.sectionTitle"))
|
|
} footer: {
|
|
Text(String(localized: "settings.advanced.data.footer"))
|
|
}
|
|
}
|
|
|
|
// MARK: - Data Actions
|
|
|
|
private func deduplicateData() {
|
|
guard let dataManager = appEnvironment?.dataManager else { return }
|
|
deduplicationResult = dataManager.deduplicateAllData()
|
|
showingDeduplicationResult = true
|
|
}
|
|
|
|
private func resetiCloudData() {
|
|
guard let cloudKitSync = appEnvironment?.cloudKitSync else { return }
|
|
Task {
|
|
do {
|
|
try await cloudKitSync.resetSync()
|
|
showingResetiCloudComplete = true
|
|
} catch {
|
|
LoggingService.shared.logCloudKitError("Failed to reset iCloud data", error: error)
|
|
}
|
|
}
|
|
}
|
|
|
|
#if !os(tvOS)
|
|
@ViewBuilder
|
|
private var notificationTestingSection: some View {
|
|
Section {
|
|
Button {
|
|
sendTestNotification()
|
|
} label: {
|
|
Label(String(localized: "settings.advanced.testing.sendTestNotification"), systemImage: "bell.badge")
|
|
}
|
|
|
|
Button {
|
|
triggerBackgroundRefresh()
|
|
} label: {
|
|
Label(String(localized: "settings.advanced.testing.triggerBackgroundRefresh"), systemImage: "arrow.clockwise")
|
|
}
|
|
} header: {
|
|
Text(String(localized: "settings.advanced.testing.notifications.sectionTitle"))
|
|
} footer: {
|
|
Text(String(localized: "settings.advanced.testing.notifications.footer"))
|
|
}
|
|
}
|
|
|
|
private func sendTestNotification() {
|
|
Task {
|
|
await appEnvironment?.notificationManager.sendTestNotification()
|
|
}
|
|
}
|
|
|
|
private func triggerBackgroundRefresh() {
|
|
guard let appEnvironment else { return }
|
|
Task {
|
|
await appEnvironment.notificationManager.triggerBackgroundRefresh(using: appEnvironment)
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
// MARK: - Preview
|
|
|
|
#Preview {
|
|
NavigationStack {
|
|
DeveloperSettingsView()
|
|
}
|
|
}
|