Sources: Add list IDs and source IDs

List IDs are used to link a source list with an actual source. Each
list entry has a unique ID that a user can compare with a source
to see if it's legitimate.

Source IDs are just identifiers for sources. Not sure what to do with
these yet but they may be useful for the future.

Signed-off-by: kingbri <bdashore3@gmail.com>
This commit is contained in:
kingbri 2022-08-05 12:15:56 -04:00
parent bf70b436db
commit 3907f23fec
8 changed files with 55 additions and 11 deletions

View file

@ -16,10 +16,12 @@ extension Source {
return NSFetchRequest<Source>(entityName: "Source") return NSFetchRequest<Source>(entityName: "Source")
} }
@NSManaged public var id: UUID
@NSManaged public var baseUrl: String @NSManaged public var baseUrl: String
@NSManaged public var enabled: Bool @NSManaged public var enabled: Bool
@NSManaged public var name: String @NSManaged public var name: String
@NSManaged public var author: String? @NSManaged public var author: String
@NSManaged public var listId: UUID?
@NSManaged public var preferredParser: Int16 @NSManaged public var preferredParser: Int16
@NSManaged public var version: Int16 @NSManaged public var version: Int16
@NSManaged public var htmlParser: SourceHtmlParser? @NSManaged public var htmlParser: SourceHtmlParser?

View file

@ -14,6 +14,7 @@ public extension SourceList {
NSFetchRequest<SourceList>(entityName: "SourceList") NSFetchRequest<SourceList>(entityName: "SourceList")
} }
@NSManaged var id: UUID
@NSManaged var author: String @NSManaged var author: String
@NSManaged var name: String @NSManaged var name: String
@NSManaged var urlString: String @NSManaged var urlString: String

View file

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21271" systemVersion="21F79" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> <model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21271" systemVersion="21F79" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Source" representedClassName="Source" syncable="YES"> <entity name="Source" representedClassName="Source" syncable="YES">
<attribute name="author" optional="YES" attributeType="String"/> <attribute name="author" attributeType="String" defaultValueString=""/>
<attribute name="baseUrl" attributeType="String" defaultValueString=""/> <attribute name="baseUrl" attributeType="String" defaultValueString=""/>
<attribute name="enabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/> <attribute name="enabled" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="id" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="listId" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String" defaultValueString=""/> <attribute name="name" attributeType="String" defaultValueString=""/>
<attribute name="preferredParser" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="preferredParser" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="version" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/> <attribute name="version" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
@ -29,6 +31,7 @@
</entity> </entity>
<entity name="SourceList" representedClassName="SourceList" syncable="YES"> <entity name="SourceList" representedClassName="SourceList" syncable="YES">
<attribute name="author" attributeType="String" defaultValueString=""/> <attribute name="author" attributeType="String" defaultValueString=""/>
<attribute name="id" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String" defaultValueString=""/> <attribute name="name" attributeType="String" defaultValueString=""/>
<attribute name="urlString" attributeType="String" defaultValueString=""/> <attribute name="urlString" attributeType="String" defaultValueString=""/>
</entity> </entity>

View file

@ -18,6 +18,7 @@ public struct SourceJson: Codable, Hashable {
let version: Int16 let version: Int16
let baseUrl: String let baseUrl: String
var author: String? var author: String?
var listId: UUID?
let rssParser: SourceRssParserJson? let rssParser: SourceRssParserJson?
let htmlParser: SourceHtmlParserJson? let htmlParser: SourceHtmlParserJson?
} }

View file

@ -33,6 +33,7 @@ public class SourceManager: ObservableObject {
for index in sourceResponse.sources.indices { for index in sourceResponse.sources.indices {
sourceResponse.sources[index].author = sourceList.author sourceResponse.sources[index].author = sourceList.author
sourceResponse.sources[index].listId = sourceList.id
} }
tempSourceUrls += sourceResponse.sources tempSourceUrls += sourceResponse.sources
@ -62,10 +63,12 @@ public class SourceManager: ObservableObject {
} }
let newSource = Source(context: backgroundContext) let newSource = Source(context: backgroundContext)
newSource.id = UUID()
newSource.name = sourceJson.name newSource.name = sourceJson.name
newSource.version = sourceJson.version newSource.version = sourceJson.version
newSource.baseUrl = sourceJson.baseUrl newSource.baseUrl = sourceJson.baseUrl
newSource.author = sourceJson.author newSource.author = sourceJson.author ?? "Unknown"
newSource.listId = sourceJson.listId
// Adds an RSS parser if present // Adds an RSS parser if present
if let rssParserJson = sourceJson.rssParser { if let rssParserJson = sourceJson.rssParser {
@ -240,6 +243,7 @@ public class SourceManager: ObservableObject {
} }
let newSourceUrl = SourceList(context: backgroundContext) let newSourceUrl = SourceList(context: backgroundContext)
newSourceUrl.id = UUID()
newSourceUrl.urlString = sourceUrl newSourceUrl.urlString = sourceUrl
newSourceUrl.name = rawResponse.name newSourceUrl.name = rawResponse.name
newSourceUrl.author = rawResponse.author newSourceUrl.author = rawResponse.author
@ -248,6 +252,7 @@ public class SourceManager: ObservableObject {
return true return true
} catch { } catch {
print(error)
urlErrorAlertText = error.localizedDescription urlErrorAlertText = error.localizedDescription
showUrlErrorAlert.toggle() showUrlErrorAlert.toggle()

View file

@ -20,7 +20,12 @@ struct SettingsSourceListView: View {
var body: some View { var body: some View {
List { List {
ForEach(sourceUrls, id: \.self) { sourceUrl in ForEach(sourceUrls, id: \.self) { sourceUrl in
Text(sourceUrl.name) VStack(alignment: .leading, spacing: 5) {
Text(sourceUrl.name)
Text("ID: \(sourceUrl.id)")
.font(.caption)
.foregroundColor(.gray)
}
} }
.onDelete { offsets in .onDelete { offsets in
for index in offsets { for index in offsets {

View file

@ -40,7 +40,7 @@ struct SourceListView: View {
.foregroundColor(.secondary) .foregroundColor(.secondary)
} }
Text("by \(source.author ?? "Unknown")") Text("by \(source.author)")
.foregroundColor(.secondary) .foregroundColor(.secondary)
} }
} }

View file

@ -10,10 +10,37 @@ import SwiftUI
struct SourceSettingsView: View { struct SourceSettingsView: View {
@Environment(\.dismiss) var dismiss @Environment(\.dismiss) var dismiss
@EnvironmentObject var navModel: NavigationViewModel
var body: some View { var body: some View {
NavView { NavView {
Form { Form {
SourceSettingsMethodView() if let selectedSource = navModel.selectedSource {
Section("Info") {
VStack(alignment: .leading, spacing: 5) {
HStack {
Text(selectedSource.name)
Text("v\(selectedSource.version)")
}
Text("by \(selectedSource.author)")
.foregroundColor(.secondary)
if let listId = selectedSource.listId {
Text("List ID: \(listId)")
.font(.caption)
.foregroundColor(.secondary)
} else {
Text("No list ID found. This source should be removed.")
.font(.caption)
.foregroundColor(.secondary)
}
}
}
SourceSettingsMethodView(selectedSource: selectedSource)
}
} }
.navigationTitle("Source settings") .navigationTitle("Source settings")
.toolbar { .toolbar {
@ -28,28 +55,28 @@ struct SourceSettingsView: View {
} }
struct SourceSettingsMethodView: View { struct SourceSettingsMethodView: View {
@EnvironmentObject var navModel: NavigationViewModel @ObservedObject var selectedSource: Source
@State private var selectedTempParser: SourcePreferredParser = .none @State private var selectedTempParser: SourcePreferredParser = .none
var body: some View { var body: some View {
Picker("Fetch method", selection: $selectedTempParser) { Picker("Fetch method", selection: $selectedTempParser) {
if navModel.selectedSource?.htmlParser != nil { if selectedSource.htmlParser != nil {
Text("Web scraping") Text("Web scraping")
.tag(SourcePreferredParser.scraping) .tag(SourcePreferredParser.scraping)
} }
if navModel.selectedSource?.rssParser != nil { if selectedSource.rssParser != nil {
Text("RSS") Text("RSS")
.tag(SourcePreferredParser.rss) .tag(SourcePreferredParser.rss)
} }
} }
.pickerStyle(.inline) .pickerStyle(.inline)
.onAppear { .onAppear {
selectedTempParser = SourcePreferredParser(rawValue: navModel.selectedSource?.preferredParser ?? 0) ?? .none selectedTempParser = SourcePreferredParser(rawValue: selectedSource.preferredParser) ?? .none
} }
.onChange(of: selectedTempParser) { newMethod in .onChange(of: selectedTempParser) { newMethod in
navModel.selectedSource?.preferredParser = newMethod.rawValue selectedSource.preferredParser = selectedTempParser.rawValue
PersistenceController.shared.save() PersistenceController.shared.save()
} }
} }