Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ class NotificationDetailsViewController: UIViewController {
return EntityListener(storageManager: AppDelegate.shared.storageManager, readOnlyEntity: note)
}()

/// Pull To Refresh Support.
///
private lazy var refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(pullToRefresh(sender:)), for: .valueChanged)
return refreshControl
}()

/// Note to be displayed!
///
private var note: Note! {
didSet {
buildDetailsRows()
reloadInterface()
}
}

Expand Down Expand Up @@ -57,7 +65,7 @@ class NotificationDetailsViewController: UIViewController {
configureEntityListener()

registerTableViewCells()
buildDetailsRows()
reloadInterface()
}
}

Expand All @@ -69,8 +77,6 @@ private extension NotificationDetailsViewController {
/// Setup: Navigation
///
func configureNavigationItem() {
title = note.title

// Don't show the Notifications title in the next-view's back button
navigationItem.backBarButtonItem = UIBarButtonItem(title: String(), style: .plain, target: nil, action: nil)
}
Expand All @@ -87,6 +93,7 @@ private extension NotificationDetailsViewController {
// Hide "Empty Rows"
tableView.tableFooterView = UIView()
tableView.backgroundColor = StyleManager.tableViewBackgroundColor
tableView.refreshControl = refreshControl
}

/// Setup: EntityListener
Expand Down Expand Up @@ -114,13 +121,44 @@ private extension NotificationDetailsViewController {
}


// MARK: - Sync
//
private extension NotificationDetailsViewController {

/// Refresh Control's Callback.
///
@IBAction func pullToRefresh(sender: UIRefreshControl) {
WooAnalytics.shared.track(.notificationsListPulledToRefresh)

synchronizeNotification(noteId: note.noteId) {
sender.endRefreshing()
}
}

/// Synchronizes the Notifications associated to the active WordPress.com account.
///
func synchronizeNotification(noteId: Int64, onCompletion: @escaping () -> Void) {
let action = NotificationAction.synchronizeNotification(noteId: noteId) { error in
if let error = error {
DDLogError("⛔️ Error synchronizing notification [\(noteId)]: \(error)")
}

onCompletion()
}

StoresManager.shared.dispatch(action)
}
}


// MARK: - Private Methods
//
private extension NotificationDetailsViewController {

/// Reloads all of the Notification Detail Rows!
/// Reloads all of the Details Interface
///
func buildDetailsRows() {
func reloadInterface() {
title = note.title
rows = NoteDetailsRow.details(from: note)
tableView.reloadData()
}
Expand Down
1 change: 1 addition & 0 deletions Yosemite/Yosemite/Actions/NotificationAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Networking
//
public enum NotificationAction: Action {
case synchronizeNotifications(onCompletion: (Error?) -> Void)
case synchronizeNotification(noteId: Int64, onCompletion: (Error?) -> Void)
case updateLastSeen(timestamp: String, onCompletion: (Error?) -> Void)
case updateReadStatus(noteID: Int64, read: Bool, onCompletion: (Error?) -> Void)
}
3 changes: 1 addition & 2 deletions Yosemite/Yosemite/Model/ReadOnly/Note+ReadOnlyType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ extension Yosemite.Note: ReadOnlyType {
return false
}

return storageNote.noteID == noteId &&
storageNote.noteHash == hash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why I even included this here originally 🤷‍♂️ 😆 !

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries!!! I've noticed because the "EntityListener" wasn't picking up the changes!

return storageNote.noteID == noteId
}
}
26 changes: 25 additions & 1 deletion Yosemite/Yosemite/Stores/NotificationStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class NotificationStore: Store {
switch action {
case .synchronizeNotifications(let onCompletion):
synchronizeNotifications(onCompletion: onCompletion)
case .synchronizeNotification(let noteId, let onCompletion):
synchronizeNotification(with: noteId, onCompletion: onCompletion)
case .updateLastSeen(let timestamp, let onCompletion):
updateLastSeen(timestamp: timestamp, onCompletion: onCompletion)
case .updateReadStatus(let noteID, let read, let onCompletion):
Expand Down Expand Up @@ -81,7 +83,28 @@ private extension NotificationStore {
}
}



/// Synchronizes the Notification matching the specified ID, and updates the local entity.
///
/// - Parameters:
/// - noteId: Notification ID of the note to be downloaded.
/// - onCompletion: Closure to be executed on completion.
///
func synchronizeNotification(with noteId: Int64, onCompletion: @escaping (Error?) -> Void) {
let remote = NotificationsRemote(network: network)

remote.loadNotes(noteIds: [noteId]) { notes, error in
guard let notes = notes else {
onCompletion(error)
return
}

self.updateLocalNotes(with: notes) {
onCompletion(nil)
}
}
}


/// Updates the last seen notification
///
Expand All @@ -92,6 +115,7 @@ private extension NotificationStore {
}
}


/// Updates the read status for the given notification ID
///
func updateReadStatus(noteID: Int64, read: Bool, onCompletion: @escaping (Error?) -> Void) {
Expand Down
28 changes: 27 additions & 1 deletion Yosemite/YosemiteTests/Stores/NotificationStoreTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ class NotificationStoreTests: XCTestCase {
/// Initial Sync
///
let initialSyncAction = NotificationAction.synchronizeNotifications() { (error) in

XCTAssertEqual(self.viewStorage.countObjects(ofType: Storage.Note.self), 40)
notificationStore.onAction(nestedSyncAction)
}
Expand All @@ -120,6 +119,33 @@ class NotificationStoreTests: XCTestCase {
wait(for: [expectation], timeout: Constants.expectationTimeout)
}

/// Verifies that `NotificationAction.synchronizeNotification` will effectively request a single notification,
/// which will be stored in CoreData.
///
func testSynchronizeSingleNotificationEffectivelyUpdatesRequestedNote() {
let expectation = self.expectation(description: "Sync notification")
let notificationStore = NotificationStore(dispatcher: dispatcher, storageManager: storageManager, network: network)
let notificationId = Int64(100001)

network.simulateResponse(requestUrlSuffix: "notifications", filename: "notifications-load-all")
XCTAssertEqual(viewStorage.countObjects(ofType: Storage.Note.self), 0)

let syncAction = NotificationAction.synchronizeNotification(noteId: notificationId) { error in
let note = self.viewStorage.loadNotification(noteID: notificationId)
XCTAssertNil(error)
XCTAssertNotNil(note)

let request = self.network.requestsForResponseData[0] as! DotcomRequest
XCTAssertEqual(request.parameters?["ids"], String(notificationId))

expectation.fulfill()
}

notificationStore.onAction(syncAction)
wait(for: [expectation], timeout: Constants.expectationTimeout)
}


// MARK: - NotificationAction.updateLastSeen

/// Verifies that NotificationAction.updateLastSeen handles a success response from the backend properly
Expand Down