mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-25 01:31:02 +00:00
Notifications marker
This commit is contained in:
parent
69b664ce0f
commit
407bc00ee0
4 changed files with 57 additions and 20 deletions
|
@ -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 {
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue