a tool for shared writing and social publishing
at main 3.0 kB view raw
1import { useSelectingMouse } from "components/SelectionManager/selectionState"; 2import { MouseEvent, useCallback, useRef } from "react"; 3import { useUIState } from "src/useUIState"; 4import { Block } from "./Block"; 5import { isTextBlock } from "src/utils/isTextBlock"; 6import { useEntitySetContext } from "components/EntitySetProvider"; 7import { useReplicache } from "src/replicache"; 8import { getBlocksWithType } from "src/hooks/queries/useBlocks"; 9import { focusBlock } from "src/utils/focusBlock"; 10import { useIsMobile } from "src/hooks/isMobile"; 11 12let debounce: number | null = null; 13export function useBlockMouseHandlers(props: Block) { 14 let entity_set = useEntitySetContext(); 15 let isMobile = useIsMobile(); 16 let { rep } = useReplicache(); 17 let onMouseDown = useCallback( 18 (e: MouseEvent) => { 19 if ((e.target as Element).getAttribute("data-draggable")) return; 20 if ((e.target as Element).tagName === "BUTTON") return; 21 if ((e.target as Element).tagName === "SELECT") return; 22 if ((e.target as Element).tagName === "OPTION") return; 23 if (isMobile) return; 24 if (!entity_set.permissions.write) return; 25 useSelectingMouse.setState({ start: props.value }); 26 if (e.shiftKey) { 27 if ( 28 useUIState.getState().selectedBlocks[0]?.value === props.value && 29 useUIState.getState().selectedBlocks.length === 1 30 ) 31 return; 32 e.preventDefault(); 33 useUIState.getState().addBlockToSelection(props); 34 } else { 35 if (e.isDefaultPrevented()) return; 36 useUIState.getState().setFocusedBlock({ 37 entityType: "block", 38 entityID: props.value, 39 parent: props.parent, 40 }); 41 useUIState.getState().setSelectedBlock(props); 42 } 43 }, 44 [props, entity_set.permissions.write, isMobile], 45 ); 46 let onMouseEnter = useCallback( 47 async (e: MouseEvent) => { 48 if (isMobile) return; 49 if (!entity_set.permissions.write) return; 50 if (debounce) window.clearTimeout(debounce); 51 debounce = window.setTimeout(async () => { 52 debounce = null; 53 if (e.buttons !== 1) return; 54 let selection = useSelectingMouse.getState(); 55 if (!selection.start) return; 56 let siblings = 57 (await rep?.query((tx) => getBlocksWithType(tx, props.parent))) || []; 58 let startIndex = siblings.findIndex((b) => b.value === selection.start); 59 if (startIndex === -1) return; 60 let endIndex = siblings.findIndex((b) => b.value === props.value); 61 let start = Math.min(startIndex, endIndex); 62 let end = Math.max(startIndex, endIndex); 63 let selected = siblings.slice(start, end + 1).map((b) => ({ 64 value: b.value, 65 position: b.position, 66 parent: props.parent, 67 })); 68 useUIState.getState().setSelectedBlocks(selected); 69 }, 15); 70 }, 71 [rep, props, entity_set.permissions.write, isMobile], 72 ); 73 return { onMouseDown, onMouseEnter }; 74}