mirror of
https://github.com/rhysd/Mstdn.git
synced 2025-01-21 20:52:11 +01:00
implement key shortcut plugin
This commit is contained in:
parent
8bb5b78ef9
commit
ae833be107
@ -1,7 +1,7 @@
|
|||||||
import {app, systemPreferences, dialog, shell} from 'electron';
|
import {app, systemPreferences, dialog, shell} from 'electron';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import log from './log';
|
import log from './log';
|
||||||
import {CONFIG_FILE, IS_DARWIN, IS_WINDOWS} from './common';
|
import {CONFIG_FILE, IS_DARWIN, IS_WINDOWS, DATA_DIR} from './common';
|
||||||
|
|
||||||
export interface Account {
|
export interface Account {
|
||||||
host: string;
|
host: string;
|
||||||
@ -18,6 +18,7 @@ export interface Config {
|
|||||||
zoom_factor: number;
|
zoom_factor: number;
|
||||||
accounts: Account[];
|
accounts: Account[];
|
||||||
chromium_sandbox: boolean;
|
chromium_sandbox: boolean;
|
||||||
|
__DATA_DIR?: string;
|
||||||
keymaps: {[key: string]: string};
|
keymaps: {[key: string]: string};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +101,7 @@ export default function loadConfig(): Promise<Config> {
|
|||||||
if (!config.accounts || config.accounts[0].host === '' || config.accounts[0].name === '') {
|
if (!config.accounts || config.accounts[0].host === '' || config.accounts[0].name === '') {
|
||||||
recommendConfigAndDie(CONFIG_FILE);
|
recommendConfigAndDie(CONFIG_FILE);
|
||||||
} else {
|
} else {
|
||||||
|
config.__DATA_DIR = DATA_DIR;
|
||||||
resolve(config);
|
resolve(config);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1,82 +1,8 @@
|
|||||||
import * as Mousetrap from 'mousetrap';
|
|
||||||
import {Config, Account} from '../main/config';
|
import {Config, Account} from '../main/config';
|
||||||
import * as Ipc from './ipc';
|
import * as Ipc from './ipc';
|
||||||
import log from './log';
|
import setupKeymaps from './key_handler';
|
||||||
|
|
||||||
function scrollable() {
|
|
||||||
const scrollable = document.querySelector('.scrollable');
|
|
||||||
if (!scrollable) {
|
|
||||||
log.error('Scrollable element was not found!');
|
|
||||||
return {scrollTop: 0};
|
|
||||||
}
|
|
||||||
return scrollable;
|
|
||||||
}
|
|
||||||
|
|
||||||
function navigateTo(host: string, path: string) {
|
|
||||||
const url = `https://${host}${path}`;
|
|
||||||
if (window.location.href === url) {
|
|
||||||
log.info('Current URL is already', url);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const link = document.querySelector(`a[href="${path}"]`);
|
|
||||||
if (link) {
|
|
||||||
log.info('Click link by shortcut', path);
|
|
||||||
(link as HTMLAnchorElement).click();
|
|
||||||
} else {
|
|
||||||
log.info('Force navigation by shortcut', path);
|
|
||||||
window.location.href = url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ShortcutActions = {
|
|
||||||
'scroll-top': () => {
|
|
||||||
scrollable().scrollTop = 0;
|
|
||||||
},
|
|
||||||
'scroll-bottom': () => {
|
|
||||||
scrollable().scrollTop = document.body.scrollHeight;
|
|
||||||
},
|
|
||||||
'scroll-down': () => {
|
|
||||||
scrollable().scrollTop += window.innerHeight / 3;
|
|
||||||
},
|
|
||||||
'scroll-up': () => {
|
|
||||||
scrollable().scrollTop -= window.innerHeight / 3;
|
|
||||||
},
|
|
||||||
'next-account': () => {
|
|
||||||
Ipc.send('mstdn:next-account');
|
|
||||||
},
|
|
||||||
'prev-account': () => {
|
|
||||||
Ipc.send('mstdn:prev-account');
|
|
||||||
},
|
|
||||||
} as {[action: string]: () => void};
|
|
||||||
|
|
||||||
function setupKeybinds(keybinds: {[key: string]: string}, host: string) {
|
|
||||||
for (const key in keybinds) {
|
|
||||||
const action = keybinds[key];
|
|
||||||
if (action.startsWith('/')) {
|
|
||||||
Mousetrap.bind(key, e => {
|
|
||||||
e.preventDefault();
|
|
||||||
navigateTo(host, action);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const func = ShortcutActions[action];
|
|
||||||
if (!func) {
|
|
||||||
log.error('Unknown shortcut action:', action);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Mousetrap.bind(key, e => {
|
|
||||||
log.info('Shortcut:', action);
|
|
||||||
e.preventDefault();
|
|
||||||
func();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let config: Config | null = null;
|
|
||||||
|
|
||||||
Ipc.on('mstdn:config', (c: Config, a: Account) => {
|
Ipc.on('mstdn:config', (c: Config, a: Account) => {
|
||||||
config = c;
|
setupKeymaps(c, a);
|
||||||
setupKeybinds(config.keymaps, a.host);
|
|
||||||
document.title = `${document.title} @${a.name}@${a.host}`;
|
document.title = `${document.title} @${a.name}@${a.host}`;
|
||||||
});
|
});
|
||||||
|
103
renderer/key_handler.ts
Normal file
103
renderer/key_handler.ts
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import * as Mousetrap from 'mousetrap';
|
||||||
|
import * as Ipc from './ipc';
|
||||||
|
import log from './log';
|
||||||
|
import {Config, Account} from '../main/config';
|
||||||
|
|
||||||
|
function scrollable() {
|
||||||
|
const scrollable = document.querySelector('.scrollable');
|
||||||
|
if (!scrollable) {
|
||||||
|
log.error('Scrollable element was not found!');
|
||||||
|
return {scrollTop: 0};
|
||||||
|
}
|
||||||
|
return scrollable;
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigateTo(host: string, path: string) {
|
||||||
|
const url = `https://${host}${path}`;
|
||||||
|
if (window.location.href === url) {
|
||||||
|
log.info('Current URL is already', url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const link = document.querySelector(`a[href="${path}"]`);
|
||||||
|
if (link) {
|
||||||
|
log.info('Click link by shortcut', path);
|
||||||
|
(link as HTMLAnchorElement).click();
|
||||||
|
} else {
|
||||||
|
log.info('Force navigation by shortcut', path);
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShortcutActions = {
|
||||||
|
'scroll-top': () => {
|
||||||
|
scrollable().scrollTop = 0;
|
||||||
|
},
|
||||||
|
'scroll-bottom': () => {
|
||||||
|
scrollable().scrollTop = document.body.scrollHeight;
|
||||||
|
},
|
||||||
|
'scroll-down': () => {
|
||||||
|
scrollable().scrollTop += window.innerHeight / 3;
|
||||||
|
},
|
||||||
|
'scroll-up': () => {
|
||||||
|
scrollable().scrollTop -= window.innerHeight / 3;
|
||||||
|
},
|
||||||
|
'next-account': () => {
|
||||||
|
Ipc.send('mstdn:next-account');
|
||||||
|
},
|
||||||
|
'prev-account': () => {
|
||||||
|
Ipc.send('mstdn:prev-account');
|
||||||
|
},
|
||||||
|
} as {[action: string]: () => void};
|
||||||
|
|
||||||
|
export default function setupKeymaps(
|
||||||
|
config: Config,
|
||||||
|
account: Account,
|
||||||
|
) {
|
||||||
|
const dataDir = config.__DATA_DIR || '/';
|
||||||
|
for (const key in config.keymaps) {
|
||||||
|
const action = config.keymaps[key];
|
||||||
|
if (action.endsWith('.js')) {
|
||||||
|
if (config.chromium_sandbox) {
|
||||||
|
log.info('Loading external script is limited because Chromium sandbox is enabled. Disable shortcut:', action);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const script = path.join(dataDir, action);
|
||||||
|
|
||||||
|
let plugin: (c: Config, a: Account) => void;
|
||||||
|
try {
|
||||||
|
plugin = require(script);
|
||||||
|
} catch (e) {
|
||||||
|
log.error('Error while loading plugin ' + script, e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Mousetrap.bind(key, e => {
|
||||||
|
e.preventDefault();
|
||||||
|
log.info('Shortcut:', action);
|
||||||
|
try {
|
||||||
|
plugin(config, account);
|
||||||
|
} catch (e) {
|
||||||
|
log.error('Failed to run shortcut script ' + script, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (action.startsWith('/')) {
|
||||||
|
Mousetrap.bind(key, e => {
|
||||||
|
e.preventDefault();
|
||||||
|
navigateTo(account.host, action);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const func = ShortcutActions[action];
|
||||||
|
if (!func) {
|
||||||
|
log.error('Unknown shortcut action:', action);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Mousetrap.bind(key, e => {
|
||||||
|
log.info('Shortcut:', action);
|
||||||
|
e.preventDefault();
|
||||||
|
func();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user