Ferrite-backup/Ferrite/Views/SourceViews/SourceSettingsView.swift
kingbri cab6eb3bb6 Sources: Allow for dynamic properties and basic API usage
Some sources are self-hosted and require unique keys and sever
addresses.

Signed-off-by: kingbri <bdashore3@gmail.com>
2022-08-31 00:41:38 -04:00

175 lines
6 KiB
Swift

//
// SourceSettingsView.swift
// Ferrite
//
// Created by Brian Dashore on 8/4/22.
//
import SwiftUI
struct SourceSettingsView: View {
@Environment(\.dismiss) var dismiss
@EnvironmentObject var navModel: NavigationViewModel
@State private var tempBaseUrl: String = ""
var body: some View {
NavView {
Form {
if let selectedSource = navModel.selectedSource {
Section("Info") {
VStack(alignment: .leading, spacing: 5) {
HStack {
Text(selectedSource.name)
Text("v\(selectedSource.version)")
.foregroundColor(.secondary)
}
Text("by \(selectedSource.author)")
.foregroundColor(.secondary)
Group {
Text("ID: \(selectedSource.id)")
if let listId = selectedSource.listId {
Text("List ID: \(listId)")
} else {
Text("No list ID found. This source should be removed.")
}
}
.foregroundColor(.secondary)
.font(.caption)
}
}
if selectedSource.dynamicBaseUrl {
Section(
header: Text("Base URL"),
footer: Text("Enter the base URL of your server.")
) {
TextField("https://...", text: $tempBaseUrl)
.onAppear {
tempBaseUrl = selectedSource.baseUrl ?? ""
}
.onSubmit {
if tempBaseUrl.last == "/" {
selectedSource.baseUrl = String(tempBaseUrl.dropLast())
} else {
selectedSource.baseUrl = tempBaseUrl
}
PersistenceController.shared.save()
}
}
}
if let sourceApi = selectedSource.api {
SourceSettingsApiView(selectedSourceApi: sourceApi)
}
SourceSettingsMethodView(selectedSource: selectedSource)
}
}
.navigationTitle("Source settings")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Done") {
dismiss()
}
}
}
}
}
}
struct SourceSettingsApiView: View {
@ObservedObject var selectedSourceApi: SourceApi
@State private var tempClientId: String = ""
@State private var tempClientSecret: String = ""
@State private var showPassword = false
@FocusState var inFocus: Field?
enum Field {
case secure, plain
}
var body: some View {
Section(
header: Text("API credentials"),
footer: Text("Grab the required API credentials from the website. A client secret can be an API token.")
) {
if selectedSourceApi.dynamicClientId {
TextField("Client ID", text: $tempClientId)
.onAppear {
tempClientId = selectedSourceApi.clientId ?? ""
}
.onSubmit {
selectedSourceApi.clientId = tempClientId
PersistenceController.shared.save()
}
}
if selectedSourceApi.clientSecret != nil {
HStack {
Group {
if showPassword {
TextField("Token", text: $tempClientSecret)
.focused($inFocus, equals: .plain)
} else {
SecureField("Token", text: $tempClientSecret)
.focused($inFocus, equals: .secure)
}
}
.onAppear {
tempClientSecret = selectedSourceApi.clientSecret ?? ""
}
.onSubmit {
selectedSourceApi.clientSecret = tempClientSecret
PersistenceController.shared.save()
}
Spacer()
Button {
showPassword.toggle()
inFocus = showPassword ? .plain : .secure
} label: {
Image(systemName: showPassword ? "eye.slash" : "eye")
}
}
}
}
}
}
struct SourceSettingsMethodView: View {
@ObservedObject var selectedSource: Source
@State private var selectedTempParser: SourcePreferredParser = .none
var body: some View {
Picker("Fetch method", selection: $selectedTempParser) {
if selectedSource.htmlParser != nil {
Text("Web scraping")
.tag(SourcePreferredParser.scraping)
}
if selectedSource.rssParser != nil {
Text("RSS")
.tag(SourcePreferredParser.rss)
}
}
.pickerStyle(.inline)
.onAppear {
selectedTempParser = SourcePreferredParser(rawValue: selectedSource.preferredParser) ?? .none
}
.onChange(of: selectedTempParser) { _ in
selectedSource.preferredParser = selectedTempParser.rawValue
PersistenceController.shared.save()
}
}
}