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}