Skip to content

Commit

Permalink
fix(0.0.3) refactoring,
Browse files Browse the repository at this point in the history
feat(0.1.3) new fully private API Recorder with OPFS storage
feat(0.2.0) got rid of typescript
  • Loading branch information
Сидоркин Олег Валентинович authored and Сидоркин Олег Валентинович committed Aug 27, 2024
1 parent 1d00b66 commit 18b37b3
Show file tree
Hide file tree
Showing 24 changed files with 6,470 additions and 2,629 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,11 @@ OPFS, @sqlite.org/sqlite-wasm

1-Day - 500 words

The Product is Delivered by "Сделай Сам" approach.

1/ Download this repository (IQ ge 90)
2/ run )

- a/

contribute with issues, please.
2 changes: 1 addition & 1 deletion electron-builder.json5
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
entitlements: "build/entitlements.mac.plist",
entitlementsInherit: "build/entitlements.mac.plist",
"extendInfo": {
NSMicrophoneUsageDescription: "Wordly-X requires microphone access to record audio.",
NSMicrophoneUsageDescription: "Нужен доступ к Вашему микрофону.",
"com.apple.security.device.audio-input": true,
},
"artifactName": "${productName}-Mac-${version}-Installer.${ext}"
Expand Down
28 changes: 0 additions & 28 deletions electron/electron-env.d.ts

This file was deleted.

58 changes: 0 additions & 58 deletions electron/main.ts

This file was deleted.

8 changes: 8 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import globals from "globals";
import pluginJs from "@eslint/js";


export default [
{languageOptions: { globals: globals.browser }},
pluginJs.configs.recommended,
];
5 changes: 4 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cross-Origin-Embedder-Policy" content="require-corp" />
<meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin" />
<meta http-equiv="Permissions-Policy" content="microphone=(self)" />
<title>Wordly-X</title>
</head>
<body class="grid grid-cols-1 mx-4">
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script type="module" src="/src/main.mjs"></script>
</body>
</html>
19 changes: 9 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,22 @@
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build && electron-builder"
"build": "vite build && tauri"
},
"devDependencies": {
"@eslint/js": "^9.9.1",
"autoprefixer": "^10.4.20",
"electron": "^31.4.0",
"electron-builder": "^24.13.3",
"eslint": "^9.9.1",
"globals": "^15.9.0",
"postcss": "^8.4.41",
"tailwindcss": "^3.4.9",
"typescript": "^5.2.2",
"vite": "^5.1.6",
"vite-plugin-electron": "^0.28.6",
"vite-plugin-electron-renderer": "^0.14.5"
"tailwindcss": "^3.4.10",
"vite": "^5.1.6"
},
"main": "dist-electron/main.js",
"main": "dist-electron/main.mjs",
"packageManager": "[email protected]+sha512.91d93b445d9284e7ed52931369bc89a663414e5582d00eea45c67ddc459a2582919eece27c412d6ffd1bd0793ff35399381cb229326b961798ce4f4cc60ddfdb",
"dependencies": {
"@js-temporal/polyfill": "^0.4.4",
"sqlocal": "^0.11.1"
"@sqlite.org/sqlite-wasm": "3.46.1-build1",
"tauri": "^0.15.0"
}
}
147 changes: 147 additions & 0 deletions src/DB.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import {dateUtils} from "./date-utils.mjs";
import {Temporal} from "@js-temporal/polyfill";
import {getWordCount} from "./getWordCount.mjs";

import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
import path from "node:path";
import {safeStorage} from "electron";

export class DB {
db;

constructor() {
sqlite3InitModule({print: console.log, printErr: console.error})
.then((sqlite3Static) => {
this.db =
'opfs' in sqlite3Static
? new sqlite3Static.oo1.OpfsDb('/mydb.sqlite3')
: new sqlite3Static.oo1.DB('/mydb.sqlite3', 'ct');
});



this.getDatabaseFile('/mydb.sqlite3').then(databaseFile => {
const fileUrl = URL.createObjectURL(databaseFile);

const a = document.createElement('a');
a.href = fileUrl;
a.download = 'database.sqlite3';
a.click();
a.remove();

URL.revokeObjectURL(fileUrl);
})

this.init()
}

async getDatabaseFile(fileName) {
const tempFileName = `backup-${Date.now()}--${fileName}`;
await this.db.sql`VACUUM INTO ${path.join('/')}/${tempFileName}`;

let dirHandle = await navigator.storage.getDirectory();
for (let dirName of path)
dirHandle = await dirHandle.getDirectoryHandle(dirName);


const fileHandle = await dirHandle.getFileHandle(tempFileName);
const file = await fileHandle.getFile();
const fileBuffer = await file.arrayBuffer();
await dirHandle.removeEntry(tempFileName);

return new File([fileBuffer], fileName, {
type: 'application/x-sqlite3',
});
}

init() {
console.log(safeStorage.isEncryptionAvailable());
this.db.exec({
sql: `
CREATE TABLE IF NOT EXISTS diaries (
uuid TEXT PRIMARY KEY NOT NULL UNIQUE,
text TEXT NOT NULL,
date DATE NOT NULL UNIQUE,
word_count INTEGER NOT NULL DEFAULT 0
)`
})

this.db.exec({
sql: `
CREATE TABLE IF NOT EXISTS audios (
uuid TEXT PRIMARY KEY NOT NULL UNIQUE,
audio BLOB NOT NULL UNIQUE,
diary TEXT NOT NULL,
FOREIGN KEY(diary) REFERENCES diaries(uuid)
)`
})

this.db.exec({
sql: `
INSERT INTO diaries (uuid, text, date, word_count) VALUES (
${crypto.randomUUID()},
${""},
${dateUtils.getTodayString()},
${0}
)
ON CONFLICT(date) DO NOTHING;
`
})
}

async today() {
return await this.db.exec({sql: `SELECT * FROM diaries WHERE date = ${dateUtils.getTodayString()}`})
}

async timeline(yyyymm) {
const timeline= []
const isCurrentMonth = dateUtils.nowInCurrentMonth(yyyymm)
const todayDayNumber = Temporal.Now.plainDateISO().day - 1
const timelineData = await this.db.exec({sql: `SELECT date, word_count FROM diaries WHERE date >= ${dateUtils.getFirstDateOfMonth(yyyymm)} AND date <= ${dateUtils.getLastDateOfMonth(yyyymm)}`})

this._fulfillTimeline(yyyymm, timeline, isCurrentMonth, todayDayNumber, timelineData);

return timeline
}

_fulfillTimeline(yyyymm, timeline, isCurrentMonth, todayDayNumber, timelineData) {
for (let i = 0; i < yyyymm.daysInMonth; i++) {
timeline[i] = {
day: i,
word_count: 0
};
}

if (isCurrentMonth) {
for (let i = todayDayNumber; i < yyyymm.daysInMonth; i++) {
timeline[i].word_count = -1;
}
}

for (const {date, word_count} of timelineData) {
const day = Temporal.PlainDate.from(date).day - 1

timeline[timeline.findIndex((tlDay) => (tlDay.day === day))] = {
day,
word_count,
is_today: todayDayNumber === day
}
}
}

async day(yyyymmdd) {
return await this.db.exec({sql: `SELECT * FROM diaries WHERE date = ${yyyymmdd}`})
}

async updateText(text) {
await this.db.exec({sql: `UPDATE diaries SET text = ${text}, word_count = ${getWordCount(text)} WHERE date = ${dateUtils.getTodayString()}`})
}

async insertAudio(todayUUID, audioFileName) {
await this.db.exec({sql: `INSERT INTO audios (uuid, audio, diary) VALUES (${crypto.randomUUID()}, ${audioFileName}, ${todayUUID})`})
}

async getAudiosByDate(todayUUID) {
return await this.db.exec({sql: `SELECT * FROM audios WHERE diary = ${todayUUID}`})
}
}
Loading

0 comments on commit 18b37b3

Please sign in to comment.