1
0
mirror of https://github.com/rhysd/Mstdn.git synced 2025-02-01 05:52:11 +01:00

give plugins the ability to make custom key shortcuts

This commit is contained in:
rhysd 2017-04-26 15:52:57 +09:00
parent f01dea80ea
commit bfbb758ff7
4 changed files with 81 additions and 5 deletions

View File

@ -312,7 +312,7 @@ Make `package.json` manually or by `$ npm init` in the directory.
}
```
Finally make `index.js` as below:
And make `index.js` as below:
```javascript
module.exports = {
@ -324,7 +324,31 @@ module.exports = {
Package must export one object.
If the object has a function as a value of `preload` key, it will be called at page being loaded.
The function which receives two parameters `config` and `account`.
The function receives two parameters `config` and `account`.
By defining `keymaps` key you can define plugin-defined key shortcut action.
```javascript
module.exports = {
preload(config, account) {
console.log('Hello from plugin!', config, account);
},
keymaps: {
'alert-hello'(event, config, account) {
event.preventDefault();
alert('Hello, ' + account.name);
}
}
};
```
The object of `keymaps` has keymap action name (key) and its handler (value). Here 'alert-hello'
key shortcut action is defined. Key shortcut handler takes 3 arguments. `config` and `account`
is the same as `preload`'s. `event` is a `KeyboardEvent` browser event on the key shortcut
being called. You can cancel default event behavior by `.preventDefault()` method.
User can specify the key shortcut as `plugin:{plugin name}:{action name}`. In above example,
`plugin:hello:alert-hello` is available in `keymaps` section in config.json.
Note that you can use below APIs in the script.
@ -354,6 +378,8 @@ $ npm install mstdn-plugin-hello
And then write what plugin should be loaded to `"plugins"` section of your account in `config.json`.
`"hello"` should be added to the list.
If listed plugin defines some keymaps, you can specify it in `keymaps` section with
`plugin:{name}:{action}` format.
```json
{
@ -368,12 +394,17 @@ And then write what plugin should be loaded to `"plugins"` section of your accou
]
}
],
"keymaps": {
...
"ctrl+h": "plugin:hello:alert-hello"
},
...
}
```
You can enable different plugin for each your accounts.
Note that you can enable different plugin for each your accounts.
Finally open Mstdn.app and see DevTools via [Menu] -> [View] -> [Developper Tools] -> console.
If window is too small to see DevTools, please make window size bigger.

View File

@ -6,6 +6,6 @@ import PluginsLoader from './plugins';
Ipc.on('mstdn:config', (c: Config, a: Account) => {
const loader = new PluginsLoader(c, a);
loader.loadAfterAppPrepared();
setupKeymaps(c, a);
setupKeymaps(c, a, loader);
document.title = `${document.title} @${a.name}@${a.host}`;
});

View File

@ -3,6 +3,7 @@ import {remote} from 'electron';
import * as Mousetrap from 'mousetrap';
import * as Ipc from './ipc';
import log from './log';
import PluginsLoader from './plugins';
import {Config, Account} from '../main/config';
function scrollable() {
@ -58,6 +59,7 @@ const ShortcutActions = {
export default function setupKeymaps(
config: Config,
account: Account,
loader: PluginsLoader,
) {
const dataDir = config.__DATA_DIR || '/';
for (const key in config.keymaps) {
@ -85,6 +87,16 @@ export default function setupKeymaps(
log.error('Failed to run shortcut script ' + script, e);
}
});
} else if (action.startsWith('plugin:')) {
// Format is 'plugin:{name}:{action}'
const split = action.split(':').slice(1);
if (split.length <= 1) {
log.error('Invalid format keymap. Plugin-defined action should be "plugin:{name}:{action}":', action);
continue;
}
Mousetrap.bind(key, e => {
loader.runKeyShortcut(e, split[0], split[1]);
});
} else if (action.startsWith('/')) {
Mousetrap.bind(key, e => {
e.preventDefault();

View File

@ -3,7 +3,10 @@ import {Config, Account} from '../main/config';
import log from './log';
interface Plugin {
preload(c: Config, a: Account): void;
preload?(c: Config, a: Account): void;
keymaps?: {
[action: string]: (e: KeyboardEvent, c: Config, a: Account) => void;
};
}
interface Plugins {
[module_path: string]: Plugin;
@ -83,4 +86,34 @@ export default class PluginsLoader {
log.info('Plugins were loaded:', this.preloads);
return true;
}
findPluginByName(name: string): Plugin | null {
const pluginName = `mstdn-plugin-${name}`;
for (const p in this.preloads) {
if (p.endsWith(pluginName)) {
return this.preloads[p];
}
}
return null;
}
runKeyShortcut(event: KeyboardEvent, name: string, action: string) {
const plugin = this.findPluginByName(name);
if (plugin === null) {
log.error(`While trying to execute key shortcut '${action}', plugin for '${name}' not found:`, this.preloads);
return;
}
const f = (plugin.keymaps || {})[action];
if (!f) {
log.error(`There is no key shortcut action '${action}' in plugin '${name}'`, plugin);
return;
}
try {
f(event, this.config, this.account);
} catch (e) {
log.error(`Error while executing plugin-defined key short action: ${action} with plugin '${name}'`, e);
}
}
}