a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

make list button in toolbar toggle list instead of opening list toolbar

celine 6aa8f275 e40d6c7d

+63 -5
+12 -3
components/Toolbar/ListToolbar.tsx
··· 11 11 import { useUIState } from "src/useUIState"; 12 12 import { metaKey } from "src/utils/metaKey"; 13 13 import { ToolbarButton } from "."; 14 - import { indent, outdent } from "src/utils/list-operations"; 14 + import { indent, outdent, outdentFull } from "src/utils/list-operations"; 15 15 import { useEffect } from "react"; 16 16 17 17 export const ListButton = (props: { setToolbarState: (s: "list") => void }) => { 18 18 let focusedBlock = useUIState((s) => s.focusedEntity); 19 19 let isList = useEntity(focusedBlock?.entityID || null, "block/is-list"); 20 + let siblings = useBlocks( 21 + focusedBlock?.entityType === "block" ? focusedBlock.parent : null, 22 + ); 23 + 24 + let block = siblings.find((s) => s.value === focusedBlock?.entityID); 25 + let previousBlock = 26 + siblings[siblings.findIndex((b) => b.value === focusedBlock?.entityID) - 1]; 20 27 21 28 let { rep } = useReplicache(); 22 29 ··· 39 46 } 40 47 onClick={(e) => { 41 48 e.preventDefault(); 42 - if (!focusedBlock) return; 49 + if (!focusedBlock || !block) return; 43 50 if (!isList?.data.value) { 44 51 rep?.mutate.assertFact({ 45 52 entity: focusedBlock?.entityID, 46 53 attribute: "block/is-list", 47 54 data: { value: true, type: "boolean" }, 48 55 }); 56 + } else { 57 + outdentFull(block, previousBlock, rep); 49 58 } 50 - props.setToolbarState("list"); 59 + // props.setToolbarState("list"); 51 60 }} 52 61 > 53 62 <ListUnorderedSmall />
+13 -2
src/replicache/mutations.ts
··· 114 114 oldParent: string; 115 115 block: string; 116 116 newParent: string; 117 - position: { type: "first" } | { type: "end" }; 117 + position: 118 + | { type: "first" } 119 + | { type: "end" } 120 + | { type: "after"; entity: string }; 118 121 }> = async (args, ctx) => { 119 122 let children = ( 120 123 await ctx.scanIndex.eav(args.oldParent, "card/block") ··· 126 129 if (!block) return; 127 130 await ctx.retractFact(block.id); 128 131 let newPosition; 129 - switch (args.position.type) { 132 + let pos = args.position; 133 + switch (pos.type) { 130 134 case "first": { 131 135 newPosition = generateKeyBetween( 132 136 null, ··· 140 144 null, 141 145 ); 142 146 break; 147 + } 148 + case "after": { 149 + let index = newSiblings.findIndex((f) => f.data.value == pos?.entity); 150 + newPosition = generateKeyBetween( 151 + newSiblings[index]?.data.position || null, 152 + newSiblings[index + 1]?.data.position || null, 153 + ); 143 154 } 144 155 } 145 156 await ctx.assertFact({
+38
src/utils/list-operations.ts
··· 25 25 return true; 26 26 } 27 27 28 + export function outdentFull( 29 + block: Block, 30 + previousBlock: Block | null, 31 + rep?: Replicache<ReplicacheMutators> | null, 32 + ) { 33 + console.log("yo? ", block); 34 + if (!block.listData) return; 35 + 36 + // make this block not a list 37 + rep?.mutate.assertFact({ 38 + entity: block.value, 39 + attribute: "block/is-list", 40 + data: { type: "boolean", value: false }, 41 + }); 42 + 43 + // find the next block that is a level 1 list item or not a list item. 44 + // If there are none or this block is a level 1 list item, we don't need to move anything 45 + 46 + let after = block.listData?.path.find((f) => f.depth === 1)?.entity; 47 + console.log({ after }); 48 + // move this block to be after that block 49 + after && 50 + after !== block.value && 51 + rep?.mutate.moveBlock({ 52 + block: block.value, 53 + oldParent: block.listData.parent, 54 + newParent: block.parent, 55 + position: { type: "after", entity: after }, 56 + }); 57 + 58 + // move all the childen to the be under it as a level 1 list item 59 + rep?.mutate.moveChildren({ 60 + oldParent: block.value, 61 + newParent: block.parent, 62 + after: block.value, 63 + }); 64 + } 65 + 28 66 export function outdent( 29 67 block: Block, 30 68 previousBlock: Block | null,