diff --git a/package-lock.json b/package-lock.json index 904ec235..6abed8d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "mem": "~9.0.2", "preact": "~10.11.3", "preact-router": "~4.1.0", + "react-hotkeys-hook": "~4.3.2", "react-intersection-observer": "~9.4.1", "string-length": "~5.0.1", "swiped-events": "~1.1.7", @@ -4615,6 +4616,15 @@ "react": "^18.2.0" } }, + "node_modules/react-hotkeys-hook": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.3.2.tgz", + "integrity": "sha512-ZA/li3kBDHuRTtJIf7Td41UU87bPtnt9xV4r+PlEzpnFoYRDVspk3B+mlaX75zowyQygMVmoaWnM4B88lkyExQ==", + "peerDependencies": { + "react": ">=16.8.1", + "react-dom": ">=16.8.1" + } + }, "node_modules/react-intersection-observer": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz", @@ -9091,6 +9101,12 @@ "scheduler": "^0.23.0" } }, + "react-hotkeys-hook": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-4.3.2.tgz", + "integrity": "sha512-ZA/li3kBDHuRTtJIf7Td41UU87bPtnt9xV4r+PlEzpnFoYRDVspk3B+mlaX75zowyQygMVmoaWnM4B88lkyExQ==", + "requires": {} + }, "react-intersection-observer": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.4.1.tgz", diff --git a/package.json b/package.json index 6cbdcb8a..3e9a9912 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "mem": "~9.0.2", "preact": "~10.11.3", "preact-router": "~4.1.0", + "react-hotkeys-hook": "~4.3.2", "react-intersection-observer": "~9.4.1", "string-length": "~5.0.1", "swiped-events": "~1.1.7", diff --git a/src/components/compose.jsx b/src/components/compose.jsx index 67b679d4..62ff44b2 100644 --- a/src/components/compose.jsx +++ b/src/components/compose.jsx @@ -2,6 +2,7 @@ import './compose.css'; import '@github/text-expander-element'; import { useEffect, useMemo, useRef, useState } from 'preact/hooks'; +import { useHotkeys } from 'react-hotkeys-hook'; import stringLength from 'string-length'; import supportedLanguages from '../data/status-supported-languages'; @@ -597,6 +598,13 @@ function Compose({ pointerEvents: uiState === 'loading' ? 'none' : 'auto', opacity: uiState === 'loading' ? 0.5 : 1, }} + onKeyDown={(e) => { + if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { + formRef.current.dispatchEvent( + new Event('submit', { cancelable: true }), + ); + } + }} onSubmit={(e) => { e.preventDefault(); diff --git a/src/components/status.jsx b/src/components/status.jsx index 15444109..4673cb84 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -9,6 +9,7 @@ import { useRef, useState, } from 'preact/hooks'; +import { useHotkeys } from 'react-hotkeys-hook'; import { InView } from 'react-intersection-observer'; import 'swiped-events'; import useResizeObserver from 'use-resize-observer'; @@ -1298,6 +1299,8 @@ function Carousel({ mediaAttachments, index = 0, onClose = () => {} }) { }; }, []); + useHotkeys('esc', onClose, [onClose]); + return ( <>