1
0
mirror of https://github.com/metabolist/metatext synced 2025-01-14 19:07:05 +01:00

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) try FileManager.default.databaseDirectoryURL(name: id.uuidString)
} }
// swiftlint:disable:next function_body_length
static func clean(_ databaseWriter: DatabaseWriter, static func clean(_ databaseWriter: DatabaseWriter,
useHomeTimelineLastReadId: Bool, useHomeTimelineLastReadId: Bool,
useNotificationsLastReadId: Bool) throws { useNotificationsLastReadId: Bool) throws {
try databaseWriter.write { 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 { if useHomeTimelineLastReadId {
try TimelineRecord.filter(TimelineRecord.Columns.id != Timeline.home.id).deleteAll($0) 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 = Array(statusIds.prefix(index + Self.cleanAfterLastReadIdCount))
} }
statusIds += notificationStatusIds
statusIds += try Status.Id.fetchAll( statusIds += try Status.Id.fetchAll(
$0, $0,
StatusRecord.filter(statusIds.contains(StatusRecord.Columns.id) StatusRecord.filter(statusIds.contains(StatusRecord.Columns.id)
&& StatusRecord.Columns.reblogId != nil) && StatusRecord.Columns.reblogId != nil)
.select(StatusRecord.Columns.reblogId)) .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)) var accountIds = try Account.Id.fetchAll($0, StatusRecord.select(StatusRecord.Columns.accountId))
accountIds += notificationAccountIds
accountIds += try Account.Id.fetchAll( accountIds += try Account.Id.fetchAll(
$0, $0,
AccountRecord.filter(accountIds.contains(AccountRecord.Columns.id) AccountRecord.filter(accountIds.contains(AccountRecord.Columns.id)
@ -431,8 +466,8 @@ private extension ContentDatabase {
try AccountRecord.filter(!accountIds.contains(AccountRecord.Columns.id)).deleteAll($0) try AccountRecord.filter(!accountIds.contains(AccountRecord.Columns.id)).deleteAll($0)
} else { } else {
try TimelineRecord.deleteAll($0) try TimelineRecord.deleteAll($0)
try StatusRecord.deleteAll($0) try StatusRecord.filter(!notificationStatusIds.contains(StatusRecord.Columns.id)).deleteAll($0)
try AccountRecord.deleteAll($0) try AccountRecord.filter(!notificationAccountIds.contains(AccountRecord.Columns.id)).deleteAll($0)
} }
try AccountList.deleteAll($0) try AccountList.deleteAll($0)

View File

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

View File

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

View File

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