diff --git a/internal/locale/translations/de_DE.json b/internal/locale/translations/de_DE.json index 9e0595b8..cc60035a 100644 --- a/internal/locale/translations/de_DE.json +++ b/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", diff --git a/internal/locale/translations/el_EL.json b/internal/locale/translations/el_EL.json index 0e279c5c..82282163 100644 --- a/internal/locale/translations/el_EL.json +++ b/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": "Άνοιγμα αρχικού συνδέσμου στην τρέχουσα καρτέλα", diff --git a/internal/locale/translations/en_US.json b/internal/locale/translations/en_US.json index a55b0d6b..97e58fe5 100644 --- a/internal/locale/translations/en_US.json +++ b/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" ], diff --git a/internal/locale/translations/es_ES.json b/internal/locale/translations/es_ES.json index 2bfffd66..914d8994 100644 --- a/internal/locale/translations/es_ES.json +++ b/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", diff --git a/internal/locale/translations/fi_FI.json b/internal/locale/translations/fi_FI.json index 416354e6..41bd2e50 100644 --- a/internal/locale/translations/fi_FI.json +++ b/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ä", diff --git a/internal/locale/translations/fr_FR.json b/internal/locale/translations/fr_FR.json index 1c53a6a7..d616eb3e 100644 --- a/internal/locale/translations/fr_FR.json +++ b/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" ], diff --git a/internal/locale/translations/hi_IN.json b/internal/locale/translations/hi_IN.json index c580701f..199c66af 100644 --- a/internal/locale/translations/hi_IN.json +++ b/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": "वर्तमान टैब में मूल लिंक खोलें", diff --git a/internal/locale/translations/id_ID.json b/internal/locale/translations/id_ID.json index 388d80db..ee06ac61 100644 --- a/internal/locale/translations/id_ID.json +++ b/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", diff --git a/internal/locale/translations/it_IT.json b/internal/locale/translations/it_IT.json index 245eb532..6e808a02 100644 --- a/internal/locale/translations/it_IT.json +++ b/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", diff --git a/internal/locale/translations/ja_JP.json b/internal/locale/translations/ja_JP.json index 970c83ef..8c767b55 100644 --- a/internal/locale/translations/ja_JP.json +++ b/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": "現在のタブでオリジナルのリンクを開く", diff --git a/internal/locale/translations/nl_NL.json b/internal/locale/translations/nl_NL.json index e7333039..d47510e9 100644 --- a/internal/locale/translations/nl_NL.json +++ b/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", diff --git a/internal/locale/translations/pl_PL.json b/internal/locale/translations/pl_PL.json index 7098cfa3..32f3e4f8 100644 --- a/internal/locale/translations/pl_PL.json +++ b/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", diff --git a/internal/locale/translations/pt_BR.json b/internal/locale/translations/pt_BR.json index 32582bfa..56861a3a 100644 --- a/internal/locale/translations/pt_BR.json +++ b/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", diff --git a/internal/locale/translations/ru_RU.json b/internal/locale/translations/ru_RU.json index f673dd77..69c139f0 100644 --- a/internal/locale/translations/ru_RU.json +++ b/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": "Открыть оригинальную ссылку", diff --git a/internal/locale/translations/tr_TR.json b/internal/locale/translations/tr_TR.json index a59d1cac..85238400 100644 --- a/internal/locale/translations/tr_TR.json +++ b/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ç", diff --git a/internal/locale/translations/uk_UA.json b/internal/locale/translations/uk_UA.json index 66fbbb82..eeb305d7 100644 --- a/internal/locale/translations/uk_UA.json +++ b/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": "Відкрити оригінальне посилання в поточній вкладці", diff --git a/internal/locale/translations/zh_CN.json b/internal/locale/translations/zh_CN.json index a494943f..dc1079c4 100644 --- a/internal/locale/translations/zh_CN.json +++ b/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", diff --git a/internal/locale/translations/zh_TW.json b/internal/locale/translations/zh_TW.json index 58493864..4b4316f3 100644 --- a/internal/locale/translations/zh_TW.json +++ b/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": "在當前標籤頁中開啟原始連結", diff --git a/internal/template/templates/common/layout.html b/internal/template/templates/common/layout.html index d1786fc6..f456c058 100644 --- a/internal/template/templates/common/layout.html +++ b/internal/template/templates/common/layout.html @@ -154,6 +154,8 @@
  • {{ t "page.keyboard_shortcuts.go_to_previous_item" }} = p, k,
  • {{ t "page.keyboard_shortcuts.go_to_next_item" }} = n, j,
  • {{ t "page.keyboard_shortcuts.go_to_feed" }} = F
  • +
  • {{ t "page.keyboard_shortcuts.go_to_top_item" }} = g + g
  • +
  • {{ t "page.keyboard_shortcuts.go_to_bottom_item" }} = G
  • {{ t "page.keyboard_shortcuts.subtitle.pages" }}

    diff --git a/internal/ui/static/js/app.js b/internal/ui/static/js/app.js index 311d506f..00083b20 100644 --- a/internal/ui/static/js/app.js +++ b/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); diff --git a/internal/ui/static/js/bootstrap.js b/internal/ui/static/js/bootstrap.js index 0a9c2b78..b1aa4536 100644 --- a/internal/ui/static/js/bootstrap.js +++ b/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);