| 207 | } |
| 208 | |
| 209 | function useKeyCapture(input: { |
| 210 | active: () => string | null |
| 211 | stop: () => void |
| 212 | set: (id: string, keybind: string) => void |
| 213 | used: () => Map<string, { id: string; title: string }[]> |
| 214 | language: ReturnType<typeof useLanguage> |
| 215 | }) { |
| 216 | onMount(() => { |
| 217 | const handle = (event: KeyboardEvent) => { |
| 218 | const id = input.active() |
| 219 | if (!id) return |
| 220 | |
| 221 | event.preventDefault() |
| 222 | event.stopPropagation() |
| 223 | event.stopImmediatePropagation() |
| 224 | |
| 225 | if (event.key === "Escape") { |
| 226 | input.stop() |
| 227 | return |
| 228 | } |
| 229 | |
| 230 | const clear = |
| 231 | (event.key === "Backspace" || event.key === "Delete") && |
| 232 | !event.ctrlKey && |
| 233 | !event.metaKey && |
| 234 | !event.altKey && |
| 235 | !event.shiftKey |
| 236 | if (clear) { |
| 237 | input.set(id, "none") |
| 238 | input.stop() |
| 239 | return |
| 240 | } |
| 241 | |
| 242 | const next = recordKeybind(event) |
| 243 | if (!next) return |
| 244 | |
| 245 | const conflicts = new Map<string, string>() |
| 246 | for (const sig of signatures(next)) { |
| 247 | for (const item of input.used().get(sig) ?? []) { |
| 248 | if (item.id === id) continue |
| 249 | conflicts.set(item.id, item.title) |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | if (conflicts.size > 0) { |
| 254 | showToast({ |
| 255 | title: input.language.t("settings.shortcuts.conflict.title"), |
| 256 | description: input.language.t("settings.shortcuts.conflict.description", { |
| 257 | keybind: formatKeybind(next, input.language.t), |
| 258 | titles: [...conflicts.values()].join(", "), |
| 259 | }), |
| 260 | }) |
| 261 | return |
| 262 | } |
| 263 | |
| 264 | input.set(id, next) |
| 265 | input.stop() |
| 266 | } |