Skip to content

Commit 6801170

Browse files
committed
Mousetrap: remove destructive bind endpoint...
and update usage
1 parent 5bc026f commit 6801170

File tree

9 files changed

+163
-84
lines changed

9 files changed

+163
-84
lines changed

packages/common-ui/src/components/cardRendering/AudioAutoPlayer.vue

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,19 +91,24 @@ onMounted(() => {
9191
});
9292
}
9393
94-
SkldrMouseTrap.bind([
94+
// Define hotkeys
95+
const hotkeys = [
9596
{
9697
hotkey: 'up',
9798
callback: play,
9899
command: 'Replay Audio',
99100
},
100-
]);
101+
];
102+
103+
// Add bindings
104+
SkldrMouseTrap.addBinding(hotkeys);
101105
102106
play();
103107
});
104108
105109
onBeforeUnmount(() => {
106-
SkldrMouseTrap.reset();
110+
// Clean up hotkey bindings
111+
SkldrMouseTrap.removeBinding('up');
107112
stop();
108113
});
109114
</script>

packages/common-ui/src/components/studentInputs/RadioMultipleChoice.vue

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export default defineComponent({
3737
currentSelection: -1,
3838
incorrectSelections: [] as number[],
3939
containerRef: null as null | HTMLElement,
40+
_registeredHotkeys: [] as (string | string[])[],
4041
};
4142
},
4243
watch: {
@@ -102,7 +103,7 @@ export default defineComponent({
102103
return ret;
103104
},
104105
bindKeys() {
105-
SkldrMouseTrap.bind([
106+
const hotkeys = [
106107
{
107108
hotkey: 'left',
108109
callback: this.decrementSelection,
@@ -141,19 +142,21 @@ export default defineComponent({
141142
}
142143
})(i)} option`,
143144
})),
144-
]);
145+
];
146+
147+
SkldrMouseTrap.addBinding(hotkeys);
148+
149+
// Store hotkeys for cleanup
150+
this._registeredHotkeys = hotkeys.map(k => k.hotkey);
145151
},
146152
147153
unbindKeys() {
148-
// this.MouseTrap.unbind('left');
149-
// this.MouseTrap.unbind('right');
150-
// this.MouseTrap.unbind('enter');
151-
152-
// for (let i = 1; i <= this.choiceList.length; i++) {
153-
// this.MouseTrap.unbind(i.toString());
154-
// }
155-
156-
SkldrMouseTrap.reset();
154+
// Remove specific hotkeys instead of resetting all
155+
if (this._registeredHotkeys) {
156+
this._registeredHotkeys.forEach(key => {
157+
SkldrMouseTrap.removeBinding(key);
158+
});
159+
}
157160
},
158161
// bindNumberKey(n: number): void {
159162
// this.MouseTrap.bind(n.toString(), () => {

packages/common-ui/src/utils/SkldrMouseTrap.ts

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,17 @@ export class SkldrMouseTrap {
3131
});
3232
}
3333

34-
public static bind(hk: HotKey[]) {
35-
SkldrMouseTrap.reset();
36-
SkldrMouseTrap.instance().hotkeys = hk;
37-
38-
hk.forEach((k) => {
39-
Mousetrap.bindGlobal(k.hotkey, (a, b) => {
40-
console.log(`Running ${k.hotkey}`);
41-
k.callback(a, b);
42-
});
43-
});
44-
}
45-
4634
/**
47-
* Add bindings without resetting existing ones
35+
* Add keyboard bindings without resetting existing ones
36+
* @param hk Single hotkey or array of hotkeys to bind
4837
*/
4938
public static addBinding(hk: HotKey | HotKey[]) {
5039
const hotkeys = Array.isArray(hk) ? hk : [hk];
5140
const instance = SkldrMouseTrap.instance();
52-
41+
5342
// Add to internal registry
5443
instance.hotkeys = [...instance.hotkeys, ...hotkeys];
55-
44+
5645
// Bind each hotkey
5746
hotkeys.forEach((k) => {
5847
Mousetrap.bindGlobal(k.hotkey, (a, b) => {
@@ -63,23 +52,46 @@ export class SkldrMouseTrap {
6352
}
6453

6554
/**
66-
* Remove a specific binding without affecting others
55+
* Remove specific keyboard binding(s) without affecting others
56+
* @param hotkey Single hotkey or array of hotkeys to remove
6757
*/
68-
public static removeBinding(hotkey: string | string[]) {
58+
public static removeBinding(hotkey: string | string[] | Array<string | string[]>) {
6959
const instance = SkldrMouseTrap.instance();
7060
const currentHotkeys = [...instance.hotkeys];
7161

72-
// Remove from internal registry
73-
instance.hotkeys = currentHotkeys.filter(k => {
74-
// Convert both to JSON for comparison to handle arrays correctly
75-
return JSON.stringify(k.hotkey) !== JSON.stringify(hotkey);
76-
});
77-
78-
// Unbind from Mousetrap
79-
Mousetrap.unbind(hotkey);
62+
if (Array.isArray(hotkey) && !hotkey.every(k => typeof k === 'string' || typeof k === 'number')) {
63+
// If it's an array of hotkey specifiers
64+
hotkey.forEach(key => {
65+
// Remove from internal registry
66+
instance.hotkeys = instance.hotkeys.filter(k => {
67+
return JSON.stringify(k.hotkey) !== JSON.stringify(key);
68+
});
69+
70+
// Unbind from Mousetrap
71+
Mousetrap.unbind(key);
72+
});
73+
} else {
74+
// Single hotkey removal (original implementation)
75+
// Remove from internal registry
76+
instance.hotkeys = currentHotkeys.filter(k => {
77+
// Convert both to JSON for comparison to handle arrays correctly
78+
return JSON.stringify(k.hotkey) !== JSON.stringify(hotkey);
79+
});
80+
81+
// Unbind from Mousetrap
82+
Mousetrap.unbind(hotkey);
83+
}
8084
}
8185

86+
/**
87+
* Reset all keyboard bindings
88+
* @warning Consider using removeBinding() for targeted cleanup instead to avoid affecting other components
89+
*/
8290
public static reset() {
91+
console.warn(
92+
'SkldrMouseTrap.reset() may affect hotkeys registered by other components. ' +
93+
'Consider using removeBinding() with specific hotkeys for better component isolation.'
94+
);
8395
Mousetrap.reset();
8496
SkldrMouseTrap.instance().mouseTrap.reset();
8597
SkldrMouseTrap.instance().hotkeys = [];

packages/courses/src/piano/questions/echo/Playback.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ export default defineComponent({
232232
init();
233233
234234
// Bind space key
235-
SkldrMouseTrap.bind([
235+
SkldrMouseTrap.addBinding([
236236
{
237237
hotkey: 'space',
238238
callback: clearAttempt,
@@ -242,7 +242,7 @@ export default defineComponent({
242242
});
243243
244244
onBeforeUnmount(() => {
245-
SkldrMouseTrap.reset();
245+
SkldrMouseTrap.removeBinding('space');
246246
});
247247
248248
return {

packages/platform-ui/src/App.vue

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@
4141
</v-navigation-drawer>
4242

4343
<v-app-bar density="compact">
44-
<v-app-bar-nav-icon @click.stop="toggleDrawer"></v-app-bar-nav-icon>
44+
<SkMouseTrapToolTip hotkey="m" command="Toggle Menu" highlight-effect="none" position="right">
45+
<v-app-bar-nav-icon @click.stop="toggleDrawer"></v-app-bar-nav-icon>
46+
</SkMouseTrapToolTip>
4547
<v-spacer></v-spacer>
4648
<user-login-and-registration-container />
4749
</v-app-bar>
@@ -63,7 +65,7 @@
6365
</v-footer> -->
6466
<snackbar-service id="SnackbarService" />
6567
<SkMouseTrap />
66-
68+
6769
<v-footer app class="pa-0" color="transparent">
6870
<v-card flat width="100%" class="text-center">
6971
<v-card-text class="text-body-2 text-medium-emphasis">
@@ -131,20 +133,18 @@ onBeforeMount(async () => {
131133
132134
onMounted(async () => {
133135
latestBuild.value = 'buildValue not implemented';
134-
136+
135137
// Add a global shortcut to show the keyboard shortcuts dialog
136-
SkldrMouseTrap.bind([
137-
{
138-
hotkey: '?',
139-
command: 'Show keyboard shortcuts',
140-
callback: () => {
141-
const keyboardButton = document.querySelector('.mdi-keyboard');
142-
if (keyboardButton) {
143-
(keyboardButton as HTMLElement).click();
144-
}
138+
SkldrMouseTrap.addBinding({
139+
hotkey: '?',
140+
command: 'Show keyboard shortcuts',
141+
callback: () => {
142+
const keyboardButton = document.querySelector('.mdi-keyboard');
143+
if (keyboardButton) {
144+
(keyboardButton as HTMLElement).click();
145145
}
146-
}
147-
]);
146+
},
147+
});
148148
});
149149
</script>
150150

packages/platform-ui/src/components/Edit/BulkImport/CardPreviewList.vue

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,11 @@ export default defineComponent({
174174
175175
beforeUnmount() {
176176
// Clean up key bindings when component is unmounted
177-
SkldrMouseTrap.reset();
177+
if (this.shortcutsEnabled) {
178+
this.keyBindings.forEach(kb => {
179+
SkldrMouseTrap.removeBinding(kb.hotkey);
180+
});
181+
}
178182
},
179183
180184
methods: {
@@ -235,22 +239,25 @@ export default defineComponent({
235239
236240
if (this.shortcutsEnabled) {
237241
// Register keyboard shortcuts
238-
SkldrMouseTrap.bind(this.keyBindings);
242+
SkldrMouseTrap.addBinding(this.keyBindings);
239243
}
240244
},
241245
242246
enableShortcuts() {
243247
if (!this.shortcutsEnabled) {
244248
this.shortcutsEnabled = true;
245-
SkldrMouseTrap.bind(this.keyBindings);
249+
SkldrMouseTrap.addBinding(this.keyBindings);
246250
console.log('[CardPreviewList] Keyboard shortcuts enabled');
247251
}
248252
},
249253
250254
disableShortcuts() {
251255
if (this.shortcutsEnabled) {
252256
this.shortcutsEnabled = false;
253-
SkldrMouseTrap.reset();
257+
// Remove all registered key bindings
258+
this.keyBindings.forEach(kb => {
259+
SkldrMouseTrap.removeBinding(kb.hotkey);
260+
});
254261
console.log('[CardPreviewList] Keyboard shortcuts disabled');
255262
}
256263
},

0 commit comments

Comments
 (0)