refactored TabContext => NoteContext

This commit is contained in:
zadam 2021-05-22 12:26:45 +02:00
parent 29e4e2afbb
commit 274cf7312c
54 changed files with 470 additions and 459 deletions

View File

@ -1,3 +1,4 @@
- drop branches.utcDateCreated - not used for anything
- drop options.utcDateCreated - not used for anything
- isDeleted = 0 by default
- rename openTabs to openNoteContexts

View File

@ -1,4 +1,4 @@
INSERT INTO options (name, value, utcDateCreated, utcDateModified, isSynced)
SELECT 'openTabs', '[{"notePath":"' || value || '","active": true,"tabId":"1111"}]', '2019-05-01T18:31:00.874Z', '2019-05-01T18:31:00.874Z', 0 FROM options WHERE name = 'startNotePath';
DELETE FROM options WHERE name = 'startNotePath';
DELETE FROM options WHERE name = 'startNotePath';

146
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "trilium",
"version": "0.47.3",
"version": "0.47.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -711,9 +711,9 @@
"dev": true
},
"@types/eslint": {
"version": "7.2.10",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.10.tgz",
"integrity": "sha512-kUEPnMKrqbtpCq/KTaGFFKAcz6Ethm2EjCoKIDaCmfRBWLbFuTcOJfTlorwbnboXBzahqWLgUp1BQeKHiJzPUQ==",
"version": "7.2.11",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.11.tgz",
"integrity": "sha512-WYhv//5K8kQtsSc9F1Kn2vHzhYor6KpwPbARH7hwYe3C3ETD0EVx/3P5qQybUoaBEuUa9f/02JjBiXFWalYUmw==",
"dev": true,
"requires": {
"@types/estree": "*",
@ -2957,9 +2957,9 @@
}
},
"electron": {
"version": "13.0.0-beta.27",
"resolved": "https://registry.npmjs.org/electron/-/electron-13.0.0-beta.27.tgz",
"integrity": "sha512-Co5143QQBiUHLY8qKPbe4axGnFxFLIPbdBuKh0pMvhmsGsVbTK3mEihmhl/lBKQe36cu+gnODpvtZZ0uGsqlxA==",
"version": "13.0.0-beta.28",
"resolved": "https://registry.npmjs.org/electron/-/electron-13.0.0-beta.28.tgz",
"integrity": "sha512-fWNlnyRU4XtMpzsHTm20nnwMHSI580+LBOWj/75HDC012oU019O83QtzLuNsFSw0yoHFOQ8jg/dc4r6z/Xo/sA==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@ -2968,9 +2968,9 @@
},
"dependencies": {
"@types/node": {
"version": "14.14.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.45.tgz",
"integrity": "sha512-DssMqTV9UnnoxDWu959sDLZzfvqCF0qDNRjaWeYSui9xkFe61kKo4l1TWNTQONpuXEm+gLMRvdlzvNHBamzmEw==",
"version": "14.17.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.0.tgz",
"integrity": "sha512-w8VZUN/f7SSbvVReb9SWp6cJFevxb4/nkG65yLAya//98WgocKm5PLDAtSs5CtJJJM+kHmJjO/6mmYW4MHShZA==",
"dev": true
}
}
@ -3822,9 +3822,9 @@
}
},
"electron-to-chromium": {
"version": "1.3.727",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.727.tgz",
"integrity": "sha512-Mfz4FIB4FSvEwBpDfdipRIrwd6uo8gUDoRDF4QEYb4h4tSuI3ov594OrjU6on042UlFHouIJpClDODGkPcBSbg==",
"version": "1.3.735",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.735.tgz",
"integrity": "sha512-cp7MWzC3NseUJV2FJFgaiesdrS+A8ZUjX5fLAxdRlcaPDkaPGFplX930S5vf84yqDp4LjuLdKouWuVOTwUfqHQ==",
"dev": true
},
"electron-window-state": {
@ -4108,20 +4108,25 @@
"integrity": "sha512-o1JrraDGpMFaPtkuvtZ4cIBC/xuJn90KBGlxRrm3FxcfER1bPaBnBsTnypF65p+CMTXul2KrZodb3Vv3MScB4A=="
},
"express-session": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz",
"integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==",
"version": "1.17.2",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz",
"integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==",
"requires": {
"cookie": "0.4.0",
"cookie": "0.4.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~2.0.0",
"on-headers": "~1.0.2",
"parseurl": "~1.3.3",
"safe-buffer": "5.2.0",
"safe-buffer": "5.2.1",
"uid-safe": "~2.1.5"
},
"dependencies": {
"cookie": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz",
"integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA=="
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -4136,9 +4141,9 @@
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
},
"safe-buffer": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
@ -5894,9 +5899,9 @@
}
},
"nanoid": {
"version": "3.1.22",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz",
"integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ=="
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw=="
},
"napi-build-utils": {
"version": "1.0.2",
@ -6052,9 +6057,9 @@
}
},
"node-releases": {
"version": "1.1.71",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz",
"integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==",
"version": "1.1.72",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz",
"integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==",
"dev": true
},
"noop-logger": {
@ -6240,9 +6245,9 @@
}
},
"open": {
"version": "8.0.8",
"resolved": "https://registry.npmjs.org/open/-/open-8.0.8.tgz",
"integrity": "sha512-3XmKIU8+H/TVr8wB8C4vj0z748+yBydSvtpzZVS6vQ1dKNHB6AiPbhaoG+89zb80717GPk9y/7OvK0R6FXkNmQ==",
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/open/-/open-8.1.0.tgz",
"integrity": "sha512-jB5hAtsDOhCy/FNQJwQJOrGlxLUat482Yr14rbA5l2Zb1eOeoS+ccQPO036C1+z9VDBTmOZqzh1tBbI4myzIYw==",
"requires": {
"define-lazy-prop": "^2.0.0",
"is-docker": "^2.1.1",
@ -6572,13 +6577,13 @@
}
},
"postcss": {
"version": "8.2.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.8.tgz",
"integrity": "sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw==",
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.0.tgz",
"integrity": "sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ==",
"requires": {
"colorette": "^1.2.2",
"nanoid": "^3.1.20",
"source-map": "^0.6.1"
"nanoid": "^3.1.23",
"source-map-js": "^0.6.2"
},
"dependencies": {
"colorette": {
@ -7110,9 +7115,9 @@
}
},
"sanitize-html": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.3.3.tgz",
"integrity": "sha512-DCFXPt7Di0c6JUnlT90eIgrjs6TsJl/8HYU3KLdmrVclFN4O0heTcVbJiMa23OKVr6aR051XYtsgd8EWwEBwUA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.4.0.tgz",
"integrity": "sha512-Y1OgkUiTPMqwZNRLPERSEi39iOebn2XJLbeiGOBhaJD/yLqtLGu6GE5w7evx177LeGgSE+4p4e107LMiydOf6A==",
"requires": {
"deepmerge": "^4.2.2",
"escape-string-regexp": "^4.0.0",
@ -7124,36 +7129,36 @@
},
"dependencies": {
"dom-serializer": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz",
"integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
}
},
"domelementtype": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz",
"integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w=="
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
},
"domhandler": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz",
"integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz",
"integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==",
"requires": {
"domelementtype": "^2.1.0"
"domelementtype": "^2.2.0"
}
},
"domutils": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.5.0.tgz",
"integrity": "sha512-Ho16rzNMOFk2fPwChGh3D2D9OEHAfG19HgmRR2l+WLSsIstNsAYBzePH412bL0y5T44ejABIVfTHQ8nqi/tBCg==",
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.6.0.tgz",
"integrity": "sha512-y0BezHuy4MDYxh6OvolXYsH+1EMGmFbwv5FKW7ovwMG6zTPWqNPq3WF9ayZssFq+UlKdffGLbOEaghNdaOm1WA==",
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0"
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
}
},
"entities": {
@ -7167,13 +7172,13 @@
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
},
"htmlparser2": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.1.tgz",
"integrity": "sha512-GDKPd+vk4jvSuvCbyuzx/unmXkk090Azec7LovXP8as1Hn8q9p3hbjmDGbUqqhknw0ajwit6LiiWqfiTUPMK7w==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"domutils": "^2.4.4",
"domutils": "^2.5.2",
"entities": "^2.0.0"
}
}
@ -7512,6 +7517,11 @@
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"source-map-js": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
"integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug=="
},
"source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
@ -7832,9 +7842,9 @@
}
},
"terser-webpack-plugin": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.1.tgz",
"integrity": "sha512-5XNNXZiR8YO6X6KhSGXfY0QrGrCRlSwAEjIIrlRQR4W8nP69TaJUlh3bkuac6zzgspiGPfKEHcY295MMVExl5Q==",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.2.tgz",
"integrity": "sha512-6QhDaAiVHIQr5Ab3XUWZyDmrIPCHMiqJVljMF91YKyqwKkL5QHnYMkrMBy96v9Z7ev1hGhSEw1HQZc2p/s5Z8Q==",
"dev": true,
"requires": {
"jest-worker": "^26.6.2",
@ -7842,7 +7852,7 @@
"schema-utils": "^3.0.0",
"serialize-javascript": "^5.0.1",
"source-map": "^0.6.1",
"terser": "^5.5.1"
"terser": "^5.7.0"
},
"dependencies": {
"p-limit": {
@ -8240,9 +8250,9 @@
}
},
"watchpack": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz",
"integrity": "sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw==",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz",
"integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==",
"dev": true,
"requires": {
"glob-to-regexp": "^0.4.1",
@ -8264,9 +8274,9 @@
"integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w=="
},
"webpack": {
"version": "5.37.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.37.0.tgz",
"integrity": "sha512-yvdhgcI6QkQkDe1hINBAJ1UNevqNGTVaCkD2SSJcB8rcrNNl922RI8i2DXUAuNfANoxwsiXXEA4ZPZI9q2oGLA==",
"version": "5.37.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.37.1.tgz",
"integrity": "sha512-btZjGy/hSjCAAVHw+cKG+L0M+rstlyxbO2C+BOTaQ5/XAnxkDrP5sVbqWhXgo4pL3X2dcOib6rqCP20Zr9PLow==",
"dev": true,
"requires": {
"@types/eslint-scope": "^3.7.0",

View File

@ -42,7 +42,7 @@
"electron-window-state": "5.0.3",
"express": "4.17.1",
"express-partial-content": "^1.0.2",
"express-session": "1.17.1",
"express-session": "1.17.2",
"fs-extra": "10.0.0",
"helmet": "4.6.0",
"html": "1.0.0",
@ -59,13 +59,13 @@
"mime-types": "2.1.30",
"multer": "1.4.2",
"node-abi": "2.26.0",
"open": "8.0.8",
"open": "8.1.0",
"portscanner": "2.2.0",
"rand-token": "1.0.1",
"request": "^2.88.2",
"rimraf": "3.0.2",
"sanitize-filename": "1.6.3",
"sanitize-html": "2.3.3",
"sanitize-html": "2.4.0",
"sax": "1.2.4",
"semver": "7.3.5",
"serve-favicon": "2.5.0",
@ -80,7 +80,7 @@
},
"devDependencies": {
"cross-env": "7.0.3",
"electron": "13.0.0-beta.26",
"electron": "13.0.0-beta.28",
"electron-builder": "22.11.3",
"electron-packager": "15.2.0",
"electron-rebuild": "2.3.5",
@ -89,7 +89,7 @@
"jsdoc": "3.6.7",
"lorem-ipsum": "2.0.3",
"rcedit": "3.0.0",
"webpack": "5.37.0",
"webpack": "5.37.1",
"webpack-cli": "4.7.0"
},
"optionalDependencies": {

View File

@ -20,7 +20,7 @@ export async function showDialog() {
return false;
}
appContext.tabManager.getActiveTabContext().setNote(suggestion.notePath);
appContext.tabManager.getActiveNoteContext().setNote(suggestion.notePath);
});
// if you open the Jump To dialog soon after using it previously it can often mean that you

View File

@ -12,9 +12,9 @@ const $okButton = $("#note-info-ok-button");
export async function showDialog() {
utils.openDialog($dialog);
const activeTabContext = appContext.tabManager.getActiveTabContext();
const {note} = activeTabContext;
const noteComplement = await activeTabContext.getNoteComplement();
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
const {note} = activeNoteContext;
const noteComplement = await activeNoteContext.getNoteComplement();
$noteId.text(note.noteId);
$dateCreated.text(noteComplement.dateCreated);

View File

@ -7,7 +7,7 @@ const $noteSource = $("#note-source");
export async function showDialog() {
utils.openDialog($dialog);
const noteCompletement = await appContext.tabManager.getActiveTabContext().getNoteComplement();
const noteCompletement = await appContext.tabManager.getActiveNoteContext().getNoteComplement();
$noteSource.text(formatHtml(noteCompletement.content));
}
@ -37,4 +37,4 @@ function formatNode(node, level) {
}
return node;
}
}

View File

@ -56,7 +56,7 @@ export async function showDialog(ancestorNoteId) {
await froca.reloadNotes([change.noteId]);
appContext.tabManager.getActiveTabContext().setNote(change.noteId);
appContext.tabManager.getActiveNoteContext().setNote(change.noteId);
}
});

View File

@ -145,23 +145,23 @@ $(window).on('beforeunload', () => {
});
function isNotePathInAddress() {
const [notePath, tabId] = treeService.getHashValueFromAddress();
const [notePath, ntxId] = treeService.getHashValueFromAddress();
return notePath.startsWith("root")
// empty string is for empty/uninitialized tab
|| (notePath === '' && !!tabId);
|| (notePath === '' && !!ntxId);
}
$(window).on('hashchange', function() {
if (isNotePathInAddress()) {
const [notePath, tabId] = treeService.getHashValueFromAddress();
const [notePath, ntxId] = treeService.getHashValueFromAddress();
if (!notePath) {
console.log(`Invalid hash value "${document.location.hash}", ignoring.`);
return;
}
appContext.tabManager.switchToTab(tabId, notePath);
appContext.tabManager.switchToTab(ntxId, notePath);
}
});

View File

@ -74,8 +74,8 @@ export default class Entrypoints extends Component {
await ws.waitForMaxKnownEntityChangeId();
const hoistedNoteId = appContext.tabManager.getActiveTabContext()
? appContext.tabManager.getActiveTabContext().hoistedNoteId
const hoistedNoteId = appContext.tabManager.getActiveNoteContext()
? appContext.tabManager.getActiveNoteContext().hoistedNoteId
: 'root';
await appContext.tabManager.openTabWithNote(note.noteId, true, null, hoistedNoteId);
@ -84,29 +84,29 @@ export default class Entrypoints extends Component {
}
async toggleNoteHoistingCommand() {
const tabContext = appContext.tabManager.getActiveTabContext();
const noteContext = appContext.tabManager.getActiveNoteContext();
if (tabContext.note.noteId === tabContext.hoistedNoteId) {
await tabContext.unhoist();
if (noteContext.note.noteId === noteContext.hoistedNoteId) {
await noteContext.unhoist();
}
else if (tabContext.note.type !== 'search') {
await tabContext.setHoistedNoteId(tabContext.note.noteId);
else if (noteContext.note.type !== 'search') {
await noteContext.setHoistedNoteId(noteContext.note.noteId);
}
}
async hoistNoteCommand({noteId}) {
const tabContext = appContext.tabManager.getActiveTabContext();
const noteContext = appContext.tabManager.getActiveNoteContext();
if (tabContext.hoistedNoteId !== noteId) {
await tabContext.setHoistedNoteId(noteId);
if (noteContext.hoistedNoteId !== noteId) {
await noteContext.setHoistedNoteId(noteId);
}
}
async unhoistCommand() {
const activeTabContext = appContext.tabManager.getActiveTabContext();
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
if (activeTabContext) {
activeTabContext.unhoist();
if (activeNoteContext) {
activeNoteContext.unhoist();
}
}
@ -194,8 +194,8 @@ export default class Entrypoints extends Component {
}
async runActiveNoteCommand() {
const tabContext = appContext.tabManager.getActiveTabContext();
const note = tabContext.note;
const noteContext = appContext.tabManager.getActiveNoteContext();
const note = noteContext.note;
// ctrl+enter is also used elsewhere so make sure we're running only when appropriate
if (!note || note.type !== 'code') {
@ -210,7 +210,7 @@ export default class Entrypoints extends Component {
} else if (note.mime === 'text/x-sqlite;schema=trilium') {
const result = await server.post("sql/execute/" + note.noteId);
this.triggerEvent('sqlQueryResults', {tabId: tabContext.tabId, results: result.results});
this.triggerEvent('sqlQueryResults', {ntxId: noteContext.ntxId, results: result.results});
}
toastService.showMessage("Note executed");

View File

@ -56,7 +56,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @returns {Promise<void>}
*/
this.activateNote = async notePath => {
await appContext.tabManager.getActiveTabContext().setNote(notePath);
await appContext.tabManager.getActiveNoteContext().setNote(notePath);
};
/**
@ -68,7 +68,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
this.activateNewNote = async notePath => {
await ws.waitForMaxKnownEntityChangeId();
await appContext.tabManager.getActiveTabContext().setNote(notePath);
await appContext.tabManager.getActiveNoteContext().setNote(notePath);
appContext.triggerEvent('focusAndSelectTitle');
};
@ -406,10 +406,10 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @return {Promise}
*/
this.setHoistedNoteId = (noteId) => {
const activeTabContext = appContext.tabManager.getActiveTabContext();
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
if (activeTabContext) {
activeTabContext.setHoistedNoteId(noteId);
if (activeNoteContext) {
activeNoteContext.setHoistedNoteId(noteId);
}
};

View File

@ -2,16 +2,16 @@ import appContext from "./app_context.js";
import treeService from "./tree.js";
function getHoistedNoteId() {
const activeTabContext = appContext.tabManager.getActiveTabContext();
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
return activeTabContext ? activeTabContext.hoistedNoteId : 'root';
return activeNoteContext ? activeNoteContext.hoistedNoteId : 'root';
}
async function unhoist() {
const activeTabContext = appContext.tabManager.getActiveTabContext();
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
if (activeTabContext) {
await activeTabContext.unhoist();
if (activeNoteContext) {
await activeNoteContext.unhoist();
}
}
@ -25,15 +25,15 @@ function isHoistedNode(node) {
|| node.data.noteId === getHoistedNoteId();
}
async function checkNoteAccess(notePath, tabContext) {
const resolvedNotePath = await treeService.resolveNotePath(notePath, tabContext.hoistedNoteId);
async function checkNoteAccess(notePath, noteContext) {
const resolvedNotePath = await treeService.resolveNotePath(notePath, noteContext.hoistedNoteId);
if (!resolvedNotePath) {
console.log("Cannot activate " + notePath);
return false;
}
const hoistedNoteId = tabContext.hoistedNoteId;
const hoistedNoteId = noteContext.hoistedNoteId;
if (!resolvedNotePath.includes(hoistedNoteId)) {
const confirmDialog = await import('../dialogs/confirm.js');

View File

@ -64,7 +64,7 @@ ws.subscribeToMessages(async message => {
toastService.showPersistent(toast);
if (message.result.importedNoteId) {
await appContext.tabManager.getActiveTabContext().setNote(message.result.importedNoteId);
await appContext.tabManager.getActiveNoteContext().setNote(message.result.importedNoteId);
}
}
});

View File

@ -27,7 +27,7 @@ async function setupActionsForElement(scope, $el, component) {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
utils.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, {tabId: appContext.tabManager.activeTabId}));
utils.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeTabId}));
}
}
}
@ -35,7 +35,7 @@ async function setupActionsForElement(scope, $el, component) {
getActionsForScope("window").then(actions => {
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
utils.bindGlobalShortcut(shortcut, () => appContext.triggerCommand(action.actionName, {tabId: appContext.tabManager.activeTabId}));
utils.bindGlobalShortcut(shortcut, () => appContext.triggerCommand(action.actionName, {ntxId: appContext.tabManager.activeTabId}));
}
}
});
@ -43,7 +43,7 @@ getActionsForScope("window").then(actions => {
server.get('keyboard-shortcuts-for-notes').then(shortcutForNotes => {
for (const shortcut in shortcutForNotes) {
utils.bindGlobalShortcut(shortcut, async () => {
appContext.tabManager.getActiveTabContext().setNote(shortcutForNotes[shortcut]);
appContext.tabManager.getActiveNoteContext().setNote(shortcutForNotes[shortcut]);
});
}
});

View File

@ -81,15 +81,15 @@ function goToLink(e) {
appContext.tabManager.openTabWithNoteWithHoisting(notePath);
}
else if (e.which === 1) {
const tabId = $(e.target).closest("[data-tab-id]").attr("data-tab-id");
const ntxId = $(e.target).closest("[data-tab-id]").attr("data-tab-id");
const tabContext = tabId
? appContext.tabManager.getTabContextById(tabId)
: appContext.tabManager.getActiveTabContext();
const noteContext = ntxId
? appContext.tabManager.getNoteContextById(ntxId)
: appContext.tabManager.getActiveNoteContext();
tabContext.setNote(notePath).then(() => {
if (tabContext !== appContext.tabManager.getActiveTabContext()) {
appContext.tabManager.activateTab(tabContext.tabId);
noteContext.setNote(notePath).then(() => {
if (noteContext !== appContext.tabManager.getActiveNoteContext()) {
appContext.tabManager.activateTab(noteContext.ntxId);
}
});
}

View File

@ -27,14 +27,14 @@ export default class MainTreeExecutors extends Component {
}
async createNoteIntoCommand() {
const activeTabContext = appContext.tabManager.getActiveTabContext();
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
if (!activeTabContext) {
if (!activeNoteContext) {
return;
}
await noteCreateService.createNote(activeTabContext.notePath, {
isProtected: activeTabContext.note.isProtected,
await noteCreateService.createNote(activeNoteContext.notePath, {
isProtected: activeNoteContext.note.isProtected,
saveSelection: false
});
}

View File

@ -48,14 +48,14 @@ async function createNote(parentNotePath, options = {}) {
await ws.waitForMaxKnownEntityChangeId();
if (options.activate) {
const activeTabContext = appContext.tabManager.getActiveTabContext();
await activeTabContext.setNote(`${parentNotePath}/${note.noteId}`);
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
await activeNoteContext.setNote(`${parentNotePath}/${note.noteId}`);
if (options.focus === 'title') {
appContext.triggerEvent('focusAndSelectTitle');
}
else if (options.focus === 'content') {
appContext.triggerEvent('focusOnDetail', {tabId: activeTabContext.tabId});
appContext.triggerEvent('focusOnDetail', {ntxId: activeNoteContext.ntxId});
}
}
@ -90,8 +90,8 @@ async function duplicateSubtree(noteId, parentNotePath) {
await ws.waitForMaxKnownEntityChangeId();
const activeTabContext = appContext.tabManager.getActiveTabContext();
activeTabContext.setNote(`${parentNotePath}/${note.noteId}`);
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
activeNoteContext.setNote(`${parentNotePath}/${note.noteId}`);
const origNote = await froca.getNote(noteId);
toastService.showMessage(`Note "${origNote.title}" has been duplicated`);

View File

@ -64,17 +64,17 @@ export default class RootCommandExecutor extends Component {
async showSQLConsoleCommand() {
const sqlConsoleNote = await dateNoteService.createSqlConsole();
const tabContext = await appContext.tabManager.openTabWithNote(sqlConsoleNote.noteId, true);
const noteContext = await appContext.tabManager.openTabWithNote(sqlConsoleNote.noteId, true);
appContext.triggerEvent('focusOnDetail', {tabId: tabContext.tabId});
appContext.triggerEvent('focusOnDetail', {ntxId: noteContext.ntxId});
}
async searchNotesCommand({searchString, ancestorNoteId}) {
const searchNote = await dateNoteService.createSearchNote({searchString, ancestorNoteId});
const tabContext = await appContext.tabManager.openTabWithNote(searchNote.noteId, true);
const noteContext = await appContext.tabManager.openTabWithNote(searchNote.noteId, true);
appContext.triggerCommand('focusOnSearchDefinition', {tabId: tabContext.tabId});
appContext.triggerCommand('focusOnSearchDefinition', {ntxId: noteContext.ntxId});
}
async searchInSubtreeCommand({notePath}) {

View File

@ -4,14 +4,14 @@ const REQUEST_LOGGING_ENABLED = false;
async function getHeaders(headers) {
const appContext = (await import('./app_context.js')).default;
const activeTabContext = appContext.tabManager ? appContext.tabManager.getActiveTabContext() : null;
const activeNoteContext = appContext.tabManager ? appContext.tabManager.getActiveNoteContext() : null;
// headers need to be lowercase because node.js automatically converts them to lower case
// also avoiding using underscores instead of dashes since nginx filters them out by default
const allHeaders = {
'trilium-source-id': glob.sourceId,
'trilium-local-now-datetime': utils.localNowDateTime(),
'trilium-hoisted-note-id': activeTabContext ? activeTabContext.hoistedNoteId : null,
'trilium-hoisted-note-id': activeNoteContext ? activeNoteContext.hoistedNoteId : null,
'x-csrf-token': glob.csrfToken
};

View File

@ -7,21 +7,21 @@ import Component from "../widgets/component.js";
import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
class TabContext extends Component {
class NoteContext extends Component {
/**
* @param {string|null} tabId
* @param {string|null} ntxId
*/
constructor(tabId = null, hoistedNoteId = 'root', parentTabId = null) {
constructor(ntxId = null, hoistedNoteId = 'root', mainNtxId = null) {
super();
this.tabId = tabId || utils.randomString(4);
this.ntxId = ntxId || utils.randomString(4);
this.hoistedNoteId = hoistedNoteId;
this.parentTabId = parentTabId;
this.mainNtxId = mainNtxId;
}
setEmpty() {
this.triggerEvent('tabNoteSwitched', {
tabContext: this,
noteContext: this,
notePath: this.notePath
});
}
@ -33,7 +33,7 @@ class TabContext extends Component {
return;
}
await this.triggerEvent('beforeNoteSwitch', {tabContext: this});
await this.triggerEvent('beforeNoteSwitch', {noteContext: this});
utils.closeActiveDialog();
@ -49,7 +49,7 @@ class TabContext extends Component {
if (triggerSwitchEvent) {
await this.triggerEvent('tabNoteSwitched', {
tabContext: this,
noteContext: this,
notePath: this.notePath
});
}
@ -60,13 +60,13 @@ class TabContext extends Component {
}
}
getAllSubTabContexts() {
return appContext.tabManager.tabContexts.filter(tc => tc.tabId === this.tabId || tc.parentTabId === this.tabId);
getAllSubNoteContexts() {
return appContext.tabManager.noteContexts.filter(nc => nc.ntxId === this.ntxId || nc.mainNtxId === this.ntxId);
}
getMainTabContext() {
if (this.parentTabId) {
return appContext.tabManager.getTabContextById(this.parentTabId);
getMainNoteContext() {
if (this.mainNtxId) {
return appContext.tabManager.getNoteContextById(this.mainNtxId);
}
else {
return this;
@ -138,7 +138,7 @@ class TabContext extends Component {
}
isActive() {
return appContext.tabManager.activeTabId === this.tabId;
return appContext.tabManager.activeTabId === this.ntxId;
}
getTabState() {
@ -147,8 +147,8 @@ class TabContext extends Component {
}
return {
tabId: this.tabId,
parentTabId: this.parentTabId,
ntxId: this.ntxId,
mainNtxId: this.mainNtxId,
notePath: this.notePath,
hoistedNoteId: this.hoistedNoteId,
active: this.isActive()
@ -168,7 +168,7 @@ class TabContext extends Component {
await this.triggerEvent('hoistedNoteChanged', {
noteId: noteIdToHoist,
tabId: this.tabId
ntxId: this.ntxId
});
}
@ -181,7 +181,7 @@ class TabContext extends Component {
this.notePath = null;
this.triggerEvent('tabNoteSwitched', {
tabContext: this,
noteContext: this,
notePath: this.notePath
});
}
@ -189,4 +189,4 @@ class TabContext extends Component {
}
}
export default TabContext;
export default NoteContext;

View File

@ -5,7 +5,7 @@ import options from "./options.js";
import froca from "./froca.js";
import treeService from "./tree.js";
import utils from "./utils.js";
import TabContext from "./tab_context.js";
import NoteContext from "./tab_context.js";
import appContext from "./app_context.js";
export default class TabManager extends Component {
@ -19,8 +19,8 @@ export default class TabManager extends Component {
return;
}
const openTabs = this.tabContexts
.map(tc => tc.getTabState())
const openTabs = this.noteContexts
.map(nc => nc.getTabState())
.filter(t => !!t);
await server.put('options', {
@ -31,14 +31,14 @@ export default class TabManager extends Component {
appContext.addBeforeUnloadListener(this);
}
/** @type {TabContext[]} */
get tabContexts() {
/** @type {NoteContext[]} */
get noteContexts() {
return this.children;
}
/** @type {TabContext[]} */
get mainTabContexts() {
return this.tabContexts.filter(tc => !tc.parentTabId)
/** @type {NoteContext[]} */
get mainNoteContexts() {
return this.noteContexts.filter(nc => !nc.mainNtxId)
}
async loadTabs() {
@ -104,13 +104,13 @@ export default class TabManager extends Component {
await this.tabsUpdate.allowUpdateWithoutChange(async () => {
for (const tab of filteredTabs) {
await this.openTabWithNote(tab.notePath, tab.active, tab.tabId, tab.hoistedNoteId, tab.parentTabId);
await this.openTabWithNote(tab.notePath, tab.active, tab.ntxId, tab.hoistedNoteId, tab.mainNtxId);
}
});
}
tabNoteSwitchedEvent({tabContext}) {
if (tabContext.isActive()) {
tabNoteSwitchedEvent({noteContext}) {
if (noteContext.isActive()) {
this.setCurrentNotePathToHash();
}
@ -118,11 +118,11 @@ export default class TabManager extends Component {
}
setCurrentNotePathToHash() {
const activeTabContext = this.getActiveTabContext();
const activeNoteContext = this.getActiveNoteContext();
if (window.history.length === 0 // first history entry
|| (activeTabContext && activeTabContext.notePath !== treeService.getHashValueFromAddress()[0])) {
const url = '#' + (activeTabContext.notePath || "") + "-" + activeTabContext.tabId;
|| (activeNoteContext && activeNoteContext.notePath !== treeService.getHashValueFromAddress()[0])) {
const url = '#' + (activeNoteContext.notePath || "") + "-" + activeNoteContext.ntxId;
// using pushState instead of directly modifying document.location because it does not trigger hashchange
window.history.pushState(null, "", url);
@ -130,46 +130,46 @@ export default class TabManager extends Component {
document.title = "Trilium Notes";
if (activeTabContext.note) {
if (activeNoteContext.note) {
// it helps navigating in history if note title is included in the title
document.title += " - " + activeTabContext.note.title;
document.title += " - " + activeNoteContext.note.title;
}
this.triggerEvent('activeNoteChanged'); // trigger this even in on popstate event
}
/** @return {TabContext[]} */
getTabContexts() {
return this.tabContexts;
/** @return {NoteContext[]} */
getNoteContexts() {
return this.noteContexts;
}
/** @returns {TabContext} */
getTabContextById(tabId) {
const tabContext = this.tabContexts.find(tc => tc.tabId === tabId);
/** @returns {NoteContext} */
getNoteContextById(ntxId) {
const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId);
if (!tabContext) {
throw new Error(`Cannot find tabContext id='${tabId}'`);
if (!noteContext) {
throw new Error(`Cannot find noteContext id='${ntxId}'`);
}
return tabContext;
return noteContext;
}
/** @returns {TabContext} */
getActiveTabContext() {
/** @returns {NoteContext} */
getActiveNoteContext() {
return this.activeTabId
? this.getTabContextById(this.activeTabId)
? this.getNoteContextById(this.activeTabId)
: null;
}
/** @returns {string|null} */
getActiveTabNotePath() {
const activeContext = this.getActiveTabContext();
const activeContext = this.getActiveNoteContext();
return activeContext ? activeContext.notePath : null;
}
/** @return {NoteShort} */
getActiveTabNote() {
const activeContext = this.getActiveTabContext();
const activeContext = this.getActiveNoteContext();
return activeContext ? activeContext.note : null;
}
@ -187,79 +187,79 @@ export default class TabManager extends Component {
return activeNote ? activeNote.type : null;
}
async switchToTab(tabId, notePath) {
const tabContext = this.tabContexts.find(tc => tc.tabId === tabId)
async switchToTab(ntxId, notePath) {
const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId)
|| await this.openEmptyTab();
this.activateTab(tabContext.tabId);
await tabContext.setNote(notePath);
this.activateTab(noteContext.ntxId);
await noteContext.setNote(notePath);
}
async openAndActivateEmptyTab() {
const tabContext = await this.openEmptyTab();
const noteContext = await this.openEmptyTab();
await this.activateTab(tabContext.tabId);
await this.activateTab(noteContext.ntxId);
await tabContext.setEmpty();
await noteContext.setEmpty();
}
async openEmptyTab(tabId, hoistedNoteId = 'root', parentTabId = null) {
const tabContext = new TabContext(tabId, hoistedNoteId, parentTabId);
async openEmptyTab(ntxId, hoistedNoteId = 'root', mainNtxId = null) {
const noteContext = new NoteContext(ntxId, hoistedNoteId, mainNtxId);
const existingTabContext = this.children.find(tc => tc.tabId === tabContext.tabId);
const existingNoteContext = this.children.find(nc => nc.ntxId === noteContext.ntxId);
if (existingTabContext) {
return existingTabContext;
if (existingNoteContext) {
return existingNoteContext;
}
this.child(tabContext);
this.child(noteContext);
await this.triggerEvent('newTabOpened', {tabContext});
await this.triggerEvent('newTabOpened', {noteContext});
return tabContext;
return noteContext;
}
/**
* If the requested notePath is within current note hoisting scope then keep the note hoisting also for the new tab.
*/
async openTabWithNoteWithHoisting(notePath) {
const tabContext = this.getActiveTabContext();
const noteContext = this.getActiveNoteContext();
let hoistedNoteId = 'root';
if (tabContext) {
const resolvedNotePath = await treeService.resolveNotePath(notePath, tabContext.hoistedNoteId);
if (noteContext) {
const resolvedNotePath = await treeService.resolveNotePath(notePath, noteContext.hoistedNoteId);
if (resolvedNotePath.includes(tabContext.hoistedNoteId)) {
hoistedNoteId = tabContext.hoistedNoteId;
if (resolvedNotePath.includes(noteContext.hoistedNoteId)) {
hoistedNoteId = noteContext.hoistedNoteId;
}
}
return this.openTabWithNote(notePath, false, null, hoistedNoteId);
}
async openTabWithNote(notePath, activate, tabId, hoistedNoteId = 'root', parentTabId = null) {
const tabContext = await this.openEmptyTab(tabId, hoistedNoteId, parentTabId);
async openTabWithNote(notePath, activate, ntxId, hoistedNoteId = 'root', mainNtxId = null) {
const noteContext = await this.openEmptyTab(ntxId, hoistedNoteId, mainNtxId);
if (notePath) {
await tabContext.setNote(notePath, !activate); // if activate is false then send normal noteSwitched event
await noteContext.setNote(notePath, !activate); // if activate is false then send normal noteSwitched event
}
if (activate) {
this.activateTab(tabContext.tabId, false);
this.activateTab(noteContext.ntxId, false);
await this.triggerEvent('tabNoteSwitchedAndActivated', {
tabContext,
notePath: tabContext.notePath // resolved note path
noteContext,
notePath: noteContext.notePath // resolved note path
});
}
return tabContext;
return noteContext;
}
async activateOrOpenNote(noteId) {
for (const tabContext of this.getTabContexts()) {
if (tabContext.note && tabContext.note.noteId === noteId) {
this.activateTab(tabContext.tabId);
for (const noteContext of this.getNoteContexts()) {
if (noteContext.note && noteContext.note.noteId === noteId) {
this.activateTab(noteContext.ntxId);
return;
}
@ -270,16 +270,16 @@ export default class TabManager extends Component {
await this.openTabWithNote(noteId, true);
}
activateTab(tabId, triggerEvent = true) {
if (tabId === this.activeTabId) {
activateTab(ntxId, triggerEvent = true) {
if (ntxId === this.activeTabId) {
return;
}
this.activeTabId = tabId;
this.activeTabId = ntxId;
if (triggerEvent) {
this.triggerEvent('activeTabChanged', {
tabContext: this.getTabContextById(tabId)
noteContext: this.getNoteContextById(ntxId)
});
}
@ -288,23 +288,23 @@ export default class TabManager extends Component {
this.setCurrentNotePathToHash();
}
async removeTab(tabId) {
const mainTabContextToRemove = this.getTabContextById(tabId).getMainTabContext();
async removeTab(ntxId) {
const mainNoteContextToRemove = this.getNoteContextById(ntxId).getMainNoteContext();
// close dangling autocompletes after closing the tab
$(".aa-input").autocomplete("close");
const tabIdsToRemove = mainTabContextToRemove.getAllSubTabContexts().map(tc => tc.tabId);
const ntxIdsToRemove = mainNoteContextToRemove.getAllSubNoteContexts().map(nc => nc.ntxId);
await this.triggerEvent('beforeTabRemove', { tabIds: tabIdsToRemove });
await this.triggerEvent('beforeTabRemove', { ntxIds: ntxIdsToRemove });
if (this.mainTabContexts.length <= 1) {
if (this.mainNoteContexts.length <= 1) {
await this.openAndActivateEmptyTab();
}
else if (tabIdsToRemove.includes(this.activeTabId)) {
const idx = this.mainTabContexts.findIndex(tc => tc.tabId === mainTabContextToRemove.tabId);
else if (ntxIdsToRemove.includes(this.activeTabId)) {
const idx = this.mainNoteContexts.findIndex(nc => nc.ntxId === mainNoteContextToRemove.ntxId);
if (idx === this.mainTabContexts.length - 1) {
if (idx === this.mainNoteContexts.length - 1) {
this.activatePreviousTabCommand();
}
else {
@ -312,35 +312,35 @@ export default class TabManager extends Component {
}
}
this.children = this.children.filter(tc => !tabIdsToRemove.includes(tc.tabId));
this.children = this.children.filter(nc => !ntxIdsToRemove.includes(nc.ntxId));
this.triggerEvent('tabRemoved', {tabIds: tabIdsToRemove});
this.triggerEvent('tabRemoved', {ntxIds: ntxIdsToRemove});
this.tabsUpdate.scheduleUpdate();
}
tabReorderEvent({tabIdsInOrder}) {
tabReorderEvent({ntxIdsInOrder}) {
const order = {};
for (const i in tabIdsInOrder) {
order[tabIdsInOrder[i]] = i;
for (const i in ntxIdsInOrder) {
order[ntxIdsInOrder[i]] = i;
}
this.children.sort((a, b) => order[a.tabId] < order[b.tabId] ? -1 : 1);
this.children.sort((a, b) => order[a.ntxId] < order[b.ntxId] ? -1 : 1);
this.tabsUpdate.scheduleUpdate();
}
activateNextTabCommand() {
const oldIdx = this.mainTabContexts.findIndex(tc => tc.tabId === this.activeTabId);
const newActiveTabId = this.mainTabContexts[oldIdx === this.tabContexts.length - 1 ? 0 : oldIdx + 1].tabId;
const oldIdx = this.mainNoteContexts.findIndex(nc => nc.ntxId === this.activeTabId);
const newActiveTabId = this.mainNoteContexts[oldIdx === this.noteContexts.length - 1 ? 0 : oldIdx + 1].ntxId;
this.activateTab(newActiveTabId);
}
activatePreviousTabCommand() {
const oldIdx = this.mainTabContexts.findIndex(tc => tc.tabId === this.activeTabId);
const newActiveTabId = this.mainTabContexts[oldIdx === 0 ? this.tabContexts.length - 1 : oldIdx - 1].tabId;
const oldIdx = this.mainNoteContexts.findIndex(nc => nc.ntxId === this.activeTabId);
const newActiveTabId = this.mainNoteContexts[oldIdx === 0 ? this.noteContexts.length - 1 : oldIdx - 1].ntxId;
this.activateTab(newActiveTabId);
}
@ -360,23 +360,23 @@ export default class TabManager extends Component {
}
async removeAllTabsCommand() {
for (const tabIdToRemove of this.tabContexts.map(tc => tc.tabId)) {
await this.removeTab(tabIdToRemove);
for (const ntxIdToRemove of this.noteContexts.map(nc => nc.ntxId)) {
await this.removeTab(ntxIdToRemove);
}
}
async removeAllTabsExceptForThisCommand({tabId}) {
for (const tabIdToRemove of this.tabContexts.map(tc => tc.tabId)) {
if (tabIdToRemove !== tabId) {
await this.removeTab(tabIdToRemove);
async removeAllTabsExceptForThisCommand({ntxId}) {
for (const ntxIdToRemove of this.noteContexts.map(nc => nc.ntxId)) {
if (ntxIdToRemove !== ntxId) {
await this.removeTab(ntxIdToRemove);
}
}
}
moveTabToNewWindowCommand({tabId}) {
const {notePath, hoistedNoteId} = this.getTabContextById(tabId);
moveTabToNewWindowCommand({ntxId}) {
const {notePath, hoistedNoteId} = this.getNoteContextById(ntxId);
this.removeTab(tabId);
this.removeTab(ntxId);
this.triggerCommand('openInWindow', {notePath, hoistedNoteId});
}

View File

@ -24,7 +24,7 @@ async function resolveNotePath(notePath, hoistedNoteId = 'root') {
async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logErrors = true) {
utils.assertArguments(notePath);
// we might get notePath with the tabId suffix, remove it if present
// we might get notePath with the ntxId suffix, remove it if present
notePath = notePath.split("-")[0].trim();
if (notePath.length === 0) {
@ -154,7 +154,7 @@ function getNoteIdFromNotePath(notePath) {
const lastSegment = path[path.length - 1];
// path could have also tabId suffix
// path could have also ntxId suffix
return lastSegment.split("-")[0];
}
@ -180,7 +180,7 @@ function getNoteIdAndParentIdFromNotePath(notePath) {
const lastSegment = path[path.length - 1];
// path could have also tabId suffix
// path could have also ntxId suffix
noteId = lastSegment.split("-")[0];
if (path.length > 1) {

View File

@ -39,7 +39,7 @@ class TreeContextMenu {
const note = await froca.getNote(this.node.data.noteId);
const branch = froca.getBranch(this.node.data.branchId);
const isNotRoot = note.noteId !== 'root';
const isHoisted = note.noteId === appContext.tabManager.getActiveTabContext().hoistedNoteId;
const isHoisted = note.noteId === appContext.tabManager.getActiveNoteContext().hoistedNoteId;
const parentNote = isNotRoot ? await froca.getNote(branch.parentNoteId) : null;
// some actions don't support multi-note so they are disabled when notes are selected

View File

@ -226,15 +226,15 @@ export default class AttributeEditorWidget extends TabAwareWidget {
}
// triggered from keyboard shortcut
addNewLabelEvent({tabId}) {
if (this.isTab(tabId)) {
addNewLabelEvent({ntxId}) {
if (this.isTab(ntxId)) {
this.handleAddNewAttributeCommand('addNewLabel');
}
}
// triggered from keyboard shortcut
addNewRelationEvent({tabId}) {
if (this.isTab(tabId)) {
addNewRelationEvent({ntxId}) {
if (this.isTab(ntxId)) {
this.handleAddNewAttributeCommand('addNewRelation');
}
}
@ -482,8 +482,8 @@ export default class AttributeEditorWidget extends TabAwareWidget {
}
}
async focusOnAttributesEvent({tabId}) {
if (this.tabContext.tabId === tabId) {
async focusOnAttributesEvent({ntxId}) {
if (this.noteContext.ntxId === ntxId) {
if (this.$editor.is(":visible")) {
this.$editor.trigger('focus');
@ -492,7 +492,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
});
}
else {
this.triggerEvent('focusOnDetail', {tabId: this.tabContext.tabId});
this.triggerEvent('focusOnDetail', {ntxId: this.noteContext.ntxId});
}
}
}

View File

@ -56,7 +56,7 @@ export default class CalendarWidget extends CollapsibleWidget {
const note = await dateNoteService.getDateNote(date);
if (note) {
appContext.tabManager.getActiveTabContext().setNote(note.noteId);
appContext.tabManager.getActiveNoteContext().setNote(note.noteId);
}
else {
alert("Cannot find day note");

View File

@ -100,7 +100,7 @@ export default class NoteInfoWidget extends CollapsibleWidget {
}
async refreshWithNote(note) {
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
this.$noteId.text(note.noteId);
this.$dateCreated

View File

@ -14,20 +14,20 @@ export default class PaneContainer extends FlexContainer {
this.css('flex-grow', '1');
}
async newTabOpenedEvent({tabContext}) {
async newTabOpenedEvent({noteContext}) {
const widget = this.widgetFactory();
const $renderedWidget = widget.render();
$renderedWidget.attr("data-tab-id", tabContext.tabId);
$renderedWidget.attr("data-tab-id", noteContext.ntxId);
$renderedWidget.on('click', () => appContext.tabManager.activateTab(tabContext.tabId));
$renderedWidget.on('click', () => appContext.tabManager.activateTab(noteContext.ntxId));
this.$widget.append($renderedWidget);
this.widgets[tabContext.tabId] = widget;
this.widgets[noteContext.ntxId] = widget;
await widget.handleEvent('setTabContext', { tabContext });
await widget.handleEvent('setNoteContext', { noteContext });
this.child(widget);
@ -35,11 +35,11 @@ export default class PaneContainer extends FlexContainer {
}
async openNewPaneCommand() {
const tabContext = await appContext.tabManager.openEmptyTab(null, 'root', appContext.tabManager.getActiveTabContext().tabId);
const noteContext = await appContext.tabManager.openEmptyTab(null, 'root', appContext.tabManager.getActiveNoteContext().ntxId);
await appContext.tabManager.activateTab(tabContext.tabId);
await appContext.tabManager.activateTab(noteContext.ntxId);
await tabContext.setEmpty();
await noteContext.setEmpty();
}
async refresh() {
@ -49,16 +49,16 @@ export default class PaneContainer extends FlexContainer {
toggleInt(show) {} // not needed
toggleExt(show) {
const activeTabId = appContext.tabManager.getActiveTabContext().getMainTabContext().tabId;
const activeTabId = appContext.tabManager.getActiveNoteContext().getMainNoteContext().ntxId;
for (const tabId in this.widgets) {
const tabContext = appContext.tabManager.getTabContextById(tabId);
for (const ntxId in this.widgets) {
const noteContext = appContext.tabManager.getNoteContextById(ntxId);
const widget = this.widgets[tabId];
widget.toggleExt(show && activeTabId && [tabContext.tabId, tabContext.parentTabId].includes(activeTabId));
const widget = this.widgets[ntxId];
widget.toggleExt(show && activeTabId && [noteContext.ntxId, noteContext.mainNtxId].includes(activeTabId));
if (!widget.hasBeenAlreadyShown) {
widget.handleEvent('activeTabChanged', {tabContext});
widget.handleEvent('activeTabChanged', {noteContext});
}
}
}
@ -71,7 +71,7 @@ export default class PaneContainer extends FlexContainer {
handleEventInChildren(name, data) {
if (['tabNoteSwitched', 'tabNoteSwitchedAndActivated'].includes(name)) {
// this event is propagated only to the widgets of a particular tab
const widget = this.widgets[data.tabContext.tabId];
const widget = this.widgets[data.noteContext.ntxId];
if (!widget) {
return Promise.resolve();
@ -79,23 +79,23 @@ export default class PaneContainer extends FlexContainer {
const promises = [];
if (appContext.tabManager.getActiveTabContext().getMainTabContext() === data.tabContext.getMainTabContext()) {
if (appContext.tabManager.getActiveNoteContext().getMainNoteContext() === data.noteContext.getMainNoteContext()) {
promises.push(widget.handleEvent('activeTabChanged', data));
}
for (const subTabContext of data.tabContext.getMainTabContext().getAllSubTabContexts()) {
const subWidget = this.widgets[subTabContext.tabId];
for (const subNoteContext of data.noteContext.getMainNoteContext().getAllSubNoteContexts()) {
const subWidget = this.widgets[subNoteContext.ntxId];
if (!subWidget) {
continue;
}
if (subTabContext !== data.tabContext && !subWidget.hasBeenAlreadyShown) {
promises.push(widget.handleEvent('activeTabChanged', {tabContext: subTabContext}));
if (subNoteContext !== data.noteContext && !subWidget.hasBeenAlreadyShown) {
promises.push(widget.handleEvent('activeTabChanged', {noteContext: subNoteContext}));
continue;
}
if (subTabContext === data.tabContext && (subWidget.hasBeenAlreadyShown || name === 'tabNoteSwitchedAndActivated')) {
if (subNoteContext === data.noteContext && (subWidget.hasBeenAlreadyShown || name === 'tabNoteSwitchedAndActivated')) {
subWidget.hasBeenAlreadyShown = true;
promises.push(widget.handleEvent('tabNoteSwitched', data));
@ -112,15 +112,15 @@ export default class PaneContainer extends FlexContainer {
if (name === 'activeTabChanged') {
const promises = [];
for (const subTabContext of data.tabContext.getMainTabContext().getAllSubTabContexts()) {
console.log("subTabContext", subTabContext);
for (const subNoteContext of data.noteContext.getMainNoteContext().getAllSubNoteContexts()) {
console.log("subNoteContext", subNoteContext);
const widget = this.widgets[subTabContext.tabId];
const widget = this.widgets[subNoteContext.ntxId];
if (!widget.hasBeenAlreadyShown) {
widget.hasBeenAlreadyShown = true;
promises.push(widget.handleEvent(name, {tabContext: subTabContext}));
promises.push(widget.handleEvent(name, {noteContext: subNoteContext}));
}
}

View File

@ -7,9 +7,9 @@ export default class ScrollingContainer extends Container {
this.css('height: 100%; overflow: auto;');
}
async tabNoteSwitchedEvent({tabContext, notePath}) {
// if notePath does not match then the tabContext has been switched to another note in the mean time
if (tabContext.notePath === notePath) {
async tabNoteSwitchedEvent({noteContext, notePath}) {
// if notePath does not match then the noteContext has been switched to another note in the mean time
if (noteContext.notePath === notePath) {
this.$widget.scrollTop(0);
}
}

View File

@ -60,7 +60,7 @@ export default class HistoryNavigationWidget extends BasicWidget {
for (const idx in this.webContents.history) {
const url = this.webContents.history[idx];
const [_, notePathWithTab] = url.split('#');
const [notePath, tabId] = notePathWithTab.split('-');
const [notePath, ntxId] = notePathWithTab.split('-');
const title = await treeService.getNotePathTitle(notePath);

View File

@ -114,7 +114,7 @@ export default class NoteActionsWidget extends TabAwareWidget {
return;
}
import('../dialogs/export.js').then(d => d.showDialog(this.tabContext.notePath, 'single'));
import('../dialogs/export.js').then(d => d.showDialog(this.noteContext.notePath, 'single'));
});
this.$importNoteButton = this.$widget.find('.import-files-button');

View File

@ -55,7 +55,7 @@ export default class NoteDetailWidget extends TabAwareWidget {
this.typeWidgets = {};
this.spacedUpdate = new SpacedUpdate(async () => {
const {note} = this.tabContext;
const {note} = this.noteContext;
const {noteId} = note;
const dto = note.dto;
@ -119,12 +119,12 @@ export default class NoteDetailWidget extends TabAwareWidget {
this.$widget.append($renderedWidget);
await typeWidget.handleEvent('setTabContext', {tabContext: this.tabContext});
await typeWidget.handleEvent('setNoteContext', {noteContext: this.noteContext});
// this is happening in update() so note has been already set and we need to reflect this
await typeWidget.handleEvent('tabNoteSwitched', {
tabContext: this.tabContext,
notePath: this.tabContext.notePath
noteContext: this.noteContext,
notePath: this.noteContext.notePath
});
this.child(typeWidget);
@ -150,8 +150,8 @@ export default class NoteDetailWidget extends TabAwareWidget {
let type = note.type;
if (type === 'text' && !this.tabContext.textPreviewDisabled) {
const noteComplement = await this.tabContext.getNoteComplement();
if (type === 'text' && !this.noteContext.textPreviewDisabled) {
const noteComplement = await this.noteContext.getNoteComplement();
if (note.hasLabel('readOnly') ||
(noteComplement.content
@ -161,8 +161,8 @@ export default class NoteDetailWidget extends TabAwareWidget {
}
}
if (type === 'code' && !this.tabContext.codePreviewDisabled) {
const noteComplement = await this.tabContext.getNoteComplement();
if (type === 'code' && !this.noteContext.codePreviewDisabled) {
const noteComplement = await this.noteContext.getNoteComplement();
if (note.hasLabel('readOnly') ||
(noteComplement.content
@ -187,8 +187,8 @@ export default class NoteDetailWidget extends TabAwareWidget {
return type;
}
async focusOnDetailEvent({tabId}) {
if (this.tabContext.tabId === tabId) {
async focusOnDetailEvent({ntxId}) {
if (this.noteContext.ntxId === ntxId) {
await this.refresh();
const widget = this.getTypeWidget();
@ -196,20 +196,20 @@ export default class NoteDetailWidget extends TabAwareWidget {
}
}
async beforeNoteSwitchEvent({tabContext}) {
if (this.isTab(tabContext.tabId)) {
async beforeNoteSwitchEvent({noteContext}) {
if (this.isTab(noteContext.ntxId)) {
await this.spacedUpdate.updateNowIfNecessary();
}
}
async beforeTabRemoveEvent({tabIds}) {
if (this.isTab(tabIds)) {
async beforeTabRemoveEvent({ntxIds}) {
if (this.isTab(ntxIds)) {
await this.spacedUpdate.updateNowIfNecessary();
}
}
async printActiveNoteEvent() {
if (!this.tabContext.isActive()) {
if (!this.noteContext.isActive()) {
return;
}
@ -241,8 +241,8 @@ export default class NoteDetailWidget extends TabAwareWidget {
});
}
hoistedNoteChangedEvent({tabId}) {
if (this.isTab(tabId)) {
hoistedNoteChangedEvent({ntxId}) {
if (this.isTab(ntxId)) {
this.refresh();
}
}
@ -278,14 +278,14 @@ export default class NoteDetailWidget extends TabAwareWidget {
return this.spacedUpdate.isAllSavedAndTriggerUpdate();
}
textPreviewDisabledEvent({tabContext}) {
if (this.isTab(tabContext.tabId)) {
textPreviewDisabledEvent({noteContext}) {
if (this.isTab(noteContext.ntxId)) {
this.refresh();
}
}
codePreviewDisabledEvent({tabContext}) {
if (this.isTab(tabContext.tabId)) {
codePreviewDisabledEvent({noteContext}) {
if (this.isTab(noteContext.ntxId)) {
this.refresh();
}
}
@ -310,7 +310,7 @@ export default class NoteDetailWidget extends TabAwareWidget {
}
renderActiveNoteEvent() {
if (this.tabContext.isActive()) {
if (this.noteContext.isActive()) {
this.refresh();
}
}

View File

@ -77,8 +77,8 @@ export default class NoteListWidget extends TabAwareWidget {
* If it's evaluated before note detail then it's clearly intersected (visible) although after note detail load
* it is not intersected (visible) anymore.
*/
noteDetailRefreshedEvent({tabId}) {
if (!this.isTab(tabId)) {
noteDetailRefreshedEvent({ntxId}) {
if (!this.isTab(ntxId)) {
return;
}

View File

@ -50,7 +50,7 @@ export default class NoteTitleWidget extends TabAwareWidget {
this.$noteTitle.on('input', () => this.spacedUpdate.scheduleUpdate());
utils.bindElShortcut(this.$noteTitle, 'return', () => {
this.triggerCommand('focusOnAttributes', {tabId: this.tabContext.tabId});
this.triggerCommand('focusOnAttributes', {ntxId: this.noteContext.ntxId});
});
}
@ -66,26 +66,26 @@ export default class NoteTitleWidget extends TabAwareWidget {
this.$noteTitle.toggleClass("protected", !!note.isProtected);
}
async beforeNoteSwitchEvent({tabContext}) {
if (this.isTab(tabContext.tabId)) {
async beforeNoteSwitchEvent({noteContext}) {
if (this.isTab(noteContext.ntxId)) {
await this.spacedUpdate.updateNowIfNecessary();
}
}
async beforeTabRemoveEvent({tabIds}) {
if (this.isTab(tabIds)) {
async beforeTabRemoveEvent({ntxIds}) {
if (this.isTab(ntxIds)) {
await this.spacedUpdate.updateNowIfNecessary();
}
}
focusOnTitleEvent() {
if (this.tabContext && this.tabContext.isActive()) {
if (this.noteContext && this.noteContext.isActive()) {
this.$noteTitle.trigger('focus');
}
}
focusAndSelectTitleEvent() {
if (this.tabContext && this.tabContext.isActive()) {
if (this.noteContext && this.noteContext.isActive()) {
this.$noteTitle
.trigger('focus')
.trigger('select');

View File

@ -395,8 +395,8 @@ export default class NoteTreeWidget extends TabAwareWidget {
const notePath = treeService.getNotePath(data.node);
const activeTabContext = appContext.tabManager.getActiveTabContext();
await activeTabContext.setNote(notePath);
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
await activeNoteContext.setNote(notePath);
if (utils.isMobile()) {
this.triggerCommand('setActiveScreen', {screen: 'detail'});
@ -525,13 +525,13 @@ export default class NoteTreeWidget extends TabAwareWidget {
}
const note = await froca.getNote(node.data.noteId);
const activeTabContext = appContext.tabManager.getActiveTabContext();
const activeNoteContext = appContext.tabManager.getActiveNoteContext();
const $span = $(node.span);
$span.find('.tree-item-button').remove();
const isHoistedNote = activeTabContext && activeTabContext.hoistedNoteId === note.noteId && note.noteId !== 'root';
const isHoistedNote = activeNoteContext && activeNoteContext.hoistedNoteId === note.noteId && note.noteId !== 'root';
if (isHoistedNote) {
const $unhoistButton = $('<span class="tree-item-button unhoist-button bx bx-door-open" title="Unhoist"></span>');
@ -810,7 +810,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
}
async scrollToActiveNoteEvent() {
const activeContext = appContext.tabManager.getActiveTabContext();
const activeContext = appContext.tabManager.getActiveNoteContext();
if (activeContext && activeContext.notePath) {
this.tree.$container.focus();
@ -920,7 +920,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
}
isEnabled() {
return !!this.tabContext;
return !!this.noteContext;
}
async refresh() {
@ -939,12 +939,12 @@ export default class NoteTreeWidget extends TabAwareWidget {
oldActiveNode.setFocus(false);
}
if (this.tabContext && this.tabContext.notePath && !this.tabContext.note.isDeleted) {
const newActiveNode = await this.getNodeFromPath(this.tabContext.notePath);
if (this.noteContext && this.noteContext.notePath && !this.noteContext.note.isDeleted) {
const newActiveNode = await this.getNodeFromPath(this.noteContext.notePath);
if (newActiveNode) {
if (!newActiveNode.isVisible()) {
await this.expandToNote(this.tabContext.notePath);
await this.expandToNote(this.noteContext.notePath);
}
newActiveNode.setActive(true, {noEvents: true, noFocus: !oldActiveNodeFocused});
@ -993,8 +993,8 @@ export default class NoteTreeWidget extends TabAwareWidget {
*/
const noteIdsToKeepExpanded = new Set(
appContext.tabManager.getTabContexts()
.map(tc => tc.notePathArray)
appContext.tabManager.getNoteContexts()
.map(nc => nc.notePathArray)
.flat()
);
@ -1159,10 +1159,10 @@ export default class NoteTreeWidget extends TabAwareWidget {
if (node) {
// FIXME: this is conceptually wrong
// here note tree is responsible for updating global state of the application
// this should be done by tabcontext / tabmanager and note tree should only listen to
// this should be done by NoteContext / TabManager and note tree should only listen to
// changes in active note and just set the "active" state
// We don't await since that can bring up infinite cycles when e.g. custom widget does some backend requests which wait for max sync ID processed
appContext.tabManager.getActiveTabContext().setNote(nextNotePath).then(() => {
appContext.tabManager.getActiveNoteContext().setNote(nextNotePath).then(() => {
const newActiveNode = this.getActiveNode();
// return focus if the previously active node was also focused
@ -1232,25 +1232,25 @@ export default class NoteTreeWidget extends TabAwareWidget {
}
}
async hoistedNoteChangedEvent({tabId}) {
if (this.isTab(tabId)) {
async hoistedNoteChangedEvent({ntxId}) {
if (this.isTab(ntxId)) {
this.filterHoistedBranch();
}
}
async filterHoistedBranch() {
if (this.tabContext) {
if (this.noteContext) {
// make sure the hoisted node is loaded (can be unloaded e.g. after tree collapse in another tab)
const hoistedNotePath = await treeService.resolveNotePath(this.tabContext.hoistedNoteId);
const hoistedNotePath = await treeService.resolveNotePath(this.noteContext.hoistedNoteId);
await this.getNodeFromPath(hoistedNotePath);
if (this.tabContext.hoistedNoteId === 'root') {
if (this.noteContext.hoistedNoteId === 'root') {
this.tree.clearFilter();
}
else {
// hack when hoisted note is cloned then it could be filtered multiple times while we want only 1
this.tree.filterBranches(node =>
node.data.noteId === this.tabContext.hoistedNoteId // optimization to not having always resolve the node path
node.data.noteId === this.noteContext.hoistedNoteId // optimization to not having always resolve the node path
&& treeService.getNotePath(node) === hoistedNotePath);
}
}

View File

@ -136,7 +136,7 @@ export default class NoteTypeWidget extends TabAwareWidget {
}
async confirmChangeIfContent() {
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
if (!noteComplement.content || !noteComplement.content.trim().length) {
return true;

View File

@ -98,13 +98,13 @@ export default class QuickSearchWidget extends BasicWidget {
if (!e.target || e.target.nodeName !== 'A') {
// click on the link is handled by link handling but we want the whole item clickable
appContext.tabManager.getActiveTabContext().setNote(note.noteId);
appContext.tabManager.getActiveNoteContext().setNote(note.noteId);
}
});
utils.bindElShortcut($link, 'return', () => {
this.$dropdownToggle.dropdown("hide");
appContext.tabManager.getActiveTabContext().setNote(note.noteId);
appContext.tabManager.getActiveNoteContext().setNote(note.noteId);
});
this.$dropdownMenu.append($link);
@ -131,7 +131,7 @@ export default class QuickSearchWidget extends BasicWidget {
async showInFullSearch() {
const searchNote = await dateNotesService.createSearchNote({searchString: this.$searchString.val()});
await appContext.tabManager.getActiveTabContext().setNote(searchNote.noteId);
await appContext.tabManager.getActiveNoteContext().setNote(searchNote.noteId);
}
quickSearchEvent() {

View File

@ -56,8 +56,8 @@ export default class SearchResultWidget extends TabAwareWidget {
await noteListRenderer.renderList();
}
searchRefreshedEvent({tabId}) {
if (!this.isTab(tabId)) {
searchRefreshedEvent({ntxId}) {
if (!this.isTab(ntxId)) {
return;
}

View File

@ -25,8 +25,8 @@ export default class SqlResultWidget extends TabAwareWidget {
this.$sqlConsoleResultContainer = this.$widget.find('.sql-console-result-container');
}
async sqlQueryResultsEvent({tabId, results}) {
if (!this.isTab(tabId)) {
async sqlQueryResultsEvent({ntxId, results}) {
if (!this.isTab(ntxId)) {
return;
}

View File

@ -2,17 +2,17 @@ import BasicWidget from "./basic_widget.js";
import appContext from "../services/app_context.js";
export default class TabAwareWidget extends BasicWidget {
isTab(tabId) {
if (Array.isArray(tabId)) {
return this.tabContext && tabId.includes(this.tabContext.tabId);
isTab(ntxId) {
if (Array.isArray(ntxId)) {
return this.noteContext && ntxId.includes(this.noteContext.ntxId);
}
else {
return this.tabContext && this.tabContext.tabId === tabId;
return this.noteContext && this.noteContext.ntxId === ntxId;
}
}
isTabOrParent(tabId) {
return this.tabContext && (this.tabContext.tabId === tabId || this.tabContext.parentTabId === tabId);
isTabOrParent(ntxId) {
return this.noteContext && (this.noteContext.ntxId === ntxId || this.noteContext.mainNtxId === ntxId);
}
isNote(noteId) {
@ -20,7 +20,7 @@ export default class TabAwareWidget extends BasicWidget {
}
get note() {
return this.tabContext && this.tabContext.note;
return this.noteContext && this.noteContext.note;
}
get noteId() {
@ -28,11 +28,11 @@ export default class TabAwareWidget extends BasicWidget {
}
get notePath() {
return this.tabContext && this.tabContext.notePath;
return this.noteContext && this.noteContext.notePath;
}
get hoistedNoteId() {
return this.tabContext && this.tabContext.hoistedNoteId;
return this.noteContext && this.noteContext.hoistedNoteId;
}
isEnabled() {
@ -59,9 +59,9 @@ export default class TabAwareWidget extends BasicWidget {
async refreshWithNote(note) {}
async tabNoteSwitchedEvent({tabContext, notePath}) {
// if notePath does not match then the tabContext has been switched to another note in the mean time
if (tabContext.notePath === notePath) {
async tabNoteSwitchedEvent({noteContext, notePath}) {
// if notePath does not match then the noteContext has been switched to another note in the mean time
if (noteContext.notePath === notePath) {
await this.noteSwitched();
}
}
@ -70,8 +70,8 @@ export default class TabAwareWidget extends BasicWidget {
await this.refresh();
}
async activeTabChangedEvent({tabContext}) {
this.tabContext = tabContext;
async activeTabChangedEvent({noteContext}) {
this.noteContext = noteContext;
await this.activeTabChanged();
}
@ -81,18 +81,18 @@ export default class TabAwareWidget extends BasicWidget {
}
// when note is both switched and activated, this should not produce double refresh
async tabNoteSwitchedAndActivatedEvent({tabContext, notePath}) {
this.tabContext = tabContext;
async tabNoteSwitchedAndActivatedEvent({noteContext, notePath}) {
this.noteContext = noteContext;
// if notePath does not match then the tabContext has been switched to another note in the mean time
// if notePath does not match then the noteContext has been switched to another note in the mean time
if (this.notePath === notePath) {
await this.refresh();
}
}
setTabContextEvent({tabContext}) {
/** @var {TabContext} */
this.tabContext = tabContext;
setNoteContextEvent({noteContext}) {
/** @var {NoteContext} */
this.noteContext = noteContext;
}
async noteTypeMimeChangedEvent({noteId}) {
@ -106,8 +106,8 @@ export default class TabAwareWidget extends BasicWidget {
}
async lazyLoadedEvent() {
if (!this.tabContext) { // has not been loaded yet
this.tabContext = appContext.tabManager.getActiveTabContext();
if (!this.noteContext) { // has not been loaded yet
this.noteContext = appContext.tabManager.getActiveNoteContext();
}
await this.refresh();

View File

@ -13,34 +13,34 @@ export default class TabCachingWidget extends TabAwareWidget {
return this.$widget = $(`<div class="marker" style="display: none;">`);
}
async newTabOpenedEvent({tabContext}) {
const {tabId} = tabContext;
async newTabOpenedEvent({noteContext}) {
const {ntxId} = noteContext;
if (this.widgets[tabId]) {
if (this.widgets[ntxId]) {
return;
}
this.widgets[tabId] = this.widgetFactory();
this.widgets[ntxId] = this.widgetFactory();
const $renderedWidget = this.widgets[tabId].render();
this.widgets[tabId].toggleExt(false); // new tab is always not active, can be activated after creation
const $renderedWidget = this.widgets[ntxId].render();
this.widgets[ntxId].toggleExt(false); // new tab is always not active, can be activated after creation
this.$widget.after($renderedWidget);
keyboardActionsService.updateDisplayedShortcuts($renderedWidget);
await this.widgets[tabId].handleEvent('setTabContext', {tabContext});
await this.widgets[ntxId].handleEvent('setNoteContext', {noteContext});
this.child(this.widgets[tabId]); // add as child only once it is ready (rendered with tabContext)
this.child(this.widgets[ntxId]); // add as child only once it is ready (rendered with noteContext)
}
tabRemovedEvent({tabIds}) {
for (const tabId of tabIds) {
const widget = this.widgets[tabId];
tabRemovedEvent({ntxIds}) {
for (const ntxId of ntxIds) {
const widget = this.widgets[ntxId];
if (widget) {
widget.remove();
delete this.widgets[tabId];
delete this.widgets[ntxId];
this.children = this.children.filter(ch => ch !== widget);
}
@ -54,8 +54,8 @@ export default class TabCachingWidget extends TabAwareWidget {
toggleInt(show) {} // not needed
toggleExt(show) {
for (const tabId in this.widgets) {
this.widgets[tabId].toggleExt(show && this.isTab(tabId));
for (const ntxId in this.widgets) {
this.widgets[ntxId].toggleExt(show && this.isTab(ntxId));
}
}
@ -67,10 +67,10 @@ export default class TabCachingWidget extends TabAwareWidget {
handleEventInChildren(name, data) {
if (['tabNoteSwitched', 'tabNoteSwitchedAndActivated'].includes(name)) {
// this event is propagated only to the widgets of a particular tab
let widget = this.widgets[data.tabContext.tabId];
let widget = this.widgets[data.noteContext.ntxId];
if (!widget) {
widget = this.widgets[data.tabContext.parentTabId];
widget = this.widgets[data.noteContext.mainNtxId];
}
if (widget && (widget.hasBeenAlreadyShown || name === 'tabNoteSwitchedAndActivated')) {
@ -84,10 +84,10 @@ export default class TabCachingWidget extends TabAwareWidget {
}
if (name === 'activeTabChanged') {
let widget = this.widgets[data.tabContext.tabId];
let widget = this.widgets[data.noteContext.ntxId];
if (!widget) {
widget = this.widgets[data.tabContext.parentTabId];
widget = this.widgets[data.noteContext.mainNtxId];
}
if (widget.hasBeenAlreadyShown) {

View File

@ -266,7 +266,7 @@ export default class TabRowWidget extends BasicWidget {
this.$widget.on('contextmenu', '.note-tab', e => {
e.preventDefault();
const tabId = $(e.target).closest(".note-tab").attr('data-tab-id');
const ntxId = $(e.target).closest(".note-tab").attr('data-tab-id');
contextMenu.show({
x: e.pageX,
@ -277,7 +277,7 @@ export default class TabRowWidget extends BasicWidget {
{title: "Close all tabs except for this", command: "removeAllTabsExceptForThis", uiIcon: "x"},
],
selectMenuItemHandler: ({command}) => {
this.triggerCommand(command, {tabId});
this.triggerCommand(command, {ntxId});
}
});
});
@ -388,8 +388,8 @@ export default class TabRowWidget extends BasicWidget {
this.$style.html(styleHTML);
}
addTab(tabId) {
const $tab = $(TAB_TPL).attr('data-tab-id', tabId);
addTab(ntxId) {
const $tab = $(TAB_TPL).attr('data-tab-id', ntxId);
keyboardActionService.updateDisplayedShortcuts($tab);
@ -407,9 +407,9 @@ export default class TabRowWidget extends BasicWidget {
}
closeActiveTabCommand({$el}) {
const tabId = $el.closest(".note-tab").attr('data-tab-id');
const ntxId = $el.closest(".note-tab").attr('data-tab-id');
appContext.tabManager.removeTab(tabId);
appContext.tabManager.removeTab(ntxId);
}
setTabCloseEvent($tab) {
@ -427,31 +427,31 @@ export default class TabRowWidget extends BasicWidget {
}
activeTabChangedEvent() {
let activeTabContext = appContext.tabManager.getActiveTabContext();
let activeNoteContext = appContext.tabManager.getActiveNoteContext();
if (!activeTabContext) {
if (!activeNoteContext) {
return;
}
if (activeTabContext.parentTabId) {
activeTabContext = appContext.tabManager.getTabContextById(activeTabContext.parentTabId);
if (activeNoteContext.mainNtxId) {
activeNoteContext = appContext.tabManager.getNoteContextById(activeNoteContext.mainNtxId);
}
const tabEl = this.getTabById(activeTabContext.tabId)[0];
const tabEl = this.getTabById(activeNoteContext.ntxId)[0];
const activeTabEl = this.activeTabEl;
if (activeTabEl === tabEl) return;
if (activeTabEl) activeTabEl.removeAttribute('active');
if (tabEl) tabEl.setAttribute('active', '');
}
newTabOpenedEvent({tabContext}) {
if (!tabContext.parentTabId) {
this.addTab(tabContext.tabId);
newTabOpenedEvent({noteContext}) {
if (!noteContext.mainNtxId) {
this.addTab(noteContext.ntxId);
}
}
removeTab(tabId) {
const tabEl = this.getTabById(tabId)[0];
removeTab(ntxId) {
const tabEl = this.getTabById(ntxId)[0];
if (tabEl) {
tabEl.parentNode.removeChild(tabEl);
@ -470,17 +470,17 @@ export default class TabRowWidget extends BasicWidget {
$tab.find('.note-tab-title').text(title);
}
getTabById(tabId) {
return this.$widget.find(`[data-tab-id='${tabId}']`);
getTabById(ntxId) {
return this.$widget.find(`[data-tab-id='${ntxId}']`);
}
getTabId($tab) {
return $tab.attr('data-tab-id');
}
tabRemovedEvent({tabIds}) {
for (const tabId of tabIds) {
this.removeTab(tabId);
tabRemovedEvent({ntxIds}) {
for (const ntxId of ntxIds) {
this.removeTab(ntxId);
}
}
@ -567,7 +567,7 @@ export default class TabRowWidget extends BasicWidget {
}
if (Math.abs(moveVector.y) > 100) {
this.triggerCommand('moveTabToNewWindow', {tabId: this.getTabId($(tabEl))});
this.triggerCommand('moveTabToNewWindow', {ntxId: this.getTabId($(tabEl))});
}
});
});
@ -581,7 +581,7 @@ export default class TabRowWidget extends BasicWidget {
tabEl.parentNode.insertBefore(tabEl, beforeEl);
}
this.triggerEvent('tabReorder', {tabIdsInOrder: this.getTabIdsInOrder()});
this.triggerEvent('tabReorder', {ntxIdsInOrder: this.getTabIdsInOrder()});
this.layoutTabs();
}
@ -611,20 +611,20 @@ export default class TabRowWidget extends BasicWidget {
return closestIndex;
};
tabNoteSwitchedAndActivatedEvent({tabContext}) {
tabNoteSwitchedAndActivatedEvent({noteContext}) {
this.activeTabChangedEvent();
this.updateTabById(tabContext.parentTabId || tabContext.tabId);
this.updateTabById(noteContext.mainNtxId || noteContext.ntxId);
}
tabNoteSwitchedEvent({tabContext}) {
this.updateTabById(tabContext.parentTabId || tabContext.tabId);
tabNoteSwitchedEvent({noteContext}) {
this.updateTabById(noteContext.mainNtxId || noteContext.ntxId);
}
updateTabById(tabId) {
const $tab = this.getTabById(tabId);
updateTabById(ntxId) {
const $tab = this.getTabById(ntxId);
const {note} = appContext.tabManager.getTabContextById(tabId);
const {note} = appContext.tabManager.getNoteContextById(ntxId);
this.updateTab($tab, note);
}
@ -640,10 +640,10 @@ export default class TabRowWidget extends BasicWidget {
}
}
const tabContext = appContext.tabManager.getTabContextById(this.getTabId($tab));
const noteContext = appContext.tabManager.getNoteContextById(this.getTabId($tab));
if (tabContext) {
const hoistedNote = froca.getNoteFromCache(tabContext.hoistedNoteId);
if (noteContext) {
const hoistedNote = froca.getNoteFromCache(noteContext.hoistedNoteId);
if (hoistedNote) {
$tab.find('.note-tab-icon')
@ -671,38 +671,38 @@ export default class TabRowWidget extends BasicWidget {
}
async entitiesReloadedEvent({loadResults}) {
for (const tabContext of appContext.tabManager.tabContexts) {
if (!tabContext.noteId) {
for (const noteContext of appContext.tabManager.noteContexts) {
if (!noteContext.noteId) {
continue;
}
if (loadResults.isNoteReloaded(tabContext.noteId) ||
if (loadResults.isNoteReloaded(noteContext.noteId) ||
loadResults.getAttributes().find(attr =>
['workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor'].includes(attr.name)
&& attr.isAffecting(tabContext.note))
&& attr.isAffecting(noteContext.note))
) {
const $tab = this.getTabById(tabContext.tabId);
const $tab = this.getTabById(noteContext.ntxId);
this.updateTab($tab, tabContext.note);
this.updateTab($tab, noteContext.note);
}
}
}
frocaReloadedEvent() {
for (const tabContext of appContext.tabManager.tabContexts) {
const $tab = this.getTabById(tabContext.tabId);
for (const noteContext of appContext.tabManager.noteContexts) {
const $tab = this.getTabById(noteContext.ntxId);
this.updateTab($tab, tabContext.note);
this.updateTab($tab, noteContext.note);
}
}
hoistedNoteChangedEvent({tabId}) {
const $tab = this.getTabById(tabId);
hoistedNoteChangedEvent({ntxId}) {
const $tab = this.getTabById(ntxId);
if ($tab) {
const tabContext = appContext.tabManager.getTabContextById(tabId);
const noteContext = appContext.tabManager.getNoteContextById(ntxId);
this.updateTab($tab, tabContext.note);
this.updateTab($tab, noteContext.note);
}
}
}

View File

@ -126,7 +126,7 @@ export default class FilePropertiesWidget extends TabAwareWidget {
this.$fileName.text(attributeMap.originalFileName || "?");
this.$fileType.text(note.mime);
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
this.$fileSize.text(noteComplement.contentLength + " bytes");

View File

@ -67,7 +67,7 @@ export default class ImagePropertiesWidget extends TabAwareWidget {
this.$imageDownloadButton = this.$widget.find(".image-download");
this.$imageDownloadButton.on('click', () => openService.downloadFileNote(this.noteId));
this.$copyToClipboardButton.on('click', () => this.triggerEvent(`copyImageToClipboard`, {tabId: this.tabContext.tabId}));
this.$copyToClipboardButton.on('click', () => this.triggerEvent(`copyImageToClipboard`, {ntxId: this.noteContext.ntxId}));
this.$uploadNewRevisionButton.on("click", () => {
this.$uploadNewRevisionInput.trigger("click");
@ -109,7 +109,7 @@ export default class ImagePropertiesWidget extends TabAwareWidget {
this.$widget.show();
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
this.$fileName.text(attributeMap.originalFileName || "?");
this.$fileSize.text(noteComplement.contentLength + " bytes");

View File

@ -271,7 +271,7 @@ export default class SearchDefinitionWidget extends TabAwareWidget {
toastService.showError(e.message);
}
this.triggerEvent('searchRefreshed', {tabId: this.tabContext.tabId});
this.triggerEvent('searchRefreshed', {ntxId: this.noteContext.ntxId});
}
async refreshSearchDefinitionCommand() {

View File

@ -23,7 +23,7 @@ export default class AbstractTextTypeWidget extends TypeWidget {
const noteId = this.getNoteIdFromImage(imgSrc);
if (noteId) {
appContext.tabManager.getActiveTabContext().setNote(noteId);
appContext.tabManager.getActiveNoteContext().setNote(noteId);
} else {
window.open(imgSrc, '_blank');
}

View File

@ -72,7 +72,7 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|| note.mime === 'text/x-sqlite;schema=trilium'
);
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
await this.spacedUpdate.allowUpdateWithoutChange(() => {
// CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)

View File

@ -61,7 +61,7 @@ export default class EmptyTypeWidget extends TypeWidget {
return false;
}
appContext.tabManager.getActiveTabContext().setNote(suggestion.notePath);
appContext.tabManager.getActiveNoteContext().setNote(suggestion.notePath);
});
noteAutocompleteService.showRecentNotes(this.$autoComplete);

View File

@ -53,7 +53,7 @@ export default class FileTypeWidget extends TypeWidget {
async doRefresh(note) {
this.$widget.show();
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
this.$previewContent.empty().hide();
this.$pdfPreview.attr('src', '').empty().hide();

View File

@ -62,8 +62,8 @@ class ImageTypeWidget extends TypeWidget {
this.$imageView.prop("src", `api/images/${note.noteId}/${note.title}?${imageHash}`);
}
copyImageToClipboardEvent({tabId}) {
if (!this.isTab(tabId)) {
copyImageToClipboardEvent({ntxId}) {
if (!this.isTab(ntxId)) {
return;
}

View File

@ -36,14 +36,14 @@ export default class ReadOnlyCodeTypeWidget extends TypeWidget {
this.$content = this.$widget.find('.note-detail-read-only-code-content');
this.$widget.find('.edit-code-note-button').on('click', () => {
this.tabContext.codePreviewDisabled = true;
this.noteContext.codePreviewDisabled = true;
this.triggerEvent('codePreviewDisabled', {tabContext: this.tabContext});
this.triggerEvent('codePreviewDisabled', {noteContext: this.noteContext});
});
}
async doRefresh(note) {
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
this.$content.text(noteComplement.content);
}

View File

@ -63,9 +63,9 @@ export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget {
this.$content = this.$widget.find('.note-detail-readonly-text-content');
this.$widget.find('.edit-text-note-button').on('click', () => {
this.tabContext.textPreviewDisabled = true;
this.noteContext.textPreviewDisabled = true;
this.triggerEvent('textPreviewDisabled', {tabContext: this.tabContext});
this.triggerEvent('textPreviewDisabled', {noteContext: this.noteContext});
});
this.setupImageOpening(true);

View File

@ -246,7 +246,7 @@ export default class RelationMapTypeWidget extends TypeWidget {
}
};
const noteComplement = await this.tabContext.getNoteComplement();
const noteComplement = await this.noteContext.getNoteComplement();
if (noteComplement.content) {
try {

View File

@ -38,7 +38,7 @@ export default class RenderTypeWidget extends TypeWidget {
}
renderActiveNoteEvent() {
if (this.tabContext.isActive()) {
if (this.noteContext.isActive()) {
this.refresh();
}
}

View File

@ -23,7 +23,7 @@ export default class TypeWidget extends TabAwareWidget {
await this.doRefresh(this.note);
this.triggerEvent('noteDetailRefreshed', {tabId: this.tabContext.tabId});
this.triggerEvent('noteDetailRefreshed', {ntxId: this.noteContext.ntxId});
}
}
@ -35,14 +35,14 @@ export default class TypeWidget extends TabAwareWidget {
focus() {}
textPreviewDisabledEvent({tabContext}) {
if (this.isTab(tabContext.tabId)) {
textPreviewDisabledEvent({noteContext}) {
if (this.isTab(noteContext.ntxId)) {
this.refresh();
}
}
codePreviewDisabledEvent({tabContext}) {
if (this.isTab(tabContext.tabId)) {
codePreviewDisabledEvent({noteContext}) {
if (this.isTab(noteContext.ntxId)) {
this.refresh();
}
}