mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Tools: Apply rule @typescript-eslint/type-annotation-spacing
This commit is contained in:
parent
62feb7ff60
commit
d20694e52c
@ -115,6 +115,8 @@ module.exports = {
|
||||
'space-before-blocks': 'error',
|
||||
'spaced-comment': ['error', 'always'],
|
||||
'keyword-spacing': ['error', { 'before': true, 'after': true }],
|
||||
|
||||
'@typescript-eslint/type-annotation-spacing': ['error', { 'before': false, 'after': true }],
|
||||
},
|
||||
'plugins': [
|
||||
'react',
|
||||
|
@ -6,12 +6,12 @@ import executeSandboxCall from '@joplin/lib/services/plugins/utils/executeSandbo
|
||||
import Global from '@joplin/lib/services/plugins/api/Global';
|
||||
import mapEventHandlersToIds, { EventHandlers } from '@joplin/lib/services/plugins/utils/mapEventHandlersToIds';
|
||||
|
||||
function createConsoleWrapper(pluginId:string) {
|
||||
const wrapper:any = {};
|
||||
function createConsoleWrapper(pluginId: string) {
|
||||
const wrapper: any = {};
|
||||
|
||||
for (const n in console) {
|
||||
if (!console.hasOwnProperty(n)) continue;
|
||||
wrapper[n] = (...args:any[]) => {
|
||||
wrapper[n] = (...args: any[]) => {
|
||||
const newArgs = args.slice();
|
||||
newArgs.splice(0, 0, `Plugin "${pluginId}":`);
|
||||
return (console as any)[n](...newArgs);
|
||||
@ -30,7 +30,7 @@ function createConsoleWrapper(pluginId:string) {
|
||||
|
||||
export default class PluginRunner extends BasePluginRunner {
|
||||
|
||||
private eventHandlers_:EventHandlers = {};
|
||||
private eventHandlers_: EventHandlers = {};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@ -38,13 +38,13 @@ export default class PluginRunner extends BasePluginRunner {
|
||||
this.eventHandler = this.eventHandler.bind(this);
|
||||
}
|
||||
|
||||
private async eventHandler(eventHandlerId:string, args:any[]) {
|
||||
private async eventHandler(eventHandlerId: string, args: any[]) {
|
||||
const cb = this.eventHandlers_[eventHandlerId];
|
||||
return cb(...args);
|
||||
}
|
||||
|
||||
private newSandboxProxy(pluginId:string, sandbox:Global) {
|
||||
const target = async (path:string, args:any[]) => {
|
||||
private newSandboxProxy(pluginId: string, sandbox: Global) {
|
||||
const target = async (path: string, args: any[]) => {
|
||||
return executeSandboxCall(pluginId, sandbox, `joplin.${path}`, mapEventHandlersToIds(args, this.eventHandlers_), this.eventHandler);
|
||||
};
|
||||
|
||||
@ -54,8 +54,8 @@ export default class PluginRunner extends BasePluginRunner {
|
||||
};
|
||||
}
|
||||
|
||||
async run(plugin:Plugin, sandbox:Global):Promise<void> {
|
||||
return new Promise((resolve:Function, reject:Function) => {
|
||||
async run(plugin: Plugin, sandbox: Global): Promise<void> {
|
||||
return new Promise((resolve: Function, reject: Function) => {
|
||||
const onStarted = () => {
|
||||
plugin.off('started', onStarted);
|
||||
resolve();
|
||||
|
@ -5,7 +5,7 @@ const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('./tes
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
|
||||
function newTestMdToHtml(options:any = null) {
|
||||
function newTestMdToHtml(options: any = null) {
|
||||
options = {
|
||||
ResourceModel: {
|
||||
isResourceUrl: () => false,
|
||||
@ -19,7 +19,7 @@ function newTestMdToHtml(options:any = null) {
|
||||
|
||||
describe('MdToHtml', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
@ -39,7 +39,7 @@ describe('MdToHtml', function() {
|
||||
|
||||
// if (mdFilename !== 'sanitize_9.md') continue;
|
||||
|
||||
const mdToHtmlOptions:any = {
|
||||
const mdToHtmlOptions: any = {
|
||||
bodyOnly: true,
|
||||
};
|
||||
|
||||
@ -83,7 +83,7 @@ describe('MdToHtml', function() {
|
||||
}));
|
||||
|
||||
it('should return enabled plugin assets', asyncTest(async () => {
|
||||
const pluginOptions:any = {};
|
||||
const pluginOptions: any = {};
|
||||
const pluginNames = MdToHtml.pluginNames();
|
||||
|
||||
for (const n of pluginNames) pluginOptions[n] = { enabled: false };
|
||||
|
@ -4,7 +4,7 @@ const { expectThrow } = require('./test-utils.js');
|
||||
|
||||
// On Windows, path.resolve is going to convert a path such as
|
||||
// /tmp/file.txt to c:\tmp\file.txt
|
||||
function platformPath(path:string) {
|
||||
function platformPath(path: string) {
|
||||
if (shim.isWindows()) {
|
||||
return `c:${path.replace(/\//g, '\\')}`;
|
||||
} else {
|
||||
|
@ -4,7 +4,7 @@ const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('../..
|
||||
|
||||
describe('services_plugins_sandboxProxy', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
@ -16,9 +16,9 @@ describe('services_plugins_sandboxProxy', function() {
|
||||
args: any[],
|
||||
}
|
||||
|
||||
const results:Result[] = [];
|
||||
const results: Result[] = [];
|
||||
|
||||
const target:Target = (path:string, args:any[]) => {
|
||||
const target: Target = (path: string, args: any[]) => {
|
||||
results.push({ path, args });
|
||||
};
|
||||
|
||||
@ -39,9 +39,9 @@ describe('services_plugins_sandboxProxy', function() {
|
||||
args: any[],
|
||||
}
|
||||
|
||||
const results:Result[] = [];
|
||||
const results: Result[] = [];
|
||||
|
||||
const target:Target = (path:string, args:any[]) => {
|
||||
const target: Target = (path: string, args: any[]) => {
|
||||
results.push({ path, args });
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,7 @@ interface TestCommand {
|
||||
runtime: CommandRuntime,
|
||||
}
|
||||
|
||||
function newService():CommandService {
|
||||
function newService(): CommandService {
|
||||
const service = new CommandService();
|
||||
const mockStore = {
|
||||
getState: () => {
|
||||
@ -21,12 +21,12 @@ function newService():CommandService {
|
||||
return service;
|
||||
}
|
||||
|
||||
function createCommand(name:string, options:any):TestCommand {
|
||||
const declaration:CommandDeclaration = {
|
||||
function createCommand(name: string, options: any): TestCommand {
|
||||
const declaration: CommandDeclaration = {
|
||||
name: name,
|
||||
};
|
||||
|
||||
const runtime:CommandRuntime = {
|
||||
const runtime: CommandRuntime = {
|
||||
execute: options.execute,
|
||||
};
|
||||
|
||||
@ -35,7 +35,7 @@ function createCommand(name:string, options:any):TestCommand {
|
||||
return { declaration, runtime };
|
||||
}
|
||||
|
||||
function registerCommand(service:CommandService, cmd:TestCommand) {
|
||||
function registerCommand(service: CommandService, cmd: TestCommand) {
|
||||
service.registerDeclaration(cmd.declaration);
|
||||
service.registerRuntime(cmd.declaration.name, cmd.runtime);
|
||||
}
|
||||
@ -55,7 +55,7 @@ describe('services_CommandService', function() {
|
||||
const service = newService();
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(service);
|
||||
|
||||
const executedCommands:string[] = [];
|
||||
const executedCommands: string[] = [];
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: () => {
|
||||
@ -172,9 +172,9 @@ describe('services_CommandService', function() {
|
||||
execute: () => {},
|
||||
}));
|
||||
|
||||
const clickedCommands:string[] = [];
|
||||
const clickedCommands: string[] = [];
|
||||
|
||||
const onClick = (commandName:string) => {
|
||||
const onClick = (commandName: string) => {
|
||||
clickedCommands.push(commandName);
|
||||
};
|
||||
|
||||
@ -234,7 +234,7 @@ describe('services_CommandService', function() {
|
||||
let propValue = null;
|
||||
|
||||
registerCommand(service, createCommand('test1', {
|
||||
execute: (_context:any, greeting:string) => {
|
||||
execute: (_context: any, greeting: string) => {
|
||||
propValue = greeting;
|
||||
},
|
||||
}));
|
||||
|
@ -19,7 +19,7 @@ function exportDir() {
|
||||
return `${__dirname}/export`;
|
||||
}
|
||||
|
||||
function fieldsEqual(model1:any, model2:any, fieldNames:string[]) {
|
||||
function fieldsEqual(model1: any, model2: any, fieldNames: string[]) {
|
||||
for (let i = 0; i < fieldNames.length; i++) {
|
||||
const f = fieldNames[i];
|
||||
expect(model1[f]).toBe(model2[f], `For key ${f}`);
|
||||
@ -86,7 +86,7 @@ describe('services_InteropService', function() {
|
||||
await service.import({ path: filePath });
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.map((f:any) => f.title).sort().join(' - ')).toBe('folder - folder (1)');
|
||||
expect(allFolders.map((f: any) => f.title).sort().join(' - ')).toBe('folder - folder (1)');
|
||||
}));
|
||||
|
||||
it('should import folders, and only de-duplicate titles when needed', asyncTest(async () => {
|
||||
@ -447,14 +447,14 @@ describe('services_InteropService', function() {
|
||||
sourcePath: '',
|
||||
};
|
||||
|
||||
const module:Module = {
|
||||
const module: Module = {
|
||||
type: ModuleType.Importer,
|
||||
description: 'Test Import Module',
|
||||
format: 'testing',
|
||||
fileExtensions: ['test'],
|
||||
isCustom: true,
|
||||
|
||||
onExec: async (context:CustomImportContext) => {
|
||||
onExec: async (context: CustomImportContext) => {
|
||||
result.hasBeenExecuted = true;
|
||||
result.sourcePath = context.sourcePath;
|
||||
},
|
||||
@ -479,7 +479,7 @@ describe('services_InteropService', function() {
|
||||
|
||||
const filePath = `${exportDir()}/example.test`;
|
||||
|
||||
const result:any = {
|
||||
const result: any = {
|
||||
destPath: '',
|
||||
itemTypes: [],
|
||||
items: [],
|
||||
@ -488,28 +488,28 @@ describe('services_InteropService', function() {
|
||||
closeCalled: false,
|
||||
};
|
||||
|
||||
const module:Module = {
|
||||
const module: Module = {
|
||||
type: ModuleType.Exporter,
|
||||
description: 'Test Export Module',
|
||||
format: 'testing',
|
||||
fileExtensions: ['test'],
|
||||
isCustom: true,
|
||||
|
||||
onInit: async (context:CustomExportContext) => {
|
||||
onInit: async (context: CustomExportContext) => {
|
||||
result.destPath = context.destPath;
|
||||
},
|
||||
|
||||
onProcessItem: async (_context:CustomExportContext, itemType:number, item:any) => {
|
||||
onProcessItem: async (_context: CustomExportContext, itemType: number, item: any) => {
|
||||
result.itemTypes.push(itemType);
|
||||
result.items.push(item);
|
||||
},
|
||||
|
||||
onProcessResource: async (_context:CustomExportContext, resource:any, filePath:string) => {
|
||||
onProcessResource: async (_context: CustomExportContext, resource: any, filePath: string) => {
|
||||
result.resources.push(resource);
|
||||
result.filePaths.push(filePath);
|
||||
},
|
||||
|
||||
onClose: async (_context:CustomExportContext) => {
|
||||
onClose: async (_context: CustomExportContext) => {
|
||||
result.closeCalled = true;
|
||||
},
|
||||
};
|
||||
@ -524,7 +524,7 @@ describe('services_InteropService', function() {
|
||||
expect(result.destPath).toBe(filePath);
|
||||
expect(result.itemTypes.sort().join('_')).toBe('1_1_2_4');
|
||||
expect(result.items.length).toBe(4);
|
||||
expect(result.items.map((o:any) => o.title).sort().join('_')).toBe('folder1_note1_note2_photo.jpg');
|
||||
expect(result.items.map((o: any) => o.title).sort().join('_')).toBe('folder1_note1_note2_photo.jpg');
|
||||
expect(result.resources.length).toBe(1);
|
||||
expect(result.resources[0].title).toBe('photo.jpg');
|
||||
expect(result.filePaths.length).toBe(1);
|
||||
|
@ -79,7 +79,7 @@ describe('services_PluginService', function() {
|
||||
|
||||
const allFolders = await Folder.all();
|
||||
expect(allFolders.length).toBe(2);
|
||||
expect(allFolders.map((f:any) => f.title).sort().join(', ')).toBe('multi - simple1, multi - simple2');
|
||||
expect(allFolders.map((f: any) => f.title).sort().join(', ')).toBe('multi - simple1, multi - simple2');
|
||||
}));
|
||||
|
||||
it('should load plugins from JS bundles', asyncTest(async () => {
|
||||
|
@ -4,7 +4,7 @@ import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
const { db, asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
|
||||
|
||||
function describeIfCompatible(name:string, fn:any, elseFn:any) {
|
||||
function describeIfCompatible(name: string, fn: any, elseFn: any) {
|
||||
if (['win32', 'darwin'].includes(shim.platformName())) {
|
||||
return describe(name, fn);
|
||||
} else {
|
||||
@ -14,14 +14,14 @@ function describeIfCompatible(name:string, fn:any, elseFn:any) {
|
||||
|
||||
describeIfCompatible('services_KeychainService', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
await setupDatabaseAndSynchronizer(1, { keychainEnabled: true });
|
||||
await switchClient(1, { keychainEnabled: true });
|
||||
await Setting.deleteKeychainPasswords();
|
||||
done();
|
||||
});
|
||||
|
||||
afterEach(async (done:Function) => {
|
||||
afterEach(async (done: Function) => {
|
||||
await Setting.deleteKeychainPasswords();
|
||||
done();
|
||||
});
|
||||
|
@ -11,7 +11,7 @@ const NoteTag = require('@joplin/lib/models/NoteTag');
|
||||
const ResourceService = require('@joplin/lib/services/ResourceService').default;
|
||||
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine');
|
||||
|
||||
async function msleep(ms:number) {
|
||||
async function msleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
shim.setTimeout(() => {
|
||||
resolve();
|
||||
@ -19,7 +19,7 @@ async function msleep(ms:number) {
|
||||
});
|
||||
}
|
||||
|
||||
const createFolderForPagination = async (num:number, time:number) => {
|
||||
const createFolderForPagination = async (num: number, time: number) => {
|
||||
await Folder.save({
|
||||
title: `folder${num}`,
|
||||
updated_time: time,
|
||||
@ -27,7 +27,7 @@ const createFolderForPagination = async (num:number, time:number) => {
|
||||
}, { autoTimestamp: false });
|
||||
};
|
||||
|
||||
const createNoteForPagination = async (num:number, time:number) => {
|
||||
const createNoteForPagination = async (num: number, time: number) => {
|
||||
await Note.save({
|
||||
title: `note${num}`,
|
||||
body: `noteBody${num}`,
|
||||
@ -36,7 +36,7 @@ const createNoteForPagination = async (num:number, time:number) => {
|
||||
}, { autoTimestamp: false });
|
||||
};
|
||||
|
||||
let api:Api = null;
|
||||
let api: Api = null;
|
||||
|
||||
describe('services_rest_Api', function() {
|
||||
|
||||
@ -158,7 +158,7 @@ describe('services_rest_Api', function() {
|
||||
}));
|
||||
|
||||
it('should allow setting note properties', asyncTest(async () => {
|
||||
let response:any = null;
|
||||
let response: any = null;
|
||||
const f = await Folder.save({ title: 'mon carnet' });
|
||||
|
||||
response = await api.route(RequestMethod.POST, 'notes', null, JSON.stringify({
|
||||
|
@ -3,7 +3,7 @@ import LockHandler, { LockType, LockHandlerOptions, Lock } from '@joplin/lib/ser
|
||||
|
||||
const { isNetworkSyncTarget, asyncTest, fileApi, setupDatabaseAndSynchronizer, synchronizer, switchClient, msleep, expectThrow, expectNotThrow } = require('./test-utils.js');
|
||||
|
||||
process.on('unhandledRejection', (reason:any, p:any) => {
|
||||
process.on('unhandledRejection', (reason: any, p: any) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
@ -14,13 +14,13 @@ process.on('unhandledRejection', (reason:any, p:any) => {
|
||||
// For that reason we add this multiplier for non-memory sync targets.
|
||||
const timeoutMultipler = isNetworkSyncTarget() ? 100 : 1;
|
||||
|
||||
let lockHandler_:LockHandler = null;
|
||||
let lockHandler_: LockHandler = null;
|
||||
|
||||
function newLockHandler(options:LockHandlerOptions = null):LockHandler {
|
||||
function newLockHandler(options: LockHandlerOptions = null): LockHandler {
|
||||
return new LockHandler(fileApi(), options);
|
||||
}
|
||||
|
||||
function lockHandler():LockHandler {
|
||||
function lockHandler(): LockHandler {
|
||||
if (lockHandler_) return lockHandler_;
|
||||
lockHandler_ = new LockHandler(fileApi());
|
||||
return lockHandler_;
|
||||
@ -28,7 +28,7 @@ function lockHandler():LockHandler {
|
||||
|
||||
describe('synchronizer_LockHandler', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
// logger.setLevel(Logger.LEVEL_WARN);
|
||||
lockHandler_ = null;
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
@ -96,8 +96,8 @@ describe('synchronizer_LockHandler', function() {
|
||||
});
|
||||
|
||||
const lock = await handler.acquireLock(LockType.Sync, 'desktop', '111');
|
||||
let autoLockError:any = null;
|
||||
handler.startAutoLockRefresh(lock, (error:any) => {
|
||||
let autoLockError: any = null;
|
||||
handler.startAutoLockRefresh(lock, (error: any) => {
|
||||
autoLockError = error;
|
||||
});
|
||||
|
||||
@ -144,8 +144,8 @@ describe('synchronizer_LockHandler', function() {
|
||||
const lockHandler = newLockHandler();
|
||||
|
||||
{
|
||||
const lock1:Lock = { type: LockType.Exclusive, clientId: '1', clientType: 'd' };
|
||||
const lock2:Lock = { type: LockType.Exclusive, clientId: '2', clientType: 'd' };
|
||||
const lock1: Lock = { type: LockType.Exclusive, clientId: '1', clientType: 'd' };
|
||||
const lock2: Lock = { type: LockType.Exclusive, clientId: '2', clientType: 'd' };
|
||||
await lockHandler.saveLock_(lock1);
|
||||
await msleep(100);
|
||||
await lockHandler.saveLock_(lock2);
|
||||
|
@ -15,43 +15,43 @@ const MasterKey = require('@joplin/lib/models/MasterKey');
|
||||
|
||||
const specTimeout = 60000 * 10; // Nextcloud tests can be slow
|
||||
|
||||
let lockHandler_:LockHandler = null;
|
||||
let migrationHandler_:MigrationHandler = null;
|
||||
let lockHandler_: LockHandler = null;
|
||||
let migrationHandler_: MigrationHandler = null;
|
||||
|
||||
function lockHandler():LockHandler {
|
||||
function lockHandler(): LockHandler {
|
||||
if (lockHandler_) return lockHandler_;
|
||||
lockHandler_ = new LockHandler(fileApi());
|
||||
return lockHandler_;
|
||||
}
|
||||
|
||||
function migrationHandler(clientId:string = 'abcd'):MigrationHandler {
|
||||
function migrationHandler(clientId: string = 'abcd'): MigrationHandler {
|
||||
if (migrationHandler_) return migrationHandler_;
|
||||
migrationHandler_ = new MigrationHandler(fileApi(), lockHandler(), 'desktop', clientId);
|
||||
return migrationHandler_;
|
||||
}
|
||||
|
||||
interface MigrationTests {
|
||||
[key:string]: Function;
|
||||
[key: string]: Function;
|
||||
}
|
||||
|
||||
const migrationTests:MigrationTests = {
|
||||
const migrationTests: MigrationTests = {
|
||||
2: async function() {
|
||||
const items = (await fileApi().list('', { includeHidden: true })).items;
|
||||
expect(items.filter((i:any) => i.path === '.resource' && i.isDir).length).toBe(1);
|
||||
expect(items.filter((i:any) => i.path === 'locks' && i.isDir).length).toBe(1);
|
||||
expect(items.filter((i:any) => i.path === 'temp' && i.isDir).length).toBe(1);
|
||||
expect(items.filter((i:any) => i.path === 'info.json' && !i.isDir).length).toBe(1);
|
||||
expect(items.filter((i: any) => i.path === '.resource' && i.isDir).length).toBe(1);
|
||||
expect(items.filter((i: any) => i.path === 'locks' && i.isDir).length).toBe(1);
|
||||
expect(items.filter((i: any) => i.path === 'temp' && i.isDir).length).toBe(1);
|
||||
expect(items.filter((i: any) => i.path === 'info.json' && !i.isDir).length).toBe(1);
|
||||
|
||||
const versionForOldClients = await fileApi().get('.sync/version.txt');
|
||||
expect(versionForOldClients).toBe('2');
|
||||
},
|
||||
};
|
||||
|
||||
let previousSyncTargetName:string = '';
|
||||
let previousSyncTargetName: string = '';
|
||||
|
||||
describe('synchronizer_MigrationHandler', function() {
|
||||
|
||||
beforeEach(async (done:Function) => {
|
||||
beforeEach(async (done: Function) => {
|
||||
// To test the migrations, we have to use the filesystem sync target
|
||||
// because the sync target snapshots are plain files. Eventually
|
||||
// it should be possible to copy a filesystem target to memory
|
||||
@ -65,7 +65,7 @@ describe('synchronizer_MigrationHandler', function() {
|
||||
done();
|
||||
});
|
||||
|
||||
afterEach(async (done:Function) => {
|
||||
afterEach(async (done: Function) => {
|
||||
setSyncTargetName(previousSyncTargetName);
|
||||
done();
|
||||
});
|
||||
@ -74,8 +74,8 @@ describe('synchronizer_MigrationHandler', function() {
|
||||
// Check that basic folders "locks" and "temp" are created for new sync targets.
|
||||
await migrationHandler().upgrade(1);
|
||||
const result = await fileApi().list();
|
||||
expect(result.items.filter((i:any) => i.path === Dirnames.Locks).length).toBe(1);
|
||||
expect(result.items.filter((i:any) => i.path === Dirnames.Temp).length).toBe(1);
|
||||
expect(result.items.filter((i: any) => i.path === Dirnames.Locks).length).toBe(1);
|
||||
expect(result.items.filter((i: any) => i.path === Dirnames.Temp).length).toBe(1);
|
||||
}), specTimeout);
|
||||
|
||||
it('should not allow syncing if the sync target is out-dated', asyncTest(async () => {
|
||||
|
@ -19,19 +19,19 @@ interface PluginWindows {
|
||||
|
||||
export default class ElectronAppWrapper {
|
||||
|
||||
private logger_:Logger = null;
|
||||
private electronApp_:any;
|
||||
private env_:string;
|
||||
private isDebugMode_:boolean;
|
||||
private profilePath_:string;
|
||||
private win_:any = null;
|
||||
private willQuitApp_:boolean = false;
|
||||
private tray_:any = null;
|
||||
private buildDir_:string = null;
|
||||
private rendererProcessQuitReply_:RendererProcessQuitReply = null;
|
||||
private pluginWindows_:PluginWindows = {};
|
||||
private logger_: Logger = null;
|
||||
private electronApp_: any;
|
||||
private env_: string;
|
||||
private isDebugMode_: boolean;
|
||||
private profilePath_: string;
|
||||
private win_: any = null;
|
||||
private willQuitApp_: boolean = false;
|
||||
private tray_: any = null;
|
||||
private buildDir_: string = null;
|
||||
private rendererProcessQuitReply_: RendererProcessQuitReply = null;
|
||||
private pluginWindows_: PluginWindows = {};
|
||||
|
||||
constructor(electronApp:any, env:string, profilePath:string, isDebugMode:boolean) {
|
||||
constructor(electronApp: any, env: string, profilePath: string, isDebugMode: boolean) {
|
||||
this.electronApp_ = electronApp;
|
||||
this.env_ = env;
|
||||
this.isDebugMode_ = isDebugMode;
|
||||
@ -42,7 +42,7 @@ export default class ElectronAppWrapper {
|
||||
return this.electronApp_;
|
||||
}
|
||||
|
||||
setLogger(v:Logger) {
|
||||
setLogger(v: Logger) {
|
||||
this.logger_ = v;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ export default class ElectronAppWrapper {
|
||||
const windowStateKeeper = require('electron-window-state');
|
||||
|
||||
|
||||
const stateOptions:any = {
|
||||
const stateOptions: any = {
|
||||
defaultWidth: Math.round(0.8 * screen.getPrimaryDisplay().workArea.width),
|
||||
defaultHeight: Math.round(0.8 * screen.getPrimaryDisplay().workArea.height),
|
||||
file: `window-state-${this.env_}.json`,
|
||||
@ -76,7 +76,7 @@ export default class ElectronAppWrapper {
|
||||
// Load the previous state with fallback to defaults
|
||||
const windowState = windowStateKeeper(stateOptions);
|
||||
|
||||
const windowOptions:any = {
|
||||
const windowOptions: any = {
|
||||
x: windowState.x,
|
||||
y: windowState.y,
|
||||
width: windowState.width,
|
||||
@ -128,7 +128,7 @@ export default class ElectronAppWrapper {
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
this.win_.on('close', (event:any) => {
|
||||
this.win_.on('close', (event: any) => {
|
||||
// If it's on macOS, the app is completely closed only if the user chooses to close the app (willQuitApp_ will be true)
|
||||
// otherwise the window is simply hidden, and will be re-open once the app is "activated" (which happens when the
|
||||
// user clicks on the icon in the task bar).
|
||||
@ -176,7 +176,7 @@ export default class ElectronAppWrapper {
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('asynchronous-message', (_event:any, message:string, args:any) => {
|
||||
ipcMain.on('asynchronous-message', (_event: any, message: string, args: any) => {
|
||||
if (message === 'appCloseReply') {
|
||||
// We got the response from the renderer process:
|
||||
// save the response and try quit again.
|
||||
@ -187,7 +187,7 @@ export default class ElectronAppWrapper {
|
||||
|
||||
// This handler receives IPC messages from a plugin or from the main window,
|
||||
// and forwards it to the main window or the plugin window.
|
||||
ipcMain.on('pluginMessage', (_event:any, message:PluginMessage) => {
|
||||
ipcMain.on('pluginMessage', (_event: any, message: PluginMessage) => {
|
||||
if (message.target === 'mainWindow') {
|
||||
this.win_.webContents.send('pluginMessage', message);
|
||||
}
|
||||
@ -216,7 +216,7 @@ export default class ElectronAppWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
registerPluginWindow(pluginId:string, window:any) {
|
||||
registerPluginWindow(pluginId: string, window: any) {
|
||||
this.pluginWindows_[pluginId] = window;
|
||||
}
|
||||
|
||||
@ -278,7 +278,7 @@ export default class ElectronAppWrapper {
|
||||
}
|
||||
|
||||
// Note: this must be called only after the "ready" event of the app has been dispatched
|
||||
createTray(contextMenu:any) {
|
||||
createTray(contextMenu: any) {
|
||||
try {
|
||||
this.tray_ = new Tray(`${this.buildDir()}/icons/${this.trayIconFilename_()}`);
|
||||
this.tray_.setToolTip(this.electronApp_.name);
|
||||
|
@ -23,10 +23,10 @@ interface ExportNoteOptions {
|
||||
|
||||
export default class InteropServiceHelper {
|
||||
|
||||
private static async exportNoteToHtmlFile(noteId:string, exportOptions:ExportNoteOptions) {
|
||||
private static async exportNoteToHtmlFile(noteId: string, exportOptions: ExportNoteOptions) {
|
||||
const tempFile = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}.html`;
|
||||
|
||||
const fullExportOptions:ExportOptions = Object.assign({}, {
|
||||
const fullExportOptions: ExportOptions = Object.assign({}, {
|
||||
path: tempFile,
|
||||
format: 'html',
|
||||
target: FileSystemItem.File,
|
||||
@ -41,9 +41,9 @@ export default class InteropServiceHelper {
|
||||
return tempFile;
|
||||
}
|
||||
|
||||
private static async exportNoteTo_(target:string, noteId:string, options:ExportNoteOptions = {}) {
|
||||
let win:any = null;
|
||||
let htmlFile:string = null;
|
||||
private static async exportNoteTo_(target: string, noteId: string, options: ExportNoteOptions = {}) {
|
||||
let win: any = null;
|
||||
let htmlFile: string = null;
|
||||
|
||||
const cleanup = () => {
|
||||
if (win) win.destroy();
|
||||
@ -87,7 +87,7 @@ export default class InteropServiceHelper {
|
||||
// Maybe can be fixed by doing everything from main process?
|
||||
// i.e. creating a function `print()` that takes the `htmlFile` variable as input.
|
||||
|
||||
win.webContents.print(options, (success:boolean, reason:string) => {
|
||||
win.webContents.print(options, (success: boolean, reason: string) => {
|
||||
// TODO: This is correct but broken in Electron 4. Need to upgrade to 5+
|
||||
// It calls the callback right away with "false" even if the document hasn't be print yet.
|
||||
|
||||
@ -112,15 +112,15 @@ export default class InteropServiceHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static async exportNoteToPdf(noteId:string, options:ExportNoteOptions = {}) {
|
||||
public static async exportNoteToPdf(noteId: string, options: ExportNoteOptions = {}) {
|
||||
return this.exportNoteTo_('pdf', noteId, options);
|
||||
}
|
||||
|
||||
public static async printNote(noteId:string, options:ExportNoteOptions = {}) {
|
||||
public static async printNote(noteId: string, options: ExportNoteOptions = {}) {
|
||||
return this.exportNoteTo_('printer', noteId, options);
|
||||
}
|
||||
|
||||
public static async defaultFilename(noteId:string, fileExtension:string) {
|
||||
public static async defaultFilename(noteId: string, fileExtension: string) {
|
||||
// Default filename is just the date
|
||||
const date = time.formatMsToLocal(new Date().getTime(), time.dateFormat());
|
||||
let filename = friendlySafeFilename(`${date}`, 100);
|
||||
@ -134,7 +134,7 @@ export default class InteropServiceHelper {
|
||||
return `${filename}.${fileExtension}`;
|
||||
}
|
||||
|
||||
public static async export(_dispatch:Function, module:Module, options:ExportNoteOptions = null) {
|
||||
public static async export(_dispatch: Function, module: Module, options: ExportNoteOptions = null) {
|
||||
if (!options) options = {};
|
||||
|
||||
let path = null;
|
||||
@ -157,7 +157,7 @@ export default class InteropServiceHelper {
|
||||
|
||||
CommandService.instance().execute('showModalMessage', _('Exporting to "%s" as "%s" format. Please wait...', path, module.format));
|
||||
|
||||
const exportOptions:ExportOptions = {};
|
||||
const exportOptions: ExportOptions = {};
|
||||
exportOptions.path = path;
|
||||
exportOptions.format = module.format;
|
||||
exportOptions.modulePath = module.path;
|
||||
|
@ -118,7 +118,7 @@ export interface AppState extends State {
|
||||
watchedResources: any,
|
||||
}
|
||||
|
||||
const appDefaultState:AppState = {
|
||||
const appDefaultState: AppState = {
|
||||
...defaultState,
|
||||
route: {
|
||||
type: 'NAV_GO',
|
||||
@ -154,7 +154,7 @@ class Application extends BaseApplication {
|
||||
return `${Setting.value('profileDir')}/log-autoupdater.txt`;
|
||||
}
|
||||
|
||||
reducer(state:AppState = appDefaultState, action:any) {
|
||||
reducer(state: AppState = appDefaultState, action: any) {
|
||||
let newState = state;
|
||||
|
||||
try {
|
||||
@ -200,7 +200,7 @@ class Application extends BaseApplication {
|
||||
case 'NOTE_VISIBLE_PANES_TOGGLE':
|
||||
|
||||
{
|
||||
const getNextLayout = (currentLayout:any) => {
|
||||
const getNextLayout = (currentLayout: any) => {
|
||||
currentLayout = panes.length === 2 ? 'both' : currentLayout[0];
|
||||
|
||||
let paneOptions;
|
||||
@ -345,7 +345,7 @@ class Application extends BaseApplication {
|
||||
return newState;
|
||||
}
|
||||
|
||||
toggleDevTools(visible:boolean) {
|
||||
toggleDevTools(visible: boolean) {
|
||||
if (visible) {
|
||||
bridge().openDevTools();
|
||||
} else {
|
||||
@ -353,7 +353,7 @@ class Application extends BaseApplication {
|
||||
}
|
||||
}
|
||||
|
||||
async generalMiddleware(store:any, next:any, action:any) {
|
||||
async generalMiddleware(store: any, next: any, action: any) {
|
||||
if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'locale' || action.type == 'SETTING_UPDATE_ALL') {
|
||||
setLocale(Setting.value('locale'));
|
||||
// The bridge runs within the main process, with its own instance of locale.js
|
||||
@ -459,14 +459,14 @@ class Application extends BaseApplication {
|
||||
// The context menu must be setup in renderer process because that's where
|
||||
// the spell checker service lives.
|
||||
require('electron-context-menu')({
|
||||
shouldShowMenu: (_event:any, params:any) => {
|
||||
shouldShowMenu: (_event: any, params: any) => {
|
||||
// params.inputFieldType === 'none' when right-clicking the text editor. This is a bit of a hack to detect it because in this
|
||||
// case we don't want to use the built-in context menu but a custom one.
|
||||
return params.isEditable && params.inputFieldType !== 'none';
|
||||
},
|
||||
|
||||
menu: (actions:any, props:any) => {
|
||||
const spellCheckerMenuItems = SpellCheckerService.instance().contextMenuItems(props.misspelledWord, props.dictionarySuggestions).map((item:any) => new MenuItem(item));
|
||||
menu: (actions: any, props: any) => {
|
||||
const spellCheckerMenuItems = SpellCheckerService.instance().contextMenuItems(props.misspelledWord, props.dictionarySuggestions).map((item: any) => new MenuItem(item));
|
||||
|
||||
const output = [
|
||||
actions.cut(),
|
||||
@ -480,7 +480,7 @@ class Application extends BaseApplication {
|
||||
});
|
||||
}
|
||||
|
||||
async loadCustomCss(filePath:string) {
|
||||
async loadCustomCss(filePath: string) {
|
||||
let cssString = '';
|
||||
if (await fs.pathExists(filePath)) {
|
||||
try {
|
||||
@ -497,7 +497,7 @@ class Application extends BaseApplication {
|
||||
return cssString;
|
||||
}
|
||||
|
||||
async start(argv:string[]):Promise<any> {
|
||||
async start(argv: string[]): Promise<any> {
|
||||
const electronIsDev = require('electron-is-dev');
|
||||
|
||||
// If running inside a package, the command line, instead of being "node.exe <path> <flags>" is "joplin.exe <flags>" so
|
||||
@ -527,7 +527,7 @@ class Application extends BaseApplication {
|
||||
AlarmService.setDriver(new AlarmServiceDriverNode({ appName: packageInfo.build.appId }));
|
||||
AlarmService.setLogger(reg.logger());
|
||||
|
||||
reg.setShowErrorMessageBoxHandler((message:string) => { bridge().showErrorMessageBox(message); });
|
||||
reg.setShowErrorMessageBoxHandler((message: string) => { bridge().showErrorMessageBox(message); });
|
||||
|
||||
if (Setting.value('flagOpenDevTools')) {
|
||||
bridge().openDevTools();
|
||||
@ -672,7 +672,7 @@ class Application extends BaseApplication {
|
||||
ExternalEditWatcher.instance().setLogger(reg.logger());
|
||||
ExternalEditWatcher.instance().dispatch = this.store().dispatch;
|
||||
|
||||
ResourceEditWatcher.instance().initialize(reg.logger(), (action:any) => { this.store().dispatch(action); });
|
||||
ResourceEditWatcher.instance().initialize(reg.logger(), (action: any) => { this.store().dispatch(action); });
|
||||
|
||||
RevisionService.instance().runInBackground();
|
||||
|
||||
@ -705,7 +705,7 @@ class Application extends BaseApplication {
|
||||
|
||||
try {
|
||||
if (Setting.value('plugins.devPluginPaths')) {
|
||||
const paths = Setting.value('plugins.devPluginPaths').split(',').map((p:string) => p.trim());
|
||||
const paths = Setting.value('plugins.devPluginPaths').split(',').map((p: string) => p.trim());
|
||||
await PluginService.instance().loadAndRunPlugins(paths);
|
||||
}
|
||||
|
||||
@ -732,7 +732,7 @@ class Application extends BaseApplication {
|
||||
|
||||
}
|
||||
|
||||
let application_:Application = null;
|
||||
let application_: Application = null;
|
||||
|
||||
function app() {
|
||||
if (!application_) application_ = new Application();
|
||||
|
@ -11,15 +11,15 @@ interface LastSelectedPath {
|
||||
}
|
||||
|
||||
interface LastSelectedPaths {
|
||||
[key:string]: LastSelectedPath,
|
||||
[key: string]: LastSelectedPath,
|
||||
}
|
||||
|
||||
export class Bridge {
|
||||
|
||||
private electronWrapper_:ElectronAppWrapper;
|
||||
private lastSelectedPaths_:LastSelectedPaths;
|
||||
private electronWrapper_: ElectronAppWrapper;
|
||||
private lastSelectedPaths_: LastSelectedPaths;
|
||||
|
||||
constructor(electronWrapper:ElectronAppWrapper) {
|
||||
constructor(electronWrapper: ElectronAppWrapper) {
|
||||
this.electronWrapper_ = electronWrapper;
|
||||
this.lastSelectedPaths_ = {
|
||||
file: null,
|
||||
@ -43,11 +43,11 @@ export class Bridge {
|
||||
return this.electronWrapper_.window();
|
||||
}
|
||||
|
||||
showItemInFolder(fullPath:string) {
|
||||
showItemInFolder(fullPath: string) {
|
||||
return require('electron').shell.showItemInFolder(toSystemSlashes(fullPath));
|
||||
}
|
||||
|
||||
newBrowserWindow(options:any) {
|
||||
newBrowserWindow(options: any) {
|
||||
return new BrowserWindow(options);
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ export class Bridge {
|
||||
return { width: s[0], height: s[1] };
|
||||
}
|
||||
|
||||
windowSetSize(width:number, height:number) {
|
||||
windowSetSize(width: number, height: number) {
|
||||
if (!this.window()) return;
|
||||
return this.window().setSize(width, height);
|
||||
}
|
||||
@ -76,7 +76,7 @@ export class Bridge {
|
||||
return this.window().webContents.closeDevTools();
|
||||
}
|
||||
|
||||
showSaveDialog(options:any) {
|
||||
showSaveDialog(options: any) {
|
||||
const { dialog } = require('electron');
|
||||
if (!options) options = {};
|
||||
if (!('defaultPath' in options) && this.lastSelectedPaths_.file) options.defaultPath = this.lastSelectedPaths_.file;
|
||||
@ -87,7 +87,7 @@ export class Bridge {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
showOpenDialog(options:any) {
|
||||
showOpenDialog(options: any) {
|
||||
const { dialog } = require('electron');
|
||||
if (!options) options = {};
|
||||
let fileType = 'file';
|
||||
@ -102,13 +102,13 @@ export class Bridge {
|
||||
}
|
||||
|
||||
// Don't use this directly - call one of the showXxxxxxxMessageBox() instead
|
||||
showMessageBox_(window:any, options:any):number {
|
||||
showMessageBox_(window: any, options: any): number {
|
||||
const { dialog } = require('electron');
|
||||
if (!window) window = this.window();
|
||||
return dialog.showMessageBoxSync(window, options);
|
||||
}
|
||||
|
||||
showErrorMessageBox(message:string) {
|
||||
showErrorMessageBox(message: string) {
|
||||
return this.showMessageBox_(this.window(), {
|
||||
type: 'error',
|
||||
message: message,
|
||||
@ -116,7 +116,7 @@ export class Bridge {
|
||||
});
|
||||
}
|
||||
|
||||
showConfirmMessageBox(message:string, options:any = null) {
|
||||
showConfirmMessageBox(message: string, options: any = null) {
|
||||
if (options === null) options = {};
|
||||
|
||||
const result = this.showMessageBox_(this.window(), Object.assign({}, {
|
||||
@ -130,7 +130,7 @@ export class Bridge {
|
||||
}
|
||||
|
||||
/* returns the index of the clicked button */
|
||||
showMessageBox(message:string, options:any = null) {
|
||||
showMessageBox(message: string, options: any = null) {
|
||||
if (options === null) options = {};
|
||||
|
||||
const result = this.showMessageBox_(this.window(), Object.assign({}, {
|
||||
@ -142,7 +142,7 @@ export class Bridge {
|
||||
return result;
|
||||
}
|
||||
|
||||
showInfoMessageBox(message:string, options:any = {}) {
|
||||
showInfoMessageBox(message: string, options: any = {}) {
|
||||
const result = this.showMessageBox_(this.window(), Object.assign({}, {
|
||||
type: 'info',
|
||||
message: message,
|
||||
@ -151,7 +151,7 @@ export class Bridge {
|
||||
return result === 0;
|
||||
}
|
||||
|
||||
setLocale(locale:string) {
|
||||
setLocale(locale: string) {
|
||||
setLocale(locale);
|
||||
}
|
||||
|
||||
@ -163,15 +163,15 @@ export class Bridge {
|
||||
return require('electron').MenuItem;
|
||||
}
|
||||
|
||||
openExternal(url:string) {
|
||||
openExternal(url: string) {
|
||||
return require('electron').shell.openExternal(url);
|
||||
}
|
||||
|
||||
openItem(fullPath:string) {
|
||||
openItem(fullPath: string) {
|
||||
return require('electron').shell.openItem(fullPath);
|
||||
}
|
||||
|
||||
checkForUpdates(inBackground:boolean, window:any, logFilePath:string, options:any) {
|
||||
checkForUpdates(inBackground: boolean, window: any, logFilePath: string, options: any) {
|
||||
const { checkForUpdates } = require('./checkForUpdates.js');
|
||||
checkForUpdates(inBackground, window, logFilePath, options);
|
||||
}
|
||||
@ -188,7 +188,7 @@ export class Bridge {
|
||||
return nativeTheme.shouldUseDarkColors;
|
||||
}
|
||||
|
||||
addEventListener(name:string, fn:Function) {
|
||||
addEventListener(name: string, fn: Function) {
|
||||
if (name === 'nativeThemeUpdated') {
|
||||
nativeTheme.on('updated', fn);
|
||||
} else {
|
||||
@ -218,9 +218,9 @@ export class Bridge {
|
||||
|
||||
}
|
||||
|
||||
let bridge_:Bridge = null;
|
||||
let bridge_: Bridge = null;
|
||||
|
||||
export function initBridge(wrapper:ElectronAppWrapper) {
|
||||
export function initBridge(wrapper: ElectronAppWrapper) {
|
||||
if (bridge_) throw new Error('Bridge already initialized');
|
||||
bridge_ = new Bridge(wrapper);
|
||||
return bridge_;
|
||||
|
@ -3,12 +3,12 @@ import { _ } from '@joplin/lib/locale';
|
||||
const app = require('electron').remote.app;
|
||||
const { clipboard } = require('electron');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'copyDevCommand',
|
||||
label: () => _('Copy dev mode command to clipboard'),
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
const appPath = app.getPath('exe');
|
||||
|
@ -1,12 +1,12 @@
|
||||
import CommandService, { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'focusElement',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context:any, target:string) => {
|
||||
execute: async (_context: any, target: string) => {
|
||||
if (target === 'noteBody') return CommandService.instance().execute('focusElementNoteBody');
|
||||
if (target === 'noteList') return CommandService.instance().execute('focusElementNoteList');
|
||||
if (target === 'sideBar') return CommandService.instance().execute('focusElementSideBar');
|
||||
|
@ -3,12 +3,12 @@ import { _ } from '@joplin/lib/locale';
|
||||
import bridge from '../services/bridge';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'openProfileDirectory',
|
||||
label: () => _('Open profile directory'),
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
bridge().openItem(Setting.value('profileDir'));
|
||||
|
@ -5,15 +5,15 @@ const Note = require('@joplin/lib/models/Note');
|
||||
const ExternalEditWatcher = require('@joplin/lib/services/ExternalEditWatcher');
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'startExternalEditing',
|
||||
label: () => _('Edit in external editor'),
|
||||
iconName: 'icon-share',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteId:string = null) => {
|
||||
execute: async (context: CommandContext, noteId: string = null) => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
|
||||
try {
|
||||
|
@ -3,15 +3,15 @@ import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
const ExternalEditWatcher = require('@joplin/lib/services/ExternalEditWatcher');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'stopExternalEditing',
|
||||
label: () => _('Stop external editing'),
|
||||
iconName: 'fa-stop',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteId:string = null) => {
|
||||
execute: async (context: CommandContext, noteId: string = null) => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
ExternalEditWatcher.instance().stopWatching(noteId);
|
||||
},
|
||||
|
@ -3,15 +3,15 @@ import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
import { DesktopCommandContext } from '../services/commands/types';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleExternalEditing',
|
||||
label: () => _('Toggle external editing'),
|
||||
iconName: 'icon-share',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:DesktopCommandContext, noteId:string = null) => {
|
||||
execute: async (context: DesktopCommandContext, noteId: string = null) => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
|
||||
if (!noteId) return;
|
||||
@ -23,7 +23,7 @@ export const runtime = ():CommandRuntime => {
|
||||
}
|
||||
},
|
||||
enabledCondition: 'oneNoteSelected',
|
||||
mapStateToTitle: (state:any) => {
|
||||
mapStateToTitle: (state: any) => {
|
||||
const noteId = stateUtils.selectedNoteId(state);
|
||||
return state.watchedNoteFiles.includes(noteId) ? _('Stop') : '';
|
||||
},
|
||||
|
@ -13,13 +13,13 @@ interface Props {
|
||||
title?: string,
|
||||
iconName?: string,
|
||||
level?: ButtonLevel,
|
||||
className?:string,
|
||||
onClick:Function,
|
||||
className?: string,
|
||||
onClick: Function,
|
||||
color?: string,
|
||||
iconAnimation?: string,
|
||||
tooltip?: string,
|
||||
disabled?: boolean,
|
||||
style?:any,
|
||||
style?: any,
|
||||
}
|
||||
|
||||
const StyledTitle = styled.span`
|
||||
@ -30,143 +30,143 @@ const StyledButtonBase = styled.button`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
height: ${(props:any) => `${props.theme.toolbarHeight}px`};
|
||||
min-height: ${(props:any) => `${props.theme.toolbarHeight}px`};
|
||||
max-height: ${(props:any) => `${props.theme.toolbarHeight}px`};
|
||||
width: ${(props:any) => props.iconOnly ? `${props.theme.toolbarHeight}px` : 'auto'};
|
||||
${(props:any) => props.iconOnly ? `min-width: ${props.theme.toolbarHeight}px;` : ''}
|
||||
${(props:any) => !props.iconOnly ? 'min-width: 100px;' : ''}
|
||||
${(props:any) => props.iconOnly ? `max-width: ${props.theme.toolbarHeight}px;` : ''}
|
||||
height: ${(props: any) => `${props.theme.toolbarHeight}px`};
|
||||
min-height: ${(props: any) => `${props.theme.toolbarHeight}px`};
|
||||
max-height: ${(props: any) => `${props.theme.toolbarHeight}px`};
|
||||
width: ${(props: any) => props.iconOnly ? `${props.theme.toolbarHeight}px` : 'auto'};
|
||||
${(props: any) => props.iconOnly ? `min-width: ${props.theme.toolbarHeight}px;` : ''}
|
||||
${(props: any) => !props.iconOnly ? 'min-width: 100px;' : ''}
|
||||
${(props: any) => props.iconOnly ? `max-width: ${props.theme.toolbarHeight}px;` : ''}
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
font-size: ${(props:any) => props.theme.fontSize}px;
|
||||
padding: 0 ${(props:any) => props.iconOnly ? 4 : 8}px;
|
||||
font-size: ${(props: any) => props.theme.fontSize}px;
|
||||
padding: 0 ${(props: any) => props.iconOnly ? 4 : 8}px;
|
||||
justify-content: center;
|
||||
opacity: ${(props:any) => props.disabled ? 0.5 : 1};
|
||||
opacity: ${(props: any) => props.disabled ? 0.5 : 1};
|
||||
user-select: none;
|
||||
`;
|
||||
|
||||
const StyledIcon = styled(styled.span(space))`
|
||||
font-size: ${(props:any) => props.theme.toolbarIconSize}px;
|
||||
${(props:any) => props.animation ? `animation: ${props.animation}` : ''};
|
||||
font-size: ${(props: any) => props.theme.toolbarIconSize}px;
|
||||
${(props: any) => props.animation ? `animation: ${props.animation}` : ''};
|
||||
`;
|
||||
|
||||
const StyledButtonPrimary = styled(StyledButtonBase)`
|
||||
border: none;
|
||||
background-color: ${(props:any) => props.theme.backgroundColor5};
|
||||
background-color: ${(props: any) => props.theme.backgroundColor5};
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorHover5};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorHover5};
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorActive5};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorActive5};
|
||||
}
|
||||
|
||||
${StyledIcon} {
|
||||
color: ${(props:any) => props.theme.color5};
|
||||
color: ${(props: any) => props.theme.color5};
|
||||
}
|
||||
|
||||
${StyledTitle} {
|
||||
color: ${(props:any) => props.theme.color5};
|
||||
color: ${(props: any) => props.theme.color5};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtonSecondary = styled(StyledButtonBase)`
|
||||
border: 1px solid ${(props:any) => props.theme.borderColor4};
|
||||
background-color: ${(props:any) => props.theme.backgroundColor4};
|
||||
border: 1px solid ${(props: any) => props.theme.borderColor4};
|
||||
background-color: ${(props: any) => props.theme.backgroundColor4};
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorHover4};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorHover4};
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorActive4};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorActive4};
|
||||
}
|
||||
|
||||
${StyledIcon} {
|
||||
color: ${(props:any) => props.theme.color4};
|
||||
color: ${(props: any) => props.theme.color4};
|
||||
}
|
||||
|
||||
${StyledTitle} {
|
||||
color: ${(props:any) => props.theme.color4};
|
||||
color: ${(props: any) => props.theme.color4};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtonTertiary = styled(StyledButtonBase)`
|
||||
border: 1px solid ${(props:any) => props.theme.color3};
|
||||
background-color: ${(props:any) => props.theme.backgroundColor3};
|
||||
border: 1px solid ${(props: any) => props.theme.color3};
|
||||
background-color: ${(props: any) => props.theme.backgroundColor3};
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorHoverDim3};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorHoverDim3};
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorActive3};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorActive3};
|
||||
}
|
||||
|
||||
${StyledIcon} {
|
||||
color: ${(props:any) => props.theme.color};
|
||||
color: ${(props: any) => props.theme.color};
|
||||
}
|
||||
|
||||
${StyledTitle} {
|
||||
color: ${(props:any) => props.theme.color};
|
||||
color: ${(props: any) => props.theme.color};
|
||||
opacity: 0.9;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtonSideBarSecondary = styled(StyledButtonBase)`
|
||||
background: none;
|
||||
border-color: ${(props:any) => props.theme.color2};
|
||||
color: ${(props:any) => props.theme.color2};
|
||||
border-color: ${(props: any) => props.theme.color2};
|
||||
color: ${(props: any) => props.theme.color2};
|
||||
|
||||
&:hover {
|
||||
color: ${(props:any) => props.theme.colorHover2};
|
||||
border-color: ${(props:any) => props.theme.colorHover2};
|
||||
color: ${(props: any) => props.theme.colorHover2};
|
||||
border-color: ${(props: any) => props.theme.colorHover2};
|
||||
background: none;
|
||||
|
||||
${StyledTitle} {
|
||||
color: ${(props:any) => props.theme.colorHover2};
|
||||
color: ${(props: any) => props.theme.colorHover2};
|
||||
}
|
||||
|
||||
${StyledIcon} {
|
||||
color: ${(props:any) => props.theme.colorHover2};
|
||||
color: ${(props: any) => props.theme.colorHover2};
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: ${(props:any) => props.theme.colorActive2};
|
||||
border-color: ${(props:any) => props.theme.colorActive2};
|
||||
color: ${(props: any) => props.theme.colorActive2};
|
||||
border-color: ${(props: any) => props.theme.colorActive2};
|
||||
background: none;
|
||||
|
||||
${StyledTitle} {
|
||||
color: ${(props:any) => props.theme.colorActive2};
|
||||
color: ${(props: any) => props.theme.colorActive2};
|
||||
}
|
||||
|
||||
${StyledIcon} {
|
||||
color: ${(props:any) => props.theme.colorActive2};
|
||||
color: ${(props: any) => props.theme.colorActive2};
|
||||
}
|
||||
}
|
||||
|
||||
${StyledTitle} {
|
||||
color: ${(props:any) => props.theme.color2};
|
||||
color: ${(props: any) => props.theme.color2};
|
||||
}
|
||||
|
||||
${StyledIcon} {
|
||||
color: ${(props:any) => props.theme.color2};
|
||||
color: ${(props: any) => props.theme.color2};
|
||||
}
|
||||
`;
|
||||
|
||||
function buttonClass(level:ButtonLevel) {
|
||||
function buttonClass(level: ButtonLevel) {
|
||||
if (level === ButtonLevel.Primary) return StyledButtonPrimary;
|
||||
if (level === ButtonLevel.Tertiary) return StyledButtonTertiary;
|
||||
if (level === ButtonLevel.SideBarSecondary) return StyledButtonSideBarSecondary;
|
||||
return StyledButtonSecondary;
|
||||
}
|
||||
|
||||
export default function Button(props:Props) {
|
||||
export default function Button(props: Props) {
|
||||
const iconOnly = props.iconName && !props.title;
|
||||
|
||||
const StyledButton = buttonClass(props.level);
|
||||
|
@ -15,14 +15,14 @@ export const StyledRoot = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: ${(props:any) => props.theme.backgroundColor3};
|
||||
padding-left: ${(props:any) => props.theme.configScreenPadding}px;
|
||||
background-color: ${(props: any) => props.theme.backgroundColor3};
|
||||
padding-left: ${(props: any) => props.theme.configScreenPadding}px;
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
border-top-color: ${(props:any) => props.theme.dividerColor};
|
||||
border-top-color: ${(props: any) => props.theme.dividerColor};
|
||||
`;
|
||||
|
||||
export default function ButtonBar(props:Props) {
|
||||
export default function ButtonBar(props: Props) {
|
||||
function renderOkButton() {
|
||||
if (!props.onSaveClick) return null;
|
||||
return <Button style={{ marginRight: 10 }} level={ButtonLevel.Primary} disabled={!props.hasChanges} onClick={props.onSaveClick} title={_('OK')}/>;
|
||||
|
@ -16,9 +16,9 @@ const { KeymapConfigScreen } = require('../KeymapConfig/KeymapConfigScreen');
|
||||
|
||||
class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
rowStyle_:any = null;
|
||||
rowStyle_: any = null;
|
||||
|
||||
constructor(props:any) {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
shared.init(this);
|
||||
@ -72,7 +72,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
}
|
||||
|
||||
sectionByName(name:string) {
|
||||
sectionByName(name: string) {
|
||||
const sections = shared.settingsSections({ device: 'desktop', settings: this.state.settings });
|
||||
for (const section of sections) {
|
||||
if (section.name === name) return section;
|
||||
@ -81,7 +81,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
throw new Error(`Invalid section name: ${name}`);
|
||||
}
|
||||
|
||||
screenFromName(screenName:string) {
|
||||
screenFromName(screenName: string) {
|
||||
if (screenName === 'encryption') return <EncryptionConfigScreen themeId={this.props.themeId}/>;
|
||||
if (screenName === 'server') return <ClipperConfigScreen themeId={this.props.themeId}/>;
|
||||
if (screenName === 'keymap') return <KeymapConfigScreen themeId={this.props.themeId}/>;
|
||||
@ -89,7 +89,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
throw new Error(`Invalid screen name: ${screenName}`);
|
||||
}
|
||||
|
||||
switchSection(name:string) {
|
||||
switchSection(name: string) {
|
||||
const section = this.sectionByName(name);
|
||||
let screenName = '';
|
||||
if (section.isScreen) {
|
||||
@ -104,11 +104,11 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
this.setState({ selectedSectionName: section.name, screenName: screenName });
|
||||
}
|
||||
|
||||
sideBar_selectionChange(event:any) {
|
||||
sideBar_selectionChange(event: any) {
|
||||
this.switchSection(event.section.name);
|
||||
}
|
||||
|
||||
keyValueToArray(kv:any) {
|
||||
keyValueToArray(kv: any) {
|
||||
const output = [];
|
||||
for (const k in kv) {
|
||||
if (!kv.hasOwnProperty(k)) continue;
|
||||
@ -121,7 +121,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
return output;
|
||||
}
|
||||
|
||||
renderSectionDescription(section:any) {
|
||||
renderSectionDescription(section: any) {
|
||||
const description = Setting.sectionDescription(section.name);
|
||||
if (!description) return null;
|
||||
|
||||
@ -133,10 +133,10 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
);
|
||||
}
|
||||
|
||||
sectionToComponent(key:string, section:any, settings:any, selected:boolean) {
|
||||
sectionToComponent(key: string, section: any, settings: any, selected: boolean) {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const createSettingComponents = (advanced:boolean) => {
|
||||
const createSettingComponents = (advanced: boolean) => {
|
||||
const output = [];
|
||||
for (let i = 0; i < section.metadatas.length; i++) {
|
||||
const md = section.metadatas[i];
|
||||
@ -150,7 +150,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
const settingComps = createSettingComponents(false);
|
||||
const advancedSettingComps = createSettingComponents(true);
|
||||
|
||||
const sectionStyle:any = {
|
||||
const sectionStyle: any = {
|
||||
marginTop: 20,
|
||||
marginBottom: 20,
|
||||
maxWidth: 640,
|
||||
@ -261,10 +261,10 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
);
|
||||
}
|
||||
|
||||
settingToComponent(key:string, value:any) {
|
||||
settingToComponent(key: string, value: any) {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const output:any = null;
|
||||
const output: any = null;
|
||||
|
||||
const rowStyle = {
|
||||
marginBottom: theme.mainPadding,
|
||||
@ -317,7 +317,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
paddingBottom: 4,
|
||||
});
|
||||
|
||||
const updateSettingValue = (key:string, value:any) => {
|
||||
const updateSettingValue = (key: string, value: any) => {
|
||||
// console.info(key + ' = ' + value);
|
||||
return shared.updateSettingValue(this, key, value);
|
||||
};
|
||||
@ -359,7 +359,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
<select
|
||||
value={value}
|
||||
style={selectStyle}
|
||||
onChange={(event:any) => {
|
||||
onChange={(event: any) => {
|
||||
updateSettingValue(key, event.target.value);
|
||||
}}
|
||||
>
|
||||
@ -404,7 +404,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
</div>
|
||||
);
|
||||
} else if (md.type === Setting.TYPE_STRING) {
|
||||
const inputStyle:any = Object.assign({}, textInputBaseStyle, {
|
||||
const inputStyle: any = Object.assign({}, textInputBaseStyle, {
|
||||
width: '50%',
|
||||
minWidth: '20em',
|
||||
});
|
||||
@ -413,13 +413,13 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
if (md.subType === 'file_path_and_args') {
|
||||
inputStyle.marginBottom = subLabel.marginBottom;
|
||||
|
||||
const splitCmd = (cmdString:string) => {
|
||||
const splitCmd = (cmdString: string) => {
|
||||
const path = pathUtils.extractExecutablePath(cmdString);
|
||||
const args = cmdString.substr(path.length + 1);
|
||||
return [pathUtils.unquotePath(path), args];
|
||||
};
|
||||
|
||||
const joinCmd = (cmdArray:string[]) => {
|
||||
const joinCmd = (cmdArray: string[]) => {
|
||||
if (!cmdArray[0] && !cmdArray[1]) return '';
|
||||
let cmdString = pathUtils.quotePath(cmdArray[0]);
|
||||
if (!cmdString) cmdString = '""';
|
||||
@ -427,13 +427,13 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
return cmdString;
|
||||
};
|
||||
|
||||
const onPathChange = (event:any) => {
|
||||
const onPathChange = (event: any) => {
|
||||
const cmd = splitCmd(this.state.settings[key]);
|
||||
cmd[0] = event.target.value;
|
||||
updateSettingValue(key, joinCmd(cmd));
|
||||
};
|
||||
|
||||
const onArgsChange = (event:any) => {
|
||||
const onArgsChange = (event: any) => {
|
||||
const cmd = splitCmd(this.state.settings[key]);
|
||||
cmd[1] = event.target.value;
|
||||
updateSettingValue(key, joinCmd(cmd));
|
||||
@ -462,7 +462,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
<input
|
||||
type={inputType}
|
||||
style={Object.assign({}, inputStyle, { marginBottom: 0, marginRight: 5 })}
|
||||
onChange={(event:any) => {
|
||||
onChange={(event: any) => {
|
||||
onPathChange(event);
|
||||
}}
|
||||
value={cmd[0]}
|
||||
@ -479,7 +479,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
<input
|
||||
type={inputType}
|
||||
style={inputStyle}
|
||||
onChange={(event:any) => {
|
||||
onChange={(event: any) => {
|
||||
onArgsChange(event);
|
||||
}}
|
||||
value={cmd[1]}
|
||||
@ -495,7 +495,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
const onTextChange = (event:any) => {
|
||||
const onTextChange = (event: any) => {
|
||||
updateSettingValue(key, event.target.value);
|
||||
};
|
||||
|
||||
@ -508,7 +508,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
type={inputType}
|
||||
style={inputStyle}
|
||||
value={this.state.settings[key]}
|
||||
onChange={(event:any) => {
|
||||
onChange={(event: any) => {
|
||||
onTextChange(event);
|
||||
}}
|
||||
/>
|
||||
@ -519,14 +519,14 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
);
|
||||
}
|
||||
} else if (md.type === Setting.TYPE_INT) {
|
||||
const onNumChange = (event:any) => {
|
||||
const onNumChange = (event: any) => {
|
||||
updateSettingValue(key, event.target.value);
|
||||
};
|
||||
|
||||
const label = [md.label()];
|
||||
if (md.unitLabel) label.push(`(${md.unitLabel()})`);
|
||||
|
||||
const inputStyle:any = Object.assign({}, textInputBaseStyle);
|
||||
const inputStyle: any = Object.assign({}, textInputBaseStyle);
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
@ -537,7 +537,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
type="number"
|
||||
style={inputStyle}
|
||||
value={this.state.settings[key]}
|
||||
onChange={(event:any) => {
|
||||
onChange={(event: any) => {
|
||||
onNumChange(event);
|
||||
}}
|
||||
min={md.minimum}
|
||||
@ -640,7 +640,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state:any) => {
|
||||
const mapStateToProps = (state: any) => {
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
settings: state.settings,
|
||||
|
@ -10,7 +10,7 @@ interface Props {
|
||||
|
||||
export const StyledRoot = styled.div`
|
||||
display: flex;
|
||||
background-color: ${(props:any) => props.theme.backgroundColor2};
|
||||
background-color: ${(props: any) => props.theme.backgroundColor2};
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
@ -18,22 +18,22 @@ export const StyledListItem = styled.a`
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: ${(props:any) => props.theme.mainPadding}px;
|
||||
background: ${(props:any) => props.selected ? props.theme.selectedColor2 : 'none'};
|
||||
padding: ${(props: any) => props.theme.mainPadding}px;
|
||||
background: ${(props: any) => props.selected ? props.theme.selectedColor2 : 'none'};
|
||||
transition: 0.1s;
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
opacity: ${(props:any) => props.selected ? 1 : 0.8};
|
||||
opacity: ${(props: any) => props.selected ? 1 : 0.8};
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorHover2};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorHover2};
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledListItemLabel = styled.span`
|
||||
font-size: ${(props:any) => Math.round(props.theme.fontSize * 1.2)}px;
|
||||
font-size: ${(props: any) => Math.round(props.theme.fontSize * 1.2)}px;
|
||||
font-weight: 500;
|
||||
color: ${(props:any) => props.theme.color2};
|
||||
color: ${(props: any) => props.theme.color2};
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
@ -42,15 +42,15 @@ export const StyledListItemLabel = styled.span`
|
||||
`;
|
||||
|
||||
export const StyledListItemIcon = styled.i`
|
||||
font-size: ${(props:any) => Math.round(props.theme.fontSize * 1.4)}px;
|
||||
color: ${(props:any) => props.theme.color2};
|
||||
margin-right: ${(props:any) => props.theme.mainPadding / 1.5}px;
|
||||
font-size: ${(props: any) => Math.round(props.theme.fontSize * 1.4)}px;
|
||||
color: ${(props: any) => props.theme.color2};
|
||||
margin-right: ${(props: any) => props.theme.mainPadding / 1.5}px;
|
||||
`;
|
||||
|
||||
export default function SideBar(props:Props) {
|
||||
const buttons:any[] = [];
|
||||
export default function SideBar(props: Props) {
|
||||
const buttons: any[] = [];
|
||||
|
||||
function renderButton(section:any) {
|
||||
function renderButton(section: any) {
|
||||
const selected = props.selection === section.name;
|
||||
return (
|
||||
<StyledListItem key={section.name} selected={selected} onClick={() => { props.onSelectionChange({ section: section }); }}>
|
||||
|
@ -13,12 +13,12 @@ interface Props {
|
||||
|
||||
class DropboxLoginScreenComponent extends React.Component<any, any> {
|
||||
|
||||
shared_:any;
|
||||
shared_: any;
|
||||
|
||||
constructor(props:Props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.shared_ = new Shared(this, (msg:string) => bridge().showInfoMessageBox(msg), (msg:string) => bridge().showErrorMessageBox(msg));
|
||||
this.shared_ = new Shared(this, (msg: string) => bridge().showInfoMessageBox(msg), (msg: string) => bridge().showErrorMessageBox(msg));
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
@ -61,7 +61,7 @@ class DropboxLoginScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state:any) => {
|
||||
const mapStateToProps = (state: any) => {
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
};
|
||||
|
@ -5,9 +5,9 @@ const ipcRenderer = require('electron').ipcRenderer;
|
||||
|
||||
export default class ErrorBoundary extends React.Component {
|
||||
|
||||
state:any = { error: null, errorInfo: null };
|
||||
state: any = { error: null, errorInfo: null };
|
||||
|
||||
componentDidCatch(error:any, errorInfo:any) {
|
||||
componentDidCatch(error: any, errorInfo: any) {
|
||||
this.setState({ error: error, errorInfo: errorInfo });
|
||||
}
|
||||
|
||||
|
@ -8,10 +8,10 @@ import { _ } from '@joplin/lib/locale';
|
||||
const keymapService = KeymapService.instance();
|
||||
|
||||
export interface ShortcutRecorderProps {
|
||||
onSave: (event: { commandName: string, accelerator: string }) => void,
|
||||
onReset: (event: { commandName: string }) => void,
|
||||
onCancel: (event: { commandName: string }) => void,
|
||||
onError: (event: { recorderError: Error }) => void,
|
||||
onSave: (event: { commandName: string, accelerator: string })=> void,
|
||||
onReset: (event: { commandName: string })=> void,
|
||||
onCancel: (event: { commandName: string })=> void,
|
||||
onError: (event: { recorderError: Error })=> void,
|
||||
initialAccelerator: string
|
||||
commandName: string,
|
||||
themeId: number
|
||||
|
@ -5,7 +5,7 @@ import { _ } from '@joplin/lib/locale';
|
||||
|
||||
const commandService = CommandService.instance();
|
||||
|
||||
const getLabel = (commandName: string):string => {
|
||||
const getLabel = (commandName: string): string => {
|
||||
if (commandService.exists(commandName)) return commandService.label(commandName, true);
|
||||
|
||||
// Some commands are not registered in CommandService at the moment
|
||||
|
@ -7,7 +7,7 @@ interface CommandStatus {
|
||||
[commandName: string]: boolean
|
||||
}
|
||||
|
||||
const useCommandStatus = (): [CommandStatus, (commandName: string) => void, (commandName: string) => void] => {
|
||||
const useCommandStatus = (): [CommandStatus, (commandName: string)=> void, (commandName: string)=> void] => {
|
||||
const [status, setStatus] = useState<CommandStatus>(() =>
|
||||
keymapService.getCommandNames().reduce((accumulator: CommandStatus, command: string) => {
|
||||
accumulator[command] = false;
|
||||
|
@ -10,7 +10,7 @@ const keymapService = KeymapService.instance();
|
||||
function allKeymapItems() {
|
||||
const output = keymapService.getKeymapItems().slice();
|
||||
|
||||
output.sort((a:KeymapItem, b:KeymapItem) => {
|
||||
output.sort((a: KeymapItem, b: KeymapItem) => {
|
||||
return getLabel(a.command).toLocaleLowerCase() < getLabel(b.command).toLocaleLowerCase() ? -1 : +1;
|
||||
});
|
||||
|
||||
@ -20,9 +20,9 @@ function allKeymapItems() {
|
||||
const useKeymap = (): [
|
||||
KeymapItem[],
|
||||
Error,
|
||||
(keymapItems: KeymapItem[]) => void,
|
||||
(commandName: string, accelerator: string) => void,
|
||||
(commandName: string) => void
|
||||
(keymapItems: KeymapItem[])=> void,
|
||||
(commandName: string, accelerator: string)=> void,
|
||||
(commandName: string)=> void
|
||||
] => {
|
||||
const [keymapItems, setKeymapItems] = useState<KeymapItem[]>(() => allKeymapItems());
|
||||
const [keymapError, setKeymapError] = useState<Error>(null);
|
||||
|
@ -72,13 +72,13 @@ const commands = [
|
||||
|
||||
class MainScreenComponent extends React.Component<any, any> {
|
||||
|
||||
waitForNotesSavedIID_:any;
|
||||
isPrinting_:boolean;
|
||||
styleKey_:string;
|
||||
styles_:any;
|
||||
promptOnClose_:Function;
|
||||
waitForNotesSavedIID_: any;
|
||||
isPrinting_: boolean;
|
||||
styleKey_: string;
|
||||
styles_: any;
|
||||
promptOnClose_: Function;
|
||||
|
||||
constructor(props:any) {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@ -109,7 +109,7 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
window.addEventListener('resize', this.window_resize);
|
||||
}
|
||||
|
||||
buildLayout(plugins:any):LayoutItem {
|
||||
buildLayout(plugins: any): LayoutItem {
|
||||
const rootLayoutSize = this.rootLayoutSize();
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
const sideBarMinWidth = 200;
|
||||
@ -131,7 +131,7 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
if (sizes[k].width < sideBarMinWidth) sizes[k].width = sideBarMinWidth;
|
||||
}
|
||||
|
||||
const pluginColumnChildren:LayoutItem[] = [];
|
||||
const pluginColumnChildren: LayoutItem[] = [];
|
||||
|
||||
const infos = pluginUtils.viewInfosByType(plugins, 'webview');
|
||||
|
||||
@ -264,16 +264,16 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
|
||||
updateRootLayoutSize() {
|
||||
this.setState({ layout: produce(this.state.layout, (draft:any) => {
|
||||
this.setState({ layout: produce(this.state.layout, (draft: any) => {
|
||||
const s = this.rootLayoutSize();
|
||||
draft.width = s.width;
|
||||
draft.height = s.height;
|
||||
}) });
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps:any, prevState:any) {
|
||||
componentDidUpdate(prevProps: any, prevState: any) {
|
||||
if (this.props.noteListVisibility !== prevProps.noteListVisibility || this.props.sidebarVisibility !== prevProps.sidebarVisibility) {
|
||||
this.setState({ layout: produce(this.state.layout, (draft:any) => {
|
||||
this.setState({ layout: produce(this.state.layout, (draft: any) => {
|
||||
const noteListColumn = findItemByKey(draft, 'noteListColumn');
|
||||
noteListColumn.visible = this.props.noteListVisibility;
|
||||
|
||||
@ -337,14 +337,14 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
});
|
||||
}
|
||||
|
||||
async waitForNoteToSaved(noteId:string) {
|
||||
async waitForNoteToSaved(noteId: string) {
|
||||
while (noteId && this.props.editorNoteStatuses[noteId] === 'saving') {
|
||||
console.info('Waiting for note to be saved...', this.props.editorNoteStatuses);
|
||||
await time.msleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
async printTo_(target:string, options:any) {
|
||||
async printTo_(target: string, options: any) {
|
||||
// Concurrent print calls are disallowed to avoid incorrect settings being restored upon completion
|
||||
if (this.isPrinting_) {
|
||||
console.info(`Printing ${options.path} to ${target} disallowed, already printing.`);
|
||||
@ -399,7 +399,7 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
return 50;
|
||||
}
|
||||
|
||||
styles(themeId:number, width:number, height:number, messageBoxVisible:boolean, isSidebarVisible:any, isNoteListVisible:any) {
|
||||
styles(themeId: number, width: number, height: number, messageBoxVisible: boolean, isSidebarVisible: any, isNoteListVisible: any) {
|
||||
const styleKey = [themeId, width, height, messageBoxVisible, +isSidebarVisible, +isNoteListVisible].join('_');
|
||||
if (styleKey === this.styleKey_) return this.styles_;
|
||||
|
||||
@ -449,7 +449,7 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
return this.styles_;
|
||||
}
|
||||
|
||||
renderNotification(theme:any, styles:any) {
|
||||
renderNotification(theme: any, styles: any) {
|
||||
if (!this.messageBoxVisible()) return null;
|
||||
|
||||
const onViewStatusScreen = () => {
|
||||
@ -539,7 +539,7 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
);
|
||||
}
|
||||
|
||||
messageBoxVisible(props:any = null) {
|
||||
messageBoxVisible(props: any = null) {
|
||||
if (!props) props = this.props;
|
||||
return props.hasDisabledSyncItems || props.showMissingMasterKeyMessage || props.showNeedUpgradingMasterKeyMessage || props.showShouldReencryptMessage || props.hasDisabledEncryptionItems || this.props.shouldUpgradeSyncTarget;
|
||||
}
|
||||
@ -556,16 +556,16 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
}
|
||||
|
||||
userWebview_message(event:any) {
|
||||
userWebview_message(event: any) {
|
||||
PluginService.instance().pluginById(event.pluginId).viewController(event.viewId).emitMessage(event);
|
||||
}
|
||||
|
||||
resizableLayout_resize(event:any) {
|
||||
resizableLayout_resize(event: any) {
|
||||
this.setState({ layout: event.layout });
|
||||
Setting.setValue('ui.layout', allDynamicSizes(event.layout));
|
||||
}
|
||||
|
||||
resizableLayout_renderItem(key:string, event:any) {
|
||||
resizableLayout_renderItem(key: string, event: any) {
|
||||
const eventEmitter = event.eventEmitter;
|
||||
|
||||
if (key === 'sideBar') {
|
||||
@ -640,7 +640,7 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
const styles = this.styles(this.props.themeId, style.width, style.height, this.messageBoxVisible(), sidebarVisibility, noteListVisibility);
|
||||
|
||||
if (!this.promptOnClose_) {
|
||||
this.promptOnClose_ = (answer:any, buttonType:any) => {
|
||||
this.promptOnClose_ = (answer: any, buttonType: any) => {
|
||||
return this.state.promptOptions.onClose(answer, buttonType);
|
||||
};
|
||||
}
|
||||
@ -680,7 +680,7 @@ class MainScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state:any) => {
|
||||
const mapStateToProps = (state: any) => {
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
settingEditorCodeView: state.settings['editor.codeView'],
|
||||
|
@ -5,15 +5,15 @@ import { stateUtils } from '@joplin/lib/reducer';
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
const time = require('@joplin/lib/time').default;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'editAlarm',
|
||||
label: () => _('Set alarm'),
|
||||
iconName: 'icon-alarm',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteId:string = null) => {
|
||||
execute: async (context: CommandContext, noteId: string = null) => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
|
||||
const note = await Note.load(noteId);
|
||||
@ -28,7 +28,7 @@ export const runtime = (comp:any):CommandRuntime => {
|
||||
inputType: 'datetime',
|
||||
buttons: ['ok', 'cancel', 'clear'],
|
||||
value: note.todo_due ? new Date(note.todo_due) : defaultDate,
|
||||
onClose: async (answer:any, buttonType:string) => {
|
||||
onClose: async (answer: any, buttonType: string) => {
|
||||
let newNote = null;
|
||||
|
||||
if (buttonType === 'clear') {
|
||||
@ -56,7 +56,7 @@ export const runtime = (comp:any):CommandRuntime => {
|
||||
|
||||
enabledCondition: 'oneNoteSelected && noteIsTodo && !noteTodoCompleted',
|
||||
|
||||
mapStateToTitle: (state:any) => {
|
||||
mapStateToTitle: (state: any) => {
|
||||
const note = stateUtils.selectedNote(state);
|
||||
return note && note.todo_due ? time.formatMsToLocal(note.todo_due) : null;
|
||||
},
|
||||
|
@ -5,14 +5,14 @@ import { _ } from '@joplin/lib/locale';
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'exportPdf',
|
||||
label: () => `PDF - ${_('PDF File')}`,
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteIds:string[] = null) => {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
try {
|
||||
noteIds = noteIds || context.state.selectedNoteIds;
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'hideModalMessage',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
comp.setState({ modalLayer: { visible: false, message: '' } });
|
||||
|
@ -3,21 +3,21 @@ import { _ } from '@joplin/lib/locale';
|
||||
const Folder = require('@joplin/lib/models/Folder');
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'moveToFolder',
|
||||
label: () => _('Move to notebook'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteIds:string[] = null) => {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
noteIds = noteIds || context.state.selectedNoteIds;
|
||||
|
||||
const folders:any[] = await Folder.sortFolderTree();
|
||||
const startFolders:any[] = [];
|
||||
const folders: any[] = await Folder.sortFolderTree();
|
||||
const startFolders: any[] = [];
|
||||
const maxDepth = 15;
|
||||
|
||||
const addOptions = (folders:any[], depth:number) => {
|
||||
const addOptions = (folders: any[], depth: number) => {
|
||||
for (let i = 0; i < folders.length; i++) {
|
||||
const folder = folders[i];
|
||||
startFolders.push({ key: folder.id, value: folder.id, label: folder.title, indentDepth: depth });
|
||||
@ -33,7 +33,7 @@ export const runtime = (comp:any):CommandRuntime => {
|
||||
inputType: 'dropdown',
|
||||
value: '',
|
||||
autocomplete: startFolders,
|
||||
onClose: async (answer:any) => {
|
||||
onClose: async (answer: any) => {
|
||||
if (answer != null) {
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
await Note.moveToFolder(noteIds[i], answer.value);
|
||||
|
@ -3,23 +3,23 @@ import { _ } from '@joplin/lib/locale';
|
||||
const Folder = require('@joplin/lib/models/Folder');
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'newFolder',
|
||||
label: () => _('New notebook'),
|
||||
iconName: 'fa-book',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context:CommandContext, parentId:string = null) => {
|
||||
execute: async (_context: CommandContext, parentId: string = null) => {
|
||||
comp.setState({
|
||||
promptOptions: {
|
||||
label: _('Notebook title:'),
|
||||
onClose: async (answer:string) => {
|
||||
onClose: async (answer: string) => {
|
||||
if (answer) {
|
||||
let folder = null;
|
||||
try {
|
||||
const toSave:any = { title: answer };
|
||||
const toSave: any = { title: answer };
|
||||
if (parentId) toSave.parent_id = parentId;
|
||||
folder = await Folder.save(toSave, { userSideValidation: true });
|
||||
} catch (error) {
|
||||
|
@ -4,15 +4,15 @@ const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
const TemplateUtils = require('@joplin/lib/TemplateUtils');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'newNote',
|
||||
label: () => _('New note'),
|
||||
iconName: 'fa-file',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context:CommandContext, template:string = null, isTodo:boolean = false) => {
|
||||
execute: async (_context: CommandContext, template: string = null, isTodo: boolean = false) => {
|
||||
const folderId = Setting.value('activeFolderId');
|
||||
if (!folderId) return;
|
||||
|
||||
|
@ -1,15 +1,15 @@
|
||||
import CommandService, { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'newSubFolder',
|
||||
label: () => _('New sub-notebook'),
|
||||
iconName: 'fa-book',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, parentId:string = null) => {
|
||||
execute: async (context: CommandContext, parentId: string = null) => {
|
||||
parentId = parentId || context.state.selectedFolderId;
|
||||
return CommandService.instance().execute('newFolder', parentId);
|
||||
},
|
||||
|
@ -1,15 +1,15 @@
|
||||
import CommandService, { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'newTodo',
|
||||
label: () => _('New to-do'),
|
||||
iconName: 'fa-check-square',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context:CommandContext, template:string = null) => {
|
||||
execute: async (_context: CommandContext, template: string = null) => {
|
||||
return CommandService.instance().execute('newNote', template, true);
|
||||
},
|
||||
enabledCondition: 'oneFolderSelected && !inConflictFolder',
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'openFolder',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, folderId:string) => {
|
||||
execute: async (context: CommandContext, folderId: string) => {
|
||||
context.dispatch({
|
||||
type: 'FOLDER_SELECT',
|
||||
id: folderId,
|
||||
|
@ -2,13 +2,13 @@ import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
const Folder = require('@joplin/lib/models/Folder');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'openNote',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteId:string, hash:string = null) => {
|
||||
execute: async (context: CommandContext, noteId: string, hash: string = null) => {
|
||||
const note = await Note.load(noteId);
|
||||
if (!note) throw new Error(`No such note: ${noteId}`);
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'openTag',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, tagId:string) => {
|
||||
execute: async (context: CommandContext, tagId: string) => {
|
||||
context.dispatch({
|
||||
type: 'TAG_SELECT',
|
||||
id: tagId,
|
||||
|
@ -2,15 +2,15 @@ import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'print',
|
||||
label: () => _('Print'),
|
||||
iconName: 'fa-file',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteIds:string[] = null) => {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
noteIds = noteIds || context.state.selectedNoteIds;
|
||||
|
||||
try {
|
||||
|
@ -3,14 +3,14 @@ import { _ } from '@joplin/lib/locale';
|
||||
const Folder = require('@joplin/lib/models/Folder');
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'renameFolder',
|
||||
label: () => _('Rename'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, folderId:string = null) => {
|
||||
execute: async (context: CommandContext, folderId: string = null) => {
|
||||
folderId = folderId || context.state.selectedFolderId;
|
||||
|
||||
const folder = await Folder.load(folderId);
|
||||
@ -20,7 +20,7 @@ export const runtime = (comp:any):CommandRuntime => {
|
||||
promptOptions: {
|
||||
label: _('Rename notebook:'),
|
||||
value: folder.title,
|
||||
onClose: async (answer:string) => {
|
||||
onClose: async (answer: string) => {
|
||||
if (answer !== null) {
|
||||
try {
|
||||
folder.title = answer;
|
||||
|
@ -3,14 +3,14 @@ import { _ } from '@joplin/lib/locale';
|
||||
const Tag = require('@joplin/lib/models/Tag');
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'renameTag',
|
||||
label: () => _('Rename'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, tagId:string = null) => {
|
||||
execute: async (context: CommandContext, tagId: string = null) => {
|
||||
tagId = tagId || context.state.selectedTagId;
|
||||
if (!tagId) return;
|
||||
|
||||
@ -20,7 +20,7 @@ export const runtime = (comp:any):CommandRuntime => {
|
||||
promptOptions: {
|
||||
label: _('Rename tag:'),
|
||||
value: tag.title,
|
||||
onClose: async (answer:string) => {
|
||||
onClose: async (answer: string) => {
|
||||
if (answer !== null) {
|
||||
try {
|
||||
tag.title = answer;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'search',
|
||||
iconName: 'icon-search',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
// Doesn't do anything for now but could be used to
|
||||
|
@ -2,20 +2,20 @@ import CommandService, { CommandRuntime, CommandDeclaration, CommandContext } fr
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
const TemplateUtils = require('@joplin/lib/TemplateUtils');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'selectTemplate',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context:CommandContext, noteType:string) => {
|
||||
execute: async (_context: CommandContext, noteType: string) => {
|
||||
comp.setState({
|
||||
promptOptions: {
|
||||
label: _('Template file:'),
|
||||
inputType: 'dropdown',
|
||||
value: comp.props.templates[0], // Need to start with some value
|
||||
autocomplete: comp.props.templates,
|
||||
onClose: async (answer:any) => {
|
||||
onClose: async (answer: any) => {
|
||||
if (answer) {
|
||||
if (noteType === 'note' || noteType === 'todo') {
|
||||
CommandService.instance().execute('newNote', answer.value, noteType === 'todo');
|
||||
|
@ -2,32 +2,32 @@ import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
const Tag = require('@joplin/lib/models/Tag');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'setTags',
|
||||
label: () => _('Tags'),
|
||||
iconName: 'icon-tags',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteIds:string[] = null) => {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
noteIds = noteIds || context.state.selectedNoteIds;
|
||||
|
||||
const tags = await Tag.commonTagsByNoteIds(noteIds);
|
||||
const startTags = tags
|
||||
.map((a:any) => {
|
||||
.map((a: any) => {
|
||||
return { value: a.id, label: a.title };
|
||||
})
|
||||
.sort((a:any, b:any) => {
|
||||
.sort((a: any, b: any) => {
|
||||
// sensitivity accent will treat accented characters as differemt
|
||||
// but treats caps as equal
|
||||
return a.label.localeCompare(b.label, undefined, { sensitivity: 'accent' });
|
||||
});
|
||||
const allTags = await Tag.allWithNotes();
|
||||
const tagSuggestions = allTags.map((a:any) => {
|
||||
const tagSuggestions = allTags.map((a: any) => {
|
||||
return { value: a.id, label: a.title };
|
||||
})
|
||||
.sort((a:any, b:any) => {
|
||||
.sort((a: any, b: any) => {
|
||||
// sensitivity accent will treat accented characters as differemt
|
||||
// but treats caps as equal
|
||||
return a.label.localeCompare(b.label, undefined, { sensitivity: 'accent' });
|
||||
@ -39,7 +39,7 @@ export const runtime = (comp:any):CommandRuntime => {
|
||||
inputType: 'tags',
|
||||
value: startTags,
|
||||
autocomplete: tagSuggestions,
|
||||
onClose: async (answer:any[]) => {
|
||||
onClose: async (answer: any[]) => {
|
||||
if (answer !== null) {
|
||||
const endTagTitles = answer.map(a => {
|
||||
return a.label.trim();
|
||||
@ -47,16 +47,16 @@ export const runtime = (comp:any):CommandRuntime => {
|
||||
if (noteIds.length === 1) {
|
||||
await Tag.setNoteTagsByTitles(noteIds[0], endTagTitles);
|
||||
} else {
|
||||
const startTagTitles = startTags.map((a:any) => { return a.label.trim(); });
|
||||
const addTags = endTagTitles.filter((value:string) => !startTagTitles.includes(value));
|
||||
const delTags = startTagTitles.filter((value:string) => !endTagTitles.includes(value));
|
||||
const startTagTitles = startTags.map((a: any) => { return a.label.trim(); });
|
||||
const addTags = endTagTitles.filter((value: string) => !startTagTitles.includes(value));
|
||||
const delTags = startTagTitles.filter((value: string) => !endTagTitles.includes(value));
|
||||
|
||||
// apply the tag additions and deletions to each selected note
|
||||
for (let i = 0; i < noteIds.length; i++) {
|
||||
const tags = await Tag.tagsByNoteId(noteIds[i]);
|
||||
let tagTitles = tags.map((a:any) => { return a.title; });
|
||||
let tagTitles = tags.map((a: any) => { return a.title; });
|
||||
tagTitles = tagTitles.concat(addTags);
|
||||
tagTitles = tagTitles.filter((value:string) => !delTags.includes(value));
|
||||
tagTitles = tagTitles.filter((value: string) => !delTags.includes(value));
|
||||
await Tag.setNoteTagsByTitles(noteIds[i], tagTitles);
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import { CommandDeclaration, CommandRuntime, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'showModalMessage',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (_context:CommandContext, message:string) => {
|
||||
execute: async (_context: CommandContext, message: string) => {
|
||||
let brIndex = 1;
|
||||
const lines = message.split('\n').map((line:string) => {
|
||||
const lines = message.split('\n').map((line: string) => {
|
||||
if (!line.trim()) return <br key={`${brIndex++}`}/>;
|
||||
return <div key={line} className="text">{line}</div>;
|
||||
});
|
||||
|
@ -3,14 +3,14 @@ import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'showNoteContentProperties',
|
||||
label: () => _('Statistics...'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteId:string = null) => {
|
||||
execute: async (context: CommandContext, noteId: string = null) => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
|
||||
const note = await Note.load(noteId);
|
||||
|
@ -2,15 +2,15 @@ import CommandService, { CommandRuntime, CommandDeclaration, CommandContext } fr
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'showNoteProperties',
|
||||
label: () => _('Note properties'),
|
||||
iconName: 'icon-info',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteId:string = null) => {
|
||||
execute: async (context: CommandContext, noteId: string = null) => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
|
||||
comp.setState({
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'showShareNoteDialog',
|
||||
label: () => _('Share note...'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteIds:string[] = null) => {
|
||||
execute: async (context: CommandContext, noteIds: string[] = null) => {
|
||||
noteIds = noteIds || context.state.selectedNoteIds;
|
||||
|
||||
comp.setState({
|
||||
|
@ -6,15 +6,15 @@ import { AppState } from '../../../app';
|
||||
|
||||
const Menu = bridge().Menu;
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'showSpellCheckerMenu',
|
||||
label: () => _('Spell checker'),
|
||||
iconName: 'fas fa-globe',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, selectedLanguage:string = null, useSpellChecker:boolean = null) => {
|
||||
execute: async (context: CommandContext, selectedLanguage: string = null, useSpellChecker: boolean = null) => {
|
||||
selectedLanguage = selectedLanguage === null ? context.state.settings['spellChecker.language'] : selectedLanguage;
|
||||
useSpellChecker = useSpellChecker === null ? context.state.settings['spellChecker.enabled'] : useSpellChecker;
|
||||
|
||||
@ -23,7 +23,7 @@ export const runtime = ():CommandRuntime => {
|
||||
menu.popup(bridge().window());
|
||||
},
|
||||
|
||||
mapStateToTitle(state:AppState):string {
|
||||
mapStateToTitle(state: AppState): string {
|
||||
if (!state.settings['spellChecker.enabled']) return null;
|
||||
const language = state.settings['spellChecker.language'];
|
||||
if (!language) return null;
|
||||
|
@ -3,15 +3,15 @@ import Setting from '@joplin/lib/models/Setting';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleEditors',
|
||||
label: () => _('Toggle editors'),
|
||||
iconName: 'fa-columns',
|
||||
};
|
||||
|
||||
export const runtime = ():CommandRuntime => {
|
||||
export const runtime = (): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext) => {
|
||||
execute: async (context: CommandContext) => {
|
||||
// A bit of a hack, but for now don't allow changing code view
|
||||
// while a note is being saved as it will cause a problem with
|
||||
// TinyMCE because it won't have time to send its content before
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleNoteList',
|
||||
label: () => _('Toggle note list'),
|
||||
iconName: 'fas fa-align-justify',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
comp.props.dispatch({
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleSideBar',
|
||||
label: () => _('Toggle sidebar'),
|
||||
iconName: 'fas fa-bars',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
comp.props.dispatch({
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'toggleVisiblePanes',
|
||||
label: () => _('Toggle editor layout'),
|
||||
iconName: 'icon-layout ',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
comp.props.dispatch({
|
||||
|
@ -28,8 +28,8 @@ const TemplateUtils = require('@joplin/lib/TemplateUtils');
|
||||
|
||||
const menuUtils = new MenuUtils(CommandService.instance());
|
||||
|
||||
function pluginMenuItemsCommandNames(menuItems:MenuItem[]):string[] {
|
||||
let output:string[] = [];
|
||||
function pluginMenuItemsCommandNames(menuItems: MenuItem[]): string[] {
|
||||
let output: string[] = [];
|
||||
for (const menuItem of menuItems) {
|
||||
if (menuItem.submenu) {
|
||||
output = output.concat(pluginMenuItemsCommandNames(menuItem.submenu));
|
||||
@ -40,8 +40,8 @@ function pluginMenuItemsCommandNames(menuItems:MenuItem[]):string[] {
|
||||
return output;
|
||||
}
|
||||
|
||||
function pluginCommandNames(plugins:PluginStates):string[] {
|
||||
let output:string[] = [];
|
||||
function pluginCommandNames(plugins: PluginStates): string[] {
|
||||
let output: string[] = [];
|
||||
|
||||
for (const view of pluginUtils.viewsByType(plugins, 'menu')) {
|
||||
output = output.concat(pluginMenuItemsCommandNames(view.menuItems));
|
||||
@ -54,8 +54,8 @@ function pluginCommandNames(plugins:PluginStates):string[] {
|
||||
return output;
|
||||
}
|
||||
|
||||
function createPluginMenuTree(label:string, menuItems:MenuItem[], onMenuItemClick:Function) {
|
||||
const output:any = {
|
||||
function createPluginMenuTree(label: string, menuItems: MenuItem[], onMenuItemClick: Function) {
|
||||
const output: any = {
|
||||
label: label,
|
||||
submenu: [],
|
||||
};
|
||||
@ -90,32 +90,32 @@ interface Props {
|
||||
['spellChecker.language']: string,
|
||||
}
|
||||
|
||||
const commandNames:string[] = menuCommandNames();
|
||||
const commandNames: string[] = menuCommandNames();
|
||||
|
||||
function menuItemSetChecked(id:string, checked:boolean) {
|
||||
function menuItemSetChecked(id: string, checked: boolean) {
|
||||
const menu = Menu.getApplicationMenu();
|
||||
const menuItem = menu.getMenuItemById(id);
|
||||
if (!menuItem) return;
|
||||
menuItem.checked = checked;
|
||||
}
|
||||
|
||||
function menuItemSetEnabled(id:string, enabled:boolean) {
|
||||
function menuItemSetEnabled(id: string, enabled: boolean) {
|
||||
const menu = Menu.getApplicationMenu();
|
||||
const menuItem = menu.getMenuItemById(id);
|
||||
if (!menuItem) return;
|
||||
menuItem.enabled = enabled;
|
||||
}
|
||||
|
||||
function useMenu(props:Props) {
|
||||
function useMenu(props: Props) {
|
||||
const [menu, setMenu] = useState(null);
|
||||
const [keymapLastChangeTime, setKeymapLastChangeTime] = useState(Date.now());
|
||||
const [modulesLastChangeTime, setModulesLastChangeTime] = useState(Date.now());
|
||||
|
||||
const onMenuItemClick = useCallback((commandName:string) => {
|
||||
const onMenuItemClick = useCallback((commandName: string) => {
|
||||
CommandService.instance().execute(commandName);
|
||||
}, []);
|
||||
|
||||
const onImportModuleClick = useCallback(async (module:Module, moduleSource:string) => {
|
||||
const onImportModuleClick = useCallback(async (module: Module, moduleSource: string) => {
|
||||
let path = null;
|
||||
|
||||
if (moduleSource === 'file') {
|
||||
@ -140,8 +140,8 @@ function useMenu(props:Props) {
|
||||
path,
|
||||
format: module.format,
|
||||
outputFormat: module.outputFormat,
|
||||
onProgress: (status:any) => {
|
||||
const statusStrings:string[] = Object.keys(status).map((key:string) => {
|
||||
onProgress: (status: any) => {
|
||||
const statusStrings: string[] = Object.keys(status).map((key: string) => {
|
||||
return `${key}: ${status[key]}`;
|
||||
});
|
||||
|
||||
@ -171,8 +171,8 @@ function useMenu(props:Props) {
|
||||
useEffect(() => {
|
||||
const keymapService = KeymapService.instance();
|
||||
|
||||
const pluginCommandNames = props.pluginMenuItems.map((view:any) => view.commandName);
|
||||
const menuItemDic = menuUtils.commandsToMenuItems(commandNames.concat(pluginCommandNames), (commandName:string) => onMenuItemClickRef.current(commandName));
|
||||
const pluginCommandNames = props.pluginMenuItems.map((view: any) => view.commandName);
|
||||
const menuItemDic = menuUtils.commandsToMenuItems(commandNames.concat(pluginCommandNames), (commandName: string) => onMenuItemClickRef.current(commandName));
|
||||
|
||||
const quitMenuItem = {
|
||||
label: _('Quit'),
|
||||
@ -180,7 +180,7 @@ function useMenu(props:Props) {
|
||||
click: () => { bridge().electronApp().quit(); },
|
||||
};
|
||||
|
||||
const sortNoteFolderItems = (type:string) => {
|
||||
const sortNoteFolderItems = (type: string) => {
|
||||
const sortItems = [];
|
||||
const sortOptions = Setting.enumOptions(`${type}.sortOrder.field`);
|
||||
for (const field in sortOptions) {
|
||||
@ -223,7 +223,7 @@ function useMenu(props:Props) {
|
||||
|
||||
const importItems = [];
|
||||
const exportItems = [];
|
||||
const templateItems:any[] = [];
|
||||
const templateItems: any[] = [];
|
||||
const ioService = InteropService.instance();
|
||||
const ioModules = ioService.modules();
|
||||
for (let i = 0; i < ioModules.length; i++) {
|
||||
@ -233,7 +233,7 @@ function useMenu(props:Props) {
|
||||
exportItems.push({
|
||||
label: module.fullLabel(),
|
||||
click: async () => {
|
||||
await InteropServiceHelper.export((action:any) => props.dispatch(action), module);
|
||||
await InteropServiceHelper.export((action: any) => props.dispatch(action), module);
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -314,10 +314,10 @@ function useMenu(props:Props) {
|
||||
},
|
||||
});
|
||||
|
||||
let toolsItems:any[] = [];
|
||||
let toolsItems: any[] = [];
|
||||
|
||||
// we need this workaround, because on macOS the menu is different
|
||||
const toolsItemsWindowsLinux:any[] = [
|
||||
const toolsItemsWindowsLinux: any[] = [
|
||||
{
|
||||
label: _('Options'),
|
||||
accelerator: keymapService.getAccelerator('config'),
|
||||
@ -494,7 +494,7 @@ function useMenu(props:Props) {
|
||||
});
|
||||
}
|
||||
|
||||
const rootMenus:any = {
|
||||
const rootMenus: any = {
|
||||
edit: {
|
||||
id: 'edit',
|
||||
label: _('&Edit'),
|
||||
@ -668,7 +668,7 @@ function useMenu(props:Props) {
|
||||
// It seems the "visible" property of separators is ignored by Electron, making
|
||||
// it display separators that we want hidden. So this function iterates through
|
||||
// them and remove them completely.
|
||||
const cleanUpSeparators = (items:any[]) => {
|
||||
const cleanUpSeparators = (items: any[]) => {
|
||||
const output = [];
|
||||
for (const item of items) {
|
||||
if ('visible' in item && item.type === 'separator' && !item.visible) continue;
|
||||
@ -694,7 +694,7 @@ function useMenu(props:Props) {
|
||||
}
|
||||
|
||||
for (const view of props.pluginMenuItems) {
|
||||
const location:MenuItemLocation = view.location;
|
||||
const location: MenuItemLocation = view.location;
|
||||
if (location === MenuItemLocation.Context) continue;
|
||||
|
||||
const itemParent = rootMenus[location];
|
||||
@ -713,7 +713,7 @@ function useMenu(props:Props) {
|
||||
if (!itemParent) {
|
||||
reg.logger().error('Menu location does not exist: ', location, view);
|
||||
} else {
|
||||
itemParent.submenu.push(createPluginMenuTree(view.label, view.menuItems, (commandName:string) => onMenuItemClickRef.current(commandName)));
|
||||
itemParent.submenu.push(createPluginMenuTree(view.label, view.menuItems, (commandName: string) => onMenuItemClickRef.current(commandName)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -765,7 +765,7 @@ function useMenu(props:Props) {
|
||||
menuItemSetChecked(`layoutButtonSequence_${value}`, props.layoutButtonSequence === Number(value));
|
||||
}
|
||||
|
||||
function applySortItemCheckState(type:string) {
|
||||
function applySortItemCheckState(type: string) {
|
||||
const sortOptions = Setting.enumOptions(`${type}.sortOrder.field`);
|
||||
for (const field in sortOptions) {
|
||||
if (!sortOptions.hasOwnProperty(field)) continue;
|
||||
@ -820,13 +820,13 @@ function useMenu(props:Props) {
|
||||
return menu;
|
||||
}
|
||||
|
||||
function MenuBar(props:Props):any {
|
||||
function MenuBar(props: Props): any {
|
||||
const menu = useMenu(props);
|
||||
if (menu) Menu.setApplicationMenu(menu);
|
||||
return null;
|
||||
}
|
||||
|
||||
const mapStateToProps = (state:AppState) => {
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
const whenClauseContext = stateToWhenClauseContext(state);
|
||||
|
||||
return {
|
||||
|
@ -14,8 +14,8 @@ interface MultiNoteActionsProps {
|
||||
plugins: PluginStates,
|
||||
}
|
||||
|
||||
function styles_(props:MultiNoteActionsProps) {
|
||||
return buildStyle('MultiNoteActions', props.themeId, (theme:any) => {
|
||||
function styles_(props: MultiNoteActionsProps) {
|
||||
return buildStyle('MultiNoteActions', props.themeId, (theme: any) => {
|
||||
return {
|
||||
root: {
|
||||
display: 'inline-flex',
|
||||
@ -35,10 +35,10 @@ function styles_(props:MultiNoteActionsProps) {
|
||||
});
|
||||
}
|
||||
|
||||
export default function MultiNoteActions(props:MultiNoteActionsProps) {
|
||||
export default function MultiNoteActions(props: MultiNoteActionsProps) {
|
||||
const styles = styles_(props);
|
||||
|
||||
const multiNotesButton_click = (item:any) => {
|
||||
const multiNotesButton_click = (item: any) => {
|
||||
if (item.submenu) {
|
||||
item.submenu.popup(bridge().window());
|
||||
} else {
|
||||
|
@ -21,15 +21,15 @@ interface KeyToLabelMap {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
let markupToHtml_:any = null;
|
||||
let markupToHtml_: any = null;
|
||||
function markupToHtml() {
|
||||
if (markupToHtml_) return markupToHtml_;
|
||||
markupToHtml_ = markupLanguageUtils.newMarkupToHtml();
|
||||
return markupToHtml_;
|
||||
}
|
||||
|
||||
function countElements(text:string, wordSetter:Function, characterSetter:Function, characterNoSpaceSetter:Function, lineSetter:Function) {
|
||||
Countable.count(text, (counter:any) => {
|
||||
function countElements(text: string, wordSetter: Function, characterSetter: Function, characterNoSpaceSetter: Function, lineSetter: Function) {
|
||||
Countable.count(text, (counter: any) => {
|
||||
wordSetter(counter.words);
|
||||
characterSetter(counter.all);
|
||||
characterNoSpaceSetter(counter.characters);
|
||||
@ -45,7 +45,7 @@ function formatReadTime(readTimeMinutes: number) {
|
||||
return Math.ceil(readTimeMinutes).toString();
|
||||
}
|
||||
|
||||
export default function NoteContentPropertiesDialog(props:NoteContentPropertiesDialogProps) {
|
||||
export default function NoteContentPropertiesDialog(props: NoteContentPropertiesDialogProps) {
|
||||
const theme = themeStyle(props.themeId);
|
||||
const tableBodyComps: any[] = [];
|
||||
// For the source Markdown
|
||||
|
@ -100,7 +100,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
resetScroll: () => {
|
||||
resetScroll();
|
||||
},
|
||||
scrollTo: (options:ScrollOptions) => {
|
||||
scrollTo: (options: ScrollOptions) => {
|
||||
if (options.type === ScrollOptionTypes.Hash) {
|
||||
if (!webviewRef.current) return;
|
||||
webviewRef.current.wrappedInstance.send('scrollToHash', options.value as string);
|
||||
@ -156,7 +156,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
selectedHtml: () => {
|
||||
return selectedText();
|
||||
},
|
||||
replaceSelection: (value:any) => {
|
||||
replaceSelection: (value: any) => {
|
||||
return editorRef.current.replaceSelection(value);
|
||||
},
|
||||
textBold: () => wrapSelectionWithStrings('**', '**', _('strong text')),
|
||||
@ -293,9 +293,9 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
menu.popup(bridge().window());
|
||||
}, [props.content, editorCutText, editorPasteText, editorCopyText, onEditorPaste]);
|
||||
|
||||
const loadScript = async (script:any) => {
|
||||
const loadScript = async (script: any) => {
|
||||
return new Promise((resolve) => {
|
||||
let element:any = document.createElement('script');
|
||||
let element: any = document.createElement('script');
|
||||
if (script.src.indexOf('.css') >= 0) {
|
||||
element = document.createElement('link');
|
||||
element.rel = 'stylesheet';
|
||||
@ -324,7 +324,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
let cancelled = false;
|
||||
|
||||
async function loadScripts() {
|
||||
const scriptsToLoad:{src: string, id:string, loaded: boolean}[] = [
|
||||
const scriptsToLoad: {src: string, id: string, loaded: boolean}[] = [
|
||||
{
|
||||
src: 'node_modules/codemirror/addon/dialog/dialog.css',
|
||||
id: 'codemirrorDialogStyle',
|
||||
|
@ -13,7 +13,7 @@ interface ToolbarProps {
|
||||
toolbarButtonInfos: ToolbarButtonInfo[],
|
||||
}
|
||||
|
||||
function styles_(props:ToolbarProps) {
|
||||
function styles_(props: ToolbarProps) {
|
||||
return buildStyle('CodeMirrorToolbar', props.themeId, () => {
|
||||
return {
|
||||
root: {
|
||||
@ -26,7 +26,7 @@ function styles_(props:ToolbarProps) {
|
||||
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(CommandService.instance());
|
||||
|
||||
function Toolbar(props:ToolbarProps) {
|
||||
function Toolbar(props: ToolbarProps) {
|
||||
const styles = styles_(props);
|
||||
return <ToolbarBase style={styles.root} items={props.toolbarButtonInfos} />;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ export function useScrollHandler(editorRef: any, webviewRef: any, onScroll: Func
|
||||
}
|
||||
|
||||
|
||||
export function useRootSize(dependencies:any) {
|
||||
export function useRootSize(dependencies: any) {
|
||||
const { rootRef } = dependencies;
|
||||
|
||||
const [rootSize, setRootSize] = useState({ width: 0, height: 0 });
|
||||
|
@ -22,7 +22,7 @@ const { themeStyle } = require('@joplin/lib/theme');
|
||||
const { clipboard } = require('electron');
|
||||
const supportedLocales = require('./supportedLocales');
|
||||
|
||||
function markupRenderOptions(override:any = null) {
|
||||
function markupRenderOptions(override: any = null) {
|
||||
return {
|
||||
plugins: {
|
||||
checkbox: {
|
||||
@ -37,7 +37,7 @@ function markupRenderOptions(override:any = null) {
|
||||
};
|
||||
}
|
||||
|
||||
function findBlockSource(node:any) {
|
||||
function findBlockSource(node: any) {
|
||||
const sources = node.getElementsByClassName('joplin-source');
|
||||
if (!sources.length) throw new Error('No source for node');
|
||||
const source = sources[0];
|
||||
@ -51,7 +51,7 @@ function findBlockSource(node:any) {
|
||||
};
|
||||
}
|
||||
|
||||
function newBlockSource(language:string = '', content:string = ''):any {
|
||||
function newBlockSource(language: string = '', content: string = ''): any {
|
||||
const fence = language === 'katex' ? '$$' : '```';
|
||||
const fenceLanguage = language === 'katex' ? '' : language;
|
||||
|
||||
@ -64,7 +64,7 @@ function newBlockSource(language:string = '', content:string = ''):any {
|
||||
};
|
||||
}
|
||||
|
||||
function findEditableContainer(node:any):any {
|
||||
function findEditableContainer(node: any): any {
|
||||
while (node) {
|
||||
if (node.classList && node.classList.contains('joplin-editable')) return node;
|
||||
node = node.parentNode;
|
||||
@ -72,7 +72,7 @@ function findEditableContainer(node:any):any {
|
||||
return null;
|
||||
}
|
||||
|
||||
function editableInnerHtml(html:string):string {
|
||||
function editableInnerHtml(html: string): string {
|
||||
const temp = document.createElement('div');
|
||||
temp.innerHTML = html;
|
||||
const editable = temp.getElementsByClassName('joplin-editable');
|
||||
@ -80,14 +80,14 @@ function editableInnerHtml(html:string):string {
|
||||
return editable[0].innerHTML;
|
||||
}
|
||||
|
||||
function dialogTextArea_keyDown(event:any) {
|
||||
function dialogTextArea_keyDown(event: any) {
|
||||
if (event.key === 'Tab') {
|
||||
window.requestAnimationFrame(() => event.target.focus());
|
||||
}
|
||||
}
|
||||
|
||||
let markupToHtml_ = new MarkupToHtml();
|
||||
function stripMarkup(markupLanguage:number, markup:string, options:any = null) {
|
||||
function stripMarkup(markupLanguage: number, markup: string, options: any = null) {
|
||||
if (!markupToHtml_) markupToHtml_ = new MarkupToHtml();
|
||||
return markupToHtml_.stripMarkup(markupLanguage, markup, options);
|
||||
}
|
||||
@ -95,7 +95,7 @@ function stripMarkup(markupLanguage:number, markup:string, options:any = null) {
|
||||
// Allows pressing tab in a textarea to input an actual tab (instead of changing focus)
|
||||
// taboverride will take care of actually inserting the tab character, while the keydown
|
||||
// event listener will override the default behaviour, which is to focus the next field.
|
||||
function enableTextAreaTab(enable:boolean) {
|
||||
function enableTextAreaTab(enable: boolean) {
|
||||
const textAreas = document.getElementsByClassName('tox-textarea');
|
||||
for (const textArea of textAreas) {
|
||||
taboverride.set(textArea, enable);
|
||||
@ -115,22 +115,22 @@ interface TinyMceCommand {
|
||||
}
|
||||
|
||||
interface JoplinCommandToTinyMceCommands {
|
||||
[key:string]: TinyMceCommand,
|
||||
[key: string]: TinyMceCommand,
|
||||
}
|
||||
|
||||
const joplinCommandToTinyMceCommands:JoplinCommandToTinyMceCommands = {
|
||||
const joplinCommandToTinyMceCommands: JoplinCommandToTinyMceCommands = {
|
||||
'textBold': { name: 'mceToggleFormat', value: 'bold' },
|
||||
'textItalic': { name: 'mceToggleFormat', value: 'italic' },
|
||||
'textLink': { name: 'mceLink' },
|
||||
'search': { name: 'SearchReplace' },
|
||||
};
|
||||
|
||||
let loadedCssFiles_:string[] = [];
|
||||
let loadedJsFiles_:string[] = [];
|
||||
let dispatchDidUpdateIID_:any = null;
|
||||
let changeId_:number = 1;
|
||||
let loadedCssFiles_: string[] = [];
|
||||
let loadedJsFiles_: string[] = [];
|
||||
let dispatchDidUpdateIID_: any = null;
|
||||
let changeId_: number = 1;
|
||||
|
||||
const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
const [editor, setEditor] = useState(null);
|
||||
const [scriptLoaded, setScriptLoaded] = useState(false);
|
||||
const [editorReady, setEditorReady] = useState(false);
|
||||
@ -162,7 +162,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
|
||||
usePluginServiceRegistration(ref);
|
||||
|
||||
const dispatchDidUpdate = (editor:any) => {
|
||||
const dispatchDidUpdate = (editor: any) => {
|
||||
if (dispatchDidUpdateIID_) shim.clearTimeout(dispatchDidUpdateIID_);
|
||||
dispatchDidUpdateIID_ = shim.setTimeout(() => {
|
||||
dispatchDidUpdateIID_ = null;
|
||||
@ -170,7 +170,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
}, 10);
|
||||
};
|
||||
|
||||
const insertResourcesIntoContent = useCallback(async (filePaths:string[] = null, options:any = null) => {
|
||||
const insertResourcesIntoContent = useCallback(async (filePaths: string[] = null, options: any = null) => {
|
||||
const resourceMd = await commandAttachFileToBody('', filePaths, options);
|
||||
if (!resourceMd) return;
|
||||
const result = await props.markupToHtml(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, resourceMd, markupRenderOptions({ bodyOnly: true }));
|
||||
@ -182,7 +182,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
const insertResourcesIntoContentRef = useRef(null);
|
||||
insertResourcesIntoContentRef.current = insertResourcesIntoContent;
|
||||
|
||||
const onEditorContentClick = useCallback((event:any) => {
|
||||
const onEditorContentClick = useCallback((event: any) => {
|
||||
const nodeName = event.target ? event.target.nodeName : '';
|
||||
|
||||
if (nodeName === 'INPUT' && event.target.getAttribute('type') === 'checkbox') {
|
||||
@ -216,7 +216,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
resetScroll: () => {
|
||||
if (editor) editor.getWin().scrollTo(0,0);
|
||||
},
|
||||
scrollTo: (options:ScrollOptions) => {
|
||||
scrollTo: (options: ScrollOptions) => {
|
||||
if (!editor) return;
|
||||
|
||||
if (options.type === ScrollOptionTypes.Hash) {
|
||||
@ -232,11 +232,11 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
throw new Error(`Unsupported scroll options: ${options.type}`);
|
||||
}
|
||||
},
|
||||
supportsCommand: (name:string) => {
|
||||
supportsCommand: (name: string) => {
|
||||
// TODO: should also handle commands that are not in this map (insertText, focus, etc);
|
||||
return !!joplinCommandToTinyMceCommands[name];
|
||||
},
|
||||
execCommand: async (cmd:EditorCommand) => {
|
||||
execCommand: async (cmd: EditorCommand) => {
|
||||
if (!editor) return false;
|
||||
|
||||
reg.logger().debug('TinyMce: execCommand', cmd);
|
||||
@ -263,14 +263,14 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
|
||||
if (commandProcessed) return true;
|
||||
|
||||
const additionalCommands:any = {
|
||||
const additionalCommands: any = {
|
||||
selectedText: () => {
|
||||
return stripMarkup(MarkupToHtml.MARKUP_LANGUAGE_HTML, editor.selection.getContent());
|
||||
},
|
||||
selectedHtml: () => {
|
||||
return editor.selection.getContent();
|
||||
},
|
||||
replaceSelection: (value:any) => {
|
||||
replaceSelection: (value: any) => {
|
||||
editor.selection.setContent(value);
|
||||
},
|
||||
};
|
||||
@ -284,7 +284,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
const tinyMceCmd:TinyMceCommand = { ...joplinCommandToTinyMceCommands[cmd.name] };
|
||||
const tinyMceCmd: TinyMceCommand = { ...joplinCommandToTinyMceCommands[cmd.name] };
|
||||
if (!('ui' in tinyMceCmd)) tinyMceCmd.ui = false;
|
||||
if (!('value' in tinyMceCmd)) tinyMceCmd.value = null;
|
||||
|
||||
@ -301,9 +301,9 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
// module would not load these extra files.
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
const loadScript = async (script:any) => {
|
||||
const loadScript = async (script: any) => {
|
||||
return new Promise((resolve) => {
|
||||
let element:any = document.createElement('script');
|
||||
let element: any = document.createElement('script');
|
||||
if (script.src.indexOf('.css') >= 0) {
|
||||
element = document.createElement('link');
|
||||
element.rel = 'stylesheet';
|
||||
@ -332,7 +332,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
let cancelled = false;
|
||||
|
||||
async function loadScripts() {
|
||||
const scriptsToLoad:any[] = [
|
||||
const scriptsToLoad: any[] = [
|
||||
{
|
||||
src: 'node_modules/tinymce/tinymce.min.js',
|
||||
id: 'tinyMceScript',
|
||||
@ -510,7 +510,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
const loadEditor = async () => {
|
||||
const language = closestSupportedLocale(props.locale, true, supportedLocales);
|
||||
|
||||
const pluginCommandNames:string[] = [];
|
||||
const pluginCommandNames: string[] = [];
|
||||
|
||||
const infos = pluginUtils.viewInfosByType(props.plugins, 'toolbarButton');
|
||||
|
||||
@ -551,9 +551,9 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
localization_function: _,
|
||||
contextmenu: false,
|
||||
browser_spellcheck: true,
|
||||
setup: (editor:any) => {
|
||||
setup: (editor: any) => {
|
||||
|
||||
function openEditDialog(editable:any) {
|
||||
function openEditDialog(editable: any) {
|
||||
const source = editable ? findBlockSource(editable) : newBlockSource();
|
||||
|
||||
editor.windowManager.open({
|
||||
@ -563,7 +563,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
codeTextArea: source.content,
|
||||
languageInput: source.language,
|
||||
},
|
||||
onSubmit: async (dialogApi:any) => {
|
||||
onSubmit: async (dialogApi: any) => {
|
||||
const newSource = newBlockSource(dialogApi.getData().languageInput, dialogApi.getData().codeTextArea);
|
||||
const md = `${newSource.openCharacters}${newSource.content.trim()}${newSource.closeCharacters}`;
|
||||
const result = await markupToHtml.current(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, md, { bodyOnly: true });
|
||||
@ -638,7 +638,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
onAction: function() {
|
||||
editor.execCommand('mceToggleFormat', false, 'code', { class: 'inline-code' });
|
||||
},
|
||||
onSetup: function(api:any) {
|
||||
onSetup: function(api: any) {
|
||||
api.setActive(editor.formatter.match('code'));
|
||||
const unbind = editor.formatter.formatChanged('code', api.setActive).unbind;
|
||||
|
||||
@ -669,17 +669,17 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
setupContextMenu(editor);
|
||||
|
||||
// TODO: remove event on unmount?
|
||||
editor.on('DblClick', (event:any) => {
|
||||
editor.on('DblClick', (event: any) => {
|
||||
const editable = findEditableContainer(event.target);
|
||||
if (editable) openEditDialog(editable);
|
||||
});
|
||||
|
||||
// This is triggered when an external file is dropped on the editor
|
||||
editor.on('drop', (event:any) => {
|
||||
editor.on('drop', (event: any) => {
|
||||
props_onDrop.current(event);
|
||||
});
|
||||
|
||||
editor.on('ObjectResized', function(event:any) {
|
||||
editor.on('ObjectResized', function(event: any) {
|
||||
if (event.target.nodeName === 'IMG') {
|
||||
editor.fire('joplinChange');
|
||||
dispatchDidUpdate(editor);
|
||||
@ -706,7 +706,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
// Set the initial content and load the plugin CSS and JS files
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
const loadDocumentAssets = (editor:any, pluginAssets:any[]) => {
|
||||
const loadDocumentAssets = (editor: any, pluginAssets: any[]) => {
|
||||
// Note: The way files are cached is not correct because it assumes there's only one version
|
||||
// of each file. However, when the theme change, a new CSS file, specific to the theme, is
|
||||
// created. That file should not be loaded on top of the previous one, but as a replacement.
|
||||
@ -720,7 +720,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
|
||||
const theme = themeStyle(props.themeId);
|
||||
|
||||
let docHead_:any = null;
|
||||
let docHead_: any = null;
|
||||
|
||||
function docHead() {
|
||||
if (docHead_) return docHead_;
|
||||
@ -733,15 +733,15 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
`gui/note-viewer/pluginAssets/highlight.js/${theme.codeThemeCss}`,
|
||||
].concat(
|
||||
pluginAssets
|
||||
.filter((a:any) => a.mime === 'text/css')
|
||||
.map((a:any) => a.path)
|
||||
).filter((path:string) => !loadedCssFiles_.includes(path));
|
||||
.filter((a: any) => a.mime === 'text/css')
|
||||
.map((a: any) => a.path)
|
||||
).filter((path: string) => !loadedCssFiles_.includes(path));
|
||||
|
||||
const jsFiles = [].concat(
|
||||
pluginAssets
|
||||
.filter((a:any) => a.mime === 'application/javascript')
|
||||
.map((a:any) => a.path)
|
||||
).filter((path:string) => !loadedJsFiles_.includes(path));
|
||||
.filter((a: any) => a.mime === 'application/javascript')
|
||||
.map((a: any) => a.path)
|
||||
).filter((path: string) => !loadedJsFiles_.includes(path));
|
||||
|
||||
for (const cssFile of cssFiles) loadedCssFiles_.push(cssFile);
|
||||
for (const jsFile of jsFiles) loadedJsFiles_.push(jsFile);
|
||||
@ -937,8 +937,8 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function onExecCommand(event:any) {
|
||||
const c:string = event.command;
|
||||
function onExecCommand(event: any) {
|
||||
const c: string = event.command;
|
||||
if (!c) return;
|
||||
|
||||
// We need to dispatch onChange for these commands:
|
||||
@ -972,13 +972,13 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
// onChange even though nothing is changed. The alternative would be to
|
||||
// check the content before and after, but this is too slow, so let's
|
||||
// keep it this way for now.
|
||||
function onKeyUp(event:any) {
|
||||
function onKeyUp(event: any) {
|
||||
if (['Backspace', 'Delete', 'Enter', 'Tab'].includes(event.key)) {
|
||||
onChangeHandler();
|
||||
}
|
||||
}
|
||||
|
||||
async function onPaste(event:any) {
|
||||
async function onPaste(event: any) {
|
||||
const resourceMds = await handlePasteEvent(event);
|
||||
if (resourceMds.length) {
|
||||
const result = await markupToHtml.current(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, resourceMds.join('\n'), markupRenderOptions({ bodyOnly: true }));
|
||||
@ -1000,7 +1000,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
}
|
||||
}
|
||||
|
||||
function onKeyDown(event:any) {
|
||||
function onKeyDown(event: any) {
|
||||
// Handle "paste as text". Note that when pressing CtrlOrCmd+Shift+V it's going
|
||||
// to trigger the "keydown" event but not the "paste" event, so it's ok to process
|
||||
// it here and we don't need to do anything special in onPaste
|
||||
@ -1053,7 +1053,7 @@ const TinyMCE = (props:NoteBodyEditorProps, ref:any) => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
function renderExtraToolbarButton(key:string, info:ToolbarButtonInfo) {
|
||||
function renderExtraToolbarButton(key: string, info: ToolbarButtonInfo) {
|
||||
return <ToolbarButton
|
||||
key={key}
|
||||
themeId={props.themeId}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { NoteBodyEditorProps } from '../../../utils/types';
|
||||
const { buildStyle } = require('@joplin/lib/theme');
|
||||
|
||||
export default function styles(props:NoteBodyEditorProps) {
|
||||
return buildStyle(['TinyMCE', props.style.width, props.style.height], props.themeId, (theme:any) => {
|
||||
export default function styles(props: NoteBodyEditorProps) {
|
||||
return buildStyle(['TinyMCE', props.style.width, props.style.height], props.themeId, (theme: any) => {
|
||||
const extraToolbarContainer = {
|
||||
backgroundColor: theme.backgroundColor3,
|
||||
display: 'flex',
|
||||
|
@ -6,7 +6,7 @@ const Resource = require('@joplin/lib/models/Resource');
|
||||
// x and y are the absolute coordinates, as returned by the context-menu event
|
||||
// handler on the webContent. This function will return null if the point is
|
||||
// not within the TinyMCE editor.
|
||||
function contextMenuElement(editor:any, x:number, y:number) {
|
||||
function contextMenuElement(editor: any, x: number, y: number) {
|
||||
if (!editor || !editor.getDoc()) return null;
|
||||
|
||||
const iframes = document.getElementsByClassName('tox-edit-area__iframe');
|
||||
@ -27,16 +27,16 @@ interface ContextMenuActionOptions {
|
||||
current: ContextMenuOptions,
|
||||
}
|
||||
|
||||
const contextMenuActionOptions:ContextMenuActionOptions = { current: null };
|
||||
const contextMenuActionOptions: ContextMenuActionOptions = { current: null };
|
||||
|
||||
export default function(editor:any) {
|
||||
export default function(editor: any) {
|
||||
const contextMenuItems = menuItems();
|
||||
|
||||
bridge().window().webContents.on('context-menu', (_event:any, params:any) => {
|
||||
bridge().window().webContents.on('context-menu', (_event: any, params: any) => {
|
||||
const element = contextMenuElement(editor, params.x, params.y);
|
||||
if (!element) return;
|
||||
|
||||
let itemType:ContextMenuItemType = ContextMenuItemType.None;
|
||||
let itemType: ContextMenuItemType = ContextMenuItemType.None;
|
||||
let resourceId = '';
|
||||
let linkToCopy = null;
|
||||
|
||||
@ -57,7 +57,7 @@ export default function(editor:any) {
|
||||
linkToCopy,
|
||||
textToCopy: null,
|
||||
htmlToCopy: editor.selection ? editor.selection.getContent() : '',
|
||||
insertContent: (content:string) => {
|
||||
insertContent: (content: string) => {
|
||||
editor.insertContent(content);
|
||||
},
|
||||
isReadOnly: false,
|
||||
|
@ -2,11 +2,11 @@ import { useEffect, useCallback, useRef } from 'react';
|
||||
import shim from '@joplin/lib/shim';
|
||||
|
||||
interface HookDependencies {
|
||||
editor:any,
|
||||
editor: any,
|
||||
onScroll: Function,
|
||||
}
|
||||
|
||||
export default function useScroll(dependencies:HookDependencies) {
|
||||
export default function useScroll(dependencies: HookDependencies) {
|
||||
const { editor, onScroll } = dependencies;
|
||||
const scrollTimeoutId_ = useRef(null);
|
||||
|
||||
@ -37,7 +37,7 @@ export default function useScroll(dependencies:HookDependencies) {
|
||||
return m <= 0 ? 0 : t / m;
|
||||
}, [maxScrollTop, scrollTop]);
|
||||
|
||||
const scrollToPercent = useCallback((percent:number) => {
|
||||
const scrollToPercent = useCallback((percent: number) => {
|
||||
if (!editor) return;
|
||||
editor.getWin().scrollTo(0, maxScrollTop() * percent);
|
||||
}, [editor, maxScrollTop]);
|
||||
|
@ -55,7 +55,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
const isMountedRef = useRef(true);
|
||||
const noteSearchBarRef = useRef(null);
|
||||
|
||||
const formNote_beforeLoad = useCallback(async (event:OnLoadEvent) => {
|
||||
const formNote_beforeLoad = useCallback(async (event: OnLoadEvent) => {
|
||||
await saveNoteIfWillChange(event.formNote);
|
||||
setShowRevisions(false);
|
||||
}, []);
|
||||
@ -106,7 +106,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
return async function() {
|
||||
const note = await formNoteToNote(formNote);
|
||||
reg.logger().debug('Saving note...', note);
|
||||
const savedNote:any = await Note.save(note);
|
||||
const savedNote: any = await Note.save(note);
|
||||
|
||||
setFormNote((prev: FormNote) => {
|
||||
return { ...prev, user_updated_time: savedNote.user_updated_time };
|
||||
@ -334,7 +334,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
});
|
||||
}, [props.dispatch, formNote]);
|
||||
|
||||
function renderNoNotes(rootStyle:any) {
|
||||
function renderNoNotes(rootStyle: any) {
|
||||
const emptyDivStyle = Object.assign(
|
||||
{
|
||||
backgroundColor: 'black',
|
||||
@ -365,7 +365,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
|
||||
const searchMarkers = useSearchMarkers(showLocalSearch, localSearchMarkerOptions, props.searches, props.selectedSearchId, props.highlightedWords);
|
||||
|
||||
const editorProps:NoteBodyEditorProps = {
|
||||
const editorProps: NoteBodyEditorProps = {
|
||||
ref: editorRef,
|
||||
contentKey: formNote.id,
|
||||
style: styles.tinyMCE,
|
||||
@ -417,7 +417,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
if (showRevisions) {
|
||||
const theme = themeStyle(props.themeId);
|
||||
|
||||
const revStyle:any = {
|
||||
const revStyle: any = {
|
||||
// ...props.style,
|
||||
display: 'inline-flex',
|
||||
padding: theme.margin,
|
||||
|
@ -13,7 +13,7 @@ interface Props {
|
||||
noteIsTodo: number,
|
||||
isProvisional: boolean,
|
||||
titleInputRef: any,
|
||||
onTitleChange(event: ChangeEvent<HTMLInputElement>):void,
|
||||
onTitleChange(event: ChangeEvent<HTMLInputElement>): void,
|
||||
}
|
||||
|
||||
function styles_(props: Props) {
|
||||
@ -52,10 +52,10 @@ function styles_(props: Props) {
|
||||
});
|
||||
}
|
||||
|
||||
export default function NoteTitleBar(props:Props) {
|
||||
export default function NoteTitleBar(props: Props) {
|
||||
const styles = styles_(props);
|
||||
|
||||
const onTitleKeydown = useCallback((event:any) => {
|
||||
const onTitleKeydown = useCallback((event: any) => {
|
||||
const keyCode = event.keyCode;
|
||||
|
||||
if (keyCode === 9) { // TAB
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
const declarations:CommandDeclaration[] = [
|
||||
const declarations: CommandDeclaration[] = [
|
||||
{
|
||||
name: 'insertText',
|
||||
},
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'focusElementNoteBody',
|
||||
label: () => _('Note body'),
|
||||
parentLabel: () => _('Focus'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
comp.editorRef.current.execCommand({ name: 'focus' });
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'focusElementNoteTitle',
|
||||
label: () => _('Note title'),
|
||||
parentLabel: () => _('Focus'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
if (!comp.titleInputRef.current) return;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'showLocalSearch',
|
||||
label: () => _('Search in current note'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
if (comp.editorRef.current && comp.editorRef.current.supportsCommand('search')) {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'showRevisions',
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
comp.setShowRevisions(true);
|
||||
|
@ -34,16 +34,16 @@ interface ContextMenuItem {
|
||||
}
|
||||
|
||||
interface ContextMenuItems {
|
||||
[key:string]: ContextMenuItem;
|
||||
[key: string]: ContextMenuItem;
|
||||
}
|
||||
|
||||
async function resourceInfo(options:ContextMenuOptions):Promise<any> {
|
||||
async function resourceInfo(options: ContextMenuOptions): Promise<any> {
|
||||
const resource = options.resourceId ? await Resource.load(options.resourceId) : null;
|
||||
const resourcePath = resource ? Resource.fullPath(resource) : '';
|
||||
return { resource, resourcePath };
|
||||
}
|
||||
|
||||
function handleCopyToClipboard(options:ContextMenuOptions) {
|
||||
function handleCopyToClipboard(options: ContextMenuOptions) {
|
||||
if (options.textToCopy) {
|
||||
clipboard.writeText(options.textToCopy);
|
||||
} else if (options.htmlToCopy) {
|
||||
@ -51,11 +51,11 @@ function handleCopyToClipboard(options:ContextMenuOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
export function menuItems():ContextMenuItems {
|
||||
export function menuItems(): ContextMenuItems {
|
||||
return {
|
||||
open: {
|
||||
label: _('Open...'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
try {
|
||||
await ResourceEditWatcher.instance().openAndWatch(options.resourceId);
|
||||
} catch (error) {
|
||||
@ -63,11 +63,11 @@ export function menuItems():ContextMenuItems {
|
||||
bridge().showErrorMessageBox(error.message);
|
||||
}
|
||||
},
|
||||
isActive: (itemType:ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
isActive: (itemType: ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
},
|
||||
saveAs: {
|
||||
label: _('Save as...'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
const { resourcePath, resource } = await resourceInfo(options);
|
||||
const filePath = bridge().showSaveDialog({
|
||||
defaultPath: resource.filename ? resource.filename : resource.title,
|
||||
@ -75,58 +75,58 @@ export function menuItems():ContextMenuItems {
|
||||
if (!filePath) return;
|
||||
await fs.copy(resourcePath, filePath);
|
||||
},
|
||||
isActive: (itemType:ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
isActive: (itemType: ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
},
|
||||
revealInFolder: {
|
||||
label: _('Reveal file in folder'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
const { resourcePath } = await resourceInfo(options);
|
||||
bridge().showItemInFolder(resourcePath);
|
||||
},
|
||||
isActive: (itemType:ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
isActive: (itemType: ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
},
|
||||
copyPathToClipboard: {
|
||||
label: _('Copy path to clipboard'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
const { resourcePath } = await resourceInfo(options);
|
||||
clipboard.writeText(toSystemSlashes(resourcePath));
|
||||
},
|
||||
isActive: (itemType:ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
isActive: (itemType: ContextMenuItemType) => itemType === ContextMenuItemType.Image || itemType === ContextMenuItemType.Resource,
|
||||
},
|
||||
cut: {
|
||||
label: _('Cut'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
handleCopyToClipboard(options);
|
||||
options.insertContent('');
|
||||
},
|
||||
isActive: (_itemType:ContextMenuItemType, options:ContextMenuOptions) => !options.isReadOnly && (!!options.textToCopy || !!options.htmlToCopy),
|
||||
isActive: (_itemType: ContextMenuItemType, options: ContextMenuOptions) => !options.isReadOnly && (!!options.textToCopy || !!options.htmlToCopy),
|
||||
},
|
||||
copy: {
|
||||
label: _('Copy'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
handleCopyToClipboard(options);
|
||||
},
|
||||
isActive: (_itemType:ContextMenuItemType, options:ContextMenuOptions) => !!options.textToCopy || !!options.htmlToCopy,
|
||||
isActive: (_itemType: ContextMenuItemType, options: ContextMenuOptions) => !!options.textToCopy || !!options.htmlToCopy,
|
||||
},
|
||||
paste: {
|
||||
label: _('Paste'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
const content = clipboard.readHTML() ? clipboard.readHTML() : clipboard.readText();
|
||||
options.insertContent(content);
|
||||
},
|
||||
isActive: (_itemType:ContextMenuItemType, options:ContextMenuOptions) => !options.isReadOnly && (!!clipboard.readText() || !!clipboard.readHTML()),
|
||||
isActive: (_itemType: ContextMenuItemType, options: ContextMenuOptions) => !options.isReadOnly && (!!clipboard.readText() || !!clipboard.readHTML()),
|
||||
},
|
||||
copyLinkUrl: {
|
||||
label: _('Copy Link Address'),
|
||||
onAction: async (options:ContextMenuOptions) => {
|
||||
onAction: async (options: ContextMenuOptions) => {
|
||||
clipboard.writeText(options.linkToCopy !== null ? options.linkToCopy : options.textToCopy);
|
||||
},
|
||||
isActive: (itemType:ContextMenuItemType, options:ContextMenuOptions) => itemType === ContextMenuItemType.Link || !!options.linkToCopy,
|
||||
isActive: (itemType: ContextMenuItemType, options: ContextMenuOptions) => itemType === ContextMenuItemType.Link || !!options.linkToCopy,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function contextMenu(options:ContextMenuOptions) {
|
||||
export default async function contextMenu(options: ContextMenuOptions) {
|
||||
const menu = new Menu();
|
||||
|
||||
const items = menuItems();
|
||||
|
@ -4,7 +4,7 @@ const HtmlToMd = require('@joplin/lib/HtmlToMd');
|
||||
const Note = require('@joplin/lib/models/Note');
|
||||
const { MarkupToHtml } = require('@joplin/renderer');
|
||||
|
||||
export async function htmlToMarkdown(markupLanguage: number, html: string, originalCss:string): Promise<string> {
|
||||
export async function htmlToMarkdown(markupLanguage: number, html: string, originalCss: string): Promise<string> {
|
||||
let newBody = '';
|
||||
|
||||
if (markupLanguage === MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN) {
|
||||
|
@ -52,7 +52,7 @@ export async function attachedResources(noteBody: string): Promise<any> {
|
||||
return output;
|
||||
}
|
||||
|
||||
export async function commandAttachFileToBody(body:string, filePaths:string[] = null, options:any = null) {
|
||||
export async function commandAttachFileToBody(body: string, filePaths: string[] = null, options: any = null) {
|
||||
options = {
|
||||
createFileURL: false,
|
||||
position: 0,
|
||||
@ -101,7 +101,7 @@ export function resourcesStatus(resourceInfos: any) {
|
||||
return joplinRendererUtils.resourceStatusName(lowestIndex);
|
||||
}
|
||||
|
||||
export async function handlePasteEvent(event:any) {
|
||||
export async function handlePasteEvent(event: any) {
|
||||
const output = [];
|
||||
const formats = clipboard.availableFormats();
|
||||
for (let i = 0; i < formats.length; i++) {
|
||||
|
@ -4,7 +4,7 @@ import { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUt
|
||||
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
|
||||
|
||||
export interface ToolbarButtonInfos {
|
||||
[key:string]: ToolbarButtonInfo;
|
||||
[key: string]: ToolbarButtonInfo;
|
||||
}
|
||||
|
||||
export interface NoteEditorProps {
|
||||
@ -109,7 +109,7 @@ export interface FormNote {
|
||||
originalCss: string,
|
||||
}
|
||||
|
||||
export function defaultFormNote():FormNote {
|
||||
export function defaultFormNote(): FormNote {
|
||||
return {
|
||||
id: '',
|
||||
parent_id: '',
|
||||
@ -133,7 +133,7 @@ export interface ResourceInfo {
|
||||
}
|
||||
|
||||
export interface ResourceInfos {
|
||||
[index:string]: ResourceInfo,
|
||||
[index: string]: ResourceInfo,
|
||||
}
|
||||
|
||||
export enum ScrollOptionTypes {
|
||||
|
@ -2,13 +2,13 @@ import { useCallback } from 'react';
|
||||
const Note = require('@joplin/lib/models/Note.js');
|
||||
|
||||
interface HookDependencies {
|
||||
editorRef:any,
|
||||
editorRef: any,
|
||||
}
|
||||
|
||||
export default function useDropHandler(dependencies:HookDependencies) {
|
||||
export default function useDropHandler(dependencies: HookDependencies) {
|
||||
const { editorRef } = dependencies;
|
||||
|
||||
return useCallback(async (event:any) => {
|
||||
return useCallback(async (event: any) => {
|
||||
const dt = event.dataTransfer;
|
||||
dt.dropEffect = 'copy';
|
||||
const createFileURL = event.altKey;
|
||||
|
@ -5,7 +5,7 @@ interface HookDependencies {
|
||||
folderId: string,
|
||||
}
|
||||
|
||||
export default function(dependencies:HookDependencies) {
|
||||
export default function(dependencies: HookDependencies) {
|
||||
const { folderId } = dependencies;
|
||||
const [folder, setFolder] = useState(null);
|
||||
|
||||
|
@ -23,8 +23,8 @@ interface HookDependencies {
|
||||
isProvisional: boolean,
|
||||
titleInputRef: any,
|
||||
editorRef: any,
|
||||
onBeforeLoad(event:OnLoadEvent):void,
|
||||
onAfterLoad(event:OnLoadEvent):void,
|
||||
onBeforeLoad(event: OnLoadEvent): void,
|
||||
onAfterLoad(event: OnLoadEvent): void,
|
||||
}
|
||||
|
||||
function installResourceChangeHandler(onResourceChangeHandler: Function) {
|
||||
@ -41,7 +41,7 @@ function uninstallResourceChangeHandler(onResourceChangeHandler: Function) {
|
||||
ResourceEditWatcher.instance().off('resourceChange', onResourceChangeHandler);
|
||||
}
|
||||
|
||||
function resourceInfosChanged(a:ResourceInfos, b:ResourceInfos):boolean {
|
||||
function resourceInfosChanged(a: ResourceInfos, b: ResourceInfos): boolean {
|
||||
if (Object.keys(a).length !== Object.keys(b).length) return true;
|
||||
|
||||
for (const id in a) {
|
||||
@ -57,7 +57,7 @@ function resourceInfosChanged(a:ResourceInfos, b:ResourceInfos):boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
export default function useFormNote(dependencies:HookDependencies) {
|
||||
export default function useFormNote(dependencies: HookDependencies) {
|
||||
const { syncStarted, noteId, isProvisional, titleInputRef, editorRef, onBeforeLoad, onAfterLoad } = dependencies;
|
||||
|
||||
const [formNote, setFormNote] = useState<FormNote>(defaultFormNote());
|
||||
@ -186,7 +186,7 @@ export default function useFormNote(dependencies:HookDependencies) {
|
||||
};
|
||||
}, [noteId, isProvisional, formNote]);
|
||||
|
||||
const onResourceChange = useCallback(async function(event:any = null) {
|
||||
const onResourceChange = useCallback(async function(event: any = null) {
|
||||
const resourceIds = await Note.linkedResourceIds(formNote.body);
|
||||
if (!event || resourceIds.indexOf(event.id) >= 0) {
|
||||
clearResourceCache();
|
||||
@ -213,7 +213,7 @@ export default function useFormNote(dependencies:HookDependencies) {
|
||||
async function runEffect() {
|
||||
const r = await attachedResources(formNote.body);
|
||||
if (cancelled) return;
|
||||
setResourceInfos((previous:ResourceInfos) => {
|
||||
setResourceInfos((previous: ResourceInfos) => {
|
||||
return resourceInfosChanged(previous, r) ? r : previous;
|
||||
});
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ interface MarkupToHtmlOptions {
|
||||
resourceInfos?: ResourceInfos,
|
||||
}
|
||||
|
||||
export default function useMarkupToHtml(deps:HookDependencies) {
|
||||
export default function useMarkupToHtml(deps: HookDependencies) {
|
||||
const { themeId, customCss, plugins } = deps;
|
||||
|
||||
const markupToHtml = useMemo(() => {
|
||||
|
@ -12,7 +12,7 @@ const urlUtils = require('@joplin/lib/urlUtils');
|
||||
const ResourceFetcher = require('@joplin/lib/services/ResourceFetcher.js');
|
||||
const { reg } = require('@joplin/lib/registry.js');
|
||||
|
||||
export default function useMessageHandler(scrollWhenReady:any, setScrollWhenReady:Function, editorRef:any, setLocalSearchResultCount:Function, dispatch:Function, formNote:FormNote) {
|
||||
export default function useMessageHandler(scrollWhenReady: any, setScrollWhenReady: Function, editorRef: any, setLocalSearchResultCount: Function, dispatch: Function, formNote: FormNote) {
|
||||
return useCallback(async (event: any) => {
|
||||
const msg = event.channel ? event.channel : '';
|
||||
const args = event.args;
|
||||
|
@ -9,7 +9,7 @@ interface LocalSearch {
|
||||
timestamp: number,
|
||||
}
|
||||
|
||||
function defaultLocalSearch():LocalSearch {
|
||||
function defaultLocalSearch(): LocalSearch {
|
||||
return {
|
||||
query: '',
|
||||
selectedIndex: 0,
|
||||
@ -23,8 +23,8 @@ export default function useNoteSearchBar() {
|
||||
const [showLocalSearch, setShowLocalSearch] = useState(false);
|
||||
const [localSearch, setLocalSearch] = useState<LocalSearch>(defaultLocalSearch());
|
||||
|
||||
const onChange = useCallback((query:string) => {
|
||||
setLocalSearch((prev:LocalSearch) => {
|
||||
const onChange = useCallback((query: string) => {
|
||||
setLocalSearch((prev: LocalSearch) => {
|
||||
return {
|
||||
query: query,
|
||||
selectedIndex: 0,
|
||||
@ -35,8 +35,8 @@ export default function useNoteSearchBar() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const noteSearchBarNextPrevious = useCallback((inc:number) => {
|
||||
setLocalSearch((prev:LocalSearch) => {
|
||||
const noteSearchBarNextPrevious = useCallback((inc: number) => {
|
||||
setLocalSearch((prev: LocalSearch) => {
|
||||
const ls = Object.assign({}, prev);
|
||||
ls.selectedIndex += inc;
|
||||
ls.timestamp = Date.now();
|
||||
@ -59,8 +59,8 @@ export default function useNoteSearchBar() {
|
||||
setLocalSearch(defaultLocalSearch());
|
||||
}, []);
|
||||
|
||||
const setResultCount = useCallback((count:number) => {
|
||||
setLocalSearch((prev:LocalSearch) => {
|
||||
const setResultCount = useCallback((count: number) => {
|
||||
setLocalSearch((prev: LocalSearch) => {
|
||||
if (prev.resultCount === count && !prev.searching) return prev;
|
||||
|
||||
return {
|
||||
@ -71,7 +71,7 @@ export default function useNoteSearchBar() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const searchMarkers = useCallback(():SearchMarkers => {
|
||||
const searchMarkers = useCallback((): SearchMarkers => {
|
||||
return {
|
||||
options: {
|
||||
selectedIndex: localSearch.selectedIndex,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
import PlatformImplementation from '../../../services/plugins/PlatformImplementation';
|
||||
|
||||
export default function usePluginServiceRegistration(ref:any) {
|
||||
export default function usePluginServiceRegistration(ref: any) {
|
||||
useEffect(() => {
|
||||
PlatformImplementation.instance().registerComponent('textEditor', ref);
|
||||
|
||||
|
@ -11,7 +11,7 @@ export interface SearchMarkers {
|
||||
options: SearchMarkersOptions,
|
||||
}
|
||||
|
||||
function defaultSearchMarkers():SearchMarkers {
|
||||
function defaultSearchMarkers(): SearchMarkers {
|
||||
return {
|
||||
keywords: [],
|
||||
options: {
|
||||
@ -23,8 +23,8 @@ function defaultSearchMarkers():SearchMarkers {
|
||||
}
|
||||
|
||||
|
||||
export default function useSearchMarkers(showLocalSearch:boolean, localSearchMarkerOptions:Function, searches:any[], selectedSearchId:string, highlightedWords: any[] = []) {
|
||||
return useMemo(():SearchMarkers => {
|
||||
export default function useSearchMarkers(showLocalSearch: boolean, localSearchMarkerOptions: Function, searches: any[], selectedSearchId: string, highlightedWords: any[] = []) {
|
||||
return useMemo((): SearchMarkers => {
|
||||
if (showLocalSearch) return localSearchMarkerOptions();
|
||||
|
||||
const output = defaultSearchMarkers();
|
||||
|
@ -12,18 +12,18 @@ const commandsWithDependencies = [
|
||||
];
|
||||
|
||||
interface HookDependencies {
|
||||
formNote:FormNote,
|
||||
setShowLocalSearch:Function,
|
||||
dispatch:Function,
|
||||
noteSearchBarRef:any,
|
||||
editorRef:any,
|
||||
titleInputRef:any,
|
||||
formNote: FormNote,
|
||||
setShowLocalSearch: Function,
|
||||
dispatch: Function,
|
||||
noteSearchBarRef: any,
|
||||
editorRef: any,
|
||||
titleInputRef: any,
|
||||
saveNoteAndWait: Function,
|
||||
}
|
||||
|
||||
function editorCommandRuntime(declaration:CommandDeclaration, editorRef:any):CommandRuntime {
|
||||
function editorCommandRuntime(declaration: CommandDeclaration, editorRef: any): CommandRuntime {
|
||||
return {
|
||||
execute: async (_context:CommandContext, ...args:any[]) => {
|
||||
execute: async (_context: CommandContext, ...args: any[]) => {
|
||||
if (!editorRef.current.execCommand) {
|
||||
reg.logger().warn('Received command, but editor cannot execute commands', declaration.name);
|
||||
return;
|
||||
@ -50,7 +50,7 @@ function editorCommandRuntime(declaration:CommandDeclaration, editorRef:any):Com
|
||||
};
|
||||
}
|
||||
|
||||
export default function useWindowCommandHandler(dependencies:HookDependencies) {
|
||||
export default function useWindowCommandHandler(dependencies: HookDependencies) {
|
||||
const { setShowLocalSearch, noteSearchBarRef, editorRef, titleInputRef } = dependencies;
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -23,8 +23,8 @@ const commands = [
|
||||
const StyledRoot = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: ${(props:any) => props.theme.backgroundColor3};
|
||||
border-right: 1px solid ${(props:any) => props.theme.dividerColor};
|
||||
background-color: ${(props: any) => props.theme.backgroundColor3};
|
||||
border-right: 1px solid ${(props: any) => props.theme.dividerColor};
|
||||
`;
|
||||
|
||||
class NoteListComponent extends React.Component {
|
||||
@ -104,7 +104,7 @@ class NoteListComponent extends React.Component {
|
||||
return style;
|
||||
}
|
||||
|
||||
itemContextMenu(event:any) {
|
||||
itemContextMenu(event: any) {
|
||||
const currentItemId = event.currentTarget.getAttribute('data-id');
|
||||
if (!currentItemId) return;
|
||||
|
||||
@ -143,11 +143,11 @@ class NoteListComponent extends React.Component {
|
||||
document.removeEventListener('dragend', this.onGlobalDrop_);
|
||||
}
|
||||
|
||||
dragTargetNoteIndex_(event:any) {
|
||||
dragTargetNoteIndex_(event: any) {
|
||||
return Math.abs(Math.round((event.clientY - this.itemListRef.current.offsetTop() + this.itemListRef.current.offsetScroll()) / this.itemHeight));
|
||||
}
|
||||
|
||||
noteItem_noteDragOver(event:any) {
|
||||
noteItem_noteDragOver(event: any) {
|
||||
if (this.props.notesParentType !== 'Folder') return;
|
||||
|
||||
const dt = event.dataTransfer;
|
||||
@ -161,7 +161,7 @@ class NoteListComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
async noteItem_noteDrop(event:any) {
|
||||
async noteItem_noteDrop(event: any) {
|
||||
if (this.props.notesParentType !== 'Folder') return;
|
||||
|
||||
if (this.props.noteSortOrder !== 'order') {
|
||||
@ -187,7 +187,7 @@ class NoteListComponent extends React.Component {
|
||||
}
|
||||
|
||||
|
||||
async noteItem_checkboxClick(event:any, item:any) {
|
||||
async noteItem_checkboxClick(event: any, item: any) {
|
||||
const checked = event.target.checked;
|
||||
const newNote = {
|
||||
id: item.id,
|
||||
@ -197,7 +197,7 @@ class NoteListComponent extends React.Component {
|
||||
eventManager.emit('todoToggle', { noteId: item.id, note: newNote });
|
||||
}
|
||||
|
||||
async noteItem_titleClick(event:any, item:any) {
|
||||
async noteItem_titleClick(event: any, item: any) {
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
event.preventDefault();
|
||||
this.props.dispatch({
|
||||
@ -218,7 +218,7 @@ class NoteListComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
noteItem_dragStart(event:any) {
|
||||
noteItem_dragStart(event: any) {
|
||||
let noteIds = [];
|
||||
|
||||
// Here there is two cases:
|
||||
@ -238,7 +238,7 @@ class NoteListComponent extends React.Component {
|
||||
event.dataTransfer.setData('text/x-jop-note-ids', JSON.stringify(noteIds));
|
||||
}
|
||||
|
||||
renderItem(item:any, index:number) {
|
||||
renderItem(item: any, index: number) {
|
||||
const highlightedWords = () => {
|
||||
if (this.props.notesParentType === 'Search') {
|
||||
const query = BaseModel.byId(this.props.searches, this.props.selectedSearchId);
|
||||
@ -276,12 +276,12 @@ class NoteListComponent extends React.Component {
|
||||
/>;
|
||||
}
|
||||
|
||||
itemAnchorRef(itemId:string) {
|
||||
itemAnchorRef(itemId: string) {
|
||||
if (this.itemAnchorRefs_[itemId] && this.itemAnchorRefs_[itemId].current) return this.itemAnchorRefs_[itemId].current;
|
||||
return null;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps:any) {
|
||||
componentDidUpdate(prevProps: any) {
|
||||
if (prevProps.selectedNoteIds !== this.props.selectedNoteIds && this.props.selectedNoteIds.length === 1) {
|
||||
const id = this.props.selectedNoteIds[0];
|
||||
const doRefocus = this.props.notes.length < prevProps.notes.length;
|
||||
@ -303,7 +303,7 @@ class NoteListComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
scrollNoteIndex_(keyCode:any, ctrlKey:any, metaKey:any, noteIndex:any) {
|
||||
scrollNoteIndex_(keyCode: any, ctrlKey: any, metaKey: any, noteIndex: any) {
|
||||
|
||||
if (keyCode === 33) {
|
||||
// Page Up
|
||||
@ -334,7 +334,7 @@ class NoteListComponent extends React.Component {
|
||||
return noteIndex;
|
||||
}
|
||||
|
||||
async onKeyDown(event:any) {
|
||||
async onKeyDown(event: any) {
|
||||
const keyCode = event.keyCode;
|
||||
const noteIds = this.props.selectedNoteIds;
|
||||
|
||||
@ -370,7 +370,7 @@ class NoteListComponent extends React.Component {
|
||||
event.preventDefault();
|
||||
|
||||
const notes = BaseModel.modelsByIds(this.props.notes, noteIds);
|
||||
const todos = notes.filter((n:any) => !!n.is_todo);
|
||||
const todos = notes.filter((n: any) => !!n.is_todo);
|
||||
if (!todos.length) return;
|
||||
|
||||
for (let i = 0; i < todos.length; i++) {
|
||||
@ -402,7 +402,7 @@ class NoteListComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
focusNoteId_(noteId:string) {
|
||||
focusNoteId_(noteId: string) {
|
||||
// - We need to focus the item manually otherwise focus might be lost when the
|
||||
// list is scrolled and items within it are being rebuilt.
|
||||
// - We need to use an interval because when leaving the arrow pressed, the rendering
|
||||
@ -465,7 +465,7 @@ class NoteListComponent extends React.Component {
|
||||
return <div style={emptyDivStyle}>{this.props.folders.length ? _('No notes in here. Create one by clicking on "New note".') : _('There is currently no notebook. Create one by clicking on "New notebook".')}</div>;
|
||||
}
|
||||
|
||||
renderItemList(style:any) {
|
||||
renderItemList(style: any) {
|
||||
if (!this.props.notes.length) return null;
|
||||
|
||||
return (
|
||||
@ -494,7 +494,7 @@ class NoteListComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state:AppState) => {
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
notes: state.notes,
|
||||
folders: state.folders,
|
||||
|
@ -2,15 +2,15 @@ import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'focusElementNoteList',
|
||||
label: () => _('Note list'),
|
||||
parentLabel: () => _('Focus'),
|
||||
};
|
||||
|
||||
export const runtime = (comp:any):CommandRuntime => {
|
||||
export const runtime = (comp: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async (context:CommandContext, noteId:string = null) => {
|
||||
execute: async (context: CommandContext, noteId: string = null) => {
|
||||
noteId = noteId || stateUtils.selectedNoteId(context.state);
|
||||
|
||||
if (noteId) {
|
||||
|
@ -14,8 +14,8 @@ const StyledRoot = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: ${(props:any) => props.theme.mainPadding}px;
|
||||
background-color: ${(props:any) => props.theme.backgroundColor3};
|
||||
padding: ${(props: any) => props.theme.mainPadding}px;
|
||||
background-color: ${(props: any) => props.theme.backgroundColor3};
|
||||
`;
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
@ -27,7 +27,7 @@ const ButtonContainer = styled.div`
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
export default function NoteListControls(props:Props) {
|
||||
export default function NoteListControls(props: Props) {
|
||||
const searchBarRef = useRef(null);
|
||||
|
||||
useEffect(function() {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { CommandRuntime, CommandDeclaration } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
export const declaration:CommandDeclaration = {
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'focusSearch',
|
||||
label: () => _('Search in all the notes'),
|
||||
};
|
||||
|
||||
export const runtime = (searchBarRef:any):CommandRuntime => {
|
||||
export const runtime = (searchBarRef: any): CommandRuntime => {
|
||||
return {
|
||||
execute: async () => {
|
||||
if (searchBarRef.current) searchBarRef.current.focus();
|
||||
|
@ -8,35 +8,35 @@ const { replaceRegexDiacritics, pregQuote } = require('@joplin/lib/string-utils'
|
||||
const styled = require('styled-components').default;
|
||||
|
||||
const StyledRoot = styled.div`
|
||||
width: ${(props:any) => props.width}px;
|
||||
height: ${(props:any) => props.height}px;
|
||||
opacity: ${(props:any) => props.isProvisional ? '0.5' : '1'};
|
||||
width: ${(props: any) => props.width}px;
|
||||
height: ${(props: any) => props.height}px;
|
||||
opacity: ${(props: any) => props.isProvisional ? '0.5' : '1'};
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
background-color: ${(props:any) => props.selected ? props.theme.selectedColor : 'none'};
|
||||
background-color: ${(props: any) => props.selected ? props.theme.selectedColor : 'none'};
|
||||
|
||||
border-style: solid;
|
||||
border-color: ${(props:any) => props.theme.color};
|
||||
border-top-width: ${(props:any) => props.dragItemPosition === 'top' ? 2 : 0}px;
|
||||
border-bottom-width: ${(props:any) => props.dragItemPosition === 'bottom' ? 2 : 0}px;
|
||||
border-color: ${(props: any) => props.theme.color};
|
||||
border-top-width: ${(props: any) => props.dragItemPosition === 'top' ? 2 : 0}px;
|
||||
border-bottom-width: ${(props: any) => props.dragItemPosition === 'bottom' ? 2 : 0}px;
|
||||
border-right: none;
|
||||
border-left: none;
|
||||
|
||||
// https://stackoverflow.com/questions/50174448/css-how-to-add-white-space-before-elements-border
|
||||
&::before {
|
||||
content: '';
|
||||
border-bottom: 1px solid ${(props:any) => props.theme.dividerColor};
|
||||
width: ${(props:any) => props.width - 32}px;
|
||||
border-bottom: 1px solid ${(props: any) => props.theme.dividerColor};
|
||||
width: ${(props: any) => props.width - 32}px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: ${(props:any) => props.theme.backgroundColorHover3};
|
||||
background-color: ${(props: any) => props.theme.backgroundColorHover3};
|
||||
}
|
||||
`;
|
||||
|
||||
@ -61,7 +61,7 @@ interface NoteListItemProps {
|
||||
onContextMenu(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>): void,
|
||||
}
|
||||
|
||||
function NoteListItem(props:NoteListItemProps, ref:any) {
|
||||
function NoteListItem(props: NoteListItemProps, ref: any) {
|
||||
const item = props.item;
|
||||
const theme = themeStyle(props.themeId);
|
||||
const hPadding = 16;
|
||||
|
@ -10,12 +10,12 @@ interface Props {
|
||||
|
||||
class NoteTextViewerComponent extends React.Component<Props, any> {
|
||||
|
||||
private initialized_:boolean = false;
|
||||
private domReady_:boolean = false;
|
||||
private webviewRef_:any;
|
||||
private webviewListeners_:any = null;
|
||||
private initialized_: boolean = false;
|
||||
private domReady_: boolean = false;
|
||||
private webviewRef_: any;
|
||||
private webviewListeners_: any = null;
|
||||
|
||||
constructor(props:any) {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
this.webviewRef_ = React.createRef();
|
||||
@ -26,12 +26,12 @@ class NoteTextViewerComponent extends React.Component<Props, any> {
|
||||
this.webview_message = this.webview_message.bind(this);
|
||||
}
|
||||
|
||||
webview_domReady(event:any) {
|
||||
webview_domReady(event: any) {
|
||||
this.domReady_ = true;
|
||||
if (this.props.onDomReady) this.props.onDomReady(event);
|
||||
}
|
||||
|
||||
webview_ipcMessage(event:any) {
|
||||
webview_ipcMessage(event: any) {
|
||||
if (this.props.onIpcMessage) this.props.onIpcMessage(event);
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ class NoteTextViewerComponent extends React.Component<Props, any> {
|
||||
this.webview_domReady({});
|
||||
}
|
||||
|
||||
webview_message(event:any) {
|
||||
webview_message(event: any) {
|
||||
if (!event.data || event.data.target !== 'main') return;
|
||||
|
||||
const callName = event.data.name;
|
||||
@ -123,7 +123,7 @@ class NoteTextViewerComponent extends React.Component<Props, any> {
|
||||
// Wrap WebView functions
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
send(channel:string, arg0:any = null, arg1:any = null) {
|
||||
send(channel: string, arg0: any = null, arg1: any = null) {
|
||||
const win = this.webviewRef_.current.contentWindow;
|
||||
|
||||
if (channel === 'setHtml') {
|
||||
@ -153,7 +153,7 @@ class NoteTextViewerComponent extends React.Component<Props, any> {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state:any) => {
|
||||
const mapStateToProps = (state: any) => {
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
};
|
||||
|
@ -13,8 +13,8 @@ interface NoteToolbarProps {
|
||||
toolbarButtonInfos: ToolbarButtonInfo[],
|
||||
}
|
||||
|
||||
function styles_(props:NoteToolbarProps) {
|
||||
return buildStyle('NoteToolbar', props.themeId, (theme:any) => {
|
||||
function styles_(props: NoteToolbarProps) {
|
||||
return buildStyle('NoteToolbar', props.themeId, (theme: any) => {
|
||||
return {
|
||||
root: {
|
||||
...props.style,
|
||||
@ -25,14 +25,14 @@ function styles_(props:NoteToolbarProps) {
|
||||
});
|
||||
}
|
||||
|
||||
function NoteToolbar(props:NoteToolbarProps) {
|
||||
function NoteToolbar(props: NoteToolbarProps) {
|
||||
const styles = styles_(props);
|
||||
return <ToolbarBase style={styles.root} items={props.toolbarButtonInfos} />;
|
||||
}
|
||||
|
||||
const toolbarButtonUtils = new ToolbarButtonUtils(CommandService.instance());
|
||||
|
||||
const mapStateToProps = (state:any) => {
|
||||
const mapStateToProps = (state: any) => {
|
||||
const whenClauseContext = stateToWhenClauseContext(state);
|
||||
|
||||
return {
|
||||
|
@ -14,7 +14,7 @@ interface Props {
|
||||
}
|
||||
|
||||
class OneDriveLoginScreenComponent extends React.Component<any, any> {
|
||||
constructor(props:Props) {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
@ -23,8 +23,8 @@ class OneDriveLoginScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const log = (s:any) => {
|
||||
this.setState((state:any) => {
|
||||
const log = (s: any) => {
|
||||
this.setState((state: any) => {
|
||||
const authLog = state.authLog.slice();
|
||||
authLog.push({ key: (Date.now() + Math.random()).toString(), text: s });
|
||||
return { authLog: authLog };
|
||||
@ -35,7 +35,7 @@ class OneDriveLoginScreenComponent extends React.Component<any, any> {
|
||||
const syncTarget = reg.syncTarget(syncTargetId);
|
||||
const oneDriveApiUtils = new OneDriveApiNodeUtils(syncTarget.api());
|
||||
const auth = await oneDriveApiUtils.oauthDance({
|
||||
log: (s:any) => log(s),
|
||||
log: (s: any) => log(s),
|
||||
});
|
||||
|
||||
Setting.setValue(`sync.${syncTargetId}.auth`, auth ? JSON.stringify(auth) : null);
|
||||
@ -81,7 +81,7 @@ class OneDriveLoginScreenComponent extends React.Component<any, any> {
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state:any) => {
|
||||
const mapStateToProps = (state: any) => {
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
};
|
||||
|
@ -38,19 +38,19 @@ interface onResizeEvent {
|
||||
|
||||
interface Props {
|
||||
layout: LayoutItem,
|
||||
onResize(event:onResizeEvent):void;
|
||||
onResize(event: onResizeEvent): void;
|
||||
width?: number,
|
||||
height?: number,
|
||||
renderItem: Function,
|
||||
}
|
||||
|
||||
export function allDynamicSizes(layout:LayoutItem):any {
|
||||
const output:any = {};
|
||||
export function allDynamicSizes(layout: LayoutItem): any {
|
||||
const output: any = {};
|
||||
|
||||
function recurseProcess(item:LayoutItem) {
|
||||
function recurseProcess(item: LayoutItem) {
|
||||
if (item.resizableBottom || item.resizableRight) {
|
||||
if ('width' in item || 'height' in item) {
|
||||
const size:any = {};
|
||||
const size: any = {};
|
||||
if ('width' in item) size.width = item.width;
|
||||
if ('height' in item) size.height = item.height;
|
||||
output[item.key] = size;
|
||||
@ -69,8 +69,8 @@ export function allDynamicSizes(layout:LayoutItem):any {
|
||||
return output;
|
||||
}
|
||||
|
||||
export function findItemByKey(layout:LayoutItem, key:string):LayoutItem {
|
||||
function recurseFind(item:LayoutItem):LayoutItem {
|
||||
export function findItemByKey(layout: LayoutItem, key: string): LayoutItem {
|
||||
function recurseFind(item: LayoutItem): LayoutItem {
|
||||
if (item.key === key) return item;
|
||||
|
||||
if (item.children) {
|
||||
@ -87,9 +87,9 @@ export function findItemByKey(layout:LayoutItem, key:string):LayoutItem {
|
||||
return output;
|
||||
}
|
||||
|
||||
function updateLayoutItem(layout:LayoutItem, key:string, props:any) {
|
||||
return produce(layout, (draftState:LayoutItem) => {
|
||||
function recurseFind(item:LayoutItem) {
|
||||
function updateLayoutItem(layout: LayoutItem, key: string, props: any) {
|
||||
return produce(layout, (draftState: LayoutItem) => {
|
||||
function recurseFind(item: LayoutItem) {
|
||||
if (item.key === key) {
|
||||
for (const n in props) {
|
||||
(item as any)[n] = props[n];
|
||||
@ -107,13 +107,13 @@ function updateLayoutItem(layout:LayoutItem, key:string, props:any) {
|
||||
});
|
||||
}
|
||||
|
||||
function renderContainer(item:LayoutItem, sizes:LayoutItemSizes, onResizeStart:Function, onResize:Function, onResizeStop:Function, children:any[], isLastChild:boolean):any {
|
||||
const style:any = {
|
||||
function renderContainer(item: LayoutItem, sizes: LayoutItemSizes, onResizeStart: Function, onResize: Function, onResizeStop: Function, children: any[], isLastChild: boolean): any {
|
||||
const style: any = {
|
||||
display: item.visible !== false ? 'flex' : 'none',
|
||||
flexDirection: item.direction,
|
||||
};
|
||||
|
||||
const size:Size = itemSize(item, sizes);
|
||||
const size: Size = itemSize(item, sizes);
|
||||
|
||||
const className = `resizableLayoutItem rli-${item.key}`;
|
||||
if (item.resizableRight || item.resizableBottom) {
|
||||
@ -156,12 +156,12 @@ function renderContainer(item:LayoutItem, sizes:LayoutItemSizes, onResizeStart:F
|
||||
}
|
||||
}
|
||||
|
||||
function ResizableLayout(props:Props) {
|
||||
function ResizableLayout(props: Props) {
|
||||
const eventEmitter = useRef(new EventEmitter());
|
||||
|
||||
const [resizedItem, setResizedItem] = useState<any>(null);
|
||||
|
||||
function renderLayoutItem(item:LayoutItem, sizes:LayoutItemSizes, isVisible:boolean, isLastChild:boolean):any {
|
||||
function renderLayoutItem(item: LayoutItem, sizes: LayoutItemSizes, isVisible: boolean, isLastChild: boolean): any {
|
||||
|
||||
function onResizeStart() {
|
||||
setResizedItem({
|
||||
@ -171,7 +171,7 @@ function ResizableLayout(props:Props) {
|
||||
});
|
||||
}
|
||||
|
||||
function onResize(_event:any, _direction:any, _refToElement: HTMLDivElement, delta:any) {
|
||||
function onResize(_event: any, _direction: any, _refToElement: HTMLDivElement, delta: any) {
|
||||
const newLayout = updateLayoutItem(props.layout, item.key, {
|
||||
width: resizedItem.initialWidth + delta.width,
|
||||
height: resizedItem.initialHeight + delta.height,
|
||||
@ -181,7 +181,7 @@ function ResizableLayout(props:Props) {
|
||||
eventEmitter.current.emit('resize');
|
||||
}
|
||||
|
||||
function onResizeStop(_event:any, _direction:any, _refToElement: HTMLDivElement, delta:any) {
|
||||
function onResizeStop(_event: any, _direction: any, _refToElement: HTMLDivElement, delta: any) {
|
||||
onResize(_event, _direction, _refToElement, delta);
|
||||
setResizedItem(null);
|
||||
}
|
||||
|
@ -2,28 +2,28 @@ import { useMemo } from 'react';
|
||||
import { LayoutItem, Size, dragBarThickness } from '../ResizableLayout';
|
||||
|
||||
export interface LayoutItemSizes {
|
||||
[key:string]: Size,
|
||||
[key: string]: Size,
|
||||
}
|
||||
|
||||
export function itemSize(item:LayoutItem, sizes:LayoutItemSizes):Size {
|
||||
export function itemSize(item: LayoutItem, sizes: LayoutItemSizes): Size {
|
||||
return {
|
||||
width: 'width' in item ? item.width : sizes[item.key].width,
|
||||
height: 'height' in item ? item.height : sizes[item.key].height,
|
||||
};
|
||||
}
|
||||
|
||||
function calculateChildrenSizes(item:LayoutItem, sizes:LayoutItemSizes):LayoutItemSizes {
|
||||
function calculateChildrenSizes(item: LayoutItem, sizes: LayoutItemSizes): LayoutItemSizes {
|
||||
if (!item.children) return sizes;
|
||||
|
||||
const parentSize = itemSize(item, sizes);
|
||||
|
||||
const remainingSize:Size = {
|
||||
const remainingSize: Size = {
|
||||
width: parentSize.width,
|
||||
height: parentSize.height,
|
||||
};
|
||||
|
||||
const noWidthChildren:LayoutItem[] = [];
|
||||
const noHeightChildren:LayoutItem[] = [];
|
||||
const noWidthChildren: LayoutItem[] = [];
|
||||
const noHeightChildren: LayoutItem[] = [];
|
||||
|
||||
for (const child of item.children) {
|
||||
let w = 'width' in child ? child.width : null;
|
||||
@ -65,9 +65,9 @@ function calculateChildrenSizes(item:LayoutItem, sizes:LayoutItemSizes):LayoutIt
|
||||
return sizes;
|
||||
}
|
||||
|
||||
export default function useLayoutItemSizes(layout:LayoutItem) {
|
||||
export default function useLayoutItemSizes(layout: LayoutItem) {
|
||||
return useMemo(() => {
|
||||
let sizes:LayoutItemSizes = {};
|
||||
let sizes: LayoutItemSizes = {};
|
||||
|
||||
if (!('width' in layout) || !('height' in layout)) throw new Error('width and height are required on layout root');
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
const debounce = require('debounce');
|
||||
|
||||
export default function useWindowResizeEvent(eventEmitter:any) {
|
||||
export default function useWindowResizeEvent(eventEmitter: any) {
|
||||
useEffect(() => {
|
||||
const window_resize = debounce(() => {
|
||||
eventEmitter.current.emit('resize');
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user