kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Merge branch 'hotkeys-statuses' into 'develop'
Fix hotkey navigation in media modal See merge request soapbox-pub/soapbox!2589environments/review-develop-3zknud/deployments/3578
commit
42e9d31a3e
|
@ -178,8 +178,15 @@ const StatusList: React.FC<IStatusList> = ({
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderFeedSuggestions = (): React.ReactNode => {
|
const renderFeedSuggestions = (statusId: string): React.ReactNode => {
|
||||||
return <FeedSuggestions key='suggestions' />;
|
return (
|
||||||
|
<FeedSuggestions
|
||||||
|
key='suggestions'
|
||||||
|
statusId={statusId}
|
||||||
|
onMoveUp={handleMoveUp}
|
||||||
|
onMoveDown={handleMoveDown}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderStatuses = (): React.ReactNode[] => {
|
const renderStatuses = (): React.ReactNode[] => {
|
||||||
|
@ -201,7 +208,7 @@ const StatusList: React.FC<IStatusList> = ({
|
||||||
}
|
}
|
||||||
} else if (statusId.startsWith('末suggestions-')) {
|
} else if (statusId.startsWith('末suggestions-')) {
|
||||||
if (soapboxConfig.feedInjection) {
|
if (soapboxConfig.feedInjection) {
|
||||||
acc.push(renderFeedSuggestions());
|
acc.push(renderFeedSuggestions(statusId));
|
||||||
}
|
}
|
||||||
} else if (statusId.startsWith('末pending-')) {
|
} else if (statusId.startsWith('末pending-')) {
|
||||||
acc.push(renderPendingStatus(statusId));
|
acc.push(renderPendingStatus(statusId));
|
||||||
|
|
|
@ -27,6 +27,7 @@ interface ICard {
|
||||||
className?: string
|
className?: string
|
||||||
/** Elements inside the card. */
|
/** Elements inside the card. */
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
tabIndex?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An opaque backdrop to hold a collection of related elements. */
|
/** An opaque backdrop to hold a collection of related elements. */
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { CompatRouter } from 'react-router-dom-v5-compat';
|
||||||
// @ts-ignore: it doesn't have types
|
// @ts-ignore: it doesn't have types
|
||||||
import { ScrollContext } from 'react-router-scroll-4';
|
import { ScrollContext } from 'react-router-scroll-4';
|
||||||
|
|
||||||
|
|
||||||
import { loadInstance } from 'soapbox/actions/instance';
|
import { loadInstance } from 'soapbox/actions/instance';
|
||||||
import { fetchMe } from 'soapbox/actions/me';
|
import { fetchMe } from 'soapbox/actions/me';
|
||||||
import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox';
|
import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||||
|
@ -30,6 +29,7 @@ import {
|
||||||
OnboardingWizard,
|
OnboardingWizard,
|
||||||
WaitlistPage,
|
WaitlistPage,
|
||||||
} from 'soapbox/features/ui/util/async-components';
|
} from 'soapbox/features/ui/util/async-components';
|
||||||
|
import GlobalHotkeys from 'soapbox/features/ui/util/global-hotkeys';
|
||||||
import { createGlobals } from 'soapbox/globals';
|
import { createGlobals } from 'soapbox/globals';
|
||||||
import {
|
import {
|
||||||
useAppSelector,
|
useAppSelector,
|
||||||
|
@ -176,6 +176,7 @@ const SoapboxMount = () => {
|
||||||
<BrowserRouter basename={BuildConfig.FE_SUBDIRECTORY}>
|
<BrowserRouter basename={BuildConfig.FE_SUBDIRECTORY}>
|
||||||
<CompatRouter>
|
<CompatRouter>
|
||||||
<ScrollContext shouldUpdateScroll={shouldUpdateScroll}>
|
<ScrollContext shouldUpdateScroll={shouldUpdateScroll}>
|
||||||
|
<GlobalHotkeys>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route
|
<Route
|
||||||
path='/embed/:statusId'
|
path='/embed/:statusId'
|
||||||
|
@ -201,6 +202,7 @@ const SoapboxMount = () => {
|
||||||
</div>
|
</div>
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
</GlobalHotkeys>
|
||||||
</ScrollContext>
|
</ScrollContext>
|
||||||
</CompatRouter>
|
</CompatRouter>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { HotKeys } from 'react-hotkeys';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
@ -61,15 +62,39 @@ const SuggestionItem: React.FC<ISuggestionItem> = ({ accountId }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const FeedSuggestions = () => {
|
interface IFeedSuggesetions {
|
||||||
|
statusId: string
|
||||||
|
onMoveUp?: (statusId: string, featured?: boolean) => void
|
||||||
|
onMoveDown?: (statusId: string, featured?: boolean) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const FeedSuggestions: React.FC<IFeedSuggesetions> = ({ statusId, onMoveUp, onMoveDown }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const suggestedProfiles = useAppSelector((state) => state.suggestions.items);
|
const suggestedProfiles = useAppSelector((state) => state.suggestions.items);
|
||||||
const isLoading = useAppSelector((state) => state.suggestions.isLoading);
|
const isLoading = useAppSelector((state) => state.suggestions.isLoading);
|
||||||
|
|
||||||
if (!isLoading && suggestedProfiles.size === 0) return null;
|
if (!isLoading && suggestedProfiles.size === 0) return null;
|
||||||
|
|
||||||
|
const handleHotkeyMoveUp = (e?: KeyboardEvent): void => {
|
||||||
|
if (onMoveUp) {
|
||||||
|
onMoveUp(statusId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyMoveDown = (e?: KeyboardEvent): void => {
|
||||||
|
if (onMoveDown) {
|
||||||
|
onMoveDown(statusId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlers = {
|
||||||
|
moveUp: handleHotkeyMoveUp,
|
||||||
|
moveDown: handleHotkeyMoveDown,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card size='lg' variant='rounded' className='space-y-6'>
|
<HotKeys handlers={handlers}>
|
||||||
|
<Card size='lg' variant='rounded' className='focusable space-y-6' tabIndex={0}>
|
||||||
<HStack justifyContent='between' alignItems='center'>
|
<HStack justifyContent='between' alignItems='center'>
|
||||||
<CardTitle title={intl.formatMessage(messages.heading)} />
|
<CardTitle title={intl.formatMessage(messages.heading)} />
|
||||||
|
|
||||||
|
@ -89,6 +114,7 @@ const FeedSuggestions = () => {
|
||||||
</HStack>
|
</HStack>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
</HotKeys>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -263,15 +263,12 @@ const Thread = (props: IThread) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const _selectChild = (index: number) => {
|
const _selectChild = (index: number) => {
|
||||||
|
if (!useWindowScroll) index = index + 1;
|
||||||
scroller.current?.scrollIntoView({
|
scroller.current?.scrollIntoView({
|
||||||
index,
|
index,
|
||||||
behavior: 'smooth',
|
behavior: 'smooth',
|
||||||
done: () => {
|
done: () => {
|
||||||
const element = document.querySelector<HTMLDivElement>(`#thread [data-index="${index}"] .focusable`);
|
node.current?.querySelector<HTMLDivElement>(`[data-index="${index}"] .focusable`)?.focus();
|
||||||
|
|
||||||
if (element) {
|
|
||||||
element.focus();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import React, { useEffect, useRef } from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { HotKeys } from 'react-hotkeys';
|
|
||||||
import { Switch, useHistory, useLocation, Redirect } from 'react-router-dom';
|
import { Switch, useHistory, useLocation, Redirect } from 'react-router-dom';
|
||||||
|
|
||||||
import { fetchFollowRequests } from 'soapbox/actions/accounts';
|
import { fetchFollowRequests } from 'soapbox/actions/accounts';
|
||||||
import { fetchReports, fetchUsers, fetchConfig } from 'soapbox/actions/admin';
|
import { fetchReports, fetchUsers, fetchConfig } from 'soapbox/actions/admin';
|
||||||
import { fetchAnnouncements } from 'soapbox/actions/announcements';
|
import { fetchAnnouncements } from 'soapbox/actions/announcements';
|
||||||
import { resetCompose } from 'soapbox/actions/compose';
|
|
||||||
import { fetchCustomEmojis } from 'soapbox/actions/custom-emojis';
|
import { fetchCustomEmojis } from 'soapbox/actions/custom-emojis';
|
||||||
import { fetchFilters } from 'soapbox/actions/filters';
|
import { fetchFilters } from 'soapbox/actions/filters';
|
||||||
import { fetchMarker } from 'soapbox/actions/markers';
|
import { fetchMarker } from 'soapbox/actions/markers';
|
||||||
|
@ -155,34 +153,6 @@ const GroupMembershipRequestsSlug = withHoc(GroupMembershipRequests as any, Grou
|
||||||
|
|
||||||
const EmptyPage = HomePage;
|
const EmptyPage = HomePage;
|
||||||
|
|
||||||
const keyMap = {
|
|
||||||
help: '?',
|
|
||||||
new: 'n',
|
|
||||||
search: ['s', '/'],
|
|
||||||
forceNew: 'option+n',
|
|
||||||
reply: 'r',
|
|
||||||
favourite: 'f',
|
|
||||||
react: 'e',
|
|
||||||
boost: 'b',
|
|
||||||
mention: 'm',
|
|
||||||
open: ['enter', 'o'],
|
|
||||||
openProfile: 'p',
|
|
||||||
moveDown: ['down', 'j'],
|
|
||||||
moveUp: ['up', 'k'],
|
|
||||||
back: 'backspace',
|
|
||||||
goToHome: 'g h',
|
|
||||||
goToNotifications: 'g n',
|
|
||||||
goToFavourites: 'g f',
|
|
||||||
goToPinned: 'g p',
|
|
||||||
goToProfile: 'g u',
|
|
||||||
goToBlocked: 'g b',
|
|
||||||
goToMuted: 'g m',
|
|
||||||
goToRequests: 'g r',
|
|
||||||
toggleHidden: 'x',
|
|
||||||
toggleSensitive: 'h',
|
|
||||||
openMedia: 'a',
|
|
||||||
};
|
|
||||||
|
|
||||||
interface ISwitchingColumnsArea {
|
interface ISwitchingColumnsArea {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
@ -398,7 +368,6 @@ const UI: React.FC<IUI> = ({ children }) => {
|
||||||
const userStream = useRef<any>(null);
|
const userStream = useRef<any>(null);
|
||||||
const nostrStream = useRef<any>(null);
|
const nostrStream = useRef<any>(null);
|
||||||
const node = useRef<HTMLDivElement | null>(null);
|
const node = useRef<HTMLDivElement | null>(null);
|
||||||
const hotkeys = useRef<HTMLDivElement | null>(null);
|
|
||||||
|
|
||||||
const me = useAppSelector(state => state.me);
|
const me = useAppSelector(state => state.me);
|
||||||
const { account } = useOwnAccount();
|
const { account } = useOwnAccount();
|
||||||
|
@ -529,91 +498,6 @@ const UI: React.FC<IUI> = ({ children }) => {
|
||||||
}
|
}
|
||||||
}, [pendingPolicy, !!account]);
|
}, [pendingPolicy, !!account]);
|
||||||
|
|
||||||
const handleHotkeyNew = (e?: KeyboardEvent) => {
|
|
||||||
e?.preventDefault();
|
|
||||||
if (!node.current) return;
|
|
||||||
|
|
||||||
const element = node.current.querySelector('textarea#compose-textarea') as HTMLTextAreaElement;
|
|
||||||
|
|
||||||
if (element) {
|
|
||||||
element.focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeySearch = (e?: KeyboardEvent) => {
|
|
||||||
e?.preventDefault();
|
|
||||||
if (!node.current) return;
|
|
||||||
|
|
||||||
const element = node.current.querySelector('input#search') as HTMLInputElement;
|
|
||||||
|
|
||||||
if (element) {
|
|
||||||
element.focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyForceNew = (e?: KeyboardEvent) => {
|
|
||||||
handleHotkeyNew(e);
|
|
||||||
dispatch(resetCompose());
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyBack = () => {
|
|
||||||
if (window.history && window.history.length === 1) {
|
|
||||||
history.push('/');
|
|
||||||
} else {
|
|
||||||
history.goBack();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setHotkeysRef: React.LegacyRef<HotKeys> = (c: any) => {
|
|
||||||
hotkeys.current = c;
|
|
||||||
|
|
||||||
if (!me || !hotkeys.current) return;
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
hotkeys.current.__mousetrap__.stopCallback = (_e, element) => {
|
|
||||||
return ['TEXTAREA', 'SELECT', 'INPUT', 'EM-EMOJI-PICKER'].includes(element.tagName);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyToggleHelp = () => {
|
|
||||||
dispatch(openModal('HOTKEYS'));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToHome = () => {
|
|
||||||
history.push('/');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToNotifications = () => {
|
|
||||||
history.push('/notifications');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToFavourites = () => {
|
|
||||||
if (!account) return;
|
|
||||||
history.push(`/@${account.username}/favorites`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToPinned = () => {
|
|
||||||
if (!account) return;
|
|
||||||
history.push(`/@${account.username}/pins`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToProfile = () => {
|
|
||||||
if (!account) return;
|
|
||||||
history.push(`/@${account.username}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToBlocked = () => {
|
|
||||||
history.push('/blocks');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToMuted = () => {
|
|
||||||
history.push('/mutes');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleHotkeyGoToRequests = () => {
|
|
||||||
history.push('/follow_requests');
|
|
||||||
};
|
|
||||||
|
|
||||||
const shouldHideFAB = (): boolean => {
|
const shouldHideFAB = (): boolean => {
|
||||||
const path = location.pathname;
|
const path = location.pathname;
|
||||||
return Boolean(path.match(/^\/posts\/|^\/search|^\/getting-started|^\/chats/));
|
return Boolean(path.match(/^\/posts\/|^\/search|^\/getting-started|^\/chats/));
|
||||||
|
@ -622,30 +506,11 @@ const UI: React.FC<IUI> = ({ children }) => {
|
||||||
// Wait for login to succeed or fail
|
// Wait for login to succeed or fail
|
||||||
if (me === null) return null;
|
if (me === null) return null;
|
||||||
|
|
||||||
type HotkeyHandlers = { [key: string]: (keyEvent?: KeyboardEvent) => void };
|
|
||||||
|
|
||||||
const handlers: HotkeyHandlers = {
|
|
||||||
help: handleHotkeyToggleHelp,
|
|
||||||
new: handleHotkeyNew,
|
|
||||||
search: handleHotkeySearch,
|
|
||||||
forceNew: handleHotkeyForceNew,
|
|
||||||
back: handleHotkeyBack,
|
|
||||||
goToHome: handleHotkeyGoToHome,
|
|
||||||
goToNotifications: handleHotkeyGoToNotifications,
|
|
||||||
goToFavourites: handleHotkeyGoToFavourites,
|
|
||||||
goToPinned: handleHotkeyGoToPinned,
|
|
||||||
goToProfile: handleHotkeyGoToProfile,
|
|
||||||
goToBlocked: handleHotkeyGoToBlocked,
|
|
||||||
goToMuted: handleHotkeyGoToMuted,
|
|
||||||
goToRequests: handleHotkeyGoToRequests,
|
|
||||||
};
|
|
||||||
|
|
||||||
const style: React.CSSProperties = {
|
const style: React.CSSProperties = {
|
||||||
pointerEvents: dropdownMenuIsOpen ? 'none' : undefined,
|
pointerEvents: dropdownMenuIsOpen ? 'none' : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys keyMap={keyMap} handlers={me ? handlers : undefined} ref={setHotkeysRef} attach={window} focused>
|
|
||||||
<div ref={node} style={style}>
|
<div ref={node} style={style}>
|
||||||
<div
|
<div
|
||||||
className={clsx('pointer-events-none fixed z-[90] h-screen w-screen transition', {
|
className={clsx('pointer-events-none fixed z-[90] h-screen w-screen transition', {
|
||||||
|
@ -700,7 +565,6 @@ const UI: React.FC<IUI> = ({ children }) => {
|
||||||
</BundleContainer>
|
</BundleContainer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</HotKeys>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { HotKeys } from 'react-hotkeys';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { resetCompose } from 'soapbox/actions/compose';
|
||||||
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
|
import { useAppSelector, useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
const keyMap = {
|
||||||
|
help: '?',
|
||||||
|
new: 'n',
|
||||||
|
search: ['s', '/'],
|
||||||
|
forceNew: 'option+n',
|
||||||
|
reply: 'r',
|
||||||
|
favourite: 'f',
|
||||||
|
react: 'e',
|
||||||
|
boost: 'b',
|
||||||
|
mention: 'm',
|
||||||
|
open: ['enter', 'o'],
|
||||||
|
openProfile: 'p',
|
||||||
|
moveDown: ['down', 'j'],
|
||||||
|
moveUp: ['up', 'k'],
|
||||||
|
back: 'backspace',
|
||||||
|
goToHome: 'g h',
|
||||||
|
goToNotifications: 'g n',
|
||||||
|
goToFavourites: 'g f',
|
||||||
|
goToPinned: 'g p',
|
||||||
|
goToProfile: 'g u',
|
||||||
|
goToBlocked: 'g b',
|
||||||
|
goToMuted: 'g m',
|
||||||
|
goToRequests: 'g r',
|
||||||
|
toggleHidden: 'x',
|
||||||
|
toggleSensitive: 'h',
|
||||||
|
openMedia: 'a',
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IGlobalHotkeys {
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const GlobalHotkeys: React.FC<IGlobalHotkeys> = ({ children }) => {
|
||||||
|
const hotkeys = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
const history = useHistory();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const me = useAppSelector(state => state.me);
|
||||||
|
const { account } = useOwnAccount();
|
||||||
|
|
||||||
|
const handleHotkeyNew = (e?: KeyboardEvent) => {
|
||||||
|
e?.preventDefault();
|
||||||
|
if (!hotkeys.current) return;
|
||||||
|
|
||||||
|
const element = hotkeys.current.querySelector('textarea#compose-textarea') as HTMLTextAreaElement;
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
element.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeySearch = (e?: KeyboardEvent) => {
|
||||||
|
e?.preventDefault();
|
||||||
|
if (!hotkeys.current) return;
|
||||||
|
|
||||||
|
const element = hotkeys.current.querySelector('input#search') as HTMLInputElement;
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
element.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyForceNew = (e?: KeyboardEvent) => {
|
||||||
|
handleHotkeyNew(e);
|
||||||
|
dispatch(resetCompose());
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyBack = () => {
|
||||||
|
if (window.history && window.history.length === 1) {
|
||||||
|
history.push('/');
|
||||||
|
} else {
|
||||||
|
history.goBack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setHotkeysRef: React.LegacyRef<HotKeys> = (c: any) => {
|
||||||
|
hotkeys.current = c;
|
||||||
|
|
||||||
|
if (!me || !hotkeys.current) return;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
hotkeys.current.__mousetrap__.stopCallback = (_e, element) => {
|
||||||
|
return ['TEXTAREA', 'SELECT', 'INPUT', 'EM-EMOJI-PICKER'].includes(element.tagName);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyToggleHelp = () => {
|
||||||
|
dispatch(openModal('HOTKEYS'));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToHome = () => {
|
||||||
|
history.push('/');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToNotifications = () => {
|
||||||
|
history.push('/notifications');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToFavourites = () => {
|
||||||
|
if (!account) return;
|
||||||
|
history.push(`/@${account.username}/favorites`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToPinned = () => {
|
||||||
|
if (!account) return;
|
||||||
|
history.push(`/@${account.username}/pins`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToProfile = () => {
|
||||||
|
if (!account) return;
|
||||||
|
history.push(`/@${account.username}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToBlocked = () => {
|
||||||
|
history.push('/blocks');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToMuted = () => {
|
||||||
|
history.push('/mutes');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleHotkeyGoToRequests = () => {
|
||||||
|
history.push('/follow_requests');
|
||||||
|
};
|
||||||
|
|
||||||
|
type HotkeyHandlers = { [key: string]: (keyEvent?: KeyboardEvent) => void };
|
||||||
|
|
||||||
|
const handlers: HotkeyHandlers = {
|
||||||
|
help: handleHotkeyToggleHelp,
|
||||||
|
new: handleHotkeyNew,
|
||||||
|
search: handleHotkeySearch,
|
||||||
|
forceNew: handleHotkeyForceNew,
|
||||||
|
back: handleHotkeyBack,
|
||||||
|
goToHome: handleHotkeyGoToHome,
|
||||||
|
goToNotifications: handleHotkeyGoToNotifications,
|
||||||
|
goToFavourites: handleHotkeyGoToFavourites,
|
||||||
|
goToPinned: handleHotkeyGoToPinned,
|
||||||
|
goToProfile: handleHotkeyGoToProfile,
|
||||||
|
goToBlocked: handleHotkeyGoToBlocked,
|
||||||
|
goToMuted: handleHotkeyGoToMuted,
|
||||||
|
goToRequests: handleHotkeyGoToRequests,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<HotKeys keyMap={keyMap} handlers={me ? handlers : undefined} ref={setHotkeysRef} attach={window} focused>
|
||||||
|
{children}
|
||||||
|
</HotKeys>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GlobalHotkeys;
|
Ładowanie…
Reference in New Issue