mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2026-02-10 09:43:01 -08:00
wip: make wiki channel connect to server side
This commit is contained in:
parent
81ee6b2db1
commit
219ba38e57
3 changed files with 187 additions and 0 deletions
85
src/services/wiki/wikiOperations/common.ts
Normal file
85
src/services/wiki/wikiOperations/common.ts
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import { WikiChannel } from '@/constants/channels';
|
||||
|
||||
export const wikiOperations = {
|
||||
[WikiChannel.setState]: (stateKey: string, content: string) => `
|
||||
$tw.wiki.addTiddler({ title: '$:/state/${stateKey}', text: \`${content}\` });
|
||||
`,
|
||||
[WikiChannel.addTiddler]: (nonceReceived: number, title: string, text: string, extraMeta = '{}', optionsString = '{}') => {
|
||||
const options = JSON.parse(optionsString) as { withDate?: boolean };
|
||||
return `
|
||||
const dateObject = {};
|
||||
${
|
||||
options.withDate === true
|
||||
? `
|
||||
const existedTiddler = $tw.wiki.getTiddler(\`${title}\`);
|
||||
let created = existedTiddler?.fields?.created;
|
||||
const modified = $tw.utils.stringifyDate(new Date());
|
||||
if (!existedTiddler) {
|
||||
created = $tw.utils.stringifyDate(new Date());
|
||||
}
|
||||
dateObject.created = created;
|
||||
dateObject.modified = modified;
|
||||
`
|
||||
: ''
|
||||
}
|
||||
$tw.wiki.addTiddler({ title: \`${title}\`, text: \`${text}\`, ...${extraMeta}, ...dateObject });
|
||||
`;
|
||||
},
|
||||
[WikiChannel.getTiddlerText]: (title: string) => `
|
||||
$tw.wiki.getTiddlerText(\`${title}\`);
|
||||
`,
|
||||
|
||||
[WikiChannel.runFilter]: (filter: string) => `
|
||||
$tw.wiki.compileFilter(\`${filter}\`)()
|
||||
`,
|
||||
|
||||
[WikiChannel.getTiddlersAsJson]: (filter: string) => `
|
||||
$tw.wiki.filterTiddlers(\`${filter}\`).map(title => {
|
||||
const tiddler = $tw.wiki.getTiddler(title);
|
||||
return tiddler?.fields;
|
||||
}).filter(item => item !== undefined)
|
||||
`,
|
||||
|
||||
[WikiChannel.setTiddlerText]: (title: string, value: string) => `
|
||||
$tw.wiki.setText(\`${title}\`, 'text', undefined, \`${value}\`);
|
||||
`,
|
||||
|
||||
[WikiChannel.renderWikiText]: (content: string) => `
|
||||
$tw.wiki.renderText("text/html", "text/vnd.tiddlywiki", \`${content.replaceAll('`', '\\`')}\`);
|
||||
`,
|
||||
|
||||
[WikiChannel.syncProgress]: (message: string) => `
|
||||
$tw.wiki.addTiddler({ title: '$:/state/notification/${WikiChannel.syncProgress}', text: \`${message}\` });
|
||||
$tw.notifier.display('$:/state/notification/${WikiChannel.syncProgress}');
|
||||
`,
|
||||
|
||||
[WikiChannel.generalNotification]: (message: string) => `
|
||||
$tw.wiki.addTiddler({ title: \`$:/state/notification/${WikiChannel.generalNotification}\`, text: \`${message}\` });
|
||||
$tw.notifier.display(\`$:/state/notification/${WikiChannel.generalNotification}\`);
|
||||
`,
|
||||
|
||||
[WikiChannel.openTiddler]: (tiddlerName: string) => `
|
||||
let trimmedTiddlerName = \`${tiddlerName.replaceAll('\n', '')}\`;
|
||||
let currentHandlerWidget = $tw.rootWidget;
|
||||
let handled = false;
|
||||
while (currentHandlerWidget && !handled) {
|
||||
const bubbled = currentHandlerWidget.dispatchEvent({ type: "tm-navigate", navigateTo: trimmedTiddlerName, param: trimmedTiddlerName });
|
||||
handled = !bubbled;
|
||||
currentHandlerWidget = currentHandlerWidget.children?.[0];
|
||||
}
|
||||
`,
|
||||
|
||||
[WikiChannel.sendActionMessage]: (actionMessage: string) => `
|
||||
$tw.rootWidget.dispatchEvent({ type: \`${actionMessage}\` });
|
||||
`,
|
||||
|
||||
[WikiChannel.deleteTiddler]: (title: string) => `
|
||||
$tw.wiki.deleteTiddler(\`${title}\`);
|
||||
`,
|
||||
|
||||
[WikiChannel.printTiddler]: (tiddlerName: string) => `
|
||||
var page = (${printer.printTiddler.toString()})(\`${tiddlerName}\`);
|
||||
page?.print?.();
|
||||
page?.close?.();
|
||||
`,
|
||||
};
|
||||
35
src/services/wiki/wikiOperations/web.ts
Normal file
35
src/services/wiki/wikiOperations/web.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { WikiChannel } from '@/constants/channels';
|
||||
import { wikiOperations as common } from './common';
|
||||
|
||||
export const wikiOperations = {
|
||||
...common
|
||||
[WikiChannel.syncProgress]: (message: string) => `
|
||||
$tw.wiki.addTiddler({ title: '$:/state/notification/${WikiChannel.syncProgress}', text: \`${message}\` });
|
||||
$tw.notifier.display('$:/state/notification/${WikiChannel.syncProgress}');
|
||||
`,
|
||||
|
||||
[WikiChannel.generalNotification]: (message: string) => `
|
||||
$tw.wiki.addTiddler({ title: \`$:/state/notification/${WikiChannel.generalNotification}\`, text: \`${message}\` });
|
||||
$tw.notifier.display(\`$:/state/notification/${WikiChannel.generalNotification}\`);
|
||||
`,
|
||||
|
||||
[WikiChannel.openTiddler]: (tiddlerName: string) => `
|
||||
let trimmedTiddlerName = \`${tiddlerName.replaceAll('\n', '')}\`;
|
||||
let currentHandlerWidget = $tw.rootWidget;
|
||||
let handled = false;
|
||||
while (currentHandlerWidget && !handled) {
|
||||
const bubbled = currentHandlerWidget.dispatchEvent({ type: "tm-navigate", navigateTo: trimmedTiddlerName, param: trimmedTiddlerName });
|
||||
handled = !bubbled;
|
||||
currentHandlerWidget = currentHandlerWidget.children?.[0];
|
||||
}
|
||||
`,
|
||||
|
||||
[WikiChannel.printTiddler]: async (tiddlerName: string) => {
|
||||
const printer = await import('../../libs/printer');
|
||||
return `
|
||||
var page = (${printer.printTiddler.toString()})(\`${tiddlerName}\`);
|
||||
page?.print?.();
|
||||
page?.close?.();
|
||||
`;
|
||||
},
|
||||
};
|
||||
67
src/services/wiki/wikiWorker/wikiOperation.ts
Normal file
67
src/services/wiki/wikiWorker/wikiOperation.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/* eslint-disable @typescript-eslint/promise-function-async */
|
||||
/* eslint-disable no-new-func */
|
||||
/* eslint-disable @typescript-eslint/no-implied-eval */
|
||||
/**
|
||||
* Run some wiki operations on server side, so it works even when the wiki browser view is not visible.
|
||||
*/
|
||||
|
||||
import type { ITiddlyWiki } from 'tiddlywiki';
|
||||
import { IWikiOperations } from '../wikiOperations';
|
||||
|
||||
export class IpcServerRoutes {
|
||||
private wikiInstance!: ITiddlyWiki;
|
||||
private readonly pendingIpcServerRoutesRequests: Array<(value: void | PromiseLike<void>) => void> = [];
|
||||
|
||||
setWikiInstance(wikiInstance: ITiddlyWiki) {
|
||||
this.wikiInstance = wikiInstance;
|
||||
this.pendingIpcServerRoutesRequests.forEach((resolve) => {
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
private async waitForIpcServerRoutesAvailable() {
|
||||
if (this.wikiInstance !== undefined) {
|
||||
return;
|
||||
}
|
||||
await new Promise<void>((resolve) => {
|
||||
this.pendingIpcServerRoutesRequests.push(resolve);
|
||||
});
|
||||
}
|
||||
|
||||
private executeTWJavaScriptWhenIdle(script: string): Promise<unknown> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const result = new Function(`const $tw = arguments[0];return ${script}`)(this.wikiInstance) as unknown;
|
||||
resolve(result);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
}, 1);
|
||||
});
|
||||
}
|
||||
|
||||
// ██████ ██████ ███████ ██████ █████ ████████ ██ ██████ ███ ██ ███████
|
||||
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██
|
||||
// ██ ██ ██████ █████ ██████ ███████ ██ ██ ██ ██ ██ ██ ██ ███████
|
||||
// ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||
// ██████ ██ ███████ ██ ██ ██ ██ ██ ██ ██████ ██ ████ ███████
|
||||
public wikiOperation<OP extends keyof IWikiOperations, T = string[]>(
|
||||
operationType: OP,
|
||||
...arguments_: Parameters<IWikiOperations[OP]>
|
||||
): undefined | ReturnType<IWikiOperations[OP]> {
|
||||
if (typeof wikiOperations[operationType] !== 'function') {
|
||||
throw new TypeError(`${operationType} gets no useful handler`);
|
||||
}
|
||||
if (!Array.isArray(arguments_)) {
|
||||
// TODO: better type handling here
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/restrict-template-expressions
|
||||
throw new TypeError(`${(arguments_ as any) ?? ''} (${typeof arguments_}) is not a good argument array for ${operationType}`);
|
||||
}
|
||||
// @ts-expect-error A spread argument must either have a tuple type or be passed to a rest parameter.ts(2556) this maybe a bug of ts... try remove this comment after upgrade ts. And the result become void is weird too.
|
||||
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
||||
return wikiOperations[operationType]<T>(...arguments_) as unknown as ReturnType<IWikiOperations[OP]>;
|
||||
}
|
||||
}
|
||||
|
||||
export const ipcServerRoutes: IpcServerRoutes = new IpcServerRoutes();
|
||||
Loading…
Add table
Add a link
Reference in a new issue