Support customizable shortcuts
The existing shortcuts are good defaults but some might want something different.
Work required:
- converting existing shortcuts to UserSetting entries stored in DB
- settings page where people can add bookmarks -- maybe just storing the JS values similar to https://www.toptal.com/developers/keycode
- figure out how to handle shift, control, etc
- endpoint to read the javascript keycodes (or whatever) so that the mappings can be imported into lute.js
- change the shortcuts template to read in the current shortcuts? Or simply redirect to the settings?
- acceptance test showing the change of the existing settings
Copied from #59 :
Current hotkeys are good, but some may collide with existing hotkeys (eg golden dict uses "c", but so does Lute). Perhaps allow customizing.
Involves:
- adding usersettings for the keys
- form edits for the user settings
- set the defaults for the existing keys
- somehow handle the modifiers (shift, ctl, etc)
- change the javascript switch-case or whatever to use the user settings -- likely render the user settings into the global namespace for js, and refer to that in the js
- tests
- keys must be set
This is helpful: https://www.toptal.com/developers/keycode
ChatGPT hackery:
data model in db
class KeyBinding(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
key_combination = db.Column(db.String(50), nullable=False)
function_name = db.Column(db.String(100), nullable=False)
front end listener
let userKeyBindings = {}; // Will hold keybindings fetched from the server
document.addEventListener('keydown', function(event) {
const key = `${event.ctrlKey ? 'Ctrl+' : ''}${event.altKey ? 'Alt+' : ''}${event.shiftKey ? 'Shift+' : ''}${event.metaKey ? 'Meta+' : ''}${event.key}`;
if (userKeyBindings[key]) {
const functionName = userKeyBindings[key];
if (typeof window[functionName] === 'function') {
window[functionName](); // Call the predefined JavaScript function
}
}
});
// Example predefined function
function myCustomFunction() {
console.log("Custom function called!");
}
get bindings
fetch('/api/keybindings')
.then(response => response.json())
.then(data => {
userKeyBindings = data; // Keybinding object: { "Ctrl+a": "myCustomFunction", ... }
});
api route
@app.route('/api/keybindings')
def get_keybindings():
user_id = current_user.id # Assuming you're using Flask-Login
keybindings = KeyBinding.query.filter_by(user_id=user_id).all()
bindings_dict = {kb.key_combination: kb.function_name for kb in keybindings}
return jsonify(bindings_dict)
Would also need a form etc for user to defined the bindings
Some javascript:
function getKeyString(event) {
const keys = [];
// Check for modifier keys
if (event.ctrlKey) keys.push('ctrl');
if (event.shiftKey) keys.push('shift');
if (event.altKey) keys.push('alt');
if (event.metaKey) keys.push('meta');
// Map special keys to their names
const keyMap = {
'Enter': 'return',
'Escape': 'esc',
'ArrowLeft': 'left-arrow',
'ArrowRight': 'right-arrow',
'ArrowUp': 'up-arrow',
'ArrowDown': 'down-arrow',
' ': 'space'
};
const key = keyMap[event.key] || event.key.toLowerCase();
// If it's a normal key (not a modifier), add it to the keys array
if (!['shift', 'ctrl', 'alt', 'meta'].includes(key)) {
keys.push(key);
}
return keys.join('+');
}
// Usage: Attach this function to the 'keydown' event
document.addEventListener('keydown', function(event) {
const keyString = getKeyString(event);
console.log(keyString); // For debugging, logs the key string
});
Started in branch wip_issue_141_customizable_shortcuts
Done in develop, releasing as beta 3.5.7b2 today.
Launched in 3.5.7.