Compare commits

...

11 Commits

Author SHA1 Message Date
azivner
0bdf900e2e release 0.3.2 2018-01-08 23:35:02 -05:00
azivner
90de4b8600 fixes in build script 2018-01-08 23:34:54 -05:00
azivner
4e5a95a1ac fix scrypt binary for windows 2018-01-08 20:40:20 -05:00
azivner
77278fe09e added small image to demo document 2018-01-07 23:52:32 -05:00
azivner
cfbeba80db release 0.3.1 2018-01-07 22:23:41 -05:00
azivner
865d298631 release 0.3.1 2018-01-07 22:10:13 -05:00
azivner
86b1410952 release 0.3.1 2018-01-07 21:56:39 -05:00
azivner
29eb88bac3 added consistency check 2018-01-07 20:16:31 -05:00
azivner
31b4186e17 optional cleanup of unused images 2018-01-07 14:07:59 -05:00
azivner
bde9e825c8 added binary dependencies to repo 2018-01-07 11:49:35 -05:00
azivner
0e8285a7e4 updated schema with image tables 2018-01-07 10:35:24 -05:00
21 changed files with 130 additions and 19 deletions

View File

@@ -1,22 +1,33 @@
#!/usr/bin/env bash
echo "Deleting dist"
echo "Deleting existing builds"
rm -r dist/*
cp -r ../trilium-node-binaries/sqlite/* node_modules/sqlite3/lib/binding/
cp -r ../trilium-node-binaries/scrypt/* node_modules/scrypt/bin/
./node_modules/.bin/electron-rebuild --arch=ia32
./node_modules/.bin/electron-packager . --out=dist --platform=linux --arch=ia32 --overwrite
echo "Rebuilding binaries for linux-x64"
./node_modules/.bin/electron-rebuild --arch=x64
./node_modules/.bin/electron-packager . --out=dist --platform=linux --arch=x64 --overwrite
echo "Rebuilding binaries for linux-ia32"
./node_modules/.bin/electron-rebuild --arch=ia32
./node_modules/.bin/electron-packager . --out=dist --platform=linux --arch=ia32 --overwrite
./node_modules/.bin/electron-packager . --out=dist --platform=win32 --arch=x64 --overwrite
# can't copy this before the packaging because the same file name is used for both linux and windows build
cp ../trilium-node-binaries/scrypt.node ./dist/trilium-win32-x64/resources/app/node_modules/scrypt/build/Release/
echo "Copying required windows binaries"
WIN_RES_DIR=./dist/trilium-win32-x64/resources/app
cp -r bin/deps/sqlite/* $WIN_RES_DIR/node_modules/sqlite3/lib/binding/
cp bin/deps/image/cjpeg.exe $WIN_RES_DIR/node_modules/mozjpeg/vendor/
cp bin/deps/image/pngquant.exe $WIN_RES_DIR/node_modules/pngquant-bin/vendor/
cp bin/deps/image/gifsicle.exe $WIN_RES_DIR/node_modules/giflossy/vendor/
cp bin/deps/scrypt.node $WIN_RES_DIR/node_modules/scrypt/build/Release/
echo "Cleaning up unnecessary binaries from all builds"
rm -r ./dist/trilium-linux-ia32/resources/app/bin/deps
rm -r ./dist/trilium-linux-x64/resources/app/bin/deps
rm -r ./dist/trilium-win32-x64/resources/app/bin/deps

BIN
bin/deps/image/cjpeg.exe Normal file

Binary file not shown.

BIN
bin/deps/image/gifsicle.exe Normal file

Binary file not shown.

BIN
bin/deps/image/pngquant.exe Normal file

Binary file not shown.

BIN
bin/deps/scrypt.node Normal file

Binary file not shown.

Binary file not shown.

BIN
db/image-deleted.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

1
db/main_images.sql Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
INSERT INTO notes (note_id, note_title, note_text, is_protected, is_deleted, date_created, date_modified) VALUES ('root', 'root', 'root', 0, 0, '2017-12-22T11:41:07.000Z', '2017-12-22T11:41:07.000Z');
INSERT INTO notes (note_id, note_title, note_text, is_protected, is_deleted, date_created, date_modified) VALUES ('1Heh2acXfPNt', 'Trilium Demo', '<p><strong>Welcome to Trilium Notes!</strong></p><p>&nbsp;</p><p>This is initial document provided by default Trilium to showcase some of its features and also give you some ideas how you might structure your notes. You can play with it, modify note content and tree structure as you wish.</p><p>&nbsp;</p><p>If you need any help, visit Trilium wesite: <a href="https://github.com/zadam/trilium">https://github.com/zadam/trilium</a></p><h3>Cleanup</h3><p>Once you''re finished with experimenting and want to cleanup these pages, you can simply delete them all.</p><h3>Formatting</h3><p>Trilium supports classic formatting like <i>italic</i>, <strong>bold</strong>, <i><strong>bold and italic</strong></i>. Of course you can add links like this one pointing to <a href="http://www.google.com">google.com</a></p><h4>Lists</h4><p><strong>Ordered:</strong></p><ol><li>First Item</li><li>Second item<ol><li>First sub-item</li><li>Second sub-item</li></ol></li></ol><p>&nbsp;</p><p><strong>Unordered:</strong></p><ul><li>Item</li><li>Another item<ul><li>Sub-item<ul><li>Sub-sub-item</li></ul></li></ul></li></ul><h4>Block quotes</h4><blockquote><p>Whereof one cannot speak, thereof one must be silent”</p><p> Ludwig Wittgenstein</p></blockquote><p>&nbsp;</p>', 0, 0, '2017-12-23T00:46:39.304Z', '2017-12-23T04:08:45.445Z');
INSERT INTO notes (note_id, note_title, note_text, is_protected, is_deleted, date_created, date_modified) VALUES ('1Heh2acXfPNt', 'Trilium Demo', '<figure class="image image-style-side"><img src="/api/images/ed64aET6i379/trilium-small.png"></figure><p><strong>Welcome to Trilium Notes!</strong></p><p>&nbsp;</p><p>This is initial document provided by default Trilium to showcase some of its features and also give you some ideas how you might structure your notes. You can play with it, modify note content and tree structure as you wish.</p><p>&nbsp;</p><p>If you need any help, visit Trilium wesite: <a href="https://github.com/zadam/trilium">https://github.com/zadam/trilium</a></p><h3>Cleanup</h3><p>Once you''re finished with experimenting and want to cleanup these pages, you can simply delete them all.</p><h3>Formatting</h3><p>Trilium supports classic formatting like <i>italic</i>, <strong>bold</strong>, <i><strong>bold and italic</strong></i>. Of course you can add links like this one pointing to <a href="http://www.google.com">google.com</a></p><h4>Lists</h4><p><strong>Ordered:</strong></p><ol><li>First Item</li><li>Second item<ol><li>First sub-item</li><li>Second sub-item</li></ol></li></ol><p>&nbsp;</p><p><strong>Unordered:</strong></p><ul><li>Item</li><li>Another item<ul><li>Sub-item<ul><li>Sub-sub-item</li></ul></li></ul></li></ul><h4>Block quotes</h4><blockquote><p>Whereof one cannot speak, thereof one must be silent”</p><p> Ludwig Wittgenstein</p></blockquote><p>&nbsp;</p>', 0, 0, '2017-12-23T00:46:39.304Z', '2017-12-23T04:08:45.445Z');
INSERT INTO notes (note_id, note_title, note_text, is_protected, is_deleted, date_created, date_modified) VALUES ('3RkyK9LI18dO', 'Journal', '<p>Expand note on the left pane to see content.</p>', 0, 0, '2017-12-23T01:20:04.181Z', '2017-12-23T18:07:55.377Z');
INSERT INTO notes (note_id, note_title, note_text, is_protected, is_deleted, date_created, date_modified) VALUES ('L1Ox40M1aEyy', '2016', '<p>No content.</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p>', 0, 0, '2017-12-23T01:20:45.365Z', '2017-12-23T16:40:43.129Z');
INSERT INTO notes (note_id, note_title, note_text, is_protected, is_deleted, date_created, date_modified) VALUES ('HJusZTbBU494', '2017', '<p>No content.</p>', 0, 0, '2017-12-23T01:20:50.709Z', '2017-12-23T16:41:03.119Z');

1
db/main_notes_image.sql Normal file
View File

@@ -0,0 +1 @@
INSERT INTO notes_image (note_image_id, note_id, image_id, is_deleted, date_modified, date_created) VALUES ('2EtgRRPfk4Fi', '1Heh2acXfPNt', 'ed64aET6i379', 0, '2018-01-08T04:41:30.663Z', '2018-01-08T04:41:30.663Z');

View File

@@ -83,3 +83,28 @@ CREATE INDEX `IDX_notes_history_note_date_modified_from` ON `notes_history` (
CREATE INDEX `IDX_notes_history_note_date_modified_to` ON `notes_history` (
`date_modified_to`
);
CREATE TABLE images
(
image_id TEXT PRIMARY KEY NOT NULL,
format TEXT NOT NULL,
checksum TEXT NOT NULL,
name TEXT NOT NULL,
data BLOB,
is_deleted INT NOT NULL DEFAULT 0,
date_modified TEXT NOT NULL,
date_created TEXT NOT NULL
);
CREATE TABLE notes_image
(
note_image_id TEXT PRIMARY KEY NOT NULL,
note_id TEXT NOT NULL,
image_id TEXT NOT NULL,
is_deleted INT NOT NULL DEFAULT 0,
date_modified TEXT NOT NULL,
date_created TEXT NOT NULL
);
CREATE INDEX notes_image_note_id_index ON notes_image (note_id);
CREATE INDEX notes_image_image_id_index ON notes_image (image_id);
CREATE INDEX notes_image_note_id_image_id_index ON notes_image (note_id, image_id);

View File

@@ -1,7 +1,7 @@
{
"name": "trilium",
"description": "Trilium Notes",
"version": "0.3.0",
"version": "0.3.2",
"license": "AGPL-3.0-only",
"repository": {
"type": "git",

View File

@@ -157,6 +157,7 @@ settings.addModule((async function () {
const fillSyncRowsButton = $("#fill-sync-rows-button");
const anonymizeButton = $("#anonymize-button");
const cleanupSoftDeletedButton = $("#cleanup-soft-deleted-items-button");
const cleanupUnusedImagesButton = $("#cleanup-unused-images-button");
const vacuumDatabaseButton = $("#vacuum-database-button");
forceFullSyncButton.click(async () => {
@@ -186,6 +187,14 @@ settings.addModule((async function () {
}
});
cleanupUnusedImagesButton.click(async () => {
if (confirm("Do you really want to clean up unused images?")) {
await server.post('cleanup/cleanup-unused-images');
showMessage("Unused images have been cleaned up");
}
});
vacuumDatabaseButton.click(async () => {
await server.post('cleanup/vacuum-database');

File diff suppressed because one or more lines are too long

View File

@@ -22,6 +22,10 @@ router.post('/cleanup-soft-deleted-items', auth.checkApiAuth, wrap(async (req, r
await sql.execute("DELETE FROM notes_tree WHERE is_deleted = 1");
await sql.execute("DELETE FROM notes_image WHERE is_deleted = 1");
await sql.execute("DELETE FROM images WHERE is_deleted = 1");
await sql.execute("DELETE FROM notes WHERE is_deleted = 1");
await sql.execute("DELETE FROM recent_notes");
@@ -37,6 +41,33 @@ router.post('/cleanup-soft-deleted-items', auth.checkApiAuth, wrap(async (req, r
res.send({});
}));
router.post('/cleanup-unused-images', auth.checkApiAuth, wrap(async (req, res, next) => {
const sourceId = req.headers.source_id;
await sql.doInTransaction(async () => {
const unusedImageIds = await sql.getFirstColumn(`
SELECT images.image_id
FROM images
LEFT JOIN notes_image ON notes_image.image_id = images.image_id AND notes_image.is_deleted = 0
WHERE
images.is_deleted = 0
AND notes_image.note_image_id IS NULL`);
const now = utils.nowDate();
for (const imageId of unusedImageIds) {
log.info(`Deleting unused image: ${imageId}`);
await sql.execute("UPDATE images SET is_deleted = 1, data = null, date_modified = ? WHERE image_id = ?",
[now, imageId]);
await sync_table.addImageSync(imageId, sourceId);
}
});
res.send({});
}));
router.post('/vacuum-database', auth.checkApiAuth, wrap(async (req, res, next) => {
await sql.execute("VACUUM");

View File

@@ -15,6 +15,8 @@ const jimp = require('jimp');
const imageType = require('image-type');
const sanitizeFilename = require('sanitize-filename');
const wrap = require('express-promise-wrap').wrap;
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
const fs = require('fs');
router.get('/:imageId/:filename', auth.checkApiAuthOrElectron, wrap(async (req, res, next) => {
const image = await sql.getFirst("SELECT * FROM images WHERE image_id = ?", [req.params.imageId]);
@@ -22,6 +24,10 @@ router.get('/:imageId/:filename', auth.checkApiAuthOrElectron, wrap(async (req,
if (!image) {
return res.status(404).send({});
}
else if (image.data === null) {
res.set('Content-Type', 'image/png');
return res.send(fs.readFileSync(RESOURCE_DIR + '/db/image-deleted.png'));
}
res.set('Content-Type', 'image/' + image.format);

View File

@@ -1 +1 @@
module.exports = { build_date:"2018-01-07T10:04:46-05:00", build_revision: "488e657cc43fab879662a6da23b5a69dd7591b06" };
module.exports = { build_date:"2018-01-08T23:35:02-05:00", build_revision: "90de4b8600894787907dd30c20982ab9be946657" };

View File

@@ -187,6 +187,17 @@ async function runAllChecks() {
notes_image.note_image_id IS NULL`,
"Image with no note relation", errorList);
await runCheck(`
SELECT
notes_image.note_image_id
FROM
notes_image
JOIN images USING(image_id)
WHERE
notes_image.is_deleted = 0
AND images.is_deleted = 1`,
"Note image is not deleted while image is deleted for note_image_id", errorList);
await runSyncRowChecks("notes", "note_id", errorList);
await runSyncRowChecks("notes_history", "note_history_id", errorList);
await runSyncRowChecks("notes_tree", "note_tree_id", errorList);

View File

@@ -31,11 +31,15 @@ const dbReady = new Promise((resolve, reject) => {
const schema = fs.readFileSync(resource_dir.DB_INIT_DIR + '/schema.sql', 'UTF-8');
const notesSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_notes.sql', 'UTF-8');
const notesTreeSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_notes_tree.sql', 'UTF-8');
const imagesSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_images.sql', 'UTF-8');
const notesImageSql = fs.readFileSync(resource_dir.DB_INIT_DIR + '/main_notes_image.sql', 'UTF-8');
await doInTransaction(async () => {
await executeScript(schema);
await executeScript(notesSql);
await executeScript(notesTreeSql);
await executeScript(imagesSql);
await executeScript(notesImageSql);
const startNoteId = await getFirstValue("SELECT note_id FROM notes_tree WHERE parent_note_id = 'root' AND is_deleted = 0 ORDER BY note_position");

View File

@@ -248,12 +248,24 @@
<p>This action will create a new copy of the database and anonymise it (remove all note content and leave only structure and metadata)
for sharing online for debugging purposes without fear of leaking your personal data.</p>
<h4>Cleanup</h4>
<h4>Image cleanup</h4>
<button id="cleanup-soft-deleted-items-button" class="btn btn-danger btn-sm">Permanently cleanup soft-deleted items</button> (should be executed in all synced instances)
<p>This will remove all image data of images not used in any current version of note from the database (metadata will remain).
<br/>
<br/>
This means that some images can disappear from note history.</p>
<button id="cleanup-unused-images-button" class="btn btn-warning btn-sm">Permanently cleanup unused images</button>
<h4>Soft-delete cleanup</h4>
<p>This deletes all soft deleted rows from the database. This change isn't synced and should be done manually on all instances.
<strong>Use this only if you really know what you're doing.</strong></p>
<button id="cleanup-soft-deleted-items-button" class="btn btn-danger btn-sm">Permanently cleanup soft-deleted items</button>
<h4>Vacuum database</h4>
<p>This will rebuild database which will typically result in smaller database file. No data will be actually changed.</p>
<button id="vacuum-database-button" class="btn btn-sm">Vacuum database</button>
</div>