mirror of
https://github.com/rhysd/Mstdn.git
synced 2025-02-08 11:54:16 +01:00
give plugins the ability to make custom key shortcuts
This commit is contained in:
parent
f01dea80ea
commit
bfbb758ff7
37
README.md
37
README.md
@ -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
|
```javascript
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -324,7 +324,31 @@ module.exports = {
|
|||||||
|
|
||||||
Package must export one object.
|
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.
|
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.
|
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`.
|
And then write what plugin should be loaded to `"plugins"` section of your account in `config.json`.
|
||||||
`"hello"` should be added to the list.
|
`"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
|
```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.
|
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.
|
If window is too small to see DevTools, please make window size bigger.
|
||||||
|
@ -6,6 +6,6 @@ import PluginsLoader from './plugins';
|
|||||||
Ipc.on('mstdn:config', (c: Config, a: Account) => {
|
Ipc.on('mstdn:config', (c: Config, a: Account) => {
|
||||||
const loader = new PluginsLoader(c, a);
|
const loader = new PluginsLoader(c, a);
|
||||||
loader.loadAfterAppPrepared();
|
loader.loadAfterAppPrepared();
|
||||||
setupKeymaps(c, a);
|
setupKeymaps(c, a, loader);
|
||||||
document.title = `${document.title} @${a.name}@${a.host}`;
|
document.title = `${document.title} @${a.name}@${a.host}`;
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@ import {remote} from 'electron';
|
|||||||
import * as Mousetrap from 'mousetrap';
|
import * as Mousetrap from 'mousetrap';
|
||||||
import * as Ipc from './ipc';
|
import * as Ipc from './ipc';
|
||||||
import log from './log';
|
import log from './log';
|
||||||
|
import PluginsLoader from './plugins';
|
||||||
import {Config, Account} from '../main/config';
|
import {Config, Account} from '../main/config';
|
||||||
|
|
||||||
function scrollable() {
|
function scrollable() {
|
||||||
@ -58,6 +59,7 @@ const ShortcutActions = {
|
|||||||
export default function setupKeymaps(
|
export default function setupKeymaps(
|
||||||
config: Config,
|
config: Config,
|
||||||
account: Account,
|
account: Account,
|
||||||
|
loader: PluginsLoader,
|
||||||
) {
|
) {
|
||||||
const dataDir = config.__DATA_DIR || '/';
|
const dataDir = config.__DATA_DIR || '/';
|
||||||
for (const key in config.keymaps) {
|
for (const key in config.keymaps) {
|
||||||
@ -85,6 +87,16 @@ export default function setupKeymaps(
|
|||||||
log.error('Failed to run shortcut script ' + script, e);
|
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('/')) {
|
} else if (action.startsWith('/')) {
|
||||||
Mousetrap.bind(key, e => {
|
Mousetrap.bind(key, e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -3,7 +3,10 @@ import {Config, Account} from '../main/config';
|
|||||||
import log from './log';
|
import log from './log';
|
||||||
|
|
||||||
interface Plugin {
|
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 {
|
interface Plugins {
|
||||||
[module_path: string]: Plugin;
|
[module_path: string]: Plugin;
|
||||||
@ -83,4 +86,34 @@ export default class PluginsLoader {
|
|||||||
log.info('Plugins were loaded:', this.preloads);
|
log.info('Plugins were loaded:', this.preloads);
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user