forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNoteStorage.swift
More file actions
163 lines (132 loc) · 4.34 KB
/
Copy pathNoteStorage.swift
File metadata and controls
163 lines (132 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import Foundation
@preconcurrency import GRDB
/// Actor-based storage manager for live notes during recording sessions
/// Provides crash-safe persistence for notes generated during transcription
actor NoteStorage {
static let shared = NoteStorage()
private var _dbQueue: DatabasePool?
private var _dbGeneration = -1
private var isInitialized = false
private init() {}
/// Invalidate cached DB queue (called on user switch / sign-out)
func invalidateCache() {
_dbQueue = nil
isInitialized = false
}
/// Ensure database is initialized before use
private func ensureInitialized() async throws -> DatabasePool {
if let db = _dbQueue, await RewindDatabase.shared.poolGeneration() == _dbGeneration {
return db
}
// Initialize RewindDatabase which creates our tables via migrations
do {
try await RewindDatabase.shared.initialize()
} catch {
log("NoteStorage: Database initialization failed: \(error.localizedDescription)")
throw error
}
let (queue, generation) = await RewindDatabase.shared.getDatabaseQueueWithGeneration()
guard let db = queue else {
throw LiveNoteError.databaseNotInitialized
}
_dbQueue = db
_dbGeneration = generation
isInitialized = true
return db
}
// MARK: - Note Operations
/// Create a new note for a session
@discardableResult
func createNote(
sessionId: Int64,
text: String,
timestamp: Date = Date(),
isAiGenerated: Bool = true,
segmentStartOrder: Int? = nil,
segmentEndOrder: Int? = nil
) async throws -> LiveNoteRecord {
let db = try await ensureInitialized()
let note = LiveNoteRecord(
sessionId: sessionId,
text: text,
timestamp: timestamp,
isAiGenerated: isAiGenerated,
segmentStartOrder: segmentStartOrder,
segmentEndOrder: segmentEndOrder
)
let record = try await db.write { database in
try note.inserted(database)
}
log("NoteStorage: Created note \(record.id ?? -1) for session \(sessionId) (AI: \(isAiGenerated))")
return record
}
/// Update an existing note's text
func updateNote(id: Int64, text: String) async throws {
let db = try await ensureInitialized()
try await db.write { database in
guard var record = try LiveNoteRecord.fetchOne(database, key: id) else {
throw LiveNoteError.noteNotFound
}
record.text = text
record.updatedAt = Date()
try record.update(database)
}
log("NoteStorage: Updated note \(id)")
}
/// Delete a note
func deleteNote(id: Int64) async throws {
let db = try await ensureInitialized()
try await db.write { database in
try database.execute(
sql: "DELETE FROM live_notes WHERE id = ?",
arguments: [id]
)
}
log("NoteStorage: Deleted note \(id)")
}
/// Get a note by ID
func getNote(id: Int64) async throws -> LiveNoteRecord? {
let db = try await ensureInitialized()
return try await db.read { database in
try LiveNoteRecord.fetchOne(database, key: id)
}
}
/// Get all notes for a session ordered by timestamp
func getNotes(sessionId: Int64) async throws -> [LiveNoteRecord] {
let db = try await ensureInitialized()
return try await db.read { database in
try LiveNoteRecord
.filter(Column("sessionId") == sessionId)
.order(Column("timestamp").asc)
.fetchAll(database)
}
}
/// Get note count for a session
func getNoteCount(sessionId: Int64) async throws -> Int {
let db = try await ensureInitialized()
return try await db.read { database in
try Int.fetchOne(
database,
sql: "SELECT COUNT(*) FROM live_notes WHERE sessionId = ?",
arguments: [sessionId]
) ?? 0
}
}
/// Delete all notes for a session
func deleteNotesForSession(sessionId: Int64) async throws {
let db = try await ensureInitialized()
try await db.write { database in
try database.execute(
sql: "DELETE FROM live_notes WHERE sessionId = ?",
arguments: [sessionId]
)
}
log("NoteStorage: Deleted all notes for session \(sessionId)")
}
// MARK: - Batch Operations
/// Get notes as LiveNote structs for UI
func getLiveNotes(sessionId: Int64) async throws -> [LiveNote] {
let records = try await getNotes(sessionId: sessionId)
return records.compactMap { $0.toLiveNote() }
}
}