Files
RSSuper/iOS/RSSuper/ViewModels/FeedViewModel.swift
Michael Freno 14efe072fa feat: implement cross-platform features and UI integration
- 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>
2026-03-30 23:06:12 -04:00

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)
}
}