Files
legado-ios/App/Features/RSS/RSSSourceEditorView.swift
T

93 lines
5.4 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import SwiftUI
struct RSSSourceEditorView: View {
@EnvironmentObject private var library: RSSLibraryModel
@Environment(\.dismiss) private var dismiss
@State private var source: RssSource
private let originalURL: String?
init(source: RssSource? = nil) {
let value = source ?? RssSource()
_source = State(initialValue: value)
originalURL = source?.sourceUrl
}
var body: some View {
Form {
Section("基本") {
TextField("名称", text: $source.sourceName)
TextField("URL", text: $source.sourceUrl).textInputAutocapitalization(.never).keyboardType(.URL)
requiredField("图标", \.sourceIcon)
optionalField("分组", \.sourceGroup)
optionalField("注释", \.sourceComment, axis: .vertical)
Toggle("启用", isOn: $source.enabled)
}
Section("请求与登录") {
optionalField("自定义变量说明", \.variableComment, axis: .vertical)
optionalField("JS库", \.jsLib, axis: .vertical)
Toggle("自动保存Cookie", isOn: optionalBool(\.enabledCookieJar, default: true))
optionalField("并发率", \.concurrentRate)
optionalField("请求头", \.header, axis: .vertical)
optionalField("登录地址", \.loginUrl)
optionalField("登录UI", \.loginUi, axis: .vertical)
optionalField("登录检测JS", \.loginCheckJs, axis: .vertical)
optionalField("封面解密JS", \.coverDecodeJs, axis: .vertical)
}
Section("分类与列表规则") {
optionalField("分类URL(名称::URL)", \.sortUrl, axis: .vertical)
Toggle("单URL源", isOn: $source.singleUrl)
Picker("列表样式", selection: $source.articleStyle) { ForEach(0..<5, id: \.self) { Text("样式 \($0)").tag($0) } }
optionalField("列表规则", \.ruleArticles, axis: .vertical)
optionalField("下一页规则", \.ruleNextPage, axis: .vertical)
optionalField("标题规则", \.ruleTitle, axis: .vertical)
optionalField("发布日期规则", \.rulePubDate, axis: .vertical)
optionalField("描述规则", \.ruleDescription, axis: .vertical)
optionalField("图片规则", \.ruleImage, axis: .vertical)
optionalField("链接规则", \.ruleLink, axis: .vertical)
optionalField("正文规则", \.ruleContent, axis: .vertical)
}
Section("WebView规则") {
optionalField("正文URL白名单", \.contentWhitelist, axis: .vertical)
optionalField("正文URL黑名单", \.contentBlacklist, axis: .vertical)
optionalField("跳转URL拦截JS", \.shouldOverrideUrlLoading, axis: .vertical)
optionalField("样式", \.style, axis: .vertical)
Toggle("启用JavaScript", isOn: $source.enableJs)
Toggle("使用Base URL加载", isOn: $source.loadWithBaseUrl)
optionalField("注入JS", \.injectJs, axis: .vertical)
optionalField("预注入JS", \.preloadJs, axis: .vertical)
optionalField("起始HTML", \.startHtml, axis: .vertical)
optionalField("起始样式", \.startStyle, axis: .vertical)
optionalField("起始JS", \.startJs, axis: .vertical)
Toggle("输出网页日志", isOn: $source.showWebLog)
}
Section("其他") {
Stepper("自定义排序:\(source.customOrder)", value: $source.customOrder)
Picker("类型", selection: $source.type) { Text("网页").tag(0); Text("图片").tag(1); Text("视频").tag(2) }
Toggle("启用预加载", isOn: $source.preload)
Toggle("优先加载缓存", isOn: $source.cacheFirst)
optionalField("搜索URL", \.searchUrl, axis: .vertical)
}
}
.navigationTitle(originalURL == nil ? "新建RSS源" : "编辑RSS源")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .confirmationAction) {
Button("保存") { Task { if await library.save(source, replacing: originalURL) { dismiss() } } }
}
}
}
@ViewBuilder private func optionalField(_ title: String, _ keyPath: WritableKeyPath<RssSource, String?>, axis: Axis = .horizontal) -> some View {
ReadingTextField(title, text: optionalText(keyPath), axis: axis).textInputAutocapitalization(.never)
}
@ViewBuilder private func requiredField(_ title: String, _ keyPath: WritableKeyPath<RssSource, String>, axis: Axis = .horizontal) -> some View {
ReadingTextField(title, text: Binding(get: { source[keyPath: keyPath] }, set: { source[keyPath: keyPath] = $0 }), axis: axis).textInputAutocapitalization(.never)
}
private func optionalText(_ keyPath: WritableKeyPath<RssSource, String?>) -> Binding<String> {
Binding(get: { source[keyPath: keyPath] ?? "" }, set: { source[keyPath: keyPath] = $0.isEmpty ? nil : $0 })
}
private func optionalBool(_ keyPath: WritableKeyPath<RssSource, Bool?>, default defaultValue: Bool) -> Binding<Bool> {
Binding(get: { source[keyPath: keyPath] ?? defaultValue }, set: { source[keyPath: keyPath] = $0 })
}
}