2024-04-25 16:31:18 +02:00
|
|
|
import { Dispatch } from 'redux';
|
2024-10-15 18:59:51 +02:00
|
|
|
import { ListItem, ListItemType, SetSelectedIndexCallback } from '../types';
|
2024-04-25 16:31:18 +02:00
|
|
|
import { KeyboardEventHandler, useCallback } from 'react';
|
|
|
|
import CommandService from '@joplin/lib/services/CommandService';
|
2024-10-15 18:59:51 +02:00
|
|
|
import toggleHeader from './utils/toggleHeader';
|
2024-04-25 16:31:18 +02:00
|
|
|
|
|
|
|
interface Props {
|
|
|
|
dispatch: Dispatch;
|
|
|
|
listItems: ListItem[];
|
2024-08-31 16:44:12 +02:00
|
|
|
collapsedFolderIds: string[];
|
2024-04-25 16:31:18 +02:00
|
|
|
selectedIndex: number;
|
|
|
|
updateSelectedIndex: SetSelectedIndexCallback;
|
|
|
|
}
|
|
|
|
|
2024-08-31 16:44:12 +02:00
|
|
|
|
2024-10-15 18:59:51 +02:00
|
|
|
const isToggleShortcut = (keyCode: string, selectedItem: ListItem, collapsedFolderIds: string[]) => {
|
|
|
|
if (selectedItem.kind !== ListItemType.Header && selectedItem.kind !== ListItemType.Folder) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-08-31 16:44:12 +02:00
|
|
|
if (!['Space', 'ArrowLeft', 'ArrowRight'].includes(keyCode)) {
|
|
|
|
return false;
|
|
|
|
}
|
2024-10-15 18:59:51 +02:00
|
|
|
|
2024-08-31 16:44:12 +02:00
|
|
|
if (keyCode === 'Space') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-10-15 18:59:51 +02:00
|
|
|
const isCollapsed = 'expanded' in selectedItem ? !selectedItem.expanded : collapsedFolderIds.includes(selectedItem.folder.id);
|
2024-08-31 16:44:12 +02:00
|
|
|
return (keyCode === 'ArrowRight') === isCollapsed;
|
|
|
|
};
|
|
|
|
|
2024-04-25 16:31:18 +02:00
|
|
|
const useOnSidebarKeyDownHandler = (props: Props) => {
|
2024-08-31 16:44:12 +02:00
|
|
|
const { updateSelectedIndex, listItems, selectedIndex, collapsedFolderIds, dispatch } = props;
|
2024-04-25 16:31:18 +02:00
|
|
|
|
|
|
|
return useCallback<KeyboardEventHandler<HTMLElement>>((event) => {
|
|
|
|
const selectedItem = listItems[selectedIndex];
|
2024-10-15 18:59:51 +02:00
|
|
|
let indexChange = 0;
|
2024-08-31 16:44:12 +02:00
|
|
|
|
2024-10-15 18:59:51 +02:00
|
|
|
if (selectedItem && isToggleShortcut(event.code, selectedItem, collapsedFolderIds)) {
|
2024-04-25 16:31:18 +02:00
|
|
|
event.preventDefault();
|
|
|
|
|
2024-10-15 18:59:51 +02:00
|
|
|
if (selectedItem.kind === ListItemType.Folder) {
|
|
|
|
dispatch({
|
|
|
|
type: 'FOLDER_TOGGLE',
|
|
|
|
id: selectedItem.folder.id,
|
|
|
|
});
|
|
|
|
} else if (selectedItem.kind === ListItemType.Header) {
|
|
|
|
toggleHeader(selectedItem.id);
|
|
|
|
}
|
|
|
|
} else if ((event.ctrlKey || event.metaKey) && event.code === 'KeyA') { // ctrl+a or cmd+a
|
|
|
|
event.preventDefault();
|
|
|
|
} else if (event.code === 'ArrowUp') {
|
2024-04-25 16:31:18 +02:00
|
|
|
indexChange = -1;
|
|
|
|
} else if (event.code === 'ArrowDown') {
|
|
|
|
indexChange = 1;
|
|
|
|
} else if (event.code === 'Tab') {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
if (event.shiftKey) {
|
|
|
|
void CommandService.instance().execute('focusElement', 'noteBody');
|
|
|
|
} else {
|
|
|
|
void CommandService.instance().execute('focusElement', 'noteList');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (indexChange !== 0) {
|
|
|
|
event.preventDefault();
|
|
|
|
updateSelectedIndex(selectedIndex + indexChange);
|
|
|
|
}
|
2024-08-31 16:44:12 +02:00
|
|
|
}, [selectedIndex, collapsedFolderIds, listItems, updateSelectedIndex, dispatch]);
|
2024-04-25 16:31:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
export default useOnSidebarKeyDownHandler;
|