Add Projects: third tab, swipe-to-file, per-project note capture
Notes gain an optional project (schema v4, additive). Projects derive from note values like tags — no separate entity. Tab naming (Projects/Categories) is a Settings choice applied across the UI. Claude-Session: https://claude.ai/code/session_014esDWi42URLEC6Cj17hGQ3
This commit is contained in:
@@ -137,6 +137,44 @@ struct NoteDocumentTests {
|
||||
#expect(Note.audioRelativePath(forJSONPath: legacyJSONPath) == "1999/12/\(id.stringValue).m4a")
|
||||
}
|
||||
|
||||
// MARK: - Schema v4 (project)
|
||||
|
||||
@Test func projectCodableRoundTrip() throws {
|
||||
var context = CaptureContext.empty
|
||||
context.device = "iPhone"
|
||||
let note = Note.create(text: "Ship the release notes", context: context, project: "Contextful v0.3")
|
||||
let data = try DocumentCoder.encode(note)
|
||||
let decoded = try DocumentCoder.decode(Note.self, from: data)
|
||||
#expect(decoded.payload == note.payload)
|
||||
#expect(decoded.payload.project == "Contextful v0.3")
|
||||
}
|
||||
|
||||
/// A v3 file predates the `project` key. It must decode unchanged — as an
|
||||
/// unfiled note with `project == nil` — and pass the forward gate (3 ≤ current).
|
||||
@Test func v3DocumentDecodesWithNoProject() throws {
|
||||
let id = ULID(millisecondsSinceEpoch: 1_700_000_000_000, randomHi: 7, randomLo: 8)
|
||||
let json = """
|
||||
{
|
||||
"meta": {
|
||||
"id": "\(id.stringValue)",
|
||||
"schemaVersion": 3,
|
||||
"createdAt": "2023-11-14T22:13:20Z",
|
||||
"modifiedAt": "2023-11-14T22:13:20Z"
|
||||
},
|
||||
"payload": {
|
||||
"text": "A v3 note",
|
||||
"source": "typed",
|
||||
"tags": [],
|
||||
"context": { "device": "iPhone", "timeZoneID": "UTC" }
|
||||
}
|
||||
}
|
||||
"""
|
||||
let note = try DocumentCoder.decode(Note.self, from: Data(json.utf8))
|
||||
#expect(note.meta.schemaVersion == 3)
|
||||
#expect(note.payload.project == nil)
|
||||
#expect(note.isReadable)
|
||||
}
|
||||
|
||||
@Test func createIngestedDerivesCreatedAtFromULID() {
|
||||
let id = ULID(millisecondsSinceEpoch: 1_700_000_000_000, randomHi: 5, randomLo: 6)
|
||||
var context = CaptureContext.empty
|
||||
|
||||
Reference in New Issue
Block a user