- iOS: Add BackgroundSyncService, SyncScheduler, SyncWorker, BookmarkViewModel, FeedViewModel - iOS: Add BackgroundSyncService, SyncScheduler, SyncWorker services - Linux: Add settings-store.vala, State.vala signals, view widgets (FeedList, FeedDetail, AddFeed, Search, Settings, Bookmark) - Linux: Add bookmark-store.vala, bookmark vala model, search-service.vala - Android: Add NotificationService, NotificationManager, NotificationPreferencesStore - Android: Add BookmarkDao, BookmarkRepository, SettingsStore - Add unit tests for iOS, Android, Linux - Add integration tests - Add performance benchmarks - Update tasks and documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
93 lines
2.6 KiB
Swift
93 lines
2.6 KiB
Swift
//
|
|
// FeedViewModel.swift
|
|
// RSSuper
|
|
//
|
|
// ViewModel for feed state management
|
|
//
|
|
|
|
import Foundation
|
|
import Combine
|
|
|
|
/// State enum for feed data
|
|
enum FeedState {
|
|
case idle
|
|
case loading
|
|
case success([FeedItem])
|
|
case error(String)
|
|
}
|
|
|
|
/// ViewModel for managing feed state
|
|
class FeedViewModel: ObservableObject {
|
|
@Published var feedState: FeedState = .idle
|
|
@Published var unreadCount: Int = 0
|
|
@Published var feedItems: [FeedItem] = []
|
|
|
|
private let feedService: FeedServiceProtocol
|
|
private var cancellables = Set<AnyCancellable>()
|
|
private var currentSubscriptionId: String?
|
|
|
|
init(feedService: FeedServiceProtocol = FeedService()) {
|
|
self.feedService = feedService
|
|
}
|
|
|
|
deinit {
|
|
cancellables.forEach { $0.cancel() }
|
|
}
|
|
|
|
/// Load feed items for a subscription
|
|
func loadFeedItems(subscriptionId: String) {
|
|
currentSubscriptionId = subscriptionId
|
|
feedState = .loading
|
|
|
|
Task { [weak self] in
|
|
guard let self = self else { return }
|
|
|
|
let items = self.feedService.getFeedItems(subscriptionId: subscriptionId)
|
|
|
|
DispatchQueue.main.async {
|
|
self.feedItems = items
|
|
self.feedState = .success(items)
|
|
self.unreadCount = items.filter { !$0.read }.count
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Load unread count
|
|
func loadUnreadCount(subscriptionId: String) {
|
|
let items = feedService.getFeedItems(subscriptionId: subscriptionId)
|
|
unreadCount = items.filter { !$0.read }.count
|
|
}
|
|
|
|
/// Mark an item as read
|
|
func markAsRead(itemId: String, isRead: Bool) {
|
|
let success = feedService.markItemAsRead(itemId: itemId)
|
|
|
|
if success {
|
|
if let index = feedItems.firstIndex(where: { $0.id == itemId }) {
|
|
var updatedItem = feedItems[index]
|
|
updatedItem.read = isRead
|
|
feedItems[index] = updatedItem
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Mark an item as starred
|
|
func markAsStarred(itemId: String, isStarred: Bool) {
|
|
let success = feedService.markItemAsStarred(itemId: itemId)
|
|
|
|
if success {
|
|
if let index = feedItems.firstIndex(where: { $0.id == itemId }) {
|
|
var updatedItem = feedItems[index]
|
|
updatedItem.starred = isStarred
|
|
feedItems[index] = updatedItem
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Refresh feed
|
|
func refresh(subscriptionId: String) {
|
|
loadFeedItems(subscriptionId: subscriptionId)
|
|
loadUnreadCount(subscriptionId: subscriptionId)
|
|
}
|
|
}
|