mirror of
https://github.com/metabolist/metatext
synced 2025-01-14 19:07:05 +01:00
Notifications marker
This commit is contained in:
parent
69b664ce0f
commit
407bc00ee0
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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: {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user