mirror of
https://github.com/zadam/trilium.git
synced 2025-11-04 20:36:13 +01:00
spell check support + small options tabs reorganization
This commit is contained in:
@@ -88,7 +88,10 @@ app.use((req, res, next) => {
|
||||
|
||||
// error handler
|
||||
app.use((err, req, res, next) => {
|
||||
if (err && err.message && err.message.includes("Invalid package")) {
|
||||
if (err && err.message && (
|
||||
err.message.includes("Invalid package")
|
||||
|| (err.message.includes("Router not found for request") && err.message.includes("node_modules"))
|
||||
)) {
|
||||
// electron 6 outputs a lot of such errors which do not seem important
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -177,3 +177,7 @@ entrypoints.registerEntrypoints();
|
||||
noteTooltipService.setupGlobalTooltip();
|
||||
|
||||
noteAutocompleteService.init();
|
||||
|
||||
if (utils.isElectron()) {
|
||||
import("./services/spell_check.js").then(spellCheckService => spellCheckService.initSpellCheck());
|
||||
}
|
||||
@@ -19,8 +19,7 @@ export async function showDialog() {
|
||||
import('./options/appearance.js'),
|
||||
import('./options/code_notes.js'),
|
||||
import('./options/change_password.js'),
|
||||
import('./options/note_revisions.js'),
|
||||
import('./options/protected_session.js'),
|
||||
import('./options/other.js'),
|
||||
import('./options/sidebar.js'),
|
||||
import('./options/sync.js'),
|
||||
]))
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import server from "../../services/server.js";
|
||||
import infoService from "../../services/info.js";
|
||||
|
||||
export default class NoteRevisionsOptions {
|
||||
constructor() {
|
||||
this.$form = $("#note-revision-snapshot-time-interval-form");
|
||||
this.$timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
|
||||
|
||||
this.$form.submit(() => {
|
||||
const opts = { 'noteRevisionSnapshotTimeInterval': this.$timeInterval.val() };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
optionsLoaded(options) {
|
||||
this.$timeInterval.val(options['noteRevisionSnapshotTimeInterval']);
|
||||
}
|
||||
}
|
||||
54
src/public/javascripts/dialogs/options/other.js
Normal file
54
src/public/javascripts/dialogs/options/other.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import optionsService from "../../services/options.js";
|
||||
import server from "../../services/server.js";
|
||||
import infoService from "../../services/info.js";
|
||||
|
||||
export default class ProtectedSessionOptions {
|
||||
constructor() {
|
||||
this.$spellCheckEnabled = $("#spell-check-enabled");
|
||||
this.$spellCheckLanguageCode = $("#spell-check-language-code");
|
||||
|
||||
this.$protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
|
||||
this.$noteRevisionsTimeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
|
||||
|
||||
this.$spellCheckEnabled.change(() => {
|
||||
const opts = { 'spellCheckEnabled': this.$spellCheckEnabled.is(":checked") ? "true" : "false" };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this.$spellCheckLanguageCode.change(() => {
|
||||
const opts = { 'spellCheckLanguageCode': this.$spellCheckLanguageCode.val() };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this.$protectedSessionTimeout.change(() => {
|
||||
const protectedSessionTimeout = this.$protectedSessionTimeout.val();
|
||||
|
||||
server.put('options', { 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
|
||||
optionsService.reloadOptions();
|
||||
|
||||
infoService.showMessage("Options change have been saved.");
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this.$noteRevisionsTimeInterval.change(() => {
|
||||
const opts = { 'noteRevisionSnapshotTimeInterval': this.$noteRevisionsTimeInterval.val() };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
optionsLoaded(options) {
|
||||
this.$spellCheckEnabled.prop("checked", options['spellCheckEnabled'] === 'true');
|
||||
this.$spellCheckLanguageCode.val(options['spellCheckLanguageCode']);
|
||||
|
||||
this.$protectedSessionTimeout.val(options['protectedSessionTimeout']);
|
||||
this.$noteRevisionsTimeInterval.val(options['noteRevisionSnapshotTimeInterval']);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import optionsService from "../../services/options.js";
|
||||
import server from "../../services/server.js";
|
||||
import infoService from "../../services/info.js";
|
||||
|
||||
export default class ProtectedSessionOptions {
|
||||
constructor() {
|
||||
this.$form = $("#protected-session-timeout-form");
|
||||
this.$protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
|
||||
|
||||
this.$form.submit(() => this.save());
|
||||
}
|
||||
|
||||
optionsLoaded(options) {
|
||||
this.$protectedSessionTimeout.val(options['protectedSessionTimeout']);
|
||||
}
|
||||
|
||||
save() {
|
||||
const protectedSessionTimeout = this.$protectedSessionTimeout.val();
|
||||
|
||||
server.put('options', { 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
|
||||
optionsService.reloadOptions();
|
||||
|
||||
infoService.showMessage("Options change have been saved.");
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,11 @@ function reloadOptions() {
|
||||
return optionsReady;
|
||||
}
|
||||
|
||||
/** just waits for some options without triggering reload */
|
||||
/**
|
||||
* just waits for some options without triggering reload
|
||||
*
|
||||
* @return {Options}
|
||||
*/
|
||||
async function waitForOptions() {
|
||||
return await optionsReady;
|
||||
}
|
||||
|
||||
43
src/public/javascripts/services/spell_check.js
Normal file
43
src/public/javascripts/services/spell_check.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import optionsService from "./options.js";
|
||||
|
||||
export async function initSpellCheck() {
|
||||
const options = await optionsService.waitForOptions();
|
||||
|
||||
if (!options.is('spellCheckEnabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
||||
const {remote, shell} = require('electron');
|
||||
|
||||
const spellCheckHandler = new SpellCheckHandler();
|
||||
spellCheckHandler.attachToInput();
|
||||
|
||||
spellCheckHandler.switchLanguage(options.get('spellCheckLanguageCode'));
|
||||
|
||||
spellCheckHandler.currentSpellcheckerChanged.subscribe(() => {
|
||||
console.debug(`Detected language is ${spellCheckHandler.currentSpellcheckerLanguage}`);
|
||||
});
|
||||
|
||||
const contextMenuBuilder = new ContextMenuBuilder(spellCheckHandler, null, true, (menu, menuInfo) => {
|
||||
// There's no menu.remove(id) so this is a convoluted way of removing the 'Search with Google' menu item
|
||||
const oldItems = menu.items;
|
||||
menu.clear();
|
||||
oldItems.forEach(oldItem => {
|
||||
if (!oldItem.label.includes('Google')) {
|
||||
menu.append(oldItem);
|
||||
} else {
|
||||
menu.append(new remote.MenuItem({
|
||||
label: 'Search with DuckDuckGo',
|
||||
click: () => {
|
||||
shell.openExternal(`https://duckduckgo.com/?q=${encodeURIComponent(menuInfo.selectionText)}`);
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
new ContextMenuListener(async (info) => {
|
||||
await contextMenuBuilder.showPopupMenu(info);
|
||||
});
|
||||
}
|
||||
@@ -32,7 +32,9 @@ const ALLOWED_OPTIONS = [
|
||||
'similarNotesWidget',
|
||||
'editedNotesWidget',
|
||||
'calendarWidget',
|
||||
'codeNotesMimeTypes'
|
||||
'codeNotesMimeTypes',
|
||||
'spellCheckEnabled',
|
||||
'spellCheckLanguageCode'
|
||||
];
|
||||
|
||||
async function getOptions() {
|
||||
|
||||
@@ -4,7 +4,7 @@ const build = require('./build');
|
||||
const packageJson = require('../../package');
|
||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||
|
||||
const APP_DB_VERSION = 145;
|
||||
const APP_DB_VERSION = 146;
|
||||
const SYNC_VERSION = 10;
|
||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ async function initNotSyncedOptions(initialized, startNotePath = 'root', opts =
|
||||
await optionService.createOption('similarNotesWidget', '{"enabled":true,"expanded":true,"position":600}', false);
|
||||
|
||||
await optionService.createOption('initialized', initialized ? 'true' : 'false', false);
|
||||
|
||||
await optionService.createOption('spellCheckEnabled', 'true', false);
|
||||
await optionService.createOption('spellCheckLanguageCode', 'en-US', false);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -22,15 +22,12 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-change-password">Change password</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-protected-session">Protected session</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-note-revisions">Note revisions</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-sync-setup">Sync</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-other">Other</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-advanced">Advanced</a>
|
||||
</li>
|
||||
@@ -41,8 +38,7 @@
|
||||
<% include options/sidebar.ejs %>
|
||||
<% include options/code_notes.ejs %>
|
||||
<% include options/change_password.ejs %>
|
||||
<% include options/protected_session.ejs %>
|
||||
<% include options/note_revisions.ejs %>
|
||||
<% include options/other.ejs %>
|
||||
<% include options/sync.ejs %>
|
||||
<% include options/advanced.ejs %>
|
||||
</div>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<div id="options-note-revisions" class="tab-pane">
|
||||
<h4>Note revisions snapshot interval</h4>
|
||||
|
||||
<p>Note revision snapshot time interval is time in seconds after which new note revision will be created for the note.</p>
|
||||
|
||||
<form id="note-revision-snapshot-time-interval-form">
|
||||
<div class="form-group">
|
||||
<label for="note-revision-snapshot-time-interval-in-seconds">Note revision snapshot time interval (in seconds)</label>
|
||||
<input class="form-control" id="note-revision-snapshot-time-interval-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
|
||||
<button class="btn btn-secondary" type="button" data-help-page="Note-revisions">Help</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
44
src/views/dialogs/options/other.ejs
Normal file
44
src/views/dialogs/options/other.ejs
Normal file
@@ -0,0 +1,44 @@
|
||||
<div id="options-other" class="tab-pane">
|
||||
<div>
|
||||
<h4>Spell check</h4>
|
||||
|
||||
<p>These options apply only for desktop builds, browsers will use their own native spell check.</p>
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="spell-check-enabled">
|
||||
<label class="custom-control-label" for="spell-check-enabled">Enable spellcheck</label>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="spell-check-language-code">Language code</label>
|
||||
<input type="email" class="form-control" id="spell-check-language-code" placeholder="for example "en-US", "de-AT"">
|
||||
</div>
|
||||
|
||||
<p>Changes to the spell check options will take effect after application restart.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>Protected session timeout</h4>
|
||||
|
||||
<p>Protected session timeout is a time period after which the protected session is wiped out from
|
||||
browser's memory. This is measured from the last interaction with protected notes. See <a href="https://github.com/zadam/trilium/wiki/Protected-notes" class="external">wiki</a> for more info.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="protected-session-timeout-in-seconds">Protected session timeout (in seconds)</label>
|
||||
<input class="form-control" id="protected-session-timeout-in-seconds" type="number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>Note revisions snapshot interval</h4>
|
||||
|
||||
<p>Note revision snapshot time interval is time in seconds after which new note revision will be created for the note. See <a href="https://github.com/zadam/trilium/wiki/Note-revisions" class="external">wiki</a> for more info.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="note-revision-snapshot-time-interval-in-seconds">Note revision snapshot time interval (in seconds)</label>
|
||||
<input class="form-control" id="note-revision-snapshot-time-interval-in-seconds" type="number">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,19 +0,0 @@
|
||||
<div id="options-protected-session" class="tab-pane">
|
||||
<h4>Protected session timeout</h4>
|
||||
|
||||
<p>Protected session timeout is a time period after which the protected session is wiped out from
|
||||
browser's memory. This is measured from the last interaction with protected notes.</p>
|
||||
|
||||
<form id="protected-session-timeout-form">
|
||||
<div class="form-group">
|
||||
<label for="protected-session-timeout-in-seconds">Protected session timeout (in seconds)</label>
|
||||
<input class="form-control" id="protected-session-timeout-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
|
||||
<button class="btn btn-secondary" type="button" data-help-page="Protected-notes">Help</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
Reference in New Issue
Block a user