Improve bottom loader UX

This commit is contained in:
Jackson Harper
2023-12-21 09:42:59 +08:00
parent b824f2771f
commit 7e7c9e344c
6 changed files with 101 additions and 24 deletions

View File

@ -1042,12 +1042,31 @@ struct BottomView: View {
@EnvironmentObject var dataService: DataService
var body: some View {
Color.clear
.onAppear {
Task {
await viewModel.loadMore(dataService: dataService)
if viewModel.fetcher.items.count < 5 {
Color.clear
.onAppear {
Task {
await viewModel.loadMore(dataService: dataService)
}
print("BOTTOM APPEARED")
}
print("BOTTOM APPEARED")
}
} else {
HStack {
Text("You are all caught up.")
Spacer()
if viewModel.isLoading {
ProgressView()
} else {
Button(action: {
Task {
await viewModel.loadMore(dataService: dataService)
}
}, label: {
Text("Refresh library")
})
.foregroundColor(Color.blue)
}
}.padding(10)
}
}
}

View File

@ -51,10 +51,13 @@ struct LibraryAddFeedView: View {
viewModel: LibraryAddFeedViewModel(
dataService: dataService,
feedURL: feedURL,
prefetchContent: prefetchContent,
folder: folderSelection,
selectedLabels: selectedLabels,
toastOperationHandler: toastOperationHandler
)
),
label: { Text("Add").bold() }
label: { Text("Add").bold().disabled(feedURL.isEmpty) }
)
}
}
@ -138,18 +141,24 @@ private struct SubscriptionSettings: View {
var labelRuleRow: some View {
HStack {
Text("Add Labels")
Spacer()
Spacer(minLength: 30)
Button(action: { showLabelsSelector = true }, label: {
Text("Create Rule")
if selectedLabels.count > 0 {
let labelNames = selectedLabels.map(\.unwrappedName)
Text("[\(labelNames.joined(separator: ","))]")
.lineLimit(1)
} else {
Text("Create Rule")
}
})
}
}
var body: some View {
Group {
Toggle(isOn: $prefetchContent, label: { Text("Prefetch Content:") })
// Toggle(isOn: $prefetchContent, label: { Text("Prefetch Content:") })
folderRow
labelRuleRow
// labelRuleRow
}
.sheet(isPresented: $showLabelsSelector) {
ApplyLabelsView(mode: .list(selectedLabels), onSave: { labels in

View File

@ -1,4 +1,5 @@
import Foundation
import Models
import Services
import SwiftUI
import Utils
@ -7,6 +8,9 @@ import Utils
public class LibraryAddFeedViewModel: NSObject, ObservableObject {
let dataService: DataService
let feedURL: String
let prefetchContent: Bool
let folder: String
let selectedLabels: [LinkedItemLabel]
let toastOperationHandler: ToastOperationHandler?
@Published var isLoading = true
@ -16,9 +20,12 @@ public class LibraryAddFeedViewModel: NSObject, ObservableObject {
@Published var feeds: [Feed] = []
@Published var selected: [String] = []
init(dataService: DataService, feedURL: String, toastOperationHandler: ToastOperationHandler?) {
init(dataService: DataService, feedURL: String, prefetchContent: Bool, folder: String, selectedLabels: [LinkedItemLabel], toastOperationHandler: ToastOperationHandler?) {
self.dataService = dataService
self.feedURL = feedURL
self.prefetchContent = prefetchContent
self.folder = folder
self.selectedLabels = selectedLabels
self.toastOperationHandler = toastOperationHandler
}
@ -49,7 +56,7 @@ public class LibraryAddFeedViewModel: NSObject, ObservableObject {
_ = await withTaskGroup(of: Bool.self) { group in
for feedURL in selected {
group.addTask {
(try? await self.dataService.subscribeToFeed(feedURL: feedURL)) ?? false
(try? await self.dataService.subscribeToFeed(feedURL: feedURL, folder: self.folder, fetchContent: self.prefetchContent)) ?? false
}
}
@ -78,7 +85,7 @@ public class LibraryAddFeedViewModel: NSObject, ObservableObject {
_ = await withTaskGroup(of: Bool.self) { group in
for feedURL in selected {
group.addTask {
(try? await self.dataService.subscribeToFeed(feedURL: feedURL)) ?? false
(try? await self.dataService.subscribeToFeed(feedURL: feedURL, folder: self.folder, fetchContent: self.prefetchContent)) ?? false
}
}
@ -103,6 +110,39 @@ public class LibraryAddFeedViewModel: NSObject, ObservableObject {
}
}
func setLabelsRule(dataService _: DataService, existingRule _: Rule?, ruleName _: String, filter _: String, labelIDs _: [String]) async {
// Task {
// operationMessage = "Creating label rule..."
// operationStatus = .isPerforming
// do {
// // Make sure the labels have been created
// await loadLabels(dataService: dataService)
// let existingLabelIDs = labels?.map(\.unwrappedID) ?? []
// if labelIDs.first(where: { !existingLabelIDs.contains($0) }) != nil {
// throw BasicError.message(messageText: "Label not created")
// }
//
// _ = try await dataService.createOrUpdateAddLabelsRule(
// existingID: existingRule?.id,
// name: ruleName,
// filter: filter,
// labelIDs: labelIDs
// )
// if let newRules = try? await dataService.rules() {
// if !newRules.contains(where: { $0.name == ruleName }) {
// throw BasicError.message(messageText: "Rule not created")
// }
// rules = newRules
// }
// operationMessage = "Rule created"
// operationStatus = .success
// } catch {
// operationMessage = "Failed to create label rule"
// operationStatus = .failure
// }
// }
}
func error(_ msg: String) {
errorMessage = msg
showErrorMessage = true
@ -176,7 +216,7 @@ public struct LibraryScanFeedView: View {
await viewModel.addFeeds()
}
}, label: {
Text("Add").bold()
Text("Add").bold().disabled(viewModel.selected.count < 1)
})
} else {
Button(action: {

View File

@ -266,6 +266,9 @@ struct SubscriptionsView: View {
await viewModel.loadSubscriptions(dataService: dataService)
}
}
.onDisappear {
viewModel.showOperationToast = false
}
.navigationTitle("Subscriptions")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
@ -502,7 +505,7 @@ struct SubscriptionSettingsView: View {
let labelNames = ruleLabels.map(\.unwrappedName)
Text("[\(labelNames.joined(separator: ","))]")
} else {
Text("[none]")
Text("Create Rule")
}
})
} else {
@ -535,12 +538,12 @@ struct SubscriptionSettingsView: View {
.padding(.horizontal, 15)
List {
if subscription.type != .newsletter {
Toggle(isOn: $prefetchContent, label: { Text("Prefetch Content:") })
.onAppear {
prefetchContent = subscription.fetchContent
}
}
// if subscription.type != .newsletter {
// Toggle(isOn: $prefetchContent, label: { Text("Prefetch Content:") })
// .onAppear {
// prefetchContent = subscription.fetchContent
// }
// }
folderRow
labelRuleRow
}.listStyle(.insetGrouped)

View File

@ -54,6 +54,8 @@ public struct WebReaderLoadingContainer: View {
PDFWrapperView(pdfURL: pdfURL)
}
#endif
} else if item.state == "CONTENT_NOT_FETCHED" {
ProgressView()
} else {
WebReaderContainerView(item: item, pop: { dismiss() })
#if os(iOS)

View File

@ -3,7 +3,7 @@ import Models
import SwiftGraphQL
public extension DataService {
func subscribeToFeed(feedURL: String) async throws -> Bool {
func subscribeToFeed(feedURL: String, folder: String? = nil, fetchContent: Bool? = nil) async throws -> Bool {
enum MutationResult {
case success(subscriptionIds: [String])
case error(errorMessage: String)
@ -25,7 +25,11 @@ public extension DataService {
}
let mutation = Selection.Mutation {
try $0.subscribe(input: InputObjects.SubscribeInput(url: feedURL), selection: selection)
try $0.subscribe(input: InputObjects.SubscribeInput(
fetchContent: OptionalArgument(fetchContent),
folder: OptionalArgument(folder),
url: feedURL
), selection: selection)
}
let path = appEnvironment.graphqlPath