From 924334de4966df185cb9ee6ff3f24c41f86847cf Mon Sep 17 00:00:00 2001
From: Luna D <cod7777@yandex.ru>
Date: Thu, 6 Jun 2024 20:50:13 -0400
Subject: [PATCH] Convert keyboard shortcut scripts to TypeScript

---
 assets/js/shortcuts.js | 62 -----------------------------------
 assets/js/shortcuts.ts | 74 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+), 62 deletions(-)
 delete mode 100644 assets/js/shortcuts.js
 create mode 100644 assets/js/shortcuts.ts

diff --git a/assets/js/shortcuts.js b/assets/js/shortcuts.js
deleted file mode 100644
index 67d1acbd..00000000
--- a/assets/js/shortcuts.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * Keyboard shortcuts
- */
-
-import { $ } from './utils/dom';
-
-function getHover() {
-  const thumbBoxHover = $('.media-box:hover');
-  if (thumbBoxHover) return thumbBoxHover.dataset.imageId;
-}
-
-function openFullView() {
-  const imageHover = $('[data-uris]:hover');
-  if (!imageHover) return;
-
-  window.location = JSON.parse(imageHover.dataset.uris).full;
-}
-
-function openFullViewNewTab() {
-  const imageHover = $('[data-uris]:hover');
-  if (!imageHover) return;
-
-  window.open(JSON.parse(imageHover.dataset.uris).full);
-}
-
-function click(selector) {
-  const el = $(selector);
-  if (el) el.click();
-}
-
-function isOK(event) {
-  return !event.altKey && !event.ctrlKey && !event.metaKey &&
-         document.activeElement.tagName !== 'INPUT' &&
-         document.activeElement.tagName !== 'TEXTAREA';
-}
-
-const keyCodes = {
-  74() { click('.js-prev'); },             // J - go to previous image
-  73() { click('.js-up'); },               // I - go to index page
-  75() { click('.js-next'); },             // K - go to next image
-  82() { click('.js-rand'); },             // R - go to random image
-  83() { click('.js-source-link'); },      // S - go to image source
-  76() { click('.js-tag-sauce-toggle'); }, // L - edit tags
-  79() { openFullView(); },                // O - open original
-  86() { openFullViewNewTab(); },          // V - open original in a new tab
-  70() {                                   // F - favourite image
-    getHover() ? click(`a.interaction--fave[data-image-id="${getHover()}"]`)
-      : click('.block__header a.interaction--fave');
-  },
-  85() {                                   // U - upvote image
-    getHover() ? click(`a.interaction--upvote[data-image-id="${getHover()}"]`)
-      : click('.block__header a.interaction--upvote');
-  },
-};
-
-function listenForKeys() {
-  document.addEventListener('keydown', event => {
-    if (isOK(event) && keyCodes[event.keyCode]) { keyCodes[event.keyCode](); event.preventDefault(); }
-  });
-}
-
-export { listenForKeys };
diff --git a/assets/js/shortcuts.ts b/assets/js/shortcuts.ts
new file mode 100644
index 00000000..a3254c16
--- /dev/null
+++ b/assets/js/shortcuts.ts
@@ -0,0 +1,74 @@
+/**
+ * Keyboard shortcuts
+ */
+
+import { $ } from './utils/dom';
+
+interface ShortcutKeycodes {
+  [key: string]: () => void
+}
+
+function getHover(): string | null {
+  const thumbBoxHover = $<HTMLDivElement>('.media-box:hover');
+
+  return thumbBoxHover && (thumbBoxHover.dataset.imageId || null);
+}
+
+function openFullView() {
+  const imageHover = $<HTMLDivElement>('[data-uris]:hover');
+
+  if (!imageHover || !imageHover.dataset.uris) return;
+
+  window.location = JSON.parse(imageHover.dataset.uris).full;
+}
+
+function openFullViewNewTab() {
+  const imageHover = $<HTMLDivElement>('[data-uris]:hover');
+
+  if (!imageHover || !imageHover.dataset.uris) return;
+
+  window.open(JSON.parse(imageHover.dataset.uris).full);
+}
+
+function click(selector: string) {
+  const el = $<HTMLElement>(selector);
+
+  if (el) {
+    el.click();
+  }
+}
+
+function isOK(event: KeyboardEvent): boolean {
+  return !event.altKey && !event.ctrlKey && !event.metaKey &&
+         document.activeElement !== null &&
+         document.activeElement.tagName !== 'INPUT' &&
+         document.activeElement.tagName !== 'TEXTAREA';
+}
+
+const keyCodes: ShortcutKeycodes = {
+  KeyJ() { click('.js-prev'); },             // J - go to previous image
+  KeyI() { click('.js-up'); },               // I - go to index page
+  KeyK() { click('.js-next'); },             // K - go to next image
+  KeyR() { click('.js-rand'); },             // R - go to random image
+  KeyS() { click('.js-source-link'); },      // S - go to image source
+  KeyL() { click('.js-tag-sauce-toggle'); }, // L - edit tags
+  KeyO() { openFullView(); },                // O - open original
+  KeyV() { openFullViewNewTab(); },          // V - open original in a new tab
+  KeyF() {                                   // F - favourite image
+    getHover() ? click(`a.interaction--fave[data-image-id="${getHover()}"]`)
+      : click('.block__header a.interaction--fave');
+  },
+  KeyU() {                                   // U - upvote image
+    getHover() ? click(`a.interaction--upvote[data-image-id="${getHover()}"]`)
+      : click('.block__header a.interaction--upvote');
+  },
+};
+
+export function listenForKeys() {
+  document.addEventListener('keydown', (event: KeyboardEvent) => {
+    if (isOK(event) && keyCodes[event.code]) {
+      keyCodes[event.code]();
+      event.preventDefault();
+    }
+  });
+}