Ferrite: Cleanup and refine backend

- Fix how abrupt search cancellations work
- Add a no results prompt if no results are found
- Clean up how scraping model results are returned on error
- Allow a base URL and dynamic base URL to be provided together

Signed-off-by: kingbri <bdashore3@gmail.com>
This commit is contained in:
kingbri 2022-08-12 12:08:59 -04:00
parent eb326f3354
commit 9cfb12cb14
4 changed files with 31 additions and 18 deletions

View file

@ -159,12 +159,12 @@ class ScrapingViewModel: ObservableObject {
// RSS feed scraper
@MainActor
public func scrapeRss(source: Source, rss: String) -> [SearchResult] {
guard let rssParser = source.rssParser else {
return []
}
var tempResults: [SearchResult] = []
guard let rssParser = source.rssParser else {
return tempResults
}
var items = Elements()
do {
@ -174,7 +174,7 @@ class ScrapingViewModel: ObservableObject {
toastModel?.toastDescription = "RSS scraping error, couldn't fetch items: \(error)"
print("RSS scraping error, couldn't fetch items: \(error)")
return []
return tempResults
}
for item in items {
@ -284,8 +284,10 @@ class ScrapingViewModel: ObservableObject {
// HTML scraper
@MainActor
public func scrapeHtml(source: Source, baseUrl: String, html: String) async -> [SearchResult] {
var tempResults: [SearchResult] = []
guard let htmlParser = source.htmlParser else {
return []
return tempResults
}
var rows = Elements()
@ -297,11 +299,9 @@ class ScrapingViewModel: ObservableObject {
toastModel?.toastDescription = "Scraping error, couldn't fetch rows: \(error)"
print("Scraping error, couldn't fetch rows: \(error)")
return []
return tempResults
}
var tempResults: [SearchResult] = []
// If there's an error, continue instead of returning with nothing
for row in rows {
do {

View file

@ -51,7 +51,7 @@ public class SourceManager: ObservableObject {
// If there's no base URL and it isn't dynamic, return before any transactions occur
let dynamicBaseUrl = sourceJson.dynamicBaseUrl ?? false
if (!dynamicBaseUrl && sourceJson.baseUrl == nil) || (dynamicBaseUrl && sourceJson.baseUrl != nil) {
if !dynamicBaseUrl, sourceJson.baseUrl == nil {
Task { @MainActor in
toastModel?.toastDescription = "Not adding this source because base URL parameters are malformed. Please contact the source dev."
}

View file

@ -77,7 +77,7 @@ struct ContentView: View {
await scrapingModel.scanSources(sources: sources.compactMap { $0 })
if realDebridEnabled {
if realDebridEnabled, !scrapingModel.searchResults.isEmpty {
await debridManager.populateDebridHashes(scrapingModel.searchResults)
}

View file

@ -52,24 +52,37 @@ struct SearchResultsView: View {
}
}
.overlay {
if scrapingModel.searchResults.isEmpty, navModel.showSearchProgress {
VStack(spacing: 5) {
ProgressView()
Text("Loading \(scrapingModel.currentSourceName ?? "")")
if scrapingModel.searchResults.isEmpty {
if navModel.showSearchProgress {
VStack(spacing: 5) {
ProgressView()
Text("Loading \(scrapingModel.currentSourceName ?? "")")
}
} else if isSearching, scrapingModel.runningSearchTask != nil {
Text("No results found")
}
}
}
.onChange(of: navModel.selectedTab) { tab in
// Cancel the search if tab is switched
if tab != .search, isSearching, navModel.showSearchProgress {
// Cancel the search if tab is switched while search is in progress
if tab != .search, navModel.showSearchProgress {
scrapingModel.runningSearchTask?.cancel()
scrapingModel.runningSearchTask = nil
dismissSearch()
}
}
.onChange(of: scrapingModel.searchResults) { _ in
// Cleans up any leftover search results in the event of an abrupt cancellation
if !isSearching {
scrapingModel.searchResults = []
}
}
.onChange(of: isSearching) { changed in
// Clear the results array on cancel
// Clear the results array and cleans up search tasks on cancel
if !changed {
scrapingModel.searchResults = []
scrapingModel.runningSearchTask?.cancel()
scrapingModel.runningSearchTask = nil
}
}
}