Skip to content

Commit 73f3682

Browse files
committed
fixing bugs
1 parent ff1a591 commit 73f3682

4 files changed

Lines changed: 91 additions & 2 deletions

File tree

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,37 @@ npm run build
5858

5959
---
6060

61+
## Using with Electron
62+
63+
`better-sqlite3` is a native module and must be rebuilt against Electron's Node.js runtime. If you see a `NODE_MODULE_VERSION` mismatch error, rebuild after installing dependencies:
64+
65+
```bash
66+
npm install
67+
npx electron-rebuild
68+
```
69+
70+
Or add a postinstall hook so the rebuild happens automatically:
71+
72+
```json
73+
{
74+
"scripts": {
75+
"postinstall": "electron-builder install-app-deps"
76+
}
77+
}
78+
```
79+
80+
This step is only required for Electron apps; regular Node.js consumers do not need it.
81+
82+
---
83+
84+
## Windows Data Paths
85+
86+
- **Grid 3 history**: `C:\Users\Public\Documents\Smartbox\Grid 3\Users\{username}\{langCode}\Phrases\history.sqlite`
87+
- **Grid 3 vocabularies**: `C:\Users\Public\Documents\Smartbox\Grid 3\Users\{username}\Grid Sets\`
88+
- **Snap vocabularies**: `C:\Users\{username}\AppData\Roaming\Tobii Dynavox\Snap Scene\Users\{userId}\` (`.sps`/`.spb`)
89+
90+
---
91+
6192
## 🔧 Quick Start
6293

6394
### Basic Usage (TypeScript/ES6)

src/processors/gridset/helpers.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ export function getCommonDocumentsPath(): string {
205205
* Find all Grid3 user data paths
206206
* Searches for users and language codes in the Grid3 directory structure
207207
* C:\Users\Public\Documents\Smartbox\Grid 3\Users\{UserName}\{langCode}\Phrases\history.sqlite
208+
* Grid set/vocabulary archives live alongside users at:
209+
* C:\Users\Public\Documents\Smartbox\Grid 3\Users\{UserName}\Grid Sets\
208210
* @returns Array of Grid3 user path information
209211
*/
210212
export function findGrid3UserPaths(): Grid3UserPath[] {
@@ -331,6 +333,8 @@ export function findGrid3Vocabularies(userName?: string): Grid3VocabularyPath[]
331333
* @returns Path to history.sqlite or null if not found
332334
*/
333335
export function findGrid3UserHistory(userName: string, langCode?: string): string | null {
336+
if (!userName) return null;
337+
334338
const normalizedUser = userName.toLowerCase();
335339
const normalizedLang = langCode?.toLowerCase();
336340

@@ -404,14 +408,28 @@ export function readGrid3History(historyDbPath: string): Grid3HistoryEntry[] {
404408

405409
for (const row of rows) {
406410
const phraseId: number = row.PhraseId;
407-
const contentText = parseGrid3ContentXml(String(row.ContentXml ?? row.TextValue ?? ''));
411+
const rawContentSource = [row.ContentXml, row.TextValue].find((candidate) => {
412+
if (candidate === null || candidate === undefined) return false;
413+
const asString = String(candidate);
414+
return asString.trim().length > 0;
415+
});
416+
if (rawContentSource === undefined) {
417+
continue; // Skip history rows with no usable text content
418+
}
419+
420+
const rawContentText = String(rawContentSource);
421+
const contentText = parseGrid3ContentXml(rawContentText);
422+
const rawXml =
423+
typeof row.ContentXml === 'string' && row.ContentXml.trim().length > 0
424+
? row.ContentXml
425+
: undefined;
408426
const entry =
409427
events.get(phraseId) ??
410428
({
411429
id: `grid:${phraseId}`,
412430
content: contentText,
413431
occurrences: [],
414-
rawXml: row.ContentXml,
432+
rawXml,
415433
} as Grid3HistoryEntry);
416434

417435
entry.occurrences.push({

src/processors/snap/helpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ export function findSnapPackagePath(packageNamePattern = 'TobiiDynavox'): string
163163

164164
/**
165165
* Find Snap user directories and their vocab files (.sps/.spb)
166+
* Typical path:
167+
* C:\Users\{username}\AppData\Roaming\Tobii Dynavox\Snap Scene\Users\{userId}\
166168
* @param packageNamePattern Optional package filter (default TobiiDynavox)
167169
* @returns Array of user info with vocab paths
168170
*/

test/history.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,44 @@ describe('History analytics', () => {
7171
expect(entry.occurrences[0].longitude).toBeCloseTo(-1.2);
7272
});
7373

74+
it('skips Grid 3 history rows without text and falls back to plain text when XML is missing', () => {
75+
const dbPath = path.join(tempDir, 'grid3-history-missing.sqlite');
76+
const db = new Database(dbPath);
77+
db.exec(`
78+
CREATE TABLE Phrases (Id INTEGER PRIMARY KEY AUTOINCREMENT, Text TEXT, Content TEXT);
79+
CREATE TABLE PhraseHistory (
80+
Id INTEGER PRIMARY KEY AUTOINCREMENT,
81+
PhraseId INTEGER NOT NULL,
82+
Timestamp BIGINT NOT NULL,
83+
Latitude REAL,
84+
Longitude REAL,
85+
FOREIGN KEY(PhraseId) REFERENCES Phrases(Id)
86+
);
87+
`);
88+
89+
const missingId = db
90+
.prepare('INSERT INTO Phrases (Text, Content) VALUES (?, ?)')
91+
.run(null, null).lastInsertRowid as number;
92+
const fallbackId = db
93+
.prepare('INSERT INTO Phrases (Text, Content) VALUES (?, ?)')
94+
.run('plain text only', '').lastInsertRowid as number;
95+
96+
const ts1 = dateToTicks(new Date('2024-04-04T00:00:00Z'));
97+
const ts2 = dateToTicks(new Date('2024-04-04T00:01:00Z'));
98+
99+
db.prepare(
100+
'INSERT INTO PhraseHistory (PhraseId, Timestamp, Latitude, Longitude) VALUES (?, ?, ?, ?)'
101+
).run(missingId, ts1, null, null);
102+
db.prepare(
103+
'INSERT INTO PhraseHistory (PhraseId, Timestamp, Latitude, Longitude) VALUES (?, ?, ?, ?)'
104+
).run(fallbackId, ts2, null, null);
105+
106+
const history = readGrid3History(dbPath);
107+
expect(history).toHaveLength(1);
108+
expect(history[0].content).toBe('plain text only');
109+
expect(history[0].occurrences).toHaveLength(1);
110+
});
111+
74112
it('reads Snap usage from pageset sqlite', () => {
75113
const pagesetPath = path.join(tempDir, 'snap.sps');
76114
const db = new Database(pagesetPath);

0 commit comments

Comments
 (0)