diff --git a/package.json b/package.json
index 0e229cb03..8dd374b02 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
"react-i18next": "^15.1.3",
"react-is": "18.3.1",
"spatial-navigation-polyfill": "github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6",
- "stremio-translations": "github:Stremio/stremio-translations#abe7684165a031755e9aee39da26daa806ba7824",
+ "stremio-translations": "github:Stremio/stremio-translations#01aaa201e419782b26b9f2cbe4430795021426e5",
"url": "0.11.4",
"use-long-press": "^3.2.0"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2bf50734f..e42f446f8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -90,8 +90,8 @@ importers:
specifier: github:Stremio/spatial-navigation#64871b1422466f5f45d24ebc8bbd315b2ebab6a6
version: https://codeload.github.com/Stremio/spatial-navigation/tar.gz/64871b1422466f5f45d24ebc8bbd315b2ebab6a6
stremio-translations:
- specifier: github:Stremio/stremio-translations#abe7684165a031755e9aee39da26daa806ba7824
- version: https://codeload.github.com/Stremio/stremio-translations/tar.gz/abe7684165a031755e9aee39da26daa806ba7824
+ specifier: github:Stremio/stremio-translations#01aaa201e419782b26b9f2cbe4430795021426e5
+ version: https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5
url:
specifier: 0.11.4
version: 0.11.4
@@ -4527,9 +4527,9 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
- stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/abe7684165a031755e9aee39da26daa806ba7824:
- resolution: {tarball: https://codeload.github.com/Stremio/stremio-translations/tar.gz/abe7684165a031755e9aee39da26daa806ba7824}
- version: 1.44.12
+ stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5:
+ resolution: {tarball: https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5}
+ version: 1.44.13
string-length@4.0.2:
resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
@@ -10283,7 +10283,7 @@ snapshots:
es-errors: 1.3.0
internal-slot: 1.1.0
- stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/abe7684165a031755e9aee39da26daa806ba7824: {}
+ stremio-translations@https://codeload.github.com/Stremio/stremio-translations/tar.gz/01aaa201e419782b26b9f2cbe4430795021426e5: {}
string-length@4.0.2:
dependencies:
diff --git a/src/App/App.js b/src/App/App.js
index 8bb22c679..7a1383dc4 100644
--- a/src/App/App.js
+++ b/src/App/App.js
@@ -6,11 +6,12 @@ const { useTranslation } = require('react-i18next');
const { Router } = require('stremio-router');
const { Core, Shell, Chromecast, DragAndDrop, KeyboardShortcuts, ServicesProvider } = require('stremio/services');
const { NotFound } = require('stremio/routes');
-const { FileDropProvider, PlatformProvider, ToastProvider, TooltipProvider, CONSTANTS, withCoreSuspender, useShell } = require('stremio/common');
+const { FileDropProvider, PlatformProvider, ToastProvider, TooltipProvider, ShortcutsProvider, CONSTANTS, withCoreSuspender, useShell, useBinaryState } = require('stremio/common');
const ServicesToaster = require('./ServicesToaster');
const DeepLinkHandler = require('./DeepLinkHandler');
const SearchParamsHandler = require('./SearchParamsHandler');
const { default: UpdaterBanner } = require('./UpdaterBanner');
+const { default: ShortcutsModal } = require('./ShortcutsModal');
const ErrorDialog = require('./ErrorDialog');
const withProtectedRoutes = require('./withProtectedRoutes');
const routerViewsConfig = require('./routerViewsConfig');
@@ -38,6 +39,14 @@ const App = () => {
};
}, []);
const [initialized, setInitialized] = React.useState(false);
+ const [shortcutModalOpen,, closeShortcutsModal, toggleShortcutModal] = useBinaryState(false);
+
+ const onShortcut = React.useCallback((name) => {
+ if (name === 'shortcuts') {
+ toggleShortcutModal();
+ }
+ }, [toggleShortcutModal]);
+
React.useEffect(() => {
let prevPath = window.location.hash.slice(1);
const onLocationHashChange = () => {
@@ -204,15 +213,20 @@ const App = () => {
-
-
-
-
-
+
+ {
+ shortcutModalOpen &&
+ }
+
+
+
+
+
+
diff --git a/src/App/ShortcutsModal/ShortcutsModal.tsx b/src/App/ShortcutsModal/ShortcutsModal.tsx
new file mode 100644
index 000000000..5fec24837
--- /dev/null
+++ b/src/App/ShortcutsModal/ShortcutsModal.tsx
@@ -0,0 +1,59 @@
+// Copyright (C) 2017-2023 Smart code 203358507
+
+import React, { useEffect } from 'react';
+import { createPortal } from 'react-dom';
+import { useTranslation } from 'react-i18next';
+import Icon from '@stremio/stremio-icons/react';
+import { useShortcuts } from 'stremio/common';
+import { Button, ShortcutsGroup } from 'stremio/components';
+import styles from './styles.less';
+
+type Props = {
+ onClose: () => void,
+};
+
+const ShortcutsModal = ({ onClose }: Props) => {
+ const { t } = useTranslation();
+ const { grouped } = useShortcuts();
+
+ useEffect(() => {
+ const onKeyDown = ({ key }: KeyboardEvent) => {
+ key === 'Escape' && onClose();
+ };
+
+ document.addEventListener('keydown', onKeyDown);
+ return () => document.removeEventListener('keydown', onKeyDown);
+ }, []);
+
+ return createPortal((
+
+
+
+
+
+
+ {t('SETTINGS_NAV_SHORTCUTS')}
+
+
+
+
+
+
+ {
+ grouped.map(({ name, label, shortcuts }) => (
+
+ ))
+ }
+
+
+
+ ), document.body);
+};
+
+export default ShortcutsModal;
diff --git a/src/App/ShortcutsModal/index.ts b/src/App/ShortcutsModal/index.ts
new file mode 100644
index 000000000..5a7549fac
--- /dev/null
+++ b/src/App/ShortcutsModal/index.ts
@@ -0,0 +1,2 @@
+import ShortcutsModal from './ShortcutsModal';
+export default ShortcutsModal;
diff --git a/src/App/ShortcutsModal/styles.less b/src/App/ShortcutsModal/styles.less
new file mode 100644
index 000000000..ebbc19c62
--- /dev/null
+++ b/src/App/ShortcutsModal/styles.less
@@ -0,0 +1,91 @@
+@import (reference) '~@stremio/stremio-colors/less/stremio-colors.less';
+
+.shortcuts-modal {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .backdrop {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: @color-background-dark5-40;
+ cursor: pointer;
+ }
+
+ .container {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ max-height: 80%;
+ max-width: 80%;
+ border-radius: var(--border-radius);
+ background-color: var(--modal-background-color);
+ box-shadow: var(--outer-glow);
+ overflow-y: auto;
+
+ .header {
+ flex: none;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ height: 5rem;
+ padding-left: 2.5rem;
+ padding-right: 1rem;
+
+ .title {
+ position: relative;
+ font-size: 1.5rem;
+ font-weight: 500;
+ color: var(--primary-foreground-color);
+ }
+
+ .close-button {
+ position: relative;
+ width: 3rem;
+ height: 3rem;
+ padding: 0.5rem;
+ border-radius: var(--border-radius);
+ z-index: 2;
+
+ .icon {
+ display: block;
+ width: 100%;
+ height: 100%;
+ color: var(--primary-foreground-color);
+ opacity: 0.4;
+ }
+
+ &:hover, &:focus {
+ .icon {
+ opacity: 1;
+ color: var(--primary-foreground-color);
+ }
+ }
+
+ &:focus {
+ outline-color: var(--primary-foreground-color);
+ }
+ }
+ }
+
+ .content {
+ position: relative;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ gap: 3rem;
+ padding: 0 2.5rem;
+ padding-bottom: 2rem;
+ overflow-y: auto;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/common/Shortcuts/Shortcuts.tsx b/src/common/Shortcuts/Shortcuts.tsx
new file mode 100644
index 000000000..532e9a409
--- /dev/null
+++ b/src/common/Shortcuts/Shortcuts.tsx
@@ -0,0 +1,54 @@
+import React, { createContext, useCallback, useContext, useEffect } from 'react';
+import shortcuts from './shortcuts.json';
+
+const SHORTCUTS = shortcuts.map(({ shortcuts }) => shortcuts).flat();
+
+export type ShortcutName = string;
+export type ShortcutListener = () => void;
+
+interface ShortcutsContext {
+ grouped: ShortcutGroup[],
+}
+
+const ShortcutsContext = createContext({} as ShortcutsContext);
+
+type Props = {
+ children: JSX.Element,
+ onShortcut: (name: ShortcutName) => void,
+};
+
+const ShortcutsProvider = ({ children, onShortcut }: Props) => {
+ const onKeyDown = useCallback(({ ctrlKey, shiftKey, key }: KeyboardEvent) => {
+ SHORTCUTS.forEach(({ name, combos }) => combos.forEach((keys) => {
+ const modifers = (keys.includes('Ctrl') ? ctrlKey : true)
+ && (keys.includes('Shift') ? shiftKey : true);
+
+ if (modifers && keys.includes(key.toUpperCase())) {
+ onShortcut(name as ShortcutName);
+ }
+ }));
+ }, [onShortcut]);
+
+ useEffect(() => {
+ document.addEventListener('keydown', onKeyDown);
+
+ return () => {
+ document.removeEventListener('keydown', onKeyDown);
+ };
+ }, [onKeyDown]);
+
+ return (
+
+ {children}
+
+ );
+};
+
+const useShortcuts = () => {
+ return useContext(ShortcutsContext);
+};
+
+export {
+ ShortcutsProvider,
+ useShortcuts
+};
diff --git a/src/common/Shortcuts/index.ts b/src/common/Shortcuts/index.ts
new file mode 100644
index 000000000..f7fa38a18
--- /dev/null
+++ b/src/common/Shortcuts/index.ts
@@ -0,0 +1,5 @@
+import { ShortcutsProvider, useShortcuts } from './Shortcuts';
+export {
+ ShortcutsProvider,
+ useShortcuts,
+};
diff --git a/src/common/Shortcuts/shortcuts.json b/src/common/Shortcuts/shortcuts.json
new file mode 100644
index 000000000..766288fb0
--- /dev/null
+++ b/src/common/Shortcuts/shortcuts.json
@@ -0,0 +1,89 @@
+[
+ {
+ "name": "general",
+ "label": "SETTINGS_NAV_GENERAL",
+ "shortcuts": [
+ {
+ "name": "navigateTabs",
+ "label": "SETTINGS_SHORTCUT_NAVIGATE_MENUS",
+ "combos": [["1", "2", "3", "4", "5", "6"]]
+ },
+ {
+ "name": "navigateSearch",
+ "label": "SETTINGS_SHORTCUT_GO_TO_SEARCH",
+ "combos": [["0"]]
+ },
+ {
+ "name": "fullscreen",
+ "label": "SETTINGS_SHORTCUT_FULLSCREEN",
+ "combos": [["F"]]
+ },
+ {
+ "name": "exit",
+ "label": "SETTINGS_SHORTCUT_EXIT_BACK",
+ "combos": [["Escape"]]
+ },
+ {
+ "name": "shortcuts",
+ "label": "SETTINGS_SHORTCUT_SHORTCUTS",
+ "combos": [["Ctrl", "/"]]
+ }
+ ]
+ },
+ {
+ "name": "player",
+ "label": "SETTINGS_NAV_PLAYER",
+ "shortcuts": [
+ {
+ "name": "playPause",
+ "label": "SETTINGS_SHORTCUT_PLAY_PAUSE",
+ "combos": [["Space"]]
+ },
+ {
+ "name": "seekForward",
+ "label": "SETTINGS_SHORTCUT_SEEK_FORWARD",
+ "combos": [["ArrowRight"], ["Shift", "ArrowRight"]]
+ },
+ {
+ "name": "seekBackward",
+ "label": "SETTINGS_SHORTCUT_SEEK_BACKWARD",
+ "combos": [["ArrowLeft"], ["Shift", "ArrowLeft"]]
+ },
+ {
+ "name": "volumeUp",
+ "label": "SETTINGS_SHORTCUT_VOLUME_UP",
+ "combos": [["ArrowUp"]]
+ },
+ {
+ "name": "volumeDown",
+ "label": "SETTINGS_SHORTCUT_VOLUME_DOWN",
+ "combos": [["ArrowDown"]]
+ },
+ {
+ "name": "subtitlesSize",
+ "label": "SETTINGS_SHORTCUT_SUBTITLES_SIZE",
+ "combos": [["-"], ["="]]
+ },
+ {
+ "name": "subtitlesDelay",
+ "label": "SETTINGS_SHORTCUT_SUBTITLES_DELAY",
+ "combos": [["G"], ["H"]]
+ },
+ {
+ "name": "subtitlesMenu",
+ "label": "SETTINGS_SHORTCUT_MENU_SUBTITLES",
+ "combos": [["S"]]
+ },
+ {
+ "name": "audioMenu",
+ "label": "SETTINGS_SHORTCUT_MENU_AUDIO",
+ "combos": [["A"]]
+ },
+ {
+ "name": "infoMenu",
+ "label": "SETTINGS_SHORTCUT_MENU_INFO",
+ "combos": [["I"]]
+ }
+ ]
+ }
+]
\ No newline at end of file
diff --git a/src/common/Shortcuts/types.d.ts b/src/common/Shortcuts/types.d.ts
new file mode 100644
index 000000000..e4180616d
--- /dev/null
+++ b/src/common/Shortcuts/types.d.ts
@@ -0,0 +1,11 @@
+type Shortcut = {
+ name: string,
+ label: string,
+ combos: string[][],
+};
+
+type ShortcutGroup = {
+ name: string,
+ label: string,
+ shortcuts: Shortcut[],
+};
diff --git a/src/common/index.js b/src/common/index.js
index 25df5c158..0b9cb252f 100644
--- a/src/common/index.js
+++ b/src/common/index.js
@@ -4,6 +4,7 @@ const { FileDropProvider, onFileDrop } = require('./FileDrop');
const { PlatformProvider, usePlatform } = require('./Platform');
const { ToastProvider, useToast } = require('./Toast');
const { TooltipProvider, Tooltip } = require('./Tooltips');
+const { ShortcutsProvider, useShortcuts } = require('./Shortcuts');
const comparatorWithPriorities = require('./comparatorWithPriorities');
const CONSTANTS = require('./CONSTANTS');
const { withCoreSuspender, useCoreSuspender } = require('./CoreSuspender');
@@ -35,6 +36,8 @@ module.exports = {
onFileDrop,
PlatformProvider,
usePlatform,
+ ShortcutsProvider,
+ useShortcuts,
ToastProvider,
useToast,
TooltipProvider,
diff --git a/src/components/ShortcutsGroup/Combos/Combos.less b/src/components/ShortcutsGroup/Combos/Combos.less
new file mode 100644
index 000000000..a862d54ca
--- /dev/null
+++ b/src/components/ShortcutsGroup/Combos/Combos.less
@@ -0,0 +1,22 @@
+.combos {
+ position: relative;
+ display: flex;
+ overflow: visible;
+
+ .combo {
+ position: relative;
+ display: flex;
+ overflow: visible;
+
+ .separator {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 3.5rem;
+ font-size: 1rem;
+ color: var(--primary-foreground-color);
+ opacity: 0.6;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/components/ShortcutsGroup/Combos/Combos.tsx b/src/components/ShortcutsGroup/Combos/Combos.tsx
new file mode 100644
index 000000000..0168441bc
--- /dev/null
+++ b/src/components/ShortcutsGroup/Combos/Combos.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import Keys from './Keys';
+import styles from './Combos.less';
+
+type Props = {
+ combos: string[][],
+};
+
+const Combos = ({ combos }: Props) => {
+ const { t } = useTranslation();
+
+ return (
+
+ {
+ combos.map((keys, index) => (
+
+
+ {
+ index < (combos.length - 1) && (
+
+ { t('SETTINGS_SHORTCUT_OR') }
+
+ )
+ }
+
+ ))
+ }
+
+ );
+};
+
+export default Combos;
diff --git a/src/components/ShortcutsGroup/Combos/Keys/Keys.less b/src/components/ShortcutsGroup/Combos/Keys/Keys.less
new file mode 100644
index 000000000..7bb8c76e7
--- /dev/null
+++ b/src/components/ShortcutsGroup/Combos/Keys/Keys.less
@@ -0,0 +1,26 @@
+kbd {
+ flex: none;
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ height: 2.5rem;
+ min-width: 2.5rem;
+ padding: 0 1rem;
+ font-size: 1rem;
+ font-weight: 500;
+ color: var(--primary-foreground-color);
+ border-radius: 0.25em;
+ box-shadow: 0 4px 0 1px rgba(255, 255, 255, 0.1);
+ background-color: var(--overlay-color);
+}
+
+.separator {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 2.5rem;
+ font-size: 1rem;
+ color: var(--primary-foreground-color);
+}
\ No newline at end of file
diff --git a/src/components/ShortcutsGroup/Combos/Keys/Keys.tsx b/src/components/ShortcutsGroup/Combos/Keys/Keys.tsx
new file mode 100644
index 000000000..71ec610da
--- /dev/null
+++ b/src/components/ShortcutsGroup/Combos/Keys/Keys.tsx
@@ -0,0 +1,51 @@
+import React, { Fragment, useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+import styles from './Keys.less';
+
+type Props = {
+ keys: string[],
+};
+
+const Keys = ({ keys }: Props) => {
+ const { t } = useTranslation();
+
+ const keyLabelMap: Record = useMemo(() => ({
+ 'Shift': `⇧ ${t('SETTINGS_SHORTCUT_SHIFT')}`,
+ 'Space': t('SETTINGS_SHORTCUT_SPACE'),
+ 'Ctrl': t('SETTINGS_SHORTCUT_CTRL'),
+ 'Escape': t('SETTINGS_SHORTCUT_ESC'),
+ 'ArrowUp': '↑',
+ 'ArrowDown': '↓',
+ 'ArrowLeft': '←',
+ 'ArrowRight': '→',
+ }), [t]);
+
+ const isRange = useMemo(() => {
+ return keys.length > 1 && keys.every((key) => !Number.isNaN(parseInt(key)));
+ }, [keys]);
+
+ const filteredKeys = useMemo(() => {
+ return isRange ? [keys[0], keys[keys.length - 1]] : keys;
+ }, [keys, isRange]);
+
+ return (
+ filteredKeys.map((key, index) => (
+
+
+ {keyLabelMap[key] ?? key.toUpperCase()}
+
+ {
+ index < (filteredKeys.length - 1) && (
+
+ {
+ isRange ? t('SETTINGS_SHORTCUT_TO') : '+'
+ }
+
+ )
+ }
+
+ ))
+ );
+};
+
+export default Keys;
diff --git a/src/components/ShortcutsGroup/Combos/Keys/index.ts b/src/components/ShortcutsGroup/Combos/Keys/index.ts
new file mode 100644
index 000000000..ba8d58731
--- /dev/null
+++ b/src/components/ShortcutsGroup/Combos/Keys/index.ts
@@ -0,0 +1,2 @@
+import Keys from './Keys';
+export default Keys;
diff --git a/src/components/ShortcutsGroup/Combos/index.ts b/src/components/ShortcutsGroup/Combos/index.ts
new file mode 100644
index 000000000..c66667f91
--- /dev/null
+++ b/src/components/ShortcutsGroup/Combos/index.ts
@@ -0,0 +1,2 @@
+import Combos from './Combos';
+export default Combos;
diff --git a/src/components/ShortcutsGroup/ShortcutsGroup.less b/src/components/ShortcutsGroup/ShortcutsGroup.less
new file mode 100644
index 000000000..f0fdd975c
--- /dev/null
+++ b/src/components/ShortcutsGroup/ShortcutsGroup.less
@@ -0,0 +1,44 @@
+.shortcuts-group {
+ flex: 1 1 0;
+ position: relative;
+ min-width: 30rem;
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+ overflow: visible;
+
+ .title {
+ flex: none;
+ display: flex;
+ font-size: 1rem;
+ font-weight: 400;
+ color: var(--primary-foreground-color);
+ opacity: 0.6;
+ }
+
+ .shortcuts {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+ overflow: visible;
+
+ .shortcut {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 2rem;
+ overflow: visible;
+
+ .label {
+ position: relative;
+ font-size: 1rem;
+ color: var(--primary-foreground-color);
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ }
+ }
+}
diff --git a/src/components/ShortcutsGroup/ShortcutsGroup.tsx b/src/components/ShortcutsGroup/ShortcutsGroup.tsx
new file mode 100644
index 000000000..069d5d1e8
--- /dev/null
+++ b/src/components/ShortcutsGroup/ShortcutsGroup.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import classNames from 'classnames';
+import { useTranslation } from 'react-i18next';
+import Combos from './Combos';
+import styles from './ShortcutsGroup.less';
+
+type Props = {
+ className?: string,
+ label: string,
+ shortcuts: Shortcut[],
+};
+
+const ShortcutsGroup = ({ className, label, shortcuts }: Props) => {
+ const { t } = useTranslation();
+
+ return (
+
+
+ {t(label)}
+
+
+
+ {
+ shortcuts.map(({ name, label, combos }) => (
+
+ ))
+ }
+
+
+ );
+};
+
+export default ShortcutsGroup;
diff --git a/src/components/ShortcutsGroup/index.ts b/src/components/ShortcutsGroup/index.ts
new file mode 100644
index 000000000..11f8d0678
--- /dev/null
+++ b/src/components/ShortcutsGroup/index.ts
@@ -0,0 +1,2 @@
+import ShortcutsGroup from './ShortcutsGroup';
+export default ShortcutsGroup;
diff --git a/src/components/index.ts b/src/components/index.ts
index a5638007e..a47c2c709 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -25,6 +25,7 @@ import RadioButton from './RadioButton';
import SearchBar from './SearchBar';
import SharePrompt from './SharePrompt';
import Slider from './Slider';
+import ShortcutsGroup from './ShortcutsGroup';
import TextInput from './TextInput';
import Toggle from './Toggle';
import Transition from './Transition';
@@ -59,6 +60,7 @@ export {
SearchBar,
SharePrompt,
Slider,
+ ShortcutsGroup,
TextInput,
Toggle,
Transition,
diff --git a/src/routes/Settings/Shortcuts/Shortcuts.less b/src/routes/Settings/Shortcuts/Shortcuts.less
index 40d97987d..186cfa837 100644
--- a/src/routes/Settings/Shortcuts/Shortcuts.less
+++ b/src/routes/Settings/Shortcuts/Shortcuts.less
@@ -1,27 +1,4 @@
-.shortcut-container {
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 0;
- overflow: visible;
-
- kbd {
- flex: 0 1 auto;
- height: 2.5rem;
- min-width: 2.5rem;
- line-height: 2.5rem;
- padding: 0 1rem;
- font-weight: 500;
- color: var(--primary-foreground-color);
- border-radius: 0.25em;
- box-shadow: 0 4px 0 1px var(--modal-background-color);
- background-color: var(--overlay-color);
- }
-
- .label {
- flex: none;
- margin: 0 1rem;
- white-space: nowrap;
- color: var(--primary-foreground-color);
- }
+.shortcuts-group {
+ width: 100%;
+ margin-bottom: 3rem;
}
\ No newline at end of file
diff --git a/src/routes/Settings/Shortcuts/Shortcuts.tsx b/src/routes/Settings/Shortcuts/Shortcuts.tsx
index d852280a6..a0599a503 100644
--- a/src/routes/Settings/Shortcuts/Shortcuts.tsx
+++ b/src/routes/Settings/Shortcuts/Shortcuts.tsx
@@ -1,97 +1,24 @@
import React, { forwardRef } from 'react';
-import { Section, Option } from '../components';
+import { Section } from '../components';
+import { ShortcutsGroup } from 'stremio/components';
+import { useShortcuts } from 'stremio/common';
import styles from './Shortcuts.less';
-import { useTranslation } from 'react-i18next';
const Shortcuts = forwardRef((_, ref) => {
- const { t } = useTranslation();
+ const { grouped } = useShortcuts();
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {
+ grouped.map(({ name, label, shortcuts }) => (
+
+ ))
+ }
);
});
diff --git a/tsconfig.json b/tsconfig.json
index d55ac9356..c4b0a8626 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "lib": [ "ES2016", "DOM", "DOM.Iterable"],
+ "lib": ["ESNext", "DOM", "DOM.Iterable"],
"jsx": "react",
"baseUrl": "./src",
"outDir": "./dist",