forked from shadowfacts/Tusker
Use CoreData for notifications screen
This commit is contained in:
parent
fa1daa682f
commit
f53474ac90
|
@ -46,14 +46,14 @@ public class Status: Decodable {
|
|||
return Request<Card>(method: .get, path: "/api/v1/statuses/\(status.id)/card")
|
||||
}
|
||||
|
||||
public static func getFavourites(_ status: Status, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/statuses/\(status.id)/favourited_by")
|
||||
public static func getFavourites(_ statusID: String, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/statuses/\(statusID)/favourited_by")
|
||||
request.range = range
|
||||
return request
|
||||
}
|
||||
|
||||
public static func getReblogs(_ status: Status, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/statuses/\(status.id)/reblogged_by")
|
||||
public static func getReblogs(_ statusID: String, range: RequestRange = .default) -> Request<[Account]> {
|
||||
var request = Request<[Account]>(method: .get, path: "/api/v1/statuses/\(statusID)/reblogged_by")
|
||||
request.range = range
|
||||
return request
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
import Foundation
|
||||
|
||||
public class NotificationGroup {
|
||||
public let notificationIDs: [String]
|
||||
public let notifications: [Notification]
|
||||
public let id: String
|
||||
public let kind: Notification.Kind
|
||||
public let statusState: StatusState?
|
||||
|
||||
|
||||
init?(notifications: [Notification]) {
|
||||
guard !notifications.isEmpty else { return nil }
|
||||
self.notificationIDs = notifications.map { $0.id }
|
||||
self.notifications = notifications
|
||||
self.id = notifications.first!.id
|
||||
self.kind = notifications.first!.kind
|
||||
if kind == .mention {
|
||||
|
|
|
@ -92,6 +92,12 @@
|
|||
ReferencedContainer = "container:Tusker.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "-com.apple.CoreData.ConcurrencyDebug 1"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
|
|
@ -84,7 +84,7 @@ class MastodonController {
|
|||
run(request) { response in
|
||||
guard case let .success(account, _) = response else { fatalError() }
|
||||
self.account = account
|
||||
self.cache.add(account: account)
|
||||
self.persistentContainer.addOrUpdate(account: account)
|
||||
completion?(account)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
|||
}
|
||||
}
|
||||
|
||||
func addOrUpdate(status: Status, incrementReferenceCount: Bool, completion: (() -> Void)?) {
|
||||
func addOrUpdate(status: Status, incrementReferenceCount: Bool, completion: (() -> Void)? = nil) {
|
||||
backgroundContext.perform {
|
||||
self.upsert(status: status, incrementReferenceCount: incrementReferenceCount)
|
||||
if self.backgroundContext.hasChanges {
|
||||
|
@ -91,7 +91,7 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
|||
}
|
||||
}
|
||||
|
||||
func addOrUpdate(account: Account, completion: (() -> Void)?) {
|
||||
func addOrUpdate(account: Account, completion: (() -> Void)? = nil) {
|
||||
backgroundContext.perform {
|
||||
self.upsert(account: account)
|
||||
if self.backgroundContext.hasChanges {
|
||||
|
|
|
@ -63,9 +63,8 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
|||
|
||||
self.groups.append(contentsOf: groups)
|
||||
|
||||
self.mastodonController.cache.addAll(notifications: notifications)
|
||||
self.mastodonController.cache.addAll(statuses: notifications.compactMap { $0.status })
|
||||
self.mastodonController.cache.addAll(accounts: notifications.map { $0.account })
|
||||
self.mastodonController.persistentContainer.addAll(statuses: notifications.compactMap { $0.status })
|
||||
self.mastodonController.persistentContainer.addAll(accounts: notifications.map { $0.account })
|
||||
|
||||
self.newer = pagination?.newer
|
||||
self.older = pagination?.older
|
||||
|
@ -92,7 +91,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
|||
|
||||
switch group.kind {
|
||||
case .mention:
|
||||
guard let notification = mastodonController.cache.notification(for: group.notificationIDs.first!),
|
||||
guard let notification = group.notifications.first,
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as? TimelineStatusTableViewCell else {
|
||||
fatalError()
|
||||
}
|
||||
|
@ -113,7 +112,7 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
|||
return cell
|
||||
|
||||
case .followRequest:
|
||||
guard let notification = mastodonController.cache.notification(for: group.notificationIDs.first!),
|
||||
guard let notification = group.notifications.first,
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: followRequestCell, for: indexPath) as? FollowRequestNotificationTableViewCell else { fatalError() }
|
||||
cell.delegate = self
|
||||
cell.updateUI(notification: notification)
|
||||
|
@ -195,8 +194,8 @@ class NotificationsTableViewController: EnhancedTableViewController {
|
|||
|
||||
func dismissNotificationsInGroup(at indexPath: IndexPath, completion: (() -> Void)? = nil) {
|
||||
let group = DispatchGroup()
|
||||
groups[indexPath.row].notificationIDs
|
||||
.map(Pachyderm.Notification.dismiss(id:))
|
||||
groups[indexPath.row].notifications
|
||||
.map { Pachyderm.Notification.dismiss(id: $0.id) }
|
||||
.forEach { (request) in
|
||||
group.enter()
|
||||
mastodonController.run(request) { (response) in
|
||||
|
@ -259,8 +258,8 @@ extension NotificationsTableViewController: StatusTableViewCellDelegate {
|
|||
extension NotificationsTableViewController: UITableViewDataSourcePrefetching {
|
||||
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
|
||||
for indexPath in indexPaths {
|
||||
for notificationID in groups[indexPath.row].notificationIDs {
|
||||
guard let notification = mastodonController.cache.notification(for: notificationID) else { continue }
|
||||
for notification in groups[indexPath.row].notifications {
|
||||
// todo: this account object could be stale
|
||||
_ = ImageCache.avatars.get(notification.account.avatar, completion: nil)
|
||||
}
|
||||
}
|
||||
|
@ -268,8 +267,7 @@ extension NotificationsTableViewController: UITableViewDataSourcePrefetching {
|
|||
|
||||
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
|
||||
for indexPath in indexPaths {
|
||||
for notificationID in groups[indexPath.row].notificationIDs {
|
||||
guard let notification = mastodonController.cache.notification(for: notificationID) else { continue }
|
||||
for notification in groups[indexPath.row].notifications {
|
||||
ImageCache.avatars.cancelWithoutCallback(notification.account.avatar)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,13 +73,13 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
|
|||
|
||||
if accountIDs == nil {
|
||||
// account IDs haven't been set, so perform a request to load them
|
||||
guard let status = mastodonController.cache.status(for: statusID) else {
|
||||
guard let status = mastodonController.persistentContainer.status(for: statusID) else {
|
||||
fatalError("Missing cached status \(statusID)")
|
||||
}
|
||||
|
||||
tableView.tableFooterView = UIActivityIndicatorView(style: .large)
|
||||
|
||||
let request = actionType == .favorite ? Status.getFavourites(status) : Status.getReblogs(status)
|
||||
let request = actionType == .favorite ? Status.getFavourites(status.id) : Status.getReblogs(status.id)
|
||||
mastodonController.run(request) { (response) in
|
||||
guard case let .success(accounts, _) = response else { fatalError() }
|
||||
self.mastodonController.cache.addAll(accounts: accounts)
|
||||
|
|
|
@ -38,7 +38,8 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
|||
}
|
||||
|
||||
@objc func updateUIForPreferences() {
|
||||
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account }
|
||||
// todo: is this compactMap necessary?
|
||||
let people = group.notifications.compactMap { mastodonController.persistentContainer.account(for: $0.account.id) }
|
||||
updateActionLabel(people: people)
|
||||
|
||||
for case let imageView as UIImageView in actionAvatarStackView.arrangedSubviews {
|
||||
|
@ -52,7 +53,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
|||
}
|
||||
self.group = group
|
||||
|
||||
guard let firstNotification = mastodonController.cache.notification(for: group.notificationIDs.first!) else { fatalError() }
|
||||
guard let firstNotification = group.notifications.first else { fatalError() }
|
||||
let status = firstNotification.status!
|
||||
self.statusID = status.id
|
||||
|
||||
|
@ -67,7 +68,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
|||
fatalError()
|
||||
}
|
||||
|
||||
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account }
|
||||
let people = group.notifications.compactMap { mastodonController.persistentContainer.account(for: $0.account.id) }
|
||||
|
||||
actionAvatarStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
||||
for account in people {
|
||||
|
@ -98,8 +99,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
|||
}
|
||||
|
||||
func updateTimestamp() {
|
||||
guard let id = group.notificationIDs.first,
|
||||
let notification = mastodonController.cache.notification(for: id) else {
|
||||
guard let notification = group.notifications.first else {
|
||||
fatalError("Missing cached notification")
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
|||
}
|
||||
}
|
||||
|
||||
func updateActionLabel(people: [Account]) {
|
||||
func updateActionLabel(people: [AccountMO]) {
|
||||
let verb: String
|
||||
switch group.kind {
|
||||
case .favourite:
|
||||
|
@ -163,7 +163,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
|
|||
extension ActionNotificationGroupTableViewCell: SelectableTableViewCell {
|
||||
func didSelectCell() {
|
||||
guard let delegate = delegate else { return }
|
||||
let notifications = group.notificationIDs.compactMap(mastodonController.cache.notification(for:))
|
||||
let notifications = group.notifications
|
||||
let accountIDs = notifications.map { $0.account.id }
|
||||
let action: StatusActionAccountListTableViewController.ActionType
|
||||
switch notifications.first!.kind {
|
||||
|
@ -184,7 +184,7 @@ extension ActionNotificationGroupTableViewCell: MenuPreviewProvider {
|
|||
|
||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||
return (content: {
|
||||
let notifications = self.group.notificationIDs.compactMap(self.mastodonController.cache.notification(for:))
|
||||
let notifications = self.group.notifications
|
||||
let accountIDs = notifications.map { $0.account.id }
|
||||
let action: StatusActionAccountListTableViewController.ActionType
|
||||
switch notifications.first!.kind {
|
||||
|
|
|
@ -34,7 +34,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
|||
}
|
||||
|
||||
@objc func updateUIForPreferences() {
|
||||
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account }
|
||||
let people = group.notifications.compactMap { mastodonController.persistentContainer.account(for: $0.account.id) }
|
||||
updateActionLabel(people: people)
|
||||
|
||||
for case let imageView as UIImageView in avatarStackView.arrangedSubviews {
|
||||
|
@ -45,8 +45,8 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
|||
func updateUI(group: NotificationGroup) {
|
||||
self.group = group
|
||||
|
||||
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account }
|
||||
|
||||
let people = group.notifications.compactMap { mastodonController.persistentContainer.account(for: $0.account.id) }
|
||||
|
||||
updateActionLabel(people: people)
|
||||
updateTimestamp()
|
||||
|
||||
|
@ -71,8 +71,8 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
|||
}
|
||||
}
|
||||
|
||||
func updateActionLabel(people: [Account]) {
|
||||
// todo: update to use managed objects
|
||||
func updateActionLabel(people: [AccountMO]) {
|
||||
// todo: custom emoji in people display names
|
||||
// todo: figure out how to localize this
|
||||
let peopleStr: String
|
||||
switch people.count {
|
||||
|
@ -88,8 +88,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
|||
}
|
||||
|
||||
func updateTimestamp() {
|
||||
guard let id = group.notificationIDs.first,
|
||||
let notification = mastodonController.cache.notification(for: id) else {
|
||||
guard let notification = group.notifications.first else {
|
||||
fatalError("Missing cached notification")
|
||||
}
|
||||
|
||||
|
@ -128,14 +127,14 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
|
|||
|
||||
extension FollowNotificationGroupTableViewCell: SelectableTableViewCell {
|
||||
func didSelectCell() {
|
||||
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account.id }
|
||||
switch people.count {
|
||||
let accountIDs = group.notifications.map { $0.account.id }
|
||||
switch accountIDs.count {
|
||||
case 0:
|
||||
return
|
||||
case 1:
|
||||
delegate?.selected(account: people.first!)
|
||||
delegate?.selected(account: accountIDs.first!)
|
||||
default:
|
||||
delegate?.showFollowedByList(accountIDs: people)
|
||||
delegate?.showFollowedByList(accountIDs: accountIDs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +144,7 @@ extension FollowNotificationGroupTableViewCell: MenuPreviewProvider {
|
|||
|
||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||
guard let mastodonController = mastodonController else { return nil }
|
||||
let accountIDs = self.group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account.id }
|
||||
let accountIDs = self.group.notifications.map { $0.account.id }
|
||||
return (content: {
|
||||
if accountIDs.count == 1 {
|
||||
return ProfileTableViewController(accountID: accountIDs.first!, mastodonController: mastodonController)
|
||||
|
|
Loading…
Reference in New Issue