Notifications marker

This commit is contained in:
Justin Mazzocchi 2021-02-19 19:21:55 -08:00
parent 6294b1c52f
commit 9274cd2615
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
4 changed files with 48 additions and 15 deletions

View file

@ -14,6 +14,8 @@ public protocol CollectionService {
var navigationService: NavigationService { get }
var positionTimeline: Timeline? { get }
func request(maxId: String?, minId: String?, search: Search?) -> AnyPublisher<Never, Error>
func requestMarkerLastReadId() -> AnyPublisher<CollectionItem.Id, Error>
func setMarkerLastReadId(_ id: CollectionItem.Id) -> AnyPublisher<CollectionItem.Id, Error>
}
extension CollectionService {
@ -30,4 +32,10 @@ extension CollectionService {
public var titleLocalizationComponents: AnyPublisher<[String], Never> { Empty().eraseToAnyPublisher() }
public var positionTimeline: Timeline? { nil }
public func requestMarkerLastReadId() -> AnyPublisher<CollectionItem.Id, Error> { Empty().eraseToAnyPublisher() }
public func setMarkerLastReadId(_ id: CollectionItem.Id) -> AnyPublisher<CollectionItem.Id, Error> {
Empty().eraseToAnyPublisher()
}
}

View file

@ -119,12 +119,6 @@ public extension IdentityService {
.eraseToAnyPublisher()
}
func getMarker(_ markerTimeline: Marker.Timeline) -> AnyPublisher<Marker, Error> {
mastodonAPIClient.request(MarkersEndpoint.get([markerTimeline]))
.compactMap { $0[markerTimeline.rawValue] }
.eraseToAnyPublisher()
}
func getLocalLastReadId(timeline: Timeline) -> String? {
contentDatabase.lastReadId(timelineId: timeline.id)
}

View file

@ -55,4 +55,16 @@ extension NotificationsService: CollectionService {
.flatMap { contentDatabase.insert(notifications: $0.result) }
.eraseToAnyPublisher()
}
public func requestMarkerLastReadId() -> AnyPublisher<CollectionItem.Id, Error> {
mastodonAPIClient.request(MarkersEndpoint.get([.notifications]))
.compactMap { $0.values.first?.lastReadId }
.eraseToAnyPublisher()
}
public func setMarkerLastReadId(_ id: CollectionItem.Id) -> AnyPublisher<CollectionItem.Id, Error> {
mastodonAPIClient.request(MarkersEndpoint.post([.notifications: id]))
.compactMap { $0.values.first?.lastReadId }
.eraseToAnyPublisher()
}
}

View file

@ -21,10 +21,11 @@ public class CollectionItemsViewModel: ObservableObject {
private var topVisibleIndexPath = IndexPath(item: 0, section: 0)
private let lastReadId = CurrentValueSubject<String?, Never>(nil)
private var lastSelectedLoadMore: LoadMore?
private var hasRequestedUsingMarker = false
private var markerScrollPositionItemId: CollectionItem.Id?
private var localLastReadId: CollectionItem.Id?
private var markerLastReadId: CollectionItem.Id?
private var cancellables = Set<AnyCancellable>()
// swiftlint:disable:next function_body_length
public init(collectionService: CollectionService, identityContext: IdentityContext) {
self.collectionService = collectionService
self.identityContext = identityContext
@ -50,18 +51,32 @@ public class CollectionItemsViewModel: ObservableObject {
.sink { _ in }
.store(in: &cancellables)
let debouncedLastReadId = lastReadId
.compactMap { $0 }
.removeDuplicates()
.debounce(for: .seconds(Self.lastReadIdDebounceInterval), scheduler: DispatchQueue.global())
.share()
debouncedLastReadId
.filter { [weak self] in
guard let markerLastReadId = self?.markerLastReadId else { return false }
return $0 > markerLastReadId
}
.flatMap { collectionService.setMarkerLastReadId($0) }
.receive(on: DispatchQueue.main)
.sink { _ in } receiveValue: { [weak self] in self?.markerLastReadId = $0 }
.store(in: &cancellables)
if let timeline = collectionService.positionTimeline {
if identityContext.appPreferences.positionBehavior(timeline: timeline) == .localRememberPosition {
markerScrollPositionItemId = identityContext.service.getLocalLastReadId(timeline: timeline)
localLastReadId = identityContext.service.getLocalLastReadId(timeline: timeline)
}
lastReadId
debouncedLastReadId
.filter { _ in
identityContext.appPreferences.positionBehavior(timeline: timeline) == .localRememberPosition
}
.compactMap { $0 }
.removeDuplicates()
.debounce(for: .seconds(Self.lastReadIdDebounceInterval), scheduler: DispatchQueue.global())
.flatMap { identityContext.service.setLocalLastReadId($0, timeline: timeline) }
.sink { _ in } receiveValue: { _ in }
.store(in: &cancellables)
@ -119,6 +134,10 @@ extension CollectionItemsViewModel: CollectionViewModel {
receiveCompletion: { [weak self] _ in self?.loadingSubject.send(false) })
.sink { _ in }
.store(in: &cancellables)
collectionService.requestMarkerLastReadId()
.sink { _ in } receiveValue: { [weak self] in self?.markerLastReadId = $0 }
.store(in: &cancellables)
}
public func select(indexPath: IndexPath) {
@ -375,9 +394,9 @@ private extension CollectionItemsViewModel {
let items = lastUpdate.sections.map(\.items).reduce([], +)
let newItems = newSections.map(\.items).reduce([], +)
if let itemId = markerScrollPositionItemId,
if let itemId = localLastReadId,
newItems.contains(where: { $0.itemId == itemId }) {
markerScrollPositionItemId = nil
localLastReadId = nil
return itemId
}