a tool for shared writing and social publishing
1import { Block } from "components/Blocks/Block"; 2import { Replicache } from "replicache"; 3import type { ReplicacheMutators } from "src/replicache"; 4import { useUIState } from "src/useUIState"; 5import { v7 } from "uuid"; 6 7export function indent( 8 block: Block, 9 previousBlock?: Block, 10 rep?: Replicache<ReplicacheMutators> | null, 11) { 12 if (!block.listData) return false; 13 if (!previousBlock?.listData) return false; 14 let depth = block.listData.depth; 15 let newParent = previousBlock.listData.path.find((f) => f.depth === depth); 16 if (!newParent) return false; 17 if (useUIState.getState().foldedBlocks.includes(newParent.entity)) 18 useUIState.getState().toggleFold(newParent.entity); 19 rep?.mutate.retractFact({ factID: block.factID }); 20 rep?.mutate.addLastBlock({ 21 parent: newParent.entity, 22 factID: v7(), 23 entity: block.value, 24 }); 25 return true; 26} 27 28export function outdentFull( 29 block: Block, 30 rep?: Replicache<ReplicacheMutators> | null, 31) { 32 if (!block.listData) return; 33 34 // make this block not a list 35 rep?.mutate.assertFact({ 36 entity: block.value, 37 attribute: "block/is-list", 38 data: { type: "boolean", value: false }, 39 }); 40 41 // find the next block that is a level 1 list item or not a list item. 42 // If there are none or this block is a level 1 list item, we don't need to move anything 43 44 let after = block.listData?.path.find((f) => f.depth === 1)?.entity; 45 46 // move this block to be after that block 47 after && 48 after !== block.value && 49 rep?.mutate.moveBlock({ 50 block: block.value, 51 oldParent: block.listData.parent, 52 newParent: block.parent, 53 position: { type: "after", entity: after }, 54 }); 55 56 // move all the childen to the be under it as a level 1 list item 57 rep?.mutate.moveChildren({ 58 oldParent: block.value, 59 newParent: block.parent, 60 after: block.value, 61 }); 62} 63 64export function outdent( 65 block: Block, 66 previousBlock: Block | null, 67 rep?: Replicache<ReplicacheMutators> | null, 68) { 69 if (!block.listData) return false; 70 let listData = block.listData; 71 if (listData.depth === 1) { 72 rep?.mutate.assertFact({ 73 entity: block.value, 74 attribute: "block/is-list", 75 data: { type: "boolean", value: false }, 76 }); 77 rep?.mutate.moveChildren({ 78 oldParent: block.value, 79 newParent: block.parent, 80 after: block.value, 81 }); 82 } else { 83 if (!previousBlock || !previousBlock.listData) return false; 84 let after = previousBlock.listData.path.find( 85 (f) => f.depth === listData.depth - 1, 86 )?.entity; 87 if (!after) return false; 88 let parent: string | undefined = undefined; 89 if (listData.depth === 2) { 90 parent = block.parent; 91 } else { 92 parent = previousBlock.listData.path.find( 93 (f) => f.depth === listData.depth - 2, 94 )?.entity; 95 } 96 if (!parent) return false; 97 if (useUIState.getState().foldedBlocks.includes(parent)) 98 useUIState.getState().toggleFold(parent); 99 rep?.mutate.outdentBlock({ 100 block: block.value, 101 newParent: parent, 102 oldParent: listData.parent, 103 after, 104 }); 105 } 106}