Skip to content

Commit 3a1e289

Browse files
authored
Use diffable data source for Notes (#183)
* WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * DB migration Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * Add migration debug logs Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * WIP Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * Explicit migration Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * Fix list refresh Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * Untrack file Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> * Refactor Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com> --------- Signed-off-by: Milen Pivchev <milen.pivchev@gmail.com>
1 parent a381125 commit 3a1e289

19 files changed

Lines changed: 403 additions & 833 deletions

File tree

IOCNotesUnitTests/NotesTests.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class NotesTests {
2828
KeychainHelper.password = "cloudnotes"
2929

3030
// Clear database
31-
CDNote.reset()
31+
Note.reset()
3232
}
3333

3434
deinit {
@@ -117,7 +117,7 @@ class NotesTests {
117117
#expect(note?.addNeeded == true, "Expected addNeeded to be true")
118118
KeychainHelper.offlineMode = false
119119
NoteSessionManager.shared.sync() {
120-
if CDNote.all()?.filter( { $0.addNeeded == true }).count ?? 0 > 0 {
120+
if Note.all()?.filter( { $0.addNeeded == true }).count ?? 0 > 0 {
121121
Issue.record("Expected addNeeded count to be 0")
122122
}
123123
continuation.resume()
@@ -150,8 +150,8 @@ class NotesTests {
150150

151151
group.notify(queue: .main) {
152152
#expect(completedCount == 4, "Expected all 4 notes to be added")
153-
CDNote.reset()
154-
if CDNote.all()?.count ?? 0 > 0 {
153+
Note.reset()
154+
if Note.all()?.count ?? 0 > 0 {
155155
Issue.record("Expected note count to be 0")
156156
}
157157
continuation.resume()
@@ -183,8 +183,8 @@ class NotesTests {
183183

184184
group.notify(queue: .main) {
185185
#expect(completedCount == 4, "Expected all 4 notes to be added")
186-
CDNote.reset()
187-
if CDNote.all()?.count ?? 0 > 0 {
186+
Note.reset()
187+
if Note.all()?.count ?? 0 > 0 {
188188
Issue.record("Expected note count to be 0")
189189
}
190190
continuation.resume()
@@ -196,7 +196,7 @@ class NotesTests {
196196
func addAndMove() async throws {
197197
await withCheckedContinuation { continuation in
198198
let group = DispatchGroup()
199-
var notes: [CDNote?] = []
199+
var notes: [Note?] = []
200200

201201
let contents = [
202202
"Note 1 added during add and move test",
@@ -245,7 +245,7 @@ class NotesTests {
245245

246246
moveGroup.notify(queue: .main) {
247247
#expect(updateCount == 2, "Expected 2 notes to be updated")
248-
if CDNote.all()?.filter( { $0.category == "Add and Move Category" }).count ?? 0 != 2 {
248+
if Note.all()?.filter( { $0.category == "Add and Move Category" }).count ?? 0 != 2 {
249249
Issue.record("Expected category count to be 2")
250250
}
251251
continuation.resume()
@@ -260,7 +260,7 @@ class NotesTests {
260260

261261
await withCheckedContinuation { continuation in
262262
let group = DispatchGroup()
263-
var notes: [CDNote?] = []
263+
var notes: [Note?] = []
264264

265265
let contents = [
266266
"Note 1 added during add and move test",
@@ -309,7 +309,7 @@ class NotesTests {
309309

310310
moveGroup.notify(queue: .main) {
311311
#expect(updateCount == 2, "Expected 2 notes to be updated")
312-
if CDNote.all()?.filter( { $0.category == "" }).count ?? 0 != 2 {
312+
if Note.all()?.filter( { $0.category == "" }).count ?? 0 != 2 {
313313
Issue.record("Expected category count to be 2")
314314
}
315315
continuation.resume()

Networking/NoteSessionManager.swift

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import SwiftMessages
1313
import os
1414

1515
typealias SyncCompletionBlock = () -> Void
16-
typealias SyncCompletionBlockWithNote = (_ note: CDNote?) -> Void
16+
typealias SyncCompletionBlockWithNote = (_ note: Note?) -> Void
1717

1818
struct ErrorMessage {
1919
var title: String
@@ -97,12 +97,12 @@ class NoteSessionManager {
9797
var message: ErrorMessage
9898
}
9999

100-
enum Result<CDNote, NoteError> {
101-
case success(CDNote?)
100+
enum Result<Note, NoteError> {
101+
case success(Note?)
102102
case failure(NoteError)
103103
}
104104

105-
typealias SyncHandler = (Result<CDNote, NoteError>) -> Void
105+
typealias SyncHandler = (Result<Note, NoteError>) -> Void
106106

107107
static let shared = NoteSessionManager()
108108

@@ -275,7 +275,7 @@ class NoteSessionManager {
275275
logger.notice("Synchronizing...")
276276

277277
func deleteOnServer(completion: @escaping SyncCompletionBlock) {
278-
if let notesToDelete = CDNote.notes(property: "cdDeleteNeeded"),
278+
if let notesToDelete = Note.notes(property: "deleteNeeded"),
279279
!notesToDelete.isEmpty {
280280
let group = DispatchGroup()
281281

@@ -296,7 +296,7 @@ class NoteSessionManager {
296296
}
297297

298298
func addOnServer(completion: @escaping SyncCompletionBlock) {
299-
if let notesToAdd = CDNote.notes(property: "cdAddNeeded"),
299+
if let notesToAdd = Note.notes(property: "addNeeded"),
300300
!notesToAdd.isEmpty {
301301
let group = DispatchGroup()
302302

@@ -322,7 +322,7 @@ class NoteSessionManager {
322322
}
323323

324324
func updateOnServer(completion: @escaping SyncCompletionBlock) {
325-
if let notesToUpdate = CDNote.notes(property: "cdUpdateNeeded"),
325+
if let notesToUpdate = Note.notes(property: "updateNeeded"),
326326
!notesToUpdate.isEmpty {
327327
let group = DispatchGroup()
328328

@@ -369,10 +369,10 @@ class NoteSessionManager {
369369
if let jsonArray = json as? Array<[String: Any]> {
370370
print(jsonArray)
371371
if let serverIds = jsonArray.map( { $0["id"] }) as? [Int64],
372-
let knownIds = CDNote.all()?.map({ $0.id }).filter({ $0 > 0 }) {
372+
let knownIds = Note.all()?.map({ $0.id }).filter({ $0 > 0 }) {
373373
let deletedOnServer = Set(knownIds).subtracting(Set(serverIds))
374374
if !deletedOnServer.isEmpty {
375-
CDNote.delete(ids: Array(deletedOnServer))
375+
Note.delete(ids: Array(deletedOnServer))
376376
}
377377
}
378378
let filteredDicts = jsonArray.filter({ $0.keys.count > 1 })
@@ -381,7 +381,7 @@ class NoteSessionManager {
381381
for noteDict in filteredDicts {
382382
notes.append(NoteStruct(dictionary: noteDict))
383383
}
384-
CDNote.update(notes: notes)
384+
Note.update(notes: notes)
385385
}
386386
}
387387
case let .failure(error):
@@ -427,12 +427,12 @@ class NoteSessionManager {
427427
logger.notice("Adding note...")
428428

429429
let note = NoteStruct(content: content, category: category, favorite: favorite ?? false)
430-
if let incoming = CDNote.update(note: note) { //addNeeded defaults to true
430+
if let incoming = Note.update(note: note) { //addNeeded defaults to true
431431
self.add(note: incoming, completion: completion)
432432
}
433433
}
434434

435-
func add(note: CDNote, completion: SyncCompletionBlockWithNote? = nil) {
435+
func add(note: Note, completion: SyncCompletionBlockWithNote? = nil) {
436436
if NoteSessionManager.isOnline {
437437
addToServer(note: note) { [weak self] result in
438438
switch result {
@@ -450,9 +450,9 @@ class NoteSessionManager {
450450
}
451451
}
452452

453-
func addToServer(note: CDNote, handler: @escaping SyncHandler) {
453+
func addToServer(note: Note, handler: @escaping SyncHandler) {
454454
let newNote = note
455-
var result: CDNote?
455+
var result: Note?
456456
let parameters: Parameters = ["title": note.title as Any,
457457
"content": note.content as Any,
458458
"category": note.category as Any,
@@ -479,7 +479,7 @@ class NoteSessionManager {
479479
newNote.category = note.category
480480
newNote.addNeeded = false
481481
newNote.updateNeeded = false
482-
result = CDNote.update(note: newNote)
482+
result = Note.update(note: newNote)
483483
handler(.success(result))
484484
case let .failure(error):
485485
let message = ErrorMessage(title: NSLocalizedString("Error Adding Note", comment: "The title of an error message"),
@@ -505,7 +505,7 @@ class NoteSessionManager {
505505
.responseDecodable(of: NoteStruct.self) { response in
506506
switch response.result {
507507
case let .success(note):
508-
CDNote.update(notes: [note])
508+
Note.update(notes: [note])
509509
case let .failure(error):
510510
if let urlResponse = response.response {
511511
switch urlResponse.statusCode {
@@ -516,7 +516,7 @@ class NoteSessionManager {
516516
print(error)
517517
case 404:
518518
if let guid = note.guid,
519-
let dbNote = CDNote.note(guid: guid) {
519+
let dbNote = Note.note(guid: guid) {
520520
self.add(note: dbNote, completion: nil)
521521
}
522522
default:
@@ -548,7 +548,7 @@ class NoteSessionManager {
548548
}
549549
}
550550
} else {
551-
CDNote.update(notes: [incoming])
551+
Note.update(notes: [incoming])
552552
completion?()
553553
}
554554
}
@@ -567,17 +567,17 @@ class NoteSessionManager {
567567
.responseDecodable(of: NoteStruct.self) { response in
568568
switch response.result {
569569
case let .success(note):
570-
CDNote.update(notes: [note])
570+
Note.update(notes: [note])
571571
handler(.success(nil))
572572
case let .failure(error):
573-
CDNote.update(notes: [note])
573+
Note.update(notes: [note])
574574
let message = ErrorMessage(title: NSLocalizedString("Error Updating Note", comment: "The title of an error message"),
575575
body: error.localizedDescription)
576576
if let urlResponse = response.response {
577577
switch urlResponse.statusCode {
578578
case 404, 405:
579579
if let guid = note.guid,
580-
let dbNote = CDNote.note(guid: guid) {
580+
let dbNote = Note.note(guid: guid) {
581581
self.add(note: dbNote, completion: nil)
582582
}
583583
handler(.success(nil))
@@ -597,7 +597,7 @@ class NoteSessionManager {
597597
var incoming = note
598598
incoming.deleteNeeded = true
599599
if incoming.addNeeded {
600-
CDNote.delete(note: incoming)
600+
Note.delete(note: incoming)
601601
completion?()
602602
} else if NoteSessionManager.isOnline {
603603
deleteOnServer(incoming) { [weak self] result in
@@ -612,7 +612,7 @@ class NoteSessionManager {
612612
}
613613
}
614614
} else {
615-
CDNote.update(notes: [incoming])
615+
Note.update(notes: [incoming])
616616
completion?()
617617
}
618618
}
@@ -625,7 +625,7 @@ class NoteSessionManager {
625625
.responseData { (response) in
626626
switch response.result {
627627
case .success:
628-
CDNote.delete(note: note)
628+
Note.delete(note: note)
629629
handler(.success(nil))
630630
case .failure(let error):
631631
var message = ErrorMessage(title: NSLocalizedString("Error Deleting Note", comment: "The title of an error message"),
@@ -635,14 +635,14 @@ class NoteSessionManager {
635635
case 404:
636636
//Note doesn't exist on the server but we are obviously
637637
//trying to delete it, so let's do that.
638-
CDNote.delete(note: note)
638+
Note.delete(note: note)
639639
handler(.success(nil))
640640
case 423:
641641
message.body = NSLocalizedString("Unable to delete locked file on server", comment: "")
642-
CDNote.delete(note: note)
642+
Note.delete(note: note)
643643
handler(.failure(NoteError(message: message)))
644644
default:
645-
CDNote.update(notes: [note])
645+
Note.update(notes: [note])
646646
handler(.failure(NoteError(message: message)))
647647
}
648648
}

Source/AppDelegate.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
103103
}
104104

105105
func applicationDidEnterBackground(_ application: UIApplication) {
106-
notesTableViewController?.updateFrcDelegate(update: .disable)
106+
notesTableViewController?.disableFetchedResultsController()
107107
updateFrcDelegateNeeded = true
108108
scheduleAppSync()
109109
}
@@ -130,7 +130,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
130130
}
131131

132132
updateFrcDelegateNeeded = false
133-
notesTableViewController?.updateFrcDelegate(update: .enable(withFetch: KeychainHelper.didSyncInBackground))
133+
notesTableViewController?.configureFetchedResultsController(performFetch: KeychainHelper.didSyncInBackground)
134134
KeychainHelper.didSyncInBackground = false
135135
}
136136

Source/CategoryTableViewController.swift

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
//
2-
// CategoryTableViewController.swift
3-
// iOCNotes
4-
//
5-
// Created by Peter Hedlund on 8/1/19.
6-
// Copyright © 2019 Peter Hedlund. All rights reserved.
7-
//
1+
// SPDX-FileCopyrightText: Nextcloud GmbH
2+
// SPDX-FileCopyrightText: 2026 Milen Pivchev
3+
// SPDX-License-Identifier: GPL-3.0-or-later
84

95
import UIKit
106

@@ -23,7 +19,7 @@ class CategoryTableViewController: UITableViewController {
2319
}
2420
}
2521

26-
var note: CDNote? {
22+
var note: Note? {
2723
didSet {
2824
if let category = note?.category {
2925
currentCategory = category
@@ -110,4 +106,3 @@ class CategoryTableViewController: UITableViewController {
110106
self.present(alert, animated: true, completion: nil)
111107
}
112108
}
113-

0 commit comments

Comments
 (0)