Separate feeds and newsletters on the subscriptions view

This commit is contained in:
Jackson Harper
2023-12-18 12:09:06 +08:00
parent 30771c3498
commit e312562636
3 changed files with 77 additions and 41 deletions

View File

@ -5,8 +5,8 @@ import Views
@MainActor final class SubscriptionsViewModel: ObservableObject {
@Published var isLoading = true
@Published var subscriptions = [Subscription]()
@Published var popularSubscriptions = [Subscription]()
@Published var feeds = [Subscription]()
@Published var newsletters = [Subscription]()
@Published var hasNetworkError = false
@Published var subscriptionNameToCancel: String?
@ -14,7 +14,9 @@ import Views
isLoading = true
do {
subscriptions = try await dataService.subscriptions().filter { $0.status == SubscriptionStatus.active }
let subscriptions = try await dataService.subscriptions().filter { $0.status == SubscriptionStatus.active }
feeds = subscriptions.filter { $0.type == .feed }
newsletters = subscriptions.filter { $0.type == .newsletter }
} catch {
hasNetworkError = true
}
@ -27,10 +29,10 @@ import Views
do {
try await dataService.deleteSubscription(subscriptionName: subscriptionName)
let index = subscriptions.firstIndex { $0.name == subscriptionName }
if let index = index {
subscriptions.remove(at: index)
}
// let index = subscriptions.firstIndex { $0.name == subscriptionName }
// if let index = index {
// subscriptions.remove(at: index)
// }
return true
} catch {
appLogger.debug("failed to remove subscription")
@ -49,13 +51,6 @@ struct SubscriptionsView: View {
Group {
if viewModel.isLoading {
ProgressView()
.opacity(progressViewOpacity)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1000)) {
progressViewOpacity = 1
}
}
.task { await viewModel.loadSubscriptions(dataService: dataService) }
} else if viewModel.hasNetworkError {
VStack {
Text(LocalText.subscriptionsErrorRetrieving).multilineTextAlignment(.center)
@ -65,27 +60,28 @@ struct SubscriptionsView: View {
)
.buttonStyle(RoundedRectButtonStyle())
}
} else if viewModel.subscriptions.isEmpty {
} else if viewModel.feeds.isEmpty, viewModel.newsletters.isEmpty {
VStack(alignment: .center) {
Spacer()
Text(LocalText.subscriptionsNone)
Spacer()
}
} else {
Group {
#if os(iOS)
Form {
innerBody
}
#elseif os(macOS)
List {
innerBody
}
.listStyle(InsetListStyle())
#endif
}
#if os(iOS)
Form {
innerBody
}
#elseif os(macOS)
List {
innerBody
}
.listStyle(InsetListStyle())
#endif
}
}
.task {
await viewModel.loadSubscriptions(dataService: dataService)
}
.navigationTitle("Subscriptions")
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
@ -94,20 +90,39 @@ struct SubscriptionsView: View {
private var innerBody: some View {
Group {
ForEach(viewModel.subscriptions, id: \.subscriptionID) { subscription in
SubscriptionCell(subscription: subscription)
.swipeActions(edge: .trailing) {
Button(
role: .destructive,
action: {
deleteConfirmationShown = true
viewModel.subscriptionNameToCancel = subscription.name
},
label: {
Image(systemName: "trash")
}
)
}
Section("Feeds") {
ForEach(viewModel.feeds, id: \.subscriptionID) { subscription in
SubscriptionCell(subscription: subscription)
.swipeActions(edge: .trailing) {
Button(
role: .destructive,
action: {
deleteConfirmationShown = true
viewModel.subscriptionNameToCancel = subscription.name
},
label: {
Image(systemName: "trash")
}
)
}
}
}
Section("Newsletters") {
ForEach(viewModel.newsletters, id: \.subscriptionID) { subscription in
SubscriptionCell(subscription: subscription)
.swipeActions(edge: .trailing) {
Button(
role: .destructive,
action: {
deleteConfirmationShown = true
viewModel.subscriptionNameToCancel = subscription.name
},
label: {
Image(systemName: "trash")
}
)
}
}
}
}
.alert("Are you sure you want to cancel this subscription?", isPresented: $deleteConfirmationShown) {

View File

@ -1,10 +1,12 @@
import Foundation
import SwiftGraphQL
public struct Subscription {
public let createdAt: Date?
public let description: String?
public let subscriptionID: String
public let name: String
public let type: SubscriptionType
public let newsletterEmailAddress: String?
public let status: SubscriptionStatus
public let unsubscribeHttpUrl: String?
@ -18,6 +20,7 @@ public struct Subscription {
description: String?,
subscriptionID: String,
name: String,
type: SubscriptionType,
newsletterEmailAddress: String?,
status: SubscriptionStatus,
unsubscribeHttpUrl: String?,
@ -30,6 +33,7 @@ public struct Subscription {
self.description = description
self.subscriptionID = subscriptionID
self.name = name
self.type = type
self.newsletterEmailAddress = newsletterEmailAddress
self.status = status
self.unsubscribeHttpUrl = unsubscribeHttpUrl
@ -45,3 +49,8 @@ public enum SubscriptionStatus {
case deleted
case unsubscribed
}
public enum SubscriptionType {
case newsletter
case feed
}

View File

@ -9,6 +9,7 @@ let subscriptionSelection = Selection.Subscription {
description: try $0.description(),
subscriptionID: try $0.id(),
name: try $0.name(),
type: try SubscriptionType.from($0.type()),
newsletterEmailAddress: try $0.newsletterEmail(),
status: try SubscriptionStatus.make(from: $0.status()),
unsubscribeHttpUrl: try $0.unsubscribeHttpUrl(),
@ -31,3 +32,14 @@ extension SubscriptionStatus {
}
}
}
extension SubscriptionType {
static func from(_ other: Enums.SubscriptionType) -> SubscriptionType {
switch other {
case .rss:
return .feed
case .newsletter:
return .newsletter
}
}
}