fix: timer update leaking raise crash in notification scene
This commit is contained in:
parent
389d0971cd
commit
7d1c150364
|
@ -101,6 +101,10 @@ extension MastodonNotification {
|
|||
])
|
||||
}
|
||||
}
|
||||
|
||||
public static func predicate(validTypesRaws types: [String]) -> NSPredicate {
|
||||
return NSPredicate(format: "%K IN %@", #keyPath(MastodonNotification.typeRaw), types)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -30,14 +30,16 @@ extension NotificationSection {
|
|||
guard let dependency = dependency else { return nil }
|
||||
switch notificationItem {
|
||||
case .notification(let objectID, let attribute):
|
||||
|
||||
let notification = managedObjectContext.object(with: objectID) as! MastodonNotification
|
||||
guard let type = Mastodon.Entity.Notification.NotificationType(rawValue: notification.typeRaw) else {
|
||||
// filter out invalid type using predicate
|
||||
assertionFailure()
|
||||
return nil
|
||||
return UITableViewCell()
|
||||
}
|
||||
let timeText = notification.createAt.slowedTimeAgoSinceNow
|
||||
|
||||
|
||||
let createAt = notification.createAt
|
||||
let timeText = createAt.slowedTimeAgoSinceNow
|
||||
|
||||
let actionText = type.actionText
|
||||
let actionImageName = type.actionImageName
|
||||
let color = type.color
|
||||
|
@ -57,23 +59,24 @@ extension NotificationSection {
|
|||
requestUserID: requestUserID,
|
||||
statusItemAttribute: attribute
|
||||
)
|
||||
cell.actionImageBackground.backgroundColor = color
|
||||
cell.nameLabel.text = notification.account.displayName.isEmpty ? notification.account.username : notification.account.displayName
|
||||
cell.actionLabel.text = actionText + " · " + timeText
|
||||
timestampUpdatePublisher
|
||||
.sink { _ in
|
||||
let timeText = notification.createAt.slowedTimeAgoSinceNow
|
||||
.sink { [weak cell] _ in
|
||||
guard let cell = cell else { return }
|
||||
let timeText = createAt.slowedTimeAgoSinceNow
|
||||
cell.actionLabel.text = actionText + " · " + timeText
|
||||
}
|
||||
.store(in: &cell.disposeBag)
|
||||
cell.actionImageBackground.backgroundColor = color
|
||||
cell.actionLabel.text = actionText + " · " + timeText
|
||||
cell.nameLabel.text = notification.account.displayName.isEmpty ? notification.account.username : notification.account.displayName
|
||||
if let url = notification.account.avatarImageURL() {
|
||||
cell.avatatImageView.af.setImage(
|
||||
cell.avatarImageView.af.setImage(
|
||||
withURL: url,
|
||||
placeholderImage: UIImage.placeholder(color: .systemFill),
|
||||
imageTransition: .crossDissolve(0.2)
|
||||
)
|
||||
}
|
||||
cell.avatatImageView.gesture().sink { [weak cell] _ in
|
||||
cell.avatarImageView.gesture().sink { [weak cell] _ in
|
||||
cell?.delegate?.userAvatarDidPressed(notification: notification)
|
||||
}
|
||||
.store(in: &cell.disposeBag)
|
||||
|
@ -86,8 +89,9 @@ extension NotificationSection {
|
|||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationTableViewCell.self), for: indexPath) as! NotificationTableViewCell
|
||||
cell.delegate = delegate
|
||||
timestampUpdatePublisher
|
||||
.sink { _ in
|
||||
let timeText = notification.createAt.slowedTimeAgoSinceNow
|
||||
.sink { [weak cell] _ in
|
||||
guard let cell = cell else { return }
|
||||
let timeText = createAt.slowedTimeAgoSinceNow
|
||||
cell.actionLabel.text = actionText + " · " + timeText
|
||||
}
|
||||
.store(in: &cell.disposeBag)
|
||||
|
|
|
@ -9,6 +9,7 @@ import CoreData
|
|||
import CoreDataStack
|
||||
import os.log
|
||||
import UIKit
|
||||
import MastodonSDK
|
||||
|
||||
extension NotificationViewModel {
|
||||
func setupDiffableDataSource(
|
||||
|
@ -16,7 +17,7 @@ extension NotificationViewModel {
|
|||
delegate: NotificationTableViewCellDelegate,
|
||||
dependency: NeedsDependency
|
||||
) {
|
||||
let timestampUpdatePublisher = Timer.publish(every: 30.0, on: .main, in: .common)
|
||||
let timestampUpdatePublisher = Timer.publish(every: 1.0, on: .main, in: .common)
|
||||
.autoconnect()
|
||||
.share()
|
||||
.eraseToAnyPublisher()
|
||||
|
@ -44,7 +45,14 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate {
|
|||
|
||||
guard let diffableDataSource = self.diffableDataSource else { return }
|
||||
|
||||
let predicate = fetchedResultsController.fetchRequest.predicate
|
||||
let predicate: NSPredicate = {
|
||||
let notificationTypePredicate = MastodonNotification.predicate(
|
||||
validTypesRaws: Mastodon.Entity.Notification.NotificationType.knownCases.map { $0.rawValue }
|
||||
)
|
||||
return fetchedResultsController.fetchRequest.predicate.flatMap {
|
||||
NSCompoundPredicate(andPredicateWithSubpredicates: [$0, notificationTypePredicate])
|
||||
} ?? notificationTypePredicate
|
||||
}()
|
||||
let parentManagedObjectContext = fetchedResultsController.managedObjectContext
|
||||
let managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
||||
managedObjectContext.parent = parentManagedObjectContext
|
||||
|
@ -73,19 +81,6 @@ extension NotificationViewModel: NSFetchedResultsControllerDelegate {
|
|||
newSnapshot.appendSections([.main])
|
||||
let items: [NotificationItem] = notifications.map { notification in
|
||||
let attribute: Item.StatusAttribute = oldSnapshotAttributeDict[notification.objectID] ?? Item.StatusAttribute()
|
||||
|
||||
// let attribute: Item.StatusAttribute = {
|
||||
// if let attribute = oldSnapshotAttributeDict[notification.objectID] {
|
||||
// return attribute
|
||||
// } else if let status = notification.status {
|
||||
// let attribute = Item.StatusAttribute()
|
||||
// let isSensitive = status.sensitive || !(status.spoilerText ?? "").isEmpty
|
||||
// attribute.isRevealing.value = !isSensitive
|
||||
// return attribute
|
||||
// } else {
|
||||
// return Item.StatusAttribute()
|
||||
// }
|
||||
// }()
|
||||
return NotificationItem.notification(objectID: notification.objectID, attribute: attribute)
|
||||
}
|
||||
newSnapshot.appendItems(items, toSection: .main)
|
||||
|
|
|
@ -17,7 +17,7 @@ final class NotificationStatusTableViewCell: UITableViewCell, StatusCell {
|
|||
var pollCountdownSubscription: AnyCancellable?
|
||||
var delegate: NotificationTableViewCellDelegate?
|
||||
|
||||
let avatatImageView: UIImageView = {
|
||||
let avatarImageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
imageView.layer.cornerRadius = 4
|
||||
imageView.layer.cornerCurve = .continuous
|
||||
|
@ -86,7 +86,7 @@ final class NotificationStatusTableViewCell: UITableViewCell, StatusCell {
|
|||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
avatatImageView.af.cancelImageRequest()
|
||||
avatarImageView.af.cancelImageRequest()
|
||||
statusView.updateContentWarningDisplay(isHidden: true, animated: false)
|
||||
statusView.pollTableView.dataSource = nil
|
||||
statusView.playerContainerView.reset()
|
||||
|
@ -142,13 +142,13 @@ extension NotificationStatusTableViewCell {
|
|||
avatarContainer.widthAnchor.constraint(equalToConstant: 47).priority(.required - 1)
|
||||
])
|
||||
|
||||
avatarContainer.addSubview(avatatImageView)
|
||||
avatatImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
avatarContainer.addSubview(avatarImageView)
|
||||
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
avatatImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatatImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatatImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor),
|
||||
avatatImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor)
|
||||
avatarImageView.heightAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatarImageView.widthAnchor.constraint(equalToConstant: 35).priority(.required - 1),
|
||||
avatarImageView.topAnchor.constraint(equalTo: avatarContainer.topAnchor),
|
||||
avatarImageView.leadingAnchor.constraint(equalTo: avatarContainer.leadingAnchor)
|
||||
])
|
||||
|
||||
avatarContainer.addSubview(actionImageBackground)
|
||||
|
|
|
@ -49,6 +49,18 @@ extension Mastodon.Entity.Notification {
|
|||
|
||||
case _other(String)
|
||||
|
||||
public static var knownCases: [NotificationType] {
|
||||
return [
|
||||
.follow,
|
||||
.followRequest,
|
||||
.mention,
|
||||
.reblog,
|
||||
.favourite,
|
||||
.poll,
|
||||
.status
|
||||
]
|
||||
}
|
||||
|
||||
public init?(rawValue: String) {
|
||||
switch rawValue {
|
||||
case "follow": self = .follow
|
||||
|
|
Loading…
Reference in New Issue