mirror of
https://github.com/yattee/yattee.git
synced 2026-02-20 17:59:45 +00:00
Yattee v2 rewrite
This commit is contained in:
178
Yattee/Views/Settings/AddSource/AddLocalFolderView.swift
Normal file
178
Yattee/Views/Settings/AddSource/AddLocalFolderView.swift
Normal file
@@ -0,0 +1,178 @@
|
||||
//
|
||||
// AddLocalFolderView.swift
|
||||
// Yattee
|
||||
//
|
||||
// View for adding a local folder as a media source.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
#if !os(tvOS)
|
||||
struct AddLocalFolderView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Environment(\.appEnvironment) private var appEnvironment
|
||||
|
||||
// MARK: - State
|
||||
|
||||
@State private var name = ""
|
||||
@State private var selectedFolderURL: URL?
|
||||
@State private var testResult: SourceTestResult?
|
||||
|
||||
#if os(iOS)
|
||||
@State private var showingFolderPicker = false
|
||||
#endif
|
||||
|
||||
// Closure to dismiss the parent sheet
|
||||
var dismissSheet: DismissAction?
|
||||
|
||||
// MARK: - Computed Properties
|
||||
|
||||
private var canAdd: Bool {
|
||||
!name.isEmpty && selectedFolderURL != nil
|
||||
}
|
||||
|
||||
// MARK: - Body
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
nameSection
|
||||
folderSection
|
||||
|
||||
if let result = testResult {
|
||||
SourceTestResultSection(result: result)
|
||||
}
|
||||
|
||||
actionSection
|
||||
}
|
||||
.navigationTitle(String(localized: "sources.addLocalFolder"))
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.sheet(isPresented: $showingFolderPicker) {
|
||||
FolderPickerView { url in
|
||||
handleFolderSelection(url)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// MARK: - Sections
|
||||
|
||||
private var nameSection: some View {
|
||||
Section {
|
||||
TextField(String(localized: "sources.field.name"), text: $name)
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.displayName"))
|
||||
}
|
||||
}
|
||||
|
||||
private var folderSection: some View {
|
||||
Section {
|
||||
#if os(iOS)
|
||||
Button {
|
||||
showingFolderPicker = true
|
||||
} label: {
|
||||
HStack {
|
||||
if let url = selectedFolderURL {
|
||||
Label(url.lastPathComponent, systemImage: "folder.fill")
|
||||
} else {
|
||||
Label(String(localized: "sources.selectFolder"), systemImage: "folder.badge.plus")
|
||||
}
|
||||
Spacer()
|
||||
Image(systemName: "chevron.right")
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
}
|
||||
#elseif os(macOS)
|
||||
Button {
|
||||
selectFolderMacOS()
|
||||
} label: {
|
||||
HStack {
|
||||
if let url = selectedFolderURL {
|
||||
Label(url.lastPathComponent, systemImage: "folder.fill")
|
||||
} else {
|
||||
Label(String(localized: "sources.selectFolder"), systemImage: "folder.badge.plus")
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} header: {
|
||||
Text(String(localized: "sources.header.folder"))
|
||||
} footer: {
|
||||
Text(String(localized: "sources.footer.folder"))
|
||||
}
|
||||
}
|
||||
|
||||
private var actionSection: some View {
|
||||
Section {
|
||||
Button {
|
||||
addSource()
|
||||
} label: {
|
||||
Text(String(localized: "sources.addSource"))
|
||||
}
|
||||
.disabled(!canAdd)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
private func handleFolderSelection(_ url: URL) {
|
||||
selectedFolderURL = url
|
||||
if name.isEmpty {
|
||||
name = url.lastPathComponent
|
||||
}
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
private func selectFolderMacOS() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.canChooseFiles = false
|
||||
panel.canChooseDirectories = true
|
||||
panel.allowsMultipleSelection = false
|
||||
panel.canCreateDirectories = false
|
||||
|
||||
if panel.runModal() == .OK, let url = panel.url {
|
||||
handleFolderSelection(url)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private func addSource() {
|
||||
guard let appEnvironment,
|
||||
let url = selectedFolderURL else { return }
|
||||
|
||||
Task {
|
||||
do {
|
||||
let bookmarkData = try await appEnvironment.localFileClient.createBookmark(for: url)
|
||||
|
||||
await MainActor.run {
|
||||
let source = MediaSource.localFolder(
|
||||
name: name,
|
||||
url: url,
|
||||
bookmarkData: bookmarkData
|
||||
)
|
||||
appEnvironment.mediaSourcesManager.add(source)
|
||||
if let dismissSheet {
|
||||
dismissSheet()
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
testResult = .failure(String(localized: "sources.error.folderAccess \(error.localizedDescription)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Preview
|
||||
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
AddLocalFolderView()
|
||||
.appEnvironment(.preview)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user