Procházet zdrojové kódy

Add keyboard shortcuts for scrolling to top/bottom of the item list

Matt Behrens před 2 roky
rodič
revize
1ea3953271

+ 2 - 0
internal/locale/translations/de_DE.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Zum Abonnement gehen",
     "page.keyboard_shortcuts.go_to_previous_page": "Zur vorherigen Seite gehen",
     "page.keyboard_shortcuts.go_to_next_page": "Zur nächsten Seite gehen",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Gehen Sie zum untersten Element",
+    "page.keyboard_shortcuts.go_to_top_item": "Zum obersten Artikel gehen",
     "page.keyboard_shortcuts.open_item": "Gewählten Artikel öffnen",
     "page.keyboard_shortcuts.open_original": "Original-Artikel öffnen",
     "page.keyboard_shortcuts.open_original_same_window": "Öffne den Original-Link in der aktuellen Registerkarte",

+ 2 - 0
internal/locale/translations/el_EL.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Πηγαίνετε στη ροή",
     "page.keyboard_shortcuts.go_to_previous_page": "Μετάβαση στην προηγούμενη σελίδα",
     "page.keyboard_shortcuts.go_to_next_page": "Μετάβαση στην επόμενη σελίδα",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Μετάβαση στο κάτω στοιχείο",
+    "page.keyboard_shortcuts.go_to_top_item": "Μετάβαση στο επάνω στοιχείο",
     "page.keyboard_shortcuts.open_item": "Άνοιγμα επιλεγμένου στοιχείου",
     "page.keyboard_shortcuts.open_original": "Άνοιγμα αρχικού συνδέσμου",
     "page.keyboard_shortcuts.open_original_same_window": "Άνοιγμα αρχικού συνδέσμου στην τρέχουσα καρτέλα",

+ 3 - 1
internal/locale/translations/en_US.json

@@ -176,6 +176,8 @@
     "page.keyboard_shortcuts.go_to_previous_item": "Go to previous item",
     "page.keyboard_shortcuts.go_to_next_item": "Go to next item",
     "page.keyboard_shortcuts.go_to_feed": "Go to feed",
+    "page.keyboard_shortcuts.go_to_top_item": "Go to top item",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Go to bottom item",
     "page.keyboard_shortcuts.go_to_previous_page": "Go to previous page",
     "page.keyboard_shortcuts.go_to_next_page": "Go to next page",
     "page.keyboard_shortcuts.open_item": "Open selected item",
@@ -215,7 +217,7 @@
     "page.settings.webauthn.last_seen_on": "Last Used",
     "page.settings.webauthn.register": "Register passkey",
     "page.settings.webauthn.register.error": "Unable to register passkey",
-    "page.settings.webauthn.delete" : [
+    "page.settings.webauthn.delete": [
         "Remove %d passkey",
         "Remove %d passkeys"
     ],

+ 2 - 0
internal/locale/translations/es_ES.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Ir a la fuente",
     "page.keyboard_shortcuts.go_to_previous_page": "Ir al página anterior",
     "page.keyboard_shortcuts.go_to_next_page": "Ir al página siguiente",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Ir al elemento inferior",
+    "page.keyboard_shortcuts.go_to_top_item": "Ir al elemento superior",
     "page.keyboard_shortcuts.open_item": "Abrir el elemento seleccionado",
     "page.keyboard_shortcuts.open_original": "Abrir el enlace original",
     "page.keyboard_shortcuts.open_original_same_window": "Abrir enlace original en la pestaña actual",

+ 2 - 0
internal/locale/translations/fi_FI.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Siirry syötteeseen",
     "page.keyboard_shortcuts.go_to_previous_page": "Siirry edelliselle sivulle",
     "page.keyboard_shortcuts.go_to_next_page": "Siirry seuraavalle sivulle",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Siirry alimpaan kohtaan",
+    "page.keyboard_shortcuts.go_to_top_item": "Siirry alkuun",
     "page.keyboard_shortcuts.open_item": "Avaa valittu kohde",
     "page.keyboard_shortcuts.open_original": "Avaa alkuperäinen linkki",
     "page.keyboard_shortcuts.open_original_same_window": "Avaa alkuperäinen linkki nykyisessä välilehdessä",

+ 3 - 1
internal/locale/translations/fr_FR.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Voir abonnement",
     "page.keyboard_shortcuts.go_to_previous_page": "Page précédente",
     "page.keyboard_shortcuts.go_to_next_page": "Page suivante",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Aller à l'élément du bas",
+    "page.keyboard_shortcuts.go_to_top_item": "Aller à l'élément supérieur",
     "page.keyboard_shortcuts.open_item": "Ouvrir élément sélectionné",
     "page.keyboard_shortcuts.open_original": "Ouvrir le lien original",
     "page.keyboard_shortcuts.open_original_same_window": "Ouvrir le lien original dans l'onglet en cours",
@@ -215,7 +217,7 @@
     "page.settings.webauthn.last_seen_on": "Dernière utilisation",
     "page.settings.webauthn.register": "Enregister une nouvelle clé d’accès",
     "page.settings.webauthn.register.error": "Impossible d'enregistrer la clé d’accès",
-    "page.settings.webauthn.delete" : [
+    "page.settings.webauthn.delete": [
         "Supprimer %d clé d’accès",
         "Supprimer %d clés d’accès"
     ],

+ 2 - 0
internal/locale/translations/hi_IN.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "फ़ीड पर जाएं",
     "page.keyboard_shortcuts.go_to_previous_page": "पिछले पृष्ठ पर जाएं",
     "page.keyboard_shortcuts.go_to_next_page": "अगले पेज पर जाएं",
+    "page.keyboard_shortcuts.go_to_bottom_item": "निचले आइटम पर जाएँ",
+    "page.keyboard_shortcuts.go_to_top_item": "शीर्ष आइटम पर जाएँ",
     "page.keyboard_shortcuts.open_item": "चयनित आइटम खोलें",
     "page.keyboard_shortcuts.open_original": "मूल लिंक खोलें",
     "page.keyboard_shortcuts.open_original_same_window": "वर्तमान टैब में मूल लिंक खोलें",

+ 2 - 0
internal/locale/translations/id_ID.json

@@ -169,6 +169,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Ke umpan",
     "page.keyboard_shortcuts.go_to_previous_page": "Ke halaman sebelumnya",
     "page.keyboard_shortcuts.go_to_next_page": "Ke halaman berikutnya",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Pergi ke item paling bawah",
+    "page.keyboard_shortcuts.go_to_top_item": "Pergi ke item teratas",
     "page.keyboard_shortcuts.open_item": "Buka entri yang dipilih",
     "page.keyboard_shortcuts.open_original": "Buka tautan asli",
     "page.keyboard_shortcuts.open_original_same_window": "Buka tautan asli di bilah saat ini",

+ 2 - 0
internal/locale/translations/it_IT.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Mostra il feed",
     "page.keyboard_shortcuts.go_to_previous_page": "Mostra la pagina precedente",
     "page.keyboard_shortcuts.go_to_next_page": "Mostra la pagina successiva",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Vai all'elemento in fondo",
+    "page.keyboard_shortcuts.go_to_top_item": "Vai all'elemento principale",
     "page.keyboard_shortcuts.open_item": "Apri l'articolo selezionato",
     "page.keyboard_shortcuts.open_original": "Apri la pagina web originale",
     "page.keyboard_shortcuts.open_original_same_window": "Apri il link originale nella scheda corrente",

+ 2 - 0
internal/locale/translations/ja_JP.json

@@ -169,6 +169,8 @@
     "page.keyboard_shortcuts.go_to_feed": "フィード",
     "page.keyboard_shortcuts.go_to_previous_page": "前のページ",
     "page.keyboard_shortcuts.go_to_next_page": "次のページ",
+    "page.keyboard_shortcuts.go_to_bottom_item": "一番下の項目に移動",
+    "page.keyboard_shortcuts.go_to_top_item": "先頭の項目に移動",
     "page.keyboard_shortcuts.open_item": "選択されたアイテムを開く",
     "page.keyboard_shortcuts.open_original": "オリジナルのリンクを開く",
     "page.keyboard_shortcuts.open_original_same_window": "現在のタブでオリジナルのリンクを開く",

+ 2 - 0
internal/locale/translations/nl_NL.json

@@ -179,6 +179,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Ga naar feed",
     "page.keyboard_shortcuts.go_to_previous_page": "Vorige pagina",
     "page.keyboard_shortcuts.go_to_next_page": "Volgende pagina",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Ga naar het onderste item",
+    "page.keyboard_shortcuts.go_to_top_item": "Ga naar het bovenste item",
     "page.keyboard_shortcuts.open_item": "Open geselecteerde link",
     "page.keyboard_shortcuts.open_original": "Open originele link",
     "page.keyboard_shortcuts.open_original_same_window": "Oorspronkelijke koppeling op huidig tabblad openen",

+ 2 - 0
internal/locale/translations/pl_PL.json

@@ -187,6 +187,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Przejdź do subskrypcji",
     "page.keyboard_shortcuts.go_to_previous_page": "Przejdź do poprzedniej strony",
     "page.keyboard_shortcuts.go_to_next_page": "Przejdź do następnej strony",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Przejdź do dolnego elementu",
+    "page.keyboard_shortcuts.go_to_top_item": "Przejdź do najwyższego elementu",
     "page.keyboard_shortcuts.open_item": "Otwórz zaznaczony artykuł",
     "page.keyboard_shortcuts.open_original": "Otwórz oryginalny artykuł",
     "page.keyboard_shortcuts.open_original_same_window": "Otwórz oryginalny link w bieżącej karcie",

+ 2 - 0
internal/locale/translations/pt_BR.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Ir a fonte",
     "page.keyboard_shortcuts.go_to_previous_page": "Ir a página anterior",
     "page.keyboard_shortcuts.go_to_next_page": "Ir a página seguinte",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Ir para o item inferior",
+    "page.keyboard_shortcuts.go_to_top_item": "Ir para o item superior",
     "page.keyboard_shortcuts.open_item": "Abrir o item selecionado",
     "page.keyboard_shortcuts.open_original": "Abrir o conteúdo original",
     "page.keyboard_shortcuts.open_original_same_window": "Abrir o conteúdo original na janela atual",

+ 2 - 0
internal/locale/translations/ru_RU.json

@@ -187,6 +187,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Перейти к подписке",
     "page.keyboard_shortcuts.go_to_previous_page": "Перейти к предыдущей странице",
     "page.keyboard_shortcuts.go_to_next_page": "Перейти к следующей странице",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Перейти к нижнему элементу",
+    "page.keyboard_shortcuts.go_to_top_item": "Перейти к верхнему элементу",
     "page.keyboard_shortcuts.open_item": "Открыть выбранный элемент",
     "page.keyboard_shortcuts.open_original_same_window": "Открыть оригинальную ссылку в текущей вкладке",
     "page.keyboard_shortcuts.open_original": "Открыть оригинальную ссылку",

+ 2 - 0
internal/locale/translations/tr_TR.json

@@ -178,6 +178,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Beslemeye git",
     "page.keyboard_shortcuts.go_to_previous_page": "Önceki sayfaya git",
     "page.keyboard_shortcuts.go_to_next_page": "Sonraki sayfaya git",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Alt öğeye git",
+    "page.keyboard_shortcuts.go_to_top_item": "En üstteki öğeye git",
     "page.keyboard_shortcuts.open_item": "Seçili öğeyi aç",
     "page.keyboard_shortcuts.open_original": "Orijinal bağlantıyı aç",
     "page.keyboard_shortcuts.open_original_same_window": "Orijinal bağlantıyı mevcut sekmede aç",

+ 2 - 0
internal/locale/translations/uk_UA.json

@@ -187,6 +187,8 @@
     "page.keyboard_shortcuts.go_to_feed": "Перейти до стрічки",
     "page.keyboard_shortcuts.go_to_previous_page": "Перейти до попередньої сторінки",
     "page.keyboard_shortcuts.go_to_next_page": "Перейти до наступної сторінки",
+    "page.keyboard_shortcuts.go_to_bottom_item": "Перейти до нижнього пункту",
+    "page.keyboard_shortcuts.go_to_top_item": "Перейти до верхнього пункту",
     "page.keyboard_shortcuts.open_item": "Відкрити виділений запис",
     "page.keyboard_shortcuts.open_original": "Відкрити оригінальне посилання",
     "page.keyboard_shortcuts.open_original_same_window": "Відкрити оригінальне посилання в поточній вкладці",

+ 5 - 3
internal/locale/translations/zh_CN.json

@@ -169,6 +169,8 @@
     "page.keyboard_shortcuts.go_to_feed": "转到源页面",
     "page.keyboard_shortcuts.go_to_previous_page": "上一页",
     "page.keyboard_shortcuts.go_to_next_page": "下一页",
+    "page.keyboard_shortcuts.go_to_bottom_item": "转到底部项目",
+    "page.keyboard_shortcuts.go_to_top_item": "转到顶部项目",
     "page.keyboard_shortcuts.open_item": "打开选定的文章",
     "page.keyboard_shortcuts.open_original": "打开原始链接",
     "page.keyboard_shortcuts.open_original_same_window": "在当前标签页中打开原始链接",
@@ -406,9 +408,9 @@
     "form.integration.omnivore_activate": "保存文章到 Omnivore",
     "form.integration.omnivore_url": "Omnivore API 端点",
     "form.integration.omnivore_api_key": "Omnivore API 密钥",
-    "form.integration.espial_activate":  "保存文章到 Espial",
-    "form.integration.espial_endpoint":  "Espial API 端点",
-    "form.integration.espial_api_key":  "Espial API 密钥",
+    "form.integration.espial_activate": "保存文章到 Espial",
+    "form.integration.espial_endpoint": "Espial API 端点",
+    "form.integration.espial_api_key": "Espial API 密钥",
     "form.integration.espial_tags": "Espial 标签",
     "form.integration.readwise_activate": "保存文章到 Readwise Reader",
     "form.integration.readwise_api_key": "Readwise Reader Access Token",

+ 2 - 0
internal/locale/translations/zh_TW.json

@@ -169,6 +169,8 @@
     "page.keyboard_shortcuts.go_to_feed": "轉到Feed頁面",
     "page.keyboard_shortcuts.go_to_previous_page": "上一頁",
     "page.keyboard_shortcuts.go_to_next_page": "下一頁",
+    "page.keyboard_shortcuts.go_to_bottom_item": "转到底部项目",
+    "page.keyboard_shortcuts.go_to_top_item": "转到顶部项目",
     "page.keyboard_shortcuts.open_item": "開啟選定的文章",
     "page.keyboard_shortcuts.open_original": "開啟原始連結",
     "page.keyboard_shortcuts.open_original_same_window": "在當前標籤頁中開啟原始連結",

+ 2 - 0
internal/template/templates/common/layout.html

@@ -154,6 +154,8 @@
                     <li>{{ t "page.keyboard_shortcuts.go_to_previous_item" }} = <strong>p</strong>, <strong>k</strong>, <strong>&#x23F4;</strong></li>
                     <li>{{ t "page.keyboard_shortcuts.go_to_next_item" }} = <strong>n</strong>, <strong>j</strong>, <strong>&#x23F5;</strong></li>
                     <li>{{ t "page.keyboard_shortcuts.go_to_feed" }} = <strong>F</strong></li>
+                    <li>{{ t "page.keyboard_shortcuts.go_to_top_item" }} = <strong>g + g</strong></li>
+                    <li>{{ t "page.keyboard_shortcuts.go_to_bottom_item" }} = <strong>G</strong></li>
                 </ul>
 
                 <p>{{ t "page.keyboard_shortcuts.subtitle.pages" }}</p>

+ 31 - 6
internal/ui/static/js/app.js

@@ -444,17 +444,31 @@ function goToPage(page, fallbackSelf) {
     }
 }
 
-function goToPrevious() {
+/**
+ * 
+ * @param {(number|event)} offset - many items to jump for focus. 
+ */
+function goToPrevious(offset) {
+    if (offset instanceof KeyboardEvent) {
+        offset = -1;
+    }
     if (isListView()) {
-        goToListItem(-1);
+        goToListItem(offset);
     } else {
         goToPage("previous");
     }
 }
 
-function goToNext() {
+/**
+ * 
+ * @param {(number|event)} offset - How many items to jump for focus. 
+ */
+function goToNext(offset) {
+    if (offset instanceof KeyboardEvent) {
+        offset = 1;
+    }
     if (isListView()) {
-        goToListItem(1);
+        goToListItem(offset);
     } else {
         goToPage("next");
     }
@@ -482,6 +496,10 @@ function goToFeed() {
     }
 }
 
+// Sentinel values for specific list navigation
+const TOP = 9999;
+const BOTTOM = -9999;
+
 /**
  * @param {number} offset How many items to jump for focus.
  */
@@ -501,8 +519,15 @@ function goToListItem(offset) {
         if (items[i].classList.contains("current-item")) {
             items[i].classList.remove("current-item");
 
-            const index = (i + offset + items.length) % items.length;
-            const item = items[index];
+            // By default adjust selection by offset
+            let itemOffset = (i + offset + items.length) % items.length; 
+            // Allow jumping to top or bottom
+            if (offset == TOP) {
+                itemOffset = 0;
+            } else if (offset == BOTTOM) {
+                itemOffset = items.length - 1;
+            }
+            const item = items[itemOffset];
 
             item.classList.add("current-item");
             DomHelper.scrollPageTo(item);

+ 2 - 0
internal/ui/static/js/bootstrap.js

@@ -9,6 +9,8 @@ document.addEventListener("DOMContentLoaded", () => {
         keyboardHandler.on("g f", goToFeedOrFeeds);
         keyboardHandler.on("g c", () => goToPage("categories"));
         keyboardHandler.on("g s", () => goToPage("settings"));
+        keyboardHandler.on("g g", () => goToPrevious(TOP));
+        keyboardHandler.on("G", () => goToNext(BOTTOM));
         keyboardHandler.on("ArrowLeft", goToPrevious);
         keyboardHandler.on("ArrowRight", goToNext);
         keyboardHandler.on("k", goToPrevious);