a tool for shared writing and social publishing
1import { Replicache } from "replicache"; 2import { ReplicacheMutators } from "src/replicache"; 3import { useUIState } from "src/useUIState"; 4import { scanIndex } from "src/replicache/utils"; 5import { getBlocksWithType } from "src/hooks/queries/useBlocks"; 6import { focusBlock } from "src/utils/focusBlock"; 7import { UndoManager } from "src/undoManager"; 8 9export async function deleteBlock( 10 entities: string[], 11 rep: Replicache<ReplicacheMutators>, 12 undoManager?: UndoManager, 13) { 14 // get what pagess we need to close as a result of deleting this block 15 let pagesToClose = [] as string[]; 16 for (let entity of entities) { 17 let [type] = await rep.query((tx) => 18 scanIndex(tx).eav(entity, "block/type"), 19 ); 20 if (type.data.value === "card") { 21 let [childPages] = await rep?.query( 22 (tx) => scanIndex(tx).eav(entity, "block/card") || [], 23 ); 24 pagesToClose = [childPages?.data.value]; 25 } 26 if (type.data.value === "mailbox") { 27 let [archive] = await rep?.query( 28 (tx) => scanIndex(tx).eav(entity, "mailbox/archive") || [], 29 ); 30 let [draft] = await rep?.query( 31 (tx) => scanIndex(tx).eav(entity, "mailbox/draft") || [], 32 ); 33 pagesToClose = [archive?.data.value, draft?.data.value]; 34 } 35 } 36 37 // figure out what to focus 38 let focusedBlock = useUIState.getState().focusedEntity; 39 let parent = 40 focusedBlock?.entityType === "page" 41 ? focusedBlock.entityID 42 : focusedBlock?.parent; 43 44 if (parent) { 45 let parentType = await rep?.query((tx) => 46 scanIndex(tx).eav(parent, "page/type"), 47 ); 48 // if the page is a canvas, focus the page 49 if (parentType[0]?.data.value === "canvas") { 50 useUIState 51 .getState() 52 .setFocusedBlock({ entityType: "page", entityID: parent }); 53 useUIState.getState().setSelectedBlocks([]); 54 } else { 55 // if the page is a doc, focus the previous block (or if there isn't a prev block, focus the next block) 56 let siblings = 57 (await rep?.query((tx) => getBlocksWithType(tx, parent))) || []; 58 59 let selectedBlocks = useUIState.getState().selectedBlocks; 60 let firstSelected = selectedBlocks[0]; 61 let lastSelected = selectedBlocks[entities.length - 1]; 62 63 let prevBlock = 64 siblings?.[ 65 siblings.findIndex((s) => s.value === firstSelected?.value) - 1 66 ]; 67 let prevBlockType = await rep?.query((tx) => 68 scanIndex(tx).eav(prevBlock?.value, "block/type"), 69 ); 70 71 let nextBlock = 72 siblings?.[ 73 siblings.findIndex((s) => s.value === lastSelected.value) + 1 74 ]; 75 let nextBlockType = await rep?.query((tx) => 76 scanIndex(tx).eav(nextBlock?.value, "block/type"), 77 ); 78 79 if (prevBlock) { 80 useUIState.getState().setSelectedBlock({ 81 value: prevBlock.value, 82 parent: prevBlock.parent, 83 }); 84 85 focusBlock( 86 { 87 value: prevBlock.value, 88 type: prevBlockType?.[0].data.value, 89 parent: prevBlock.parent, 90 }, 91 { type: "end" }, 92 ); 93 } else { 94 useUIState.getState().setSelectedBlock({ 95 value: nextBlock.value, 96 parent: nextBlock.parent, 97 }); 98 99 focusBlock( 100 { 101 value: nextBlock.value, 102 type: nextBlockType?.[0]?.data.value, 103 parent: nextBlock.parent, 104 }, 105 { type: "start" }, 106 ); 107 } 108 } 109 } 110 111 // close the pages 112 pagesToClose.forEach((page) => page && useUIState.getState().closePage(page)); 113 undoManager && undoManager.startGroup(); 114 115 // delete the blocks 116 await Promise.all( 117 entities.map((entity) => 118 rep?.mutate.removeBlock({ 119 blockEntity: entity, 120 }), 121 ), 122 ); 123 undoManager && undoManager.endGroup(); 124}