mirror of
https://github.com/yattee/yattee.git
synced 2026-02-20 09:49:46 +00:00
Yattee v2 rewrite
This commit is contained in:
227
Yattee/Views/Settings/AddSource/AddWebDAVView.swift
Normal file
227
Yattee/Views/Settings/AddSource/AddWebDAVView.swift
Normal file
@@ -0,0 +1,227 @@
|
||||
//
|
||||
// AddWebDAVView.swift
|
||||
// Yattee
|
||||
//
|
||||
// View for adding a WebDAV share as a media source.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct AddWebDAVView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Environment(\.appEnvironment) private var appEnvironment
|
||||
|
||||
// MARK: - State
|
||||
|
||||
@State private var name = ""
|
||||
@State private var urlString = ""
|
||||
@State private var username = ""
|
||||
@State private var password = ""
|
||||
@State private var allowInvalidCertificates = false
|
||||
|
||||
@State private var isTesting = false
|
||||
@State private var testResult: SourceTestResult?
|
||||
@State private var testProgress: String?
|
||||
|
||||
// Pre-filled from network discovery
|
||||
var prefillURL: URL?
|
||||
var prefillName: String?
|
||||
var prefillAllowInvalidCertificates: Bool = false
|
||||
|
||||
// Closure to dismiss the parent sheet
|
||||
var dismissSheet: DismissAction?
|
||||
|
||||
// MARK: - Computed Properties
|
||||
|
||||
private var canAdd: Bool {
|
||||
!name.isEmpty && !urlString.isEmpty && URL(string: urlString) != nil
|
||||
}
|
||||
|
||||
// MARK: - Body
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
nameSection
|
||||
serverSection
|
||||
authSection
|
||||
securitySection
|
||||
|
||||
if let result = testResult {
|
||||
SourceTestResultSection(result: result)
|
||||
}
|
||||
|
||||
actionSection
|
||||
}
|
||||
#if os(iOS)
|
||||
.scrollDismissesKeyboard(.interactively)
|
||||
#endif
|
||||
.navigationTitle(String(localized: "sources.addWebDAV"))
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
#endif
|
||||
.onAppear {
|
||||
if let url = prefillURL {
|
||||
urlString = url.absoluteString
|
||||
}
|
||||
if let prefillName, name.isEmpty {
|
||||
name = prefillName
|
||||
}
|
||||
if prefillAllowInvalidCertificates {
|
||||
allowInvalidCertificates = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Sections
|
||||
|
||||
private var nameSection: some View {
|
||||
Section {
|
||||
#if os(tvOS)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.name"), text: $name)
|
||||
#else
|
||||
TextField(String(localized: "sources.field.name"), text: $name)
|
||||
#endif
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.displayName"))
|
||||
}
|
||||
}
|
||||
|
||||
private var serverSection: some View {
|
||||
Section {
|
||||
#if os(tvOS)
|
||||
TVSettingsTextField(title: String(localized: "sources.placeholder.webdavUrl"), text: $urlString)
|
||||
#else
|
||||
TextField(String(localized: "sources.placeholder.webdavUrl"), text: $urlString)
|
||||
.textContentType(.URL)
|
||||
#if os(iOS)
|
||||
.keyboardType(.URL)
|
||||
.textInputAutocapitalization(.never)
|
||||
#endif
|
||||
.autocorrectionDisabled()
|
||||
#endif
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.webdav"))
|
||||
}
|
||||
}
|
||||
|
||||
private var authSection: some View {
|
||||
Section {
|
||||
#if os(tvOS)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.usernameOptional"), text: $username)
|
||||
TVSettingsTextField(title: String(localized: "sources.field.passwordOptional"), text: $password, isSecure: true)
|
||||
#else
|
||||
TextField(String(localized: "sources.field.usernameOptional"), text: $username)
|
||||
.textContentType(.username)
|
||||
#if os(iOS)
|
||||
.textInputAutocapitalization(.never)
|
||||
#endif
|
||||
.autocorrectionDisabled()
|
||||
|
||||
SecureField(String(localized: "sources.field.passwordOptional"), text: $password)
|
||||
.textContentType(.password)
|
||||
#endif
|
||||
} header: {
|
||||
Text(String(localized: "sources.header.auth"))
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.auth"))
|
||||
}
|
||||
}
|
||||
|
||||
private var securitySection: some View {
|
||||
Section {
|
||||
#if os(tvOS)
|
||||
TVSettingsToggle(
|
||||
title: String(localized: "sources.field.allowInvalidCertificates"),
|
||||
isOn: $allowInvalidCertificates
|
||||
)
|
||||
#else
|
||||
Toggle(String(localized: "sources.field.allowInvalidCertificates"), isOn: $allowInvalidCertificates)
|
||||
#endif
|
||||
} header: {
|
||||
Text(String(localized: "sources.header.security"))
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.allowInvalidCertificates"))
|
||||
}
|
||||
}
|
||||
|
||||
private var actionSection: some View {
|
||||
Section {
|
||||
Button {
|
||||
addSource()
|
||||
} label: {
|
||||
if isTesting {
|
||||
HStack {
|
||||
ProgressView()
|
||||
.controlSize(.small)
|
||||
Text(testProgress ?? String(localized: "sources.testing"))
|
||||
}
|
||||
} else {
|
||||
Text(String(localized: "sources.addSource"))
|
||||
}
|
||||
}
|
||||
.disabled(!canAdd || isTesting)
|
||||
#if os(tvOS)
|
||||
.buttonStyle(TVSettingsButtonStyle())
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
private func addSource() {
|
||||
guard let appEnvironment,
|
||||
let url = URL(string: urlString) else { return }
|
||||
|
||||
isTesting = true
|
||||
testResult = nil
|
||||
testProgress = String(localized: "sources.testing.connecting")
|
||||
|
||||
let source = MediaSource.webdav(
|
||||
name: name,
|
||||
url: url,
|
||||
username: username.isEmpty ? nil : username,
|
||||
allowInvalidCertificates: allowInvalidCertificates
|
||||
)
|
||||
|
||||
let webDAVClient = appEnvironment.webDAVClientFactory.createClient(for: source)
|
||||
|
||||
Task {
|
||||
do {
|
||||
_ = try await webDAVClient.testConnection(
|
||||
source: source,
|
||||
password: password.isEmpty ? nil : password
|
||||
)
|
||||
|
||||
await MainActor.run {
|
||||
if !password.isEmpty {
|
||||
appEnvironment.mediaSourcesManager.setPassword(password, for: source)
|
||||
}
|
||||
|
||||
appEnvironment.mediaSourcesManager.add(source)
|
||||
isTesting = false
|
||||
testProgress = nil
|
||||
if let dismissSheet {
|
||||
dismissSheet()
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
isTesting = false
|
||||
testProgress = nil
|
||||
testResult = .failure(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
AddWebDAVView()
|
||||
.appEnvironment(.preview)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user