mirror of
https://github.com/rhysd/Mstdn.git
synced 2025-01-21 20:52:11 +01:00
load preload plugins after app gets idling
This commit is contained in:
parent
da55de25d1
commit
f8e7d64b08
@ -264,14 +264,14 @@ body {
|
||||
}
|
||||
```
|
||||
|
||||
## Preload Plugin
|
||||
## Preload Plugin (experimental)
|
||||
|
||||
You can make a Node.js package which is preloaded before loading inner mastodon page.
|
||||
|
||||
Preload plugin is enabled if `chromium_sandbox` option is set to `false`. Please read above
|
||||
configuration section before using any plugin.
|
||||
|
||||
### How to make
|
||||
### How to make a plugin
|
||||
|
||||
Create `node_modules` directory in your application directory at first. And then, please make
|
||||
`mstdn-preload-hello` directory. It consists a node package.
|
||||
|
@ -1,12 +1,11 @@
|
||||
import {Config, Account} from '../main/config';
|
||||
import * as Ipc from './ipc';
|
||||
import setupKeymaps from './key_handler';
|
||||
import loadPlugins from './plugins';
|
||||
import log from './log';
|
||||
import PluginsLoader from './plugins';
|
||||
|
||||
Ipc.on('mstdn:config', (c: Config, a: Account) => {
|
||||
const plugins = loadPlugins(c, a);
|
||||
log.info('Loaded plugins:', plugins);
|
||||
const loader = new PluginsLoader(c, a);
|
||||
loader.loadAfterAppPrepared();
|
||||
setupKeymaps(c, a);
|
||||
document.title = `${document.title} @${a.name}@${a.host}`;
|
||||
});
|
||||
|
@ -8,22 +8,72 @@ interface Plugins {
|
||||
[module_path: string]: Plugin;
|
||||
}
|
||||
|
||||
export default function loadPlugins(config: Config, account: Account): Plugins {
|
||||
const ret = {} as Plugins;
|
||||
if (config.chromium_sandbox) {
|
||||
log.info('Chromium sandbox is enabled. Preload plugin is disabled.');
|
||||
return ret;
|
||||
}
|
||||
const dir_base = path.join(config.__DATA_DIR!, 'node_modules');
|
||||
for (const plugin of config.preload || []) {
|
||||
const plugin_path = path.join(dir_base, `mstdn-preload-${plugin}`);
|
||||
try {
|
||||
const preloadFunc = r(plugin_path) as Plugin;
|
||||
preloadFunc(config, account);
|
||||
ret[plugin_path] = preloadFunc;
|
||||
} catch (e) {
|
||||
log.error(`Failed to load plugin ${plugin_path}:`, e);
|
||||
export default class PluginsLoader {
|
||||
preloads: Plugins;
|
||||
loaded: boolean;
|
||||
|
||||
constructor(private config: Config, private account: Account) {
|
||||
this.loaded = false;
|
||||
this.preloads = {};
|
||||
|
||||
if (config.chromium_sandbox) {
|
||||
log.info('Chromium sandbox is enabled. Preload plugin is disabled.');
|
||||
return;
|
||||
}
|
||||
|
||||
const dir_base = path.join(config.__DATA_DIR!, 'node_modules');
|
||||
for (const plugin of config.preload || []) {
|
||||
const plugin_path = path.join(dir_base, `mstdn-preload-${plugin}`);
|
||||
try {
|
||||
this.preloads[plugin_path] = r(plugin_path) as Plugin;
|
||||
} catch (e) {
|
||||
log.error(`Failed to load plugin ${plugin_path}:`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
loadAfterAppPrepared() {
|
||||
if (Object.keys(this.preloads).length === 0) {
|
||||
log.info('No preload plugin found. Skip loading');
|
||||
this.loaded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
return new Promise<void>(resolve => {
|
||||
// In order not to prevent application's initial loading, load preload plugins
|
||||
// on an idle callback.
|
||||
window.requestIdleCallback(() => {
|
||||
log.debug('Start loading preload plugins', this.config, this.account);
|
||||
if (this.tryLoading()) {
|
||||
return resolve();
|
||||
}
|
||||
this.observeAppPrepared(this.tryLoading).then(resolve);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
observeAppPrepared(callback: () => void) {
|
||||
// TODO:
|
||||
// Make an instance of MutationObserver to observe React root.
|
||||
return Promise.resolve(callback());
|
||||
}
|
||||
|
||||
tryLoading = () => {
|
||||
if (document.querySelector('[data-react-class="Mastodon"]') === null) {
|
||||
log.info('Root element of react app was not found. App seems not to be loaded yet.');
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const key in this.preloads) {
|
||||
const f = this.preloads[key];
|
||||
try {
|
||||
f(this.config, this.account);
|
||||
} catch (e) {
|
||||
log.error(`Error while loading preload plugin '${key}':`, e);
|
||||
}
|
||||
}
|
||||
|
||||
log.info('Preload plugins were loaded:', this.preloads);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
9
typings/request-idle-callback.d.ts
vendored
Normal file
9
typings/request-idle-callback.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
interface RequestIdleCallback {
|
||||
didTimeout?: boolean;
|
||||
timeRemaining?: () => number;
|
||||
}
|
||||
|
||||
interface Window {
|
||||
requestIdleCallback(cb: (deadline: RequestIdleCallback) => any): NodeJS.Timer;
|
||||
cancelIdleCallback(id: NodeJS.Timer): void;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user