Notifications marker

This commit is contained in:
Justin Mazzocchi 2020-11-02 20:24:56 -08:00
parent 69b664ce0f
commit 407bc00ee0
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
4 changed files with 57 additions and 20 deletions

View file

@ -394,11 +394,44 @@ private extension ContentDatabase {
try FileManager.default.databaseDirectoryURL(name: id.uuidString)
}
// swiftlint:disable:next function_body_length
static func clean(_ databaseWriter: DatabaseWriter,
useHomeTimelineLastReadId: Bool,
useNotificationsLastReadId: Bool) throws {
try databaseWriter.write {
try NotificationRecord.deleteAll($0)
let notificationAccountIds: [Account.Id]
let notificationStatusIds: [Status.Id]
if useNotificationsLastReadId {
var notificationIds = try MastodonNotification.Id.fetchAll(
$0,
NotificationRecord.select(NotificationRecord.Columns.id)
.order(NotificationRecord.Columns.id.desc))
if let lastReadId = try MastodonNotification.Id.fetchOne(
$0,
LastReadIdRecord.filter(
LastReadIdRecord.Columns.markerTimeline == Marker.Timeline.notifications.rawValue)
.select(LastReadIdRecord.Columns.id))
?? notificationIds.first,
let index = notificationIds.firstIndex(of: lastReadId) {
notificationIds = Array(notificationIds.prefix(index + Self.cleanAfterLastReadIdCount))
}
try NotificationRecord.filter(!notificationIds.contains(NotificationRecord.Columns.id)).deleteAll($0)
notificationAccountIds = try Account.Id.fetchAll(
$0,
NotificationRecord.select(NotificationRecord.Columns.accountId))
notificationStatusIds = try Status.Id.fetchAll(
$0,
NotificationRecord.filter(
NotificationRecord.Columns.statusId != nil)
.select(NotificationRecord.Columns.statusId))
} else {
try NotificationRecord.deleteAll($0)
notificationAccountIds = []
notificationStatusIds = []
}
if useHomeTimelineLastReadId {
try TimelineRecord.filter(TimelineRecord.Columns.id != Timeline.home.id).deleteAll($0)
@ -416,13 +449,15 @@ private extension ContentDatabase {
statusIds = Array(statusIds.prefix(index + Self.cleanAfterLastReadIdCount))
}
statusIds += notificationStatusIds
statusIds += try Status.Id.fetchAll(
$0,
StatusRecord.filter(statusIds.contains(StatusRecord.Columns.id)
&& StatusRecord.Columns.reblogId != nil)
.select(StatusRecord.Columns.reblogId))
try StatusRecord.filter(!statusIds.contains(StatusRecord.Columns.id) ).deleteAll($0)
try StatusRecord.filter(!statusIds.contains(StatusRecord.Columns.id)).deleteAll($0)
var accountIds = try Account.Id.fetchAll($0, StatusRecord.select(StatusRecord.Columns.accountId))
accountIds += notificationAccountIds
accountIds += try Account.Id.fetchAll(
$0,
AccountRecord.filter(accountIds.contains(AccountRecord.Columns.id)
@ -431,8 +466,8 @@ private extension ContentDatabase {
try AccountRecord.filter(!accountIds.contains(AccountRecord.Columns.id)).deleteAll($0)
} else {
try TimelineRecord.deleteAll($0)
try StatusRecord.deleteAll($0)
try AccountRecord.deleteAll($0)
try StatusRecord.filter(!notificationStatusIds.contains(StatusRecord.Columns.id)).deleteAll($0)
try AccountRecord.filter(!notificationAccountIds.contains(AccountRecord.Columns.id)).deleteAll($0)
}
try AccountList.deleteAll($0)

View file

@ -3,7 +3,7 @@
import Foundation
public struct MastodonNotification: Codable, Hashable {
public let id: String
public let id: Id
public let type: NotificationType
public let account: Account
public let status: Status?
@ -16,8 +16,10 @@ public struct MastodonNotification: Codable, Hashable {
}
}
extension MastodonNotification {
public enum NotificationType: String, Codable, Unknowable {
public extension MastodonNotification {
typealias Id = String
enum NotificationType: String, Codable, Unknowable {
case follow
case mention
case reblog

View file

@ -37,6 +37,8 @@ public struct NotificationsService {
}
extension NotificationsService: CollectionService {
public var markerTimeline: Marker.Timeline? { .notifications }
public func request(maxId: String?, minId: String?) -> AnyPublisher<Never, Error> {
mastodonAPIClient.pagedRequest(NotificationsEndpoint.notifications, maxId: maxId, minId: minId)
.handleEvents(receiveOutput: {

View file

@ -21,7 +21,7 @@ final public class CollectionItemsViewModel: ObservableObject {
private let lastReadId = CurrentValueSubject<String?, Never>(nil)
private var lastSelectedLoadMore: LoadMore?
private var hasRequestedUsingMarker = false
private var hasRememberedPosition = false
private var shouldRestorePositionOfLocalLastReadId = false
private var cancellables = Set<AnyCancellable>()
public init(collectionService: CollectionService, identification: Identification) {
@ -43,6 +43,8 @@ final public class CollectionItemsViewModel: ObservableObject {
.store(in: &cancellables)
if let markerTimeline = collectionService.markerTimeline {
shouldRestorePositionOfLocalLastReadId =
identification.appPreferences.positionBehavior(markerTimeline: markerTimeline) == .rememberPosition
lastReadId.compactMap { $0 }
.removeDuplicates()
.debounce(for: 0.5, scheduler: DispatchQueue.global())
@ -144,13 +146,10 @@ extension CollectionItemsViewModel: CollectionViewModel {
public func viewedAtTop(indexPath: IndexPath) {
topVisibleIndexPath = indexPath
if items.value.count > indexPath.section, items.value[indexPath.section].count > indexPath.item {
switch items.value[indexPath.section][indexPath.item] {
case let .status(status, _):
lastReadId.send(status.id)
default:
break
}
if !shouldRestorePositionOfLocalLastReadId,
items.value.count > indexPath.section,
items.value[indexPath.section].count > indexPath.item {
lastReadId.send(items.value[indexPath.section][indexPath.item].itemId)
}
}
@ -279,12 +278,11 @@ private extension CollectionItemsViewModel {
let flatItems = items.value.reduce([], +)
let flatNewItems = newItems.reduce([], +)
if let markerTimeline = collectionService.markerTimeline,
identification.appPreferences.positionBehavior(markerTimeline: markerTimeline) == .rememberPosition,
if shouldRestorePositionOfLocalLastReadId,
let markerTimeline = collectionService.markerTimeline,
let localLastReadId = identification.service.getLocalLastReadId(markerTimeline),
flatItems.contains(where: { $0.itemId == localLastReadId }),
!hasRememberedPosition {
hasRememberedPosition = true
flatNewItems.contains(where: { $0.itemId == localLastReadId }) {
shouldRestorePositionOfLocalLastReadId = false
return localLastReadId
}