Compare commits

..

No commits in common. "0255483f976d8c9f494a92f7ca6cdcc7dbfa5883" and "2bdcb9b7f8fe4db1a26adaa3b820eca3f6303d52" have entirely different histories.

32 changed files with 187 additions and 220 deletions

View File

@ -30,7 +30,7 @@ class FollowAccountActivity: AccountActivity {
let request = Account.follow(account.id) let request = Account.follow(account.id)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(relationship, _) = response { if case let .success(relationship, _) = response {
self.mastodonController.cache.add(relationship: relationship) MastodonCache.add(relationship: relationship)
} else { } else {
// todo: display error message // todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error) UINotificationFeedbackGenerator().notificationOccurred(.error)

View File

@ -30,7 +30,7 @@ class UnfollowAccountActivity: AccountActivity {
let request = Account.unfollow(account.id) let request = Account.unfollow(account.id)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(relationship, _) = response { if case let .success(relationship, _) = response {
self.mastodonController.cache.add(relationship: relationship) MastodonCache.add(relationship: relationship)
} else { } else {
// todo: display error message // todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error) UINotificationFeedbackGenerator().notificationOccurred(.error)

View File

@ -29,7 +29,7 @@ class BookmarkStatusActivity: StatusActivity {
let request = Status.bookmark(status) let request = Status.bookmark(status)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(status, _) = response { if case let .success(status, _) = response {
self.mastodonController.cache.add(status: status) MastodonCache.add(status: status)
} else { } else {
// todo: display error message // todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error) UINotificationFeedbackGenerator().notificationOccurred(.error)

View File

@ -28,7 +28,7 @@ class PinStatusActivity: StatusActivity {
let request = Status.pin(status) let request = Status.pin(status)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(status, _) = response { if case let .success(status, _) = response {
self.mastodonController.cache.add(status: status) MastodonCache.add(status: status)
} else { } else {
// todo: display error message // todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error) UINotificationFeedbackGenerator().notificationOccurred(.error)

View File

@ -29,7 +29,7 @@ class UnbookmarkStatusActivity: StatusActivity {
let request = Status.unbookmark(status) let request = Status.unbookmark(status)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(status, _) = response { if case let .success(status, _) = response {
self.mastodonController.cache.add(status: status) MastodonCache.add(status: status)
} else { } else {
// todo: display error message // todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error) UINotificationFeedbackGenerator().notificationOccurred(.error)

View File

@ -28,7 +28,7 @@ class UnpinStatusActivity: StatusActivity {
let request = Status.unpin(status) let request = Status.unpin(status)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(status, _) = response { if case let .success(status, _) = response {
self.mastodonController.cache.add(status: status) MastodonCache.add(status: status)
} else { } else {
// todo: display error message // todo: display error message
UINotificationFeedbackGenerator().notificationOccurred(.error) UINotificationFeedbackGenerator().notificationOccurred(.error)

View File

@ -14,8 +14,6 @@ class MastodonController {
@available(*, deprecated, message: "Use dependency injection to obtain an instance") @available(*, deprecated, message: "Use dependency injection to obtain an instance")
static let shared = MastodonController() static let shared = MastodonController()
private(set) lazy var cache = MastodonCache(mastodonController: self)
private var client: Client! private var client: Client!
var account: Account! var account: Account!
@ -70,7 +68,7 @@ class MastodonController {
run(request) { response in run(request) { response in
guard case let .success(account, _) = response else { fatalError() } guard case let .success(account, _) = response else { fatalError() }
self.account = account self.account = account
self.cache.add(account: account) MastodonCache.add(account: account)
completion?(account) completion?(account)
} }
} }

View File

@ -12,26 +12,22 @@ import Pachyderm
class MastodonCache { class MastodonCache {
private var statuses = CachedDictionary<Status>(name: "Statuses") private static var statuses = CachedDictionary<Status>(name: "Statuses")
private var accounts = CachedDictionary<Account>(name: "Accounts") private static var accounts = CachedDictionary<Account>(name: "Accounts")
private var relationships = CachedDictionary<Relationship>(name: "Relationships") private static var relationships = CachedDictionary<Relationship>(name: "Relationships")
private var notifications = CachedDictionary<Pachyderm.Notification>(name: "Notifications") private static var notifications = CachedDictionary<Pachyderm.Notification>(name: "Notifications")
let statusSubject = PassthroughSubject<Status, Never>() static let statusSubject = PassthroughSubject<Status, Never>()
let accountSubject = PassthroughSubject<Account, Never>() static let accountSubject = PassthroughSubject<Account, Never>()
let mastodonController: MastodonController static var mastodonController: MastodonController { .shared }
init(mastodonController: MastodonController) {
self.mastodonController = mastodonController
}
// MARK: - Statuses // MARK: - Statuses
func status(for id: String) -> Status? { static func status(for id: String) -> Status? {
return statuses[id] return statuses[id]
} }
func set(status: Status, for id: String) { static func set(status: Status, for id: String) {
statuses[id] = status statuses[id] = status
add(account: status.account) add(account: status.account)
if let reblog = status.reblog { if let reblog = status.reblog {
@ -42,66 +38,66 @@ class MastodonCache {
statusSubject.send(status) statusSubject.send(status)
} }
func status(for id: String, completion: @escaping (Status?) -> Void) { static func status(for id: String, completion: @escaping (Status?) -> Void) {
let request = Client.getStatus(id: id) let request = Client.getStatus(id: id)
mastodonController.run(request) { response in mastodonController.run(request) { response in
guard case let .success(status, _) = response else { guard case let .success(status, _) = response else {
completion(nil) completion(nil)
return return
} }
self.set(status: status, for: id) set(status: status, for: id)
completion(status) completion(status)
} }
} }
func add(status: Status) { static func add(status: Status) {
set(status: status, for: status.id) set(status: status, for: status.id)
} }
func addAll(statuses: [Status]) { static func addAll(statuses: [Status]) {
statuses.forEach(add) statuses.forEach(add)
} }
// MARK: - Accounts // MARK: - Accounts
func account(for id: String) -> Account? { static func account(for id: String) -> Account? {
return accounts[id] return accounts[id]
} }
func set(account: Account, for id: String) { static func set(account: Account, for id: String) {
accounts[id] = account accounts[id] = account
accountSubject.send(account) accountSubject.send(account)
} }
func account(for id: String, completion: @escaping (Account?) -> Void) { static func account(for id: String, completion: @escaping (Account?) -> Void) {
let request = Client.getAccount(id: id) let request = Client.getAccount(id: id)
mastodonController.run(request) { response in mastodonController.run(request) { response in
guard case let .success(account, _) = response else { guard case let .success(account, _) = response else {
completion(nil) completion(nil)
return return
} }
self.set(account: account, for: account.id) set(account: account, for: account.id)
completion(account) completion(account)
} }
} }
func add(account: Account) { static func add(account: Account) {
set(account: account, for: account.id) set(account: account, for: account.id)
} }
func addAll(accounts: [Account]) { static func addAll(accounts: [Account]) {
accounts.forEach(add) accounts.forEach(add)
} }
// MARK: - Relationships // MARK: - Relationships
func relationship(for id: String) -> Relationship? { static func relationship(for id: String) -> Relationship? {
return relationships[id] return relationships[id]
} }
func set(relationship: Relationship, id: String) { static func set(relationship: Relationship, id: String) {
relationships[id] = relationship relationships[id] = relationship
} }
func relationship(for id: String, completion: @escaping (Relationship?) -> Void) { static func relationship(for id: String, completion: @escaping (Relationship?) -> Void) {
let request = Client.getRelationships(accounts: [id]) let request = Client.getRelationships(accounts: [id])
mastodonController.run(request) { response in mastodonController.run(request) { response in
guard case let .success(relationships, _) = response, guard case let .success(relationships, _) = response,
@ -109,33 +105,33 @@ class MastodonCache {
completion(nil) completion(nil)
return return
} }
self.set(relationship: relationship, id: relationship.id) set(relationship: relationship, id: relationship.id)
completion(relationship) completion(relationship)
} }
} }
func add(relationship: Relationship) { static func add(relationship: Relationship) {
set(relationship: relationship, id: relationship.id) set(relationship: relationship, id: relationship.id)
} }
func addAll(relationships: [Relationship]) { static func addAll(relationships: [Relationship]) {
relationships.forEach(add) relationships.forEach(add)
} }
// MARK: - Notifications // MARK: - Notifications
func notification(for id: String) -> Pachyderm.Notification? { static func notification(for id: String) -> Pachyderm.Notification? {
return notifications[id] return notifications[id]
} }
func set(notification: Pachyderm.Notification, id: String) { static func set(notification: Pachyderm.Notification, id: String) {
notifications[id] = notification notifications[id] = notification
} }
func add(notification: Pachyderm.Notification) { static func add(notification: Pachyderm.Notification) {
set(notification: notification, id: notification.id) set(notification: notification, id: notification.id)
} }
func addAll(notifications: [Pachyderm.Notification]) { static func addAll(notifications: [Pachyderm.Notification]) {
notifications.forEach(add) notifications.forEach(add)
} }

View File

@ -53,8 +53,8 @@ class AccountListTableViewController: EnhancedTableViewController {
guard let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as? AccountTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as? AccountTableViewCell else { fatalError() }
let id = accountIDs[indexPath.row] let id = accountIDs[indexPath.row]
cell.delegate = self
cell.updateUI(accountID: id) cell.updateUI(accountID: id)
cell.delegate = self
return cell return cell
} }

View File

@ -51,7 +51,7 @@ class BookmarksTableViewController: EnhancedTableViewController {
let request = Client.getBookmarks() let request = Client.getBookmarks()
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
guard case let .success(statuses, pagination) = response else { fatalError() } guard case let .success(statuses, pagination) = response else { fatalError() }
self.mastodonController.cache.addAll(statuses: statuses) MastodonCache.addAll(statuses: statuses)
self.statuses.append(contentsOf: statuses.map { ($0.id, .unknown) }) self.statuses.append(contentsOf: statuses.map { ($0.id, .unknown) })
self.newer = pagination?.newer self.newer = pagination?.newer
self.older = pagination?.older self.older = pagination?.older
@ -89,7 +89,7 @@ class BookmarksTableViewController: EnhancedTableViewController {
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
guard case let .success(newStatuses, pagination) = response else { fatalError() } guard case let .success(newStatuses, pagination) = response else { fatalError() }
self.older = pagination?.older self.older = pagination?.older
self.mastodonController.cache.addAll(statuses: newStatuses) MastodonCache.addAll(statuses: newStatuses)
self.statuses.append(contentsOf: newStatuses.map { ($0.id, .unknown) }) self.statuses.append(contentsOf: newStatuses.map { ($0.id, .unknown) })
} }
} }
@ -105,7 +105,7 @@ class BookmarksTableViewController: EnhancedTableViewController {
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? { override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let cellConfig = (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration() let cellConfig = (tableView.cellForRow(at: indexPath) as? TableViewSwipeActionProvider)?.trailingSwipeActionsConfiguration()
guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else {
return cellConfig return cellConfig
} }
@ -113,7 +113,7 @@ class BookmarksTableViewController: EnhancedTableViewController {
let request = Status.unbookmark(status) let request = Status.unbookmark(status)
self.mastodonController.run(request) { (response) in self.mastodonController.run(request) { (response) in
guard case let .success(newStatus, _) = response else { fatalError() } guard case let .success(newStatus, _) = response else { fatalError() }
self.mastodonController.cache.add(status: newStatus) MastodonCache.add(status: newStatus)
self.statuses.remove(at: indexPath.row) self.statuses.remove(at: indexPath.row)
} }
} }
@ -131,13 +131,13 @@ class BookmarksTableViewController: EnhancedTableViewController {
} }
override func getSuggestedContextMenuActions(tableView: UITableView, indexPath: IndexPath, point: CGPoint) -> [UIAction] { override func getSuggestedContextMenuActions(tableView: UITableView, indexPath: IndexPath, point: CGPoint) -> [UIAction] {
guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { return [] } guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else { return [] }
return [ return [
UIAction(title: NSLocalizedString("Unbookmark", comment: "unbookmark action title"), image: UIImage(systemName: "bookmark.fill"), identifier: .init("unbookmark"), discoverabilityTitle: nil, attributes: [], state: .off, handler: { (_) in UIAction(title: NSLocalizedString("Unbookmark", comment: "unbookmark action title"), image: UIImage(systemName: "bookmark.fill"), identifier: .init("unbookmark"), discoverabilityTitle: nil, attributes: [], state: .off, handler: { (_) in
let request = Status.unbookmark(status) let request = Status.unbookmark(status)
self.mastodonController.run(request) { (response) in self.mastodonController.run(request) { (response) in
guard case let .success(newStatus, _) = response else { fatalError() } guard case let .success(newStatus, _) = response else { fatalError() }
self.mastodonController.cache.add(status: newStatus) MastodonCache.add(status: newStatus)
self.statuses.remove(at: indexPath.row) self.statuses.remove(at: indexPath.row)
} }
}) })
@ -158,7 +158,7 @@ extension BookmarksTableViewController: StatusTableViewCellDelegate {
extension BookmarksTableViewController: UITableViewDataSourcePrefetching { extension BookmarksTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { continue } guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else { continue }
ImageCache.avatars.get(status.account.avatar, completion: nil) ImageCache.avatars.get(status.account.avatar, completion: nil)
for attachment in status.attachments where attachment.kind == .image { for attachment in status.attachments where attachment.kind == .image {
ImageCache.attachments.get(attachment.url, completion: nil) ImageCache.attachments.get(attachment.url, completion: nil)
@ -168,7 +168,7 @@ extension BookmarksTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { continue } guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else { continue }
ImageCache.avatars.cancel(status.account.avatar) ImageCache.avatars.cancel(status.account.avatar)
for attachment in status.attachments where attachment.kind == .image { for attachment in status.attachments where attachment.kind == .image {
ImageCache.attachments.cancel(attachment.url) ImageCache.attachments.cancel(attachment.url)

View File

@ -70,7 +70,7 @@ class ComposeViewController: UIViewController {
self.mastodonController = mastodonController self.mastodonController = mastodonController
self.inReplyToID = inReplyToID self.inReplyToID = inReplyToID
if let inReplyToID = inReplyToID, let inReplyTo = mastodonController.cache.status(for: inReplyToID) { if let inReplyToID = inReplyToID, let inReplyTo = MastodonCache.status(for: inReplyToID) {
accountsToMention = [inReplyTo.account.acct] + inReplyTo.mentions.map { $0.acct } accountsToMention = [inReplyTo.account.acct] + inReplyTo.mentions.map { $0.acct }
} else if let mentioningAcct = mentioningAcct { } else if let mentioningAcct = mentioningAcct {
accountsToMention = [mentioningAcct] accountsToMention = [mentioningAcct]
@ -146,13 +146,13 @@ class ComposeViewController: UIViewController {
} }
if let inReplyToID = inReplyToID { if let inReplyToID = inReplyToID {
if let status = mastodonController.cache.status(for: inReplyToID) { if let status = MastodonCache.status(for: inReplyToID) {
updateInReplyTo(inReplyTo: status) updateInReplyTo(inReplyTo: status)
} else { } else {
let loadingVC = LoadingViewController() let loadingVC = LoadingViewController()
embedChild(loadingVC) embedChild(loadingVC)
mastodonController.cache.status(for: inReplyToID) { (status) in MastodonCache.status(for: inReplyToID) { (status) in
guard let status = status else { return } guard let status = status else { return }
DispatchQueue.main.async { DispatchQueue.main.async {
self.updateInReplyTo(inReplyTo: status) self.updateInReplyTo(inReplyTo: status)
@ -514,7 +514,7 @@ class ComposeViewController: UIViewController {
self.mastodonController.run(request) { (response) in self.mastodonController.run(request) { (response) in
guard case let .success(status, _) = response else { fatalError() } guard case let .success(status, _) = response else { fatalError() }
self.postedStatus = status self.postedStatus = status
self.mastodonController.cache.add(status: status) MastodonCache.add(status: status)
if let draft = self.currentDraft { if let draft = self.currentDraft {
DraftsManager.shared.remove(draft) DraftsManager.shared.remove(draft)

View File

@ -58,14 +58,14 @@ class ConversationTableViewController: EnhancedTableViewController {
statuses = [(mainStatusID, mainStatusState)] statuses = [(mainStatusID, mainStatusState)]
guard let mainStatus = mastodonController.cache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID)") } guard let mainStatus = MastodonCache.status(for: mainStatusID) else { fatalError("Missing cached status \(mainStatusID)") }
let request = Status.getContext(mainStatus) let request = Status.getContext(mainStatus)
mastodonController.run(request) { response in mastodonController.run(request) { response in
guard case let .success(context, _) = response else { fatalError() } guard case let .success(context, _) = response else { fatalError() }
let parents = self.getDirectParents(of: mainStatus, from: context.ancestors) let parents = self.getDirectParents(of: mainStatus, from: context.ancestors)
self.mastodonController.cache.addAll(statuses: parents) MastodonCache.addAll(statuses: parents)
self.mastodonController.cache.addAll(statuses: context.descendants) MastodonCache.addAll(statuses: context.descendants)
self.statuses = parents.map { ($0.id, .unknown) } + self.statuses + context.descendants.map { ($0.id, .unknown) } self.statuses = parents.map { ($0.id, .unknown) } + self.statuses + context.descendants.map { ($0.id, .unknown) }
let indexPath = IndexPath(row: parents.count, section: 0) let indexPath = IndexPath(row: parents.count, section: 0)
DispatchQueue.main.async { DispatchQueue.main.async {
@ -104,14 +104,14 @@ class ConversationTableViewController: EnhancedTableViewController {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "mainStatusCell", for: indexPath) as? ConversationMainStatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: "mainStatusCell", for: indexPath) as? ConversationMainStatusTableViewCell else { fatalError() }
cell.selectionStyle = .none cell.selectionStyle = .none
cell.showStatusAutomatically = showStatusesAutomatically cell.showStatusAutomatically = showStatusesAutomatically
cell.delegate = self
cell.updateUI(statusID: id, state: state) cell.updateUI(statusID: id, state: state)
cell.delegate = self
return cell return cell
} else { } else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
cell.showStatusAutomatically = showStatusesAutomatically cell.showStatusAutomatically = showStatusesAutomatically
cell.delegate = self
cell.updateUI(statusID: id, state: state) cell.updateUI(statusID: id, state: state)
cell.delegate = self
return cell return cell
} }
} }
@ -169,7 +169,7 @@ extension ConversationTableViewController: StatusTableViewCellDelegate {
extension ConversationTableViewController: UITableViewDataSourcePrefetching { extension ConversationTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { continue } guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else { continue }
ImageCache.avatars.get(status.account.avatar, completion: nil) ImageCache.avatars.get(status.account.avatar, completion: nil)
for attachment in status.attachments { for attachment in status.attachments {
ImageCache.attachments.get(attachment.url, completion: nil) ImageCache.attachments.get(attachment.url, completion: nil)
@ -179,7 +179,7 @@ extension ConversationTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
guard let status = mastodonController.cache.status(for: statuses[indexPath.row].id) else { continue } guard let status = MastodonCache.status(for: statuses[indexPath.row].id) else { continue }
ImageCache.avatars.cancel(status.account.avatar) ImageCache.avatars.cancel(status.account.avatar)
for attachment in status.attachments { for attachment in status.attachments {
ImageCache.attachments.cancel(attachment.url) ImageCache.attachments.cancel(attachment.url)

View File

@ -80,7 +80,7 @@ class EditListAccountsViewController: EnhancedTableViewController {
self.nextRange = pagination?.older self.nextRange = pagination?.older
self.mastodonController.cache.addAll(accounts: accounts) MastodonCache.addAll(accounts: accounts)
var snapshot = self.dataSource.snapshot() var snapshot = self.dataSource.snapshot()
snapshot.deleteSections([.accounts]) snapshot.deleteSections([.accounts])

View File

@ -67,9 +67,9 @@ class NotificationsTableViewController: EnhancedTableViewController {
self.groups.append(contentsOf: groups) self.groups.append(contentsOf: groups)
self.mastodonController.cache.addAll(notifications: notifications) MastodonCache.addAll(notifications: notifications)
self.mastodonController.cache.addAll(statuses: notifications.compactMap { $0.status }) MastodonCache.addAll(statuses: notifications.compactMap { $0.status })
self.mastodonController.cache.addAll(accounts: notifications.map { $0.account }) MastodonCache.addAll(accounts: notifications.map { $0.account })
self.newer = pagination?.newer self.newer = pagination?.newer
self.older = pagination?.older self.older = pagination?.older
@ -92,31 +92,31 @@ class NotificationsTableViewController: EnhancedTableViewController {
switch group.kind { switch group.kind {
case .mention: case .mention:
guard let notification = mastodonController.cache.notification(for: group.notificationIDs.first!), guard let notification = MastodonCache.notification(for: group.notificationIDs.first!),
let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as? TimelineStatusTableViewCell else { let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as? TimelineStatusTableViewCell else {
fatalError() fatalError()
} }
cell.delegate = self
cell.updateUI(statusID: notification.status!.id, state: group.statusState!) cell.updateUI(statusID: notification.status!.id, state: group.statusState!)
cell.delegate = self
return cell return cell
case .favourite, .reblog: case .favourite, .reblog:
guard let cell = tableView.dequeueReusableCell(withIdentifier: actionGroupCell, for: indexPath) as? ActionNotificationGroupTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: actionGroupCell, for: indexPath) as? ActionNotificationGroupTableViewCell else { fatalError() }
cell.delegate = self
cell.updateUI(group: group) cell.updateUI(group: group)
cell.delegate = self
return cell return cell
case .follow: case .follow:
guard let cell = tableView.dequeueReusableCell(withIdentifier: followGroupCell, for: indexPath) as? FollowNotificationGroupTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: followGroupCell, for: indexPath) as? FollowNotificationGroupTableViewCell else { fatalError() }
cell.delegate = self
cell.updateUI(group: group) cell.updateUI(group: group)
cell.delegate = self
return cell return cell
case .followRequest: case .followRequest:
guard let notification = mastodonController.cache.notification(for: group.notificationIDs.first!), guard let notification = MastodonCache.notification(for: group.notificationIDs.first!),
let cell = tableView.dequeueReusableCell(withIdentifier: followRequestCell, for: indexPath) as? FollowRequestNotificationTableViewCell else { fatalError() } let cell = tableView.dequeueReusableCell(withIdentifier: followRequestCell, for: indexPath) as? FollowRequestNotificationTableViewCell else { fatalError() }
cell.delegate = self
cell.updateUI(notification: notification) cell.updateUI(notification: notification)
cell.delegate = self
return cell return cell
} }
} }
@ -135,9 +135,9 @@ class NotificationsTableViewController: EnhancedTableViewController {
self.groups.append(contentsOf: groups) self.groups.append(contentsOf: groups)
self.mastodonController.cache.addAll(notifications: newNotifications) MastodonCache.addAll(notifications: newNotifications)
self.mastodonController.cache.addAll(statuses: newNotifications.compactMap { $0.status }) MastodonCache.addAll(statuses: newNotifications.compactMap { $0.status })
self.mastodonController.cache.addAll(accounts: newNotifications.map { $0.account }) MastodonCache.addAll(accounts: newNotifications.map { $0.account })
self.older = pagination?.older self.older = pagination?.older
} }
@ -207,9 +207,9 @@ class NotificationsTableViewController: EnhancedTableViewController {
self.groups.insert(contentsOf: groups, at: 0) self.groups.insert(contentsOf: groups, at: 0)
self.mastodonController.cache.addAll(notifications: newNotifications) MastodonCache.addAll(notifications: newNotifications)
self.mastodonController.cache.addAll(statuses: newNotifications.compactMap { $0.status }) MastodonCache.addAll(statuses: newNotifications.compactMap { $0.status })
self.mastodonController.cache.addAll(accounts: newNotifications.map { $0.account }) MastodonCache.addAll(accounts: newNotifications.map { $0.account })
self.newer = pagination?.newer self.newer = pagination?.newer
@ -237,7 +237,7 @@ extension NotificationsTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
for notificationID in groups[indexPath.row].notificationIDs { for notificationID in groups[indexPath.row].notificationIDs {
guard let notification = mastodonController.cache.notification(for: notificationID) else { continue } guard let notification = MastodonCache.notification(for: notificationID) else { continue }
ImageCache.avatars.get(notification.account.avatar, completion: nil) ImageCache.avatars.get(notification.account.avatar, completion: nil)
} }
} }
@ -246,7 +246,7 @@ extension NotificationsTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
for notificationID in groups[indexPath.row].notificationIDs { for notificationID in groups[indexPath.row].notificationIDs {
guard let notification = mastodonController.cache.notification(for: notificationID) else { continue } guard let notification = MastodonCache.notification(for: notificationID) else { continue }
ImageCache.avatars.cancel(notification.account.avatar) ImageCache.avatars.cancel(notification.account.avatar)
} }
} }

View File

@ -73,12 +73,12 @@ class ProfileTableViewController: EnhancedTableViewController {
tableView.prefetchDataSource = self tableView.prefetchDataSource = self
if let accountID = accountID { if let accountID = accountID {
if mastodonController.cache.account(for: accountID) != nil { if MastodonCache.account(for: accountID) != nil {
updateAccountUI() updateAccountUI()
} else { } else {
loadingVC = LoadingViewController() loadingVC = LoadingViewController()
embedChild(loadingVC!) embedChild(loadingVC!)
mastodonController.cache.account(for: accountID) { (account) in MastodonCache.account(for: accountID) { (account) in
guard account != nil else { guard account != nil else {
let alert = UIAlertController(title: "Something Went Wrong", message: "Couldn't load the selected account", preferredStyle: .alert) let alert = UIAlertController(title: "Something Went Wrong", message: "Couldn't load the selected account", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (_) in
@ -112,14 +112,14 @@ class ProfileTableViewController: EnhancedTableViewController {
getStatuses(onlyPinned: true) { (response) in getStatuses(onlyPinned: true) { (response) in
guard case let .success(statuses, _) = response else { fatalError() } guard case let .success(statuses, _) = response else { fatalError() }
self.mastodonController.cache.addAll(statuses: statuses) MastodonCache.addAll(statuses: statuses)
self.pinnedStatuses = statuses.map { ($0.id, .unknown) } self.pinnedStatuses = statuses.map { ($0.id, .unknown) }
} }
getStatuses() { response in getStatuses() { response in
guard case let .success(statuses, pagination) = response else { fatalError() } guard case let .success(statuses, pagination) = response else { fatalError() }
self.mastodonController.cache.addAll(statuses: statuses) MastodonCache.addAll(statuses: statuses)
self.timelineSegments.append(statuses.map { ($0.id, .unknown) }) self.timelineSegments.append(statuses.map { ($0.id, .unknown) })
self.older = pagination?.older self.older = pagination?.older
@ -128,7 +128,7 @@ class ProfileTableViewController: EnhancedTableViewController {
} }
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
guard let account = mastodonController.cache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") } guard let account = MastodonCache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") }
navigationItem.title = account.realDisplayName navigationItem.title = account.realDisplayName
} }
@ -138,7 +138,7 @@ class ProfileTableViewController: EnhancedTableViewController {
} }
func sendMessageMentioning() { func sendMessageMentioning() {
guard let account = mastodonController.cache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") } guard let account = MastodonCache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") }
let vc = UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct, mastodonController: mastodonController)) let vc = UINavigationController(rootViewController: ComposeViewController(mentioningAcct: account.acct, mastodonController: mastodonController))
present(vc, animated: true) present(vc, animated: true)
} }
@ -152,7 +152,7 @@ class ProfileTableViewController: EnhancedTableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 { if section == 0 {
return accountID == nil || mastodonController.cache.account(for: accountID) == nil ? 0 : 1 return accountID == nil || MastodonCache.account(for: accountID) == nil ? 0 : 1
} else if section == 1 { } else if section == 1 {
return pinnedStatuses.count return pinnedStatuses.count
} else { } else {
@ -172,14 +172,14 @@ class ProfileTableViewController: EnhancedTableViewController {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
let (id, state) = pinnedStatuses[indexPath.row] let (id, state) = pinnedStatuses[indexPath.row]
cell.showPinned = true cell.showPinned = true
cell.delegate = self
cell.updateUI(statusID: id, state: state) cell.updateUI(statusID: id, state: state)
cell.delegate = self
return cell return cell
default: default:
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
let (id, state) = timelineSegments[indexPath.section - 2][indexPath.row] let (id, state) = timelineSegments[indexPath.section - 2][indexPath.row]
cell.delegate = self
cell.updateUI(statusID: id, state: state) cell.updateUI(statusID: id, state: state)
cell.delegate = self
return cell return cell
} }
} }
@ -193,7 +193,7 @@ class ProfileTableViewController: EnhancedTableViewController {
getStatuses(for: older) { response in getStatuses(for: older) { response in
guard case let .success(newStatuses, pagination) = response else { fatalError() } guard case let .success(newStatuses, pagination) = response else { fatalError() }
self.mastodonController.cache.addAll(statuses: newStatuses) MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[indexPath.section - 2].append(contentsOf: newStatuses.map { ($0.id, .unknown) }) self.timelineSegments[indexPath.section - 2].append(contentsOf: newStatuses.map { ($0.id, .unknown) })
self.older = pagination?.older self.older = pagination?.older
@ -219,7 +219,7 @@ class ProfileTableViewController: EnhancedTableViewController {
getStatuses(for: newer) { response in getStatuses(for: newer) { response in
guard case let .success(newStatuses, pagination) = response else { fatalError() } guard case let .success(newStatuses, pagination) = response else { fatalError() }
self.mastodonController.cache.addAll(statuses: newStatuses) MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[0].insert(contentsOf: newStatuses.map { ($0.id, .unknown) }, at: 0) self.timelineSegments[0].insert(contentsOf: newStatuses.map { ($0.id, .unknown) }, at: 0)
self.newer = pagination?.newer self.newer = pagination?.newer
@ -248,9 +248,9 @@ extension ProfileTableViewController: StatusTableViewCellDelegate {
extension ProfileTableViewController: ProfileHeaderTableViewCellDelegate { extension ProfileTableViewController: ProfileHeaderTableViewCellDelegate {
func showMoreOptions() { func showMoreOptions() {
let account = mastodonController.cache.account(for: accountID)! let account = MastodonCache.account(for: accountID)!
mastodonController.cache.relationship(for: account.id) { [weak self] (relationship) in MastodonCache.relationship(for: account.id) { [weak self] (relationship) in
guard let self = self else { return } guard let self = self else { return }
var customActivities: [UIActivity] = [OpenInSafariActivity()] var customActivities: [UIActivity] = [OpenInSafariActivity()]
@ -272,7 +272,7 @@ extension ProfileTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths where indexPath.section > 1 { for indexPath in indexPaths where indexPath.section > 1 {
let statusID = timelineSegments[indexPath.section - 2][indexPath.row].id let statusID = timelineSegments[indexPath.section - 2][indexPath.row].id
guard let status = mastodonController.cache.status(for: statusID) else { continue } guard let status = MastodonCache.status(for: statusID) else { continue }
ImageCache.avatars.get(status.account.avatar, completion: nil) ImageCache.avatars.get(status.account.avatar, completion: nil)
for attachment in status.attachments { for attachment in status.attachments {
ImageCache.attachments.get(attachment.url, completion: nil) ImageCache.attachments.get(attachment.url, completion: nil)
@ -283,7 +283,7 @@ extension ProfileTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths where indexPath.section > 1 { for indexPath in indexPaths where indexPath.section > 1 {
let statusID = timelineSegments[indexPath.section - 2][indexPath.row].id let statusID = timelineSegments[indexPath.section - 2][indexPath.row].id
guard let status = mastodonController.cache.status(for: statusID) else { continue } guard let status = MastodonCache.status(for: statusID) else { continue }
ImageCache.avatars.cancel(status.account.avatar) ImageCache.avatars.cancel(status.account.avatar)
for attachment in status.attachments { for attachment in status.attachments {
ImageCache.attachments.cancel(attachment.url) ImageCache.attachments.cancel(attachment.url)

View File

@ -65,18 +65,18 @@ class SearchResultsViewController: EnhancedTableViewController {
switch item { switch item {
case let .account(id): case let .account(id):
let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as! AccountTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as! AccountTableViewCell
cell.delegate = self
cell.updateUI(accountID: id) cell.updateUI(accountID: id)
cell.delegate = self
return cell return cell
case let .hashtag(tag): case let .hashtag(tag):
let cell = tableView.dequeueReusableCell(withIdentifier: hashtagCell, for: indexPath) as! HashtagTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: hashtagCell, for: indexPath) as! HashtagTableViewCell
cell.delegate = self
cell.updateUI(hashtag: tag) cell.updateUI(hashtag: tag)
cell.delegate = self
return cell return cell
case let .status(id, state): case let .status(id, state):
let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as! TimelineStatusTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as! TimelineStatusTableViewCell
cell.delegate = self
cell.updateUI(statusID: id, state: state) cell.updateUI(statusID: id, state: state)
cell.delegate = self
return cell return cell
} }
}) })
@ -136,7 +136,7 @@ class SearchResultsViewController: EnhancedTableViewController {
if self.onlySections.contains(.accounts) && !results.accounts.isEmpty { if self.onlySections.contains(.accounts) && !results.accounts.isEmpty {
snapshot.appendSections([.accounts]) snapshot.appendSections([.accounts])
snapshot.appendItems(results.accounts.map { .account($0.id) }, toSection: .accounts) snapshot.appendItems(results.accounts.map { .account($0.id) }, toSection: .accounts)
self.mastodonController.cache.addAll(accounts: results.accounts) MastodonCache.addAll(accounts: results.accounts)
} }
if self.onlySections.contains(.hashtags) && !results.hashtags.isEmpty { if self.onlySections.contains(.hashtags) && !results.hashtags.isEmpty {
snapshot.appendSections([.hashtags]) snapshot.appendSections([.hashtags])
@ -145,8 +145,8 @@ class SearchResultsViewController: EnhancedTableViewController {
if self.onlySections.contains(.statuses) && !results.statuses.isEmpty { if self.onlySections.contains(.statuses) && !results.statuses.isEmpty {
snapshot.appendSections([.statuses]) snapshot.appendSections([.statuses])
snapshot.appendItems(results.statuses.map { .status($0.id, .unknown) }, toSection: .statuses) snapshot.appendItems(results.statuses.map { .status($0.id, .unknown) }, toSection: .statuses)
self.mastodonController.cache.addAll(statuses: results.statuses) MastodonCache.addAll(statuses: results.statuses)
self.mastodonController.cache.addAll(accounts: results.statuses.map { $0.account }) MastodonCache.addAll(accounts: results.statuses.map { $0.account })
} }
self.dataSource.apply(snapshot) self.dataSource.apply(snapshot)
} }

View File

@ -73,7 +73,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
if accountIDs == nil { if accountIDs == nil {
// account IDs haven't been set, so perform a request to load them // 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 = MastodonCache.status(for: statusID) else {
fatalError("Missing cached status \(statusID)") fatalError("Missing cached status \(statusID)")
} }
@ -82,7 +82,7 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
let request = actionType == .favorite ? Status.getFavourites(status) : Status.getReblogs(status) let request = actionType == .favorite ? Status.getFavourites(status) : Status.getReblogs(status)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
guard case let .success(accounts, _) = response else { fatalError() } guard case let .success(accounts, _) = response else { fatalError() }
self.mastodonController.cache.addAll(accounts: accounts) MastodonCache.addAll(accounts: accounts)
DispatchQueue.main.async { DispatchQueue.main.async {
self.accountIDs = accounts.map { $0.id } self.accountIDs = accounts.map { $0.id }
self.tableView.tableFooterView = nil self.tableView.tableFooterView = nil
@ -116,14 +116,14 @@ class StatusActionAccountListTableViewController: EnhancedTableViewController {
switch indexPath.section { switch indexPath.section {
case 0: case 0:
guard let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as? TimelineStatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: statusCell, for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
cell.delegate = self
cell.updateUI(statusID: statusID, state: statusState) cell.updateUI(statusID: statusID, state: statusState)
cell.delegate = self
return cell return cell
case 1: case 1:
guard let accountIDs = accountIDs, guard let accountIDs = accountIDs,
let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as? AccountTableViewCell else { fatalError() } let cell = tableView.dequeueReusableCell(withIdentifier: accountCell, for: indexPath) as? AccountTableViewCell else { fatalError() }
cell.delegate = self
cell.updateUI(accountID: accountIDs[indexPath.row]) cell.updateUI(accountID: accountIDs[indexPath.row])
cell.delegate = self
return cell return cell
default: default:
fatalError("Invalid section \(indexPath.section)") fatalError("Invalid section \(indexPath.section)")

View File

@ -54,15 +54,6 @@ class InstanceTimelineViewController: TimelineTableViewController {
toggleSaveButton.title = toggleSaveButtonTitle toggleSaveButton.title = toggleSaveButtonTitle
} }
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAt: indexPath) as! TimelineStatusTableViewCell
cell.delegate = nil
cell.overrideMastodonController = mastodonController
return cell
}
// MARK: - Table view delegate // MARK: - Table view delegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

View File

@ -58,6 +58,7 @@ class TimelineTableViewController: EnhancedTableViewController {
tableView.prefetchDataSource = self tableView.prefetchDataSource = self
guard mastodonController.accessToken != nil else { return }
loadInitialStatuses() loadInitialStatuses()
} }
@ -65,7 +66,7 @@ class TimelineTableViewController: EnhancedTableViewController {
let request = Client.getStatuses(timeline: timeline) let request = Client.getStatuses(timeline: timeline)
mastodonController.run(request) { response in mastodonController.run(request) { response in
guard case let .success(statuses, pagination) = response else { fatalError() } guard case let .success(statuses, pagination) = response else { fatalError() }
self.mastodonController.cache.addAll(statuses: statuses) MastodonCache.addAll(statuses: statuses)
self.timelineSegments.insert(statuses.map { ($0.id, .unknown) }, at: 0) self.timelineSegments.insert(statuses.map { ($0.id, .unknown) }, at: 0)
self.newer = pagination?.newer self.newer = pagination?.newer
self.older = pagination?.older self.older = pagination?.older
@ -87,8 +88,8 @@ class TimelineTableViewController: EnhancedTableViewController {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() } guard let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as? TimelineStatusTableViewCell else { fatalError() }
let (id, state) = timelineSegments[indexPath.section][indexPath.row] let (id, state) = timelineSegments[indexPath.section][indexPath.row]
cell.delegate = self
cell.updateUI(statusID: id, state: state) cell.updateUI(statusID: id, state: state)
cell.delegate = self
return cell return cell
} }
@ -104,7 +105,7 @@ class TimelineTableViewController: EnhancedTableViewController {
mastodonController.run(request) { response in mastodonController.run(request) { response in
guard case let .success(newStatuses, pagination) = response else { fatalError() } guard case let .success(newStatuses, pagination) = response else { fatalError() }
self.older = pagination?.older self.older = pagination?.older
self.mastodonController.cache.addAll(statuses: newStatuses) MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[self.timelineSegments.count - 1].append(contentsOf: newStatuses.map { ($0.id, .unknown) }) self.timelineSegments[self.timelineSegments.count - 1].append(contentsOf: newStatuses.map { ($0.id, .unknown) })
} }
} }
@ -129,7 +130,7 @@ class TimelineTableViewController: EnhancedTableViewController {
mastodonController.run(request) { response in mastodonController.run(request) { response in
guard case let .success(newStatuses, pagination) = response else { fatalError() } guard case let .success(newStatuses, pagination) = response else { fatalError() }
self.newer = pagination?.newer self.newer = pagination?.newer
self.mastodonController.cache.addAll(statuses: newStatuses) MastodonCache.addAll(statuses: newStatuses)
self.timelineSegments[0].insert(contentsOf: newStatuses.map { ($0.id, .unknown) }, at: 0) self.timelineSegments[0].insert(contentsOf: newStatuses.map { ($0.id, .unknown) }, at: 0)
DispatchQueue.main.async { DispatchQueue.main.async {
self.refreshControl?.endRefreshing() self.refreshControl?.endRefreshing()
@ -159,7 +160,7 @@ extension TimelineTableViewController: StatusTableViewCellDelegate {
extension TimelineTableViewController: UITableViewDataSourcePrefetching { extension TimelineTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
guard let status = mastodonController.cache.status(for: statusID(for: indexPath)) else { continue } guard let status = MastodonCache.status(for: statusID(for: indexPath)) else { continue }
ImageCache.avatars.get(status.account.avatar, completion: nil) ImageCache.avatars.get(status.account.avatar, completion: nil)
for attachment in status.attachments { for attachment in status.attachments {
ImageCache.attachments.get(attachment.url, completion: nil) ImageCache.attachments.get(attachment.url, completion: nil)
@ -169,7 +170,7 @@ extension TimelineTableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths { for indexPath in indexPaths {
guard let status = mastodonController.cache.status(for: statusID(for: indexPath)) else { continue } guard let status = MastodonCache.status(for: statusID(for: indexPath)) else { continue }
ImageCache.avatars.cancel(status.account.avatar) ImageCache.avatars.cancel(status.account.avatar)
for attachment in status.attachments { for attachment in status.attachments {
ImageCache.attachments.cancel(attachment.url) ImageCache.attachments.cancel(attachment.url)

View File

@ -22,11 +22,8 @@ protocol MenuPreviewProvider {
extension MenuPreviewProvider { extension MenuPreviewProvider {
private var mastodonController: MastodonController? { navigationDelegate?.apiController }
func actionsForProfile(accountID: String) -> [UIAction] { func actionsForProfile(accountID: String) -> [UIAction] {
guard let mastodonController = mastodonController, guard let account = MastodonCache.account(for: accountID) else { return [] }
let account = mastodonController.cache.account(for: accountID) else { return [] }
return [ return [
createAction(identifier: "openinsafari", title: "Open in Safari", systemImageName: "safari", handler: { (_) in createAction(identifier: "openinsafari", title: "Open in Safari", systemImageName: "safari", handler: { (_) in
self.navigationDelegate?.selected(url: account.url) self.navigationDelegate?.selected(url: account.url)
@ -56,8 +53,7 @@ extension MenuPreviewProvider {
} }
func actionsForStatus(statusID: String) -> [UIAction] { func actionsForStatus(statusID: String) -> [UIAction] {
guard let mastodonController = mastodonController, guard let status = MastodonCache.status(for: statusID) else { return [] }
let status = mastodonController.cache.status(for: statusID) else { return [] }
return [ return [
createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { (_) in createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { (_) in
self.navigationDelegate?.reply(to: statusID) self.navigationDelegate?.reply(to: statusID)

View File

@ -194,7 +194,7 @@ extension TuskerNavigationDelegate where Self: UIViewController {
} }
private func moreOptions(forStatus statusID: String) -> UIViewController { private func moreOptions(forStatus statusID: String) -> UIViewController {
guard let status = apiController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") } guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") }
guard let url = status.url else { fatalError("Missing url for status \(statusID)") } guard let url = status.url else { fatalError("Missing url for status \(statusID)") }
var customActivites: [UIActivity] = [OpenInSafariActivity()] var customActivites: [UIActivity] = [OpenInSafariActivity()]
@ -213,7 +213,7 @@ extension TuskerNavigationDelegate where Self: UIViewController {
} }
private func moreOptions(forAccount accountID: String) -> UIViewController { private func moreOptions(forAccount accountID: String) -> UIViewController {
guard let account = apiController.cache.account(for: accountID) else { fatalError("Missing cached account \(accountID)") } guard let account = MastodonCache.account(for: accountID) else { fatalError("Missing cached account \(accountID)") }
return moreOptions(forURL: account.url) return moreOptions(forURL: account.url)
} }

View File

@ -11,7 +11,7 @@ import UIKit
class AccountTableViewCell: UITableViewCell { class AccountTableViewCell: UITableViewCell {
var delegate: TuskerNavigationDelegate? var delegate: TuskerNavigationDelegate?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController? { delegate?.apiController }
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@IBOutlet weak var displayNameLabel: UILabel! @IBOutlet weak var displayNameLabel: UILabel!
@ -32,7 +32,7 @@ class AccountTableViewCell: UITableViewCell {
@objc func updateUIForPrefrences() { @objc func updateUIForPrefrences() {
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView) avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView)
guard let account = mastodonController.cache.account(for: accountID) else { guard let account = MastodonCache.account(for: accountID) else {
fatalError("Missing cached account \(accountID!)") fatalError("Missing cached account \(accountID!)")
} }
displayNameLabel.text = account.realDisplayName displayNameLabel.text = account.realDisplayName
@ -40,7 +40,7 @@ class AccountTableViewCell: UITableViewCell {
func updateUI(accountID: String) { func updateUI(accountID: String) {
self.accountID = accountID self.accountID = accountID
guard let account = mastodonController.cache.account(for: accountID) else { guard let account = MastodonCache.account(for: accountID) else {
fatalError("Missing cached account \(accountID)") fatalError("Missing cached account \(accountID)")
} }

View File

@ -37,6 +37,8 @@ class AttachmentsContainerView: UIView {
createBlurView() createBlurView()
createHideButton() createHideButton()
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil)
} }
func getAttachmentView(for attachment: Attachment) -> AttachmentView? { func getAttachmentView(for attachment: Attachment) -> AttachmentView? {
@ -174,7 +176,11 @@ class AttachmentsContainerView: UIView {
self.isHidden = true self.isHidden = true
} }
contentHidden = Preferences.shared.blurAllMedia || status.sensitive updateUIForPreferences()
}
@objc func updateUIForPreferences() {
contentHidden = Preferences.shared.blurAllMedia || (MastodonCache.status(for: statusID)?.sensitive ?? false)
} }
private func createAttachmentView(index: Int) -> AttachmentView { private func createAttachmentView(index: Int) -> AttachmentView {

View File

@ -13,7 +13,6 @@ import SwiftSoup
class ActionNotificationGroupTableViewCell: UITableViewCell { class ActionNotificationGroupTableViewCell: UITableViewCell {
var delegate: TuskerNavigationDelegate? var delegate: TuskerNavigationDelegate?
var mastodonController: MastodonController! { delegate?.apiController }
@IBOutlet weak var actionImageView: UIImageView! @IBOutlet weak var actionImageView: UIImageView!
@IBOutlet weak var actionAvatarStackView: UIStackView! @IBOutlet weak var actionAvatarStackView: UIStackView!
@ -34,7 +33,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
} }
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account } let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account }
updateActionLabel(people: people) updateActionLabel(people: people)
for case let imageView as UIImageView in actionAvatarStackView.arrangedSubviews { for case let imageView as UIImageView in actionAvatarStackView.arrangedSubviews {
@ -48,7 +47,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
} }
self.group = group self.group = group
guard let firstNotification = mastodonController.cache.notification(for: group.notificationIDs.first!) else { fatalError() } guard let firstNotification = MastodonCache.notification(for: group.notificationIDs.first!) else { fatalError() }
let status = firstNotification.status! let status = firstNotification.status!
self.statusID = status.id self.statusID = status.id
@ -63,7 +62,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
fatalError() fatalError()
} }
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account } let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account }
actionAvatarStackView.arrangedSubviews.forEach { $0.removeFromSuperview() } actionAvatarStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }
for account in people { for account in people {
@ -94,7 +93,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
func updateTimestamp() { func updateTimestamp() {
guard let id = group.notificationIDs.first, guard let id = group.notificationIDs.first,
let notification = mastodonController.cache.notification(for: id) else { let notification = MastodonCache.notification(for: id) else {
fatalError("Missing cached notification") fatalError("Missing cached notification")
} }
@ -156,7 +155,7 @@ class ActionNotificationGroupTableViewCell: UITableViewCell {
extension ActionNotificationGroupTableViewCell: SelectableTableViewCell { extension ActionNotificationGroupTableViewCell: SelectableTableViewCell {
func didSelectCell() { func didSelectCell() {
guard let delegate = delegate else { return } guard let delegate = delegate else { return }
let notifications = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)) let notifications = group.notificationIDs.compactMap(MastodonCache.notification(for:))
let accountIDs = notifications.map { $0.account.id } let accountIDs = notifications.map { $0.account.id }
let action: StatusActionAccountListTableViewController.ActionType let action: StatusActionAccountListTableViewController.ActionType
switch notifications.first!.kind { switch notifications.first!.kind {
@ -177,7 +176,7 @@ extension ActionNotificationGroupTableViewCell: MenuPreviewProvider {
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
return (content: { return (content: {
let notifications = self.group.notificationIDs.compactMap(self.mastodonController.cache.notification(for:)) let notifications = self.group.notificationIDs.compactMap(MastodonCache.notification(for:))
let accountIDs = notifications.map { $0.account.id } let accountIDs = notifications.map { $0.account.id }
let action: StatusActionAccountListTableViewController.ActionType let action: StatusActionAccountListTableViewController.ActionType
switch notifications.first!.kind { switch notifications.first!.kind {

View File

@ -12,7 +12,7 @@ import Pachyderm
class FollowNotificationGroupTableViewCell: UITableViewCell { class FollowNotificationGroupTableViewCell: UITableViewCell {
var delegate: TuskerNavigationDelegate? var delegate: TuskerNavigationDelegate?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController? { delegate?.apiController }
@IBOutlet weak var avatarStackView: UIStackView! @IBOutlet weak var avatarStackView: UIStackView!
@IBOutlet weak var timestampLabel: UILabel! @IBOutlet weak var timestampLabel: UILabel!
@ -29,7 +29,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
} }
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account } let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account }
updateActionLabel(people: people) updateActionLabel(people: people)
for case let imageView as UIImageView in avatarStackView.arrangedSubviews { for case let imageView as UIImageView in avatarStackView.arrangedSubviews {
@ -40,7 +40,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
func updateUI(group: NotificationGroup) { func updateUI(group: NotificationGroup) {
self.group = group self.group = group
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account } let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account }
updateActionLabel(people: people) updateActionLabel(people: people)
updateTimestamp() updateTimestamp()
@ -82,7 +82,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
func updateTimestamp() { func updateTimestamp() {
guard let id = group.notificationIDs.first, guard let id = group.notificationIDs.first,
let notification = mastodonController.cache.notification(for: id) else { let notification = MastodonCache.notification(for: id) else {
fatalError("Missing cached notification") fatalError("Missing cached notification")
} }
@ -118,7 +118,7 @@ class FollowNotificationGroupTableViewCell: UITableViewCell {
extension FollowNotificationGroupTableViewCell: SelectableTableViewCell { extension FollowNotificationGroupTableViewCell: SelectableTableViewCell {
func didSelectCell() { func didSelectCell() {
let people = group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account.id } let people = group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account.id }
switch people.count { switch people.count {
case 0: case 0:
return return
@ -136,7 +136,7 @@ extension FollowNotificationGroupTableViewCell: MenuPreviewProvider {
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
guard let mastodonController = mastodonController else { return nil } guard let mastodonController = mastodonController else { return nil }
return (content: { return (content: {
let accountIDs = self.group.notificationIDs.compactMap(mastodonController.cache.notification(for:)).map { $0.account.id } let accountIDs = self.group.notificationIDs.compactMap(MastodonCache.notification(for:)).map { $0.account.id }
if accountIDs.count == 1 { if accountIDs.count == 1 {
return ProfileTableViewController(accountID: accountIDs.first!, mastodonController: mastodonController) return ProfileTableViewController(accountID: accountIDs.first!, mastodonController: mastodonController)
} else { } else {

View File

@ -12,7 +12,7 @@ import Pachyderm
class FollowRequestNotificationTableViewCell: UITableViewCell { class FollowRequestNotificationTableViewCell: UITableViewCell {
var delegate: TuskerNavigationDelegate? var delegate: TuskerNavigationDelegate?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController? { delegate?.apiController }
@IBOutlet weak var stackView: UIStackView! @IBOutlet weak var stackView: UIStackView!
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@ -90,9 +90,9 @@ class FollowRequestNotificationTableViewCell: UITableViewCell {
@IBAction func rejectButtonPressed() { @IBAction func rejectButtonPressed() {
let request = Account.rejectFollowRequest(account) let request = Account.rejectFollowRequest(account)
mastodonController.run(request) { (response) in mastodonController!.run(request) { (response) in
guard case let .success(relationship, _) = response else { fatalError() } guard case let .success(relationship, _) = response else { fatalError() }
self.mastodonController.cache.add(relationship: relationship) MastodonCache.add(relationship: relationship)
DispatchQueue.main.async { DispatchQueue.main.async {
UINotificationFeedbackGenerator().notificationOccurred(.success) UINotificationFeedbackGenerator().notificationOccurred(.success)
self.actionButtonsStackView.isHidden = true self.actionButtonsStackView.isHidden = true
@ -107,9 +107,9 @@ class FollowRequestNotificationTableViewCell: UITableViewCell {
@IBAction func acceptButtonPressed() { @IBAction func acceptButtonPressed() {
let request = Account.authorizeFollowRequest(account) let request = Account.authorizeFollowRequest(account)
mastodonController.run(request) { (response) in mastodonController!.run(request) { (response) in
guard case let .success(relationship, _) = response else { fatalError() } guard case let .success(relationship, _) = response else { fatalError() }
self.mastodonController.cache.add(relationship: relationship) MastodonCache.add(relationship: relationship)
DispatchQueue.main.async { DispatchQueue.main.async {
UINotificationFeedbackGenerator().notificationOccurred(.success) UINotificationFeedbackGenerator().notificationOccurred(.success)
self.actionButtonsStackView.isHidden = true self.actionButtonsStackView.isHidden = true

View File

@ -16,7 +16,7 @@ protocol ProfileHeaderTableViewCellDelegate: TuskerNavigationDelegate {
class ProfileHeaderTableViewCell: UITableViewCell { class ProfileHeaderTableViewCell: UITableViewCell {
var delegate: ProfileHeaderTableViewCellDelegate? var delegate: ProfileHeaderTableViewCellDelegate?
var mastodonController: MastodonController! { delegate?.apiController } var mastodonController: MastodonController? { delegate?.apiController }
@IBOutlet weak var headerImageView: UIImageView! @IBOutlet weak var headerImageView: UIImageView!
@IBOutlet weak var avatarContainerView: UIView! @IBOutlet weak var avatarContainerView: UIView!
@ -56,7 +56,7 @@ class ProfileHeaderTableViewCell: UITableViewCell {
guard accountID != self.accountID else { return } guard accountID != self.accountID else { return }
self.accountID = accountID self.accountID = accountID
guard let account = mastodonController.cache.account(for: accountID) else { fatalError("Missing cached account \(accountID)") } guard let account = MastodonCache.account(for: accountID) else { fatalError("Missing cached account \(accountID)") }
updateUIForPreferences() updateUIForPreferences()
@ -83,12 +83,12 @@ class ProfileHeaderTableViewCell: UITableViewCell {
noteLabel.setTextFromHtml(account.note) noteLabel.setTextFromHtml(account.note)
noteLabel.setEmojis(account.emojis) noteLabel.setEmojis(account.emojis)
if accountID != mastodonController.account.id { if accountID != mastodonController!.account.id {
// don't show relationship label for the user's own account // don't show relationship label for the user's own account
if let relationship = mastodonController.cache.relationship(for: accountID) { if let relationship = MastodonCache.relationship(for: accountID) {
followsYouLabel.isHidden = !relationship.followedBy followsYouLabel.isHidden = !relationship.followedBy
} else { } else {
mastodonController.cache.relationship(for: accountID) { relationship in MastodonCache.relationship(for: accountID) { relationship in
DispatchQueue.main.async { DispatchQueue.main.async {
self.followsYouLabel.isHidden = !(relationship?.followedBy ?? false) self.followsYouLabel.isHidden = !(relationship?.followedBy ?? false)
} }
@ -121,7 +121,7 @@ class ProfileHeaderTableViewCell: UITableViewCell {
} }
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
guard let account = mastodonController.cache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") } guard let account = MastodonCache.account(for: accountID) else { fatalError("Missing cached account \(accountID!)") }
avatarContainerView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarContainerView) avatarContainerView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarContainerView)
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView) avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView)

View File

@ -21,8 +21,7 @@ class BaseStatusTableViewCell: UITableViewCell {
contentLabel.navigationDelegate = delegate contentLabel.navigationDelegate = delegate
} }
} }
var overrideMastodonController: MastodonController? var mastodonController: MastodonController? { delegate?.apiController }
var mastodonController: MastodonController! { overrideMastodonController ?? delegate?.apiController }
@IBOutlet weak var avatarImageView: UIImageView! @IBOutlet weak var avatarImageView: UIImageView!
@IBOutlet weak var displayNameLabel: UILabel! @IBOutlet weak var displayNameLabel: UILabel!
@ -95,28 +94,20 @@ class BaseStatusTableViewCell: UITableViewCell {
attachmentsView.isAccessibilityElement = true attachmentsView.isAccessibilityElement = true
NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(updateUIForPreferences), name: .preferencesChanged, object: nil)
}
open func createObserversIfNecessary() {
if statusUpdater == nil {
statusUpdater = mastodonController.cache.statusSubject
.filter { $0.id == self.statusID }
.receive(on: DispatchQueue.main)
.sink(receiveValue: updateStatusState(status:))
}
if accountUpdater == nil { statusUpdater = MastodonCache.statusSubject
accountUpdater = mastodonController.cache.accountSubject .filter { $0.id == self.statusID }
.filter { $0.id == self.accountID } .receive(on: DispatchQueue.main)
.receive(on: DispatchQueue.main) .sink(receiveValue: updateStatusState(status:))
.sink(receiveValue: updateUI(account:))
} accountUpdater = MastodonCache.accountSubject
.filter { $0.id == self.accountID }
.receive(on: DispatchQueue.main)
.sink(receiveValue: updateUI(account:))
} }
func updateUI(statusID: String, state: StatusState) { func updateUI(statusID: String, state: StatusState) {
createObserversIfNecessary() guard let status = MastodonCache.status(for: statusID) else {
guard let status = mastodonController.cache.status(for: statusID) else {
fatalError("Missing cached status") fatalError("Missing cached status")
} }
self.statusID = statusID self.statusID = statusID
@ -191,10 +182,9 @@ class BaseStatusTableViewCell: UITableViewCell {
} }
@objc func updateUIForPreferences() { @objc func updateUIForPreferences() {
guard let account = mastodonController.cache.account(for: accountID) else { return } guard let account = MastodonCache.account(for: accountID) else { return }
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView) avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadius(for: avatarImageView)
displayNameLabel.text = account.realDisplayName displayNameLabel.text = account.realDisplayName
attachmentsView.contentHidden = Preferences.shared.blurAllMedia || (mastodonController.cache.status(for: statusID)?.sensitive ?? false)
} }
override func prepareForReuse() { override func prepareForReuse() {
@ -252,18 +242,18 @@ class BaseStatusTableViewCell: UITableViewCell {
} }
@IBAction func favoritePressed() { @IBAction func favoritePressed() {
guard let status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
let oldValue = favorited let oldValue = favorited
favorited = !favorited favorited = !favorited
let realStatus: Status = status.reblog ?? status let realStatus: Status = status.reblog ?? status
let request = (favorited ? Status.favourite : Status.unfavourite)(realStatus) let request = (favorited ? Status.favourite : Status.unfavourite)(realStatus)
mastodonController.run(request) { response in mastodonController!.run(request) { response in
DispatchQueue.main.async { DispatchQueue.main.async {
if case let .success(newStatus, _) = response { if case let .success(newStatus, _) = response {
self.favorited = newStatus.favourited ?? false self.favorited = newStatus.favourited ?? false
self.mastodonController.cache.add(status: newStatus) MastodonCache.add(status: newStatus)
UIImpactFeedbackGenerator(style: .light).impactOccurred() UIImpactFeedbackGenerator(style: .light).impactOccurred()
} else { } else {
self.favorited = oldValue self.favorited = oldValue
@ -277,18 +267,18 @@ class BaseStatusTableViewCell: UITableViewCell {
} }
@IBAction func reblogPressed() { @IBAction func reblogPressed() {
guard let status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
let oldValue = reblogged let oldValue = reblogged
reblogged = !reblogged reblogged = !reblogged
let realStatus: Status = status.reblog ?? status let realStatus: Status = status.reblog ?? status
let request = (reblogged ? Status.reblog : Status.unreblog)(realStatus) let request = (reblogged ? Status.reblog : Status.unreblog)(realStatus)
mastodonController.run(request) { response in mastodonController!.run(request) { response in
DispatchQueue.main.async { DispatchQueue.main.async {
if case let .success(newStatus, _) = response { if case let .success(newStatus, _) = response {
self.reblogged = newStatus.reblogged ?? false self.reblogged = newStatus.reblogged ?? false
self.mastodonController.cache.add(status: newStatus) MastodonCache.add(status: newStatus)
UIImpactFeedbackGenerator(style: .light).impactOccurred() UIImpactFeedbackGenerator(style: .light).impactOccurred()
} else { } else {
self.reblogged = oldValue self.reblogged = oldValue
@ -315,7 +305,7 @@ class BaseStatusTableViewCell: UITableViewCell {
extension BaseStatusTableViewCell: AttachmentViewDelegate { extension BaseStatusTableViewCell: AttachmentViewDelegate {
func showAttachmentsGallery(startingAt index: Int) { func showAttachmentsGallery(startingAt index: Int) {
guard let status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
let sourceViews = status.attachments.map(attachmentsView.getAttachmentView(for:)) let sourceViews = status.attachments.map(attachmentsView.getAttachmentView(for:))
delegate?.showGallery(attachments: status.attachments, sourceViews: sourceViews, startIndex: index) delegate?.showGallery(attachments: status.attachments, sourceViews: sourceViews, startIndex: index)
} }

View File

@ -38,7 +38,7 @@ class ConversationMainStatusTableViewCell: BaseStatusTableViewCell {
override func updateUI(statusID: String, state: StatusState) { override func updateUI(statusID: String, state: StatusState) {
super.updateUI(statusID: statusID, state: state) super.updateUI(statusID: statusID, state: state)
guard let status = mastodonController.cache.status(for: statusID) else { fatalError() } guard let status = MastodonCache.status(for: statusID) else { fatalError() }
var timestampAndClientText = ConversationMainStatusTableViewCell.dateFormatter.string(from: status.createdAt) var timestampAndClientText = ConversationMainStatusTableViewCell.dateFormatter.string(from: status.createdAt)
if let application = status.application { if let application = status.application {

View File

@ -41,25 +41,19 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
reblogLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(reblogLabelPressed))) reblogLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(reblogLabelPressed)))
accessibilityElements!.insert(reblogLabel!, at: 0) accessibilityElements!.insert(reblogLabel!, at: 0)
rebloggerAccountUpdater = MastodonCache.accountSubject
.filter { $0.id == self.rebloggerID }
.receive(on: DispatchQueue.main)
.sink(receiveValue: updateRebloggerLabel(reblogger:))
} }
override func createObserversIfNecessary() {
super.createObserversIfNecessary()
if rebloggerAccountUpdater == nil {
rebloggerAccountUpdater = mastodonController.cache.accountSubject
.filter { $0.id == self.rebloggerID }
.receive(on: DispatchQueue.main)
.sink(receiveValue: updateRebloggerLabel(reblogger:))
}
}
override func updateUI(statusID: String, state: StatusState) { override func updateUI(statusID: String, state: StatusState) {
guard var status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") } guard var status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID)") }
let realStatusID: String let realStatusID: String
if let rebloggedStatusID = status.reblog?.id, if let rebloggedStatusID = status.reblog?.id,
let rebloggedStatus = mastodonController.cache.status(for: rebloggedStatusID) { let rebloggedStatus = MastodonCache.status(for: rebloggedStatusID) {
reblogStatusID = statusID reblogStatusID = statusID
rebloggerID = status.account.id rebloggerID = status.account.id
status = rebloggedStatus status = rebloggedStatus
@ -84,7 +78,7 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
@objc override func updateUIForPreferences() { @objc override func updateUIForPreferences() {
super.updateUIForPreferences() super.updateUIForPreferences()
if let rebloggerID = rebloggerID, if let rebloggerID = rebloggerID,
let reblogger = mastodonController.cache.account(for: rebloggerID) { let reblogger = MastodonCache.account(for: rebloggerID) {
updateRebloggerLabel(reblogger: reblogger) updateRebloggerLabel(reblogger: reblogger)
} }
} }
@ -94,7 +88,7 @@ class TimelineStatusTableViewCell: BaseStatusTableViewCell {
} }
func updateTimestamp() { func updateTimestamp() {
guard let status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
timestampLabel.text = status.createdAt.timeAgoString() timestampLabel.text = status.createdAt.timeAgoString()
timestampLabel.accessibilityLabel = TimelineStatusTableViewCell.relativeDateFormatter.localizedString(for: status.createdAt, relativeTo: Date()) timestampLabel.accessibilityLabel = TimelineStatusTableViewCell.relativeDateFormatter.localizedString(for: status.createdAt, relativeTo: Date())
@ -150,7 +144,7 @@ extension TimelineStatusTableViewCell: TableViewSwipeActionProvider {
func leadingSwipeActionsConfiguration() -> UISwipeActionsConfiguration? { func leadingSwipeActionsConfiguration() -> UISwipeActionsConfiguration? {
guard let mastodonController = mastodonController else { return nil } guard let mastodonController = mastodonController else { return nil }
guard let status = mastodonController.cache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") } guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
let favoriteTitle: String let favoriteTitle: String
let favoriteRequest: Request<Status> let favoriteRequest: Request<Status>
@ -173,7 +167,7 @@ extension TimelineStatusTableViewCell: TableViewSwipeActionProvider {
return return
} }
completion(true) completion(true)
mastodonController.cache.add(status: status) MastodonCache.add(status: status)
} }
}) })
} }
@ -200,7 +194,7 @@ extension TimelineStatusTableViewCell: TableViewSwipeActionProvider {
return return
} }
completion(true) completion(true)
mastodonController.cache.add(status: status) MastodonCache.add(status: status)
} }
}) })
} }

View File

@ -11,12 +11,10 @@ import Pachyderm
class StatusContentLabel: ContentLabel { class StatusContentLabel: ContentLabel {
var mastodonController: MastodonController? { navigationDelegate?.apiController }
var statusID: String? { var statusID: String? {
didSet { didSet {
guard let statusID = statusID, let mastodonController = mastodonController else { return } guard let statusID = statusID else { return }
guard let status = mastodonController.cache.status(for: statusID) else { fatalError("Can't set StatusContentLabel text without cached status \(statusID)") } guard let status = MastodonCache.status(for: statusID) else { fatalError("Can't set StatusContentLabel text without cached status \(statusID)") }
setTextFromHtml(status.content) setTextFromHtml(status.content)
setEmojis(status.emojis) setEmojis(status.emojis)
} }
@ -25,8 +23,7 @@ class StatusContentLabel: ContentLabel {
override func getMention(for url: URL, text: String) -> Mention? { override func getMention(for url: URL, text: String) -> Mention? {
let mention: Mention? let mention: Mention?
if let statusID = statusID, if let statusID = statusID,
let mastodonController = mastodonController, let status = MastodonCache.status(for: statusID) {
let status = mastodonController.cache.status(for: statusID) {
mention = status.mentions.first { (mention) in mention = status.mentions.first { (mention) in
// Mastodon and Pleroma include the @ in the <a> text, GNU Social does not // Mastodon and Pleroma include the @ in the <a> text, GNU Social does not
(text.dropFirst() == mention.username || text == mention.username) && url.host == mention.url.host (text.dropFirst() == mention.username || text == mention.username) && url.host == mention.url.host
@ -40,8 +37,7 @@ class StatusContentLabel: ContentLabel {
override func getHashtag(for url: URL, text: String) -> Hashtag? { override func getHashtag(for url: URL, text: String) -> Hashtag? {
let hashtag: Hashtag? let hashtag: Hashtag?
if let statusID = statusID, if let statusID = statusID,
let mastodonController = mastodonController, let status = MastodonCache.status(for: statusID) {
let status = mastodonController.cache.status(for: statusID) {
hashtag = status.hashtags.first { (hashtag) in hashtag = status.hashtags.first { (hashtag) in
hashtag.url == url hashtag.url == url
} }

View File

@ -33,7 +33,7 @@ struct XCBActions {
private static func getStatus(from request: XCBRequest, session: XCBSession, completion: @escaping (Status) -> Void) { private static func getStatus(from request: XCBRequest, session: XCBSession, completion: @escaping (Status) -> Void) {
if let id = request.arguments["statusID"] { if let id = request.arguments["statusID"] {
mastodonController.cache.status(for: id) { (status) in MastodonCache.status(for: id) { (status) in
if let status = status { if let status = status {
completion(status) completion(status)
} else { } else {
@ -47,7 +47,7 @@ struct XCBActions {
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(results, _) = response, if case let .success(results, _) = response,
let status = results.statuses.first { let status = results.statuses.first {
mastodonController.cache.add(status: status) MastodonCache.add(status: status)
completion(status) completion(status)
} else { } else {
session.complete(with: .error, additionalData: [ session.complete(with: .error, additionalData: [
@ -64,7 +64,7 @@ struct XCBActions {
private static func getAccount(from request: XCBRequest, session: XCBSession, completion: @escaping (Account) -> Void) { private static func getAccount(from request: XCBRequest, session: XCBSession, completion: @escaping (Account) -> Void) {
if let id = request.arguments["accountID"] { if let id = request.arguments["accountID"] {
mastodonController.cache.account(for: id) { (account) in MastodonCache.account(for: id) { (account) in
if let account = account { if let account = account {
completion(account) completion(account)
} else { } else {
@ -78,7 +78,7 @@ struct XCBActions {
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(results, _) = response { if case let .success(results, _) = response {
if let account = results.accounts.first { if let account = results.accounts.first {
mastodonController.cache.add(account: account) MastodonCache.add(account: account)
completion(account) completion(account)
} else { } else {
session.complete(with: .error, additionalData: [ session.complete(with: .error, additionalData: [
@ -96,7 +96,7 @@ struct XCBActions {
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(accounts, _) = response { if case let .success(accounts, _) = response {
if let account = accounts.first { if let account = accounts.first {
mastodonController.cache.add(account: account) MastodonCache.add(account: account)
completion(account) completion(account)
} else { } else {
session.complete(with: .error, additionalData: [ session.complete(with: .error, additionalData: [
@ -203,7 +203,7 @@ struct XCBActions {
func performAction(status: Status, completion: ((Status) -> Void)?) { func performAction(status: Status, completion: ((Status) -> Void)?) {
mastodonController.run(request(status)) { (response) in mastodonController.run(request(status)) { (response) in
if case let .success(status, _) = response { if case let .success(status, _) = response {
mastodonController.cache.add(status: status) MastodonCache.add(status: status)
completion?(status) completion?(status)
session.complete(with: .success, additionalData: [ session.complete(with: .success, additionalData: [
"statusURL": status.url?.absoluteString, "statusURL": status.url?.absoluteString,
@ -289,7 +289,7 @@ struct XCBActions {
let request = Account.follow(account.id) let request = Account.follow(account.id)
mastodonController.run(request) { (response) in mastodonController.run(request) { (response) in
if case let .success(relationship, _) = response { if case let .success(relationship, _) = response {
mastodonController.cache.add(relationship: relationship) MastodonCache.add(relationship: relationship)
session.complete(with: .success, additionalData: [ session.complete(with: .success, additionalData: [
"url": account.url.absoluteString "url": account.url.absoluteString
]) ])