Skip to content

Commit

Permalink
Merge pull request #234 from frappe/feat-simplify-block-navigation
Browse files Browse the repository at this point in the history
  • Loading branch information
surajshetty3416 authored Oct 29, 2024
2 parents 55f40f4 + 47013b9 commit fb69835
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 52 deletions.
55 changes: 48 additions & 7 deletions frontend/src/components/BlockLayers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
</span>
</span>
<div v-show="canShowChildLayer(element)">
<BlockLayers :blocks="element.children" ref="childLayer" :indent="childIndent" />
<BlockLayers :blocks="element.children" :ref="childLayer" :indent="childIndent" />
</div>
</div>
</BlockContextMenu>
Expand All @@ -91,8 +91,15 @@ import BlockContextMenu from "./BlockContextMenu.vue";
import BlockLayers from "./BlockLayers.vue";
import BlocksIcon from "./Icons/Blocks.vue";
type LayerInstance = InstanceType<typeof BlockLayers>;
const store = useStore();
const childLayer = ref<InstanceType<typeof BlockLayers> | null>(null);
const childLayers = ref<LayerInstance[]>([]);
const childLayer = (el) => {
if (el) {
childLayers.value.push(el);
}
};
const props = defineProps({
blocks: {
Expand Down Expand Up @@ -123,19 +130,39 @@ const isExpanded = (block: Block) => {
return expandedLayers.value.has(block.blockId);
};
// TODO: Refactor this!
const toggleExpanded = (block: Block) => {
const blockIndex = props.blocks.findIndex((b) => b.blockId === block.blockId);
if (blockIndex === -1) {
childLayer.value?.toggleExpanded(block);
if (block.isRoot()) {
return;
}
if (isExpanded(block) && !block.isRoot()) {
if (!blockExits(block)) {
const child = childLayers.value.find((layer) => layer.blockExitsInTree(block)) as LayerInstance;
if (child) {
child.toggleExpanded(block);
}
}
if (isExpanded(block)) {
expandedLayers.value.delete(block.blockId);
} else {
expandedLayers.value.add(block.blockId);
}
};
// @ts-ignore
const isExpandedInTree = (block: Block) => {
if (!blockExits(block)) {
const child = childLayers.value.find((layer) => layer.blockExitsInTree(block)) as LayerInstance;
if (child) {
return child.isExpandedInTree(block);
}
}
return isExpanded(block);
};
const blockExits = (block: Block) => {
return props.blocks.find((b) => b.blockId === block.blockId);
};
const canShowChildLayer = (block: Block) => {
return (
((isExpanded(block) && block.hasChildren()) || (block.canHaveChildren() && !block.hasChildren())) &&
Expand All @@ -161,15 +188,29 @@ watch(
},
);
// @ts-ignore
const updateParent = (event) => {
event.item.__draggable_context.element.parentBlock = store.activeCanvas?.findBlock(
event.to.closest("[data-block-layer-id]").dataset.blockLayerId,
);
};
const blockExitsInTree = (block: Block) => {
if (blockExits(block)) {
return true;
}
for (const layer of childLayers.value) {
if (layer.blockExitsInTree(block)) {
return true;
}
}
return false;
};
defineExpose({
isExpanded,
toggleExpanded,
isExpandedInTree,
blockExitsInTree,
});
</script>
<style>
Expand Down
123 changes: 80 additions & 43 deletions frontend/src/components/BuilderCanvas.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ import {
getBlockInstance,
getBlockObject,
getNumberFromPx,
isCtrlOrCmd,
isTargetEditable,
uploadImage,
} from "@/utils/helpers";
Expand Down Expand Up @@ -428,66 +427,104 @@ function setEvents() {
});
useEventListener(document, "keydown", (ev: KeyboardEvent) => {
if (isTargetEditable(ev)) {
if (isTargetEditable(ev) || selectedBlocks.value.length !== 1) {
return;
}
if (ev.shiftKey && ev.key === "ArrowLeft") {
if (isCtrlOrCmd(ev)) {
if (selectedBlocks.value.length) {
const selectedBlock = selectedBlocks.value[0];
store.activeLayers?.toggleExpanded(selectedBlock);
return;
}
const selectedBlock = selectedBlocks.value[0];
if (ev.key === "ArrowLeft") {
const sibling = selectedBlock.getSiblingBlock("previous");
if (store.activeLayers?.isExpandedInTree(selectedBlock)) {
store.activeLayers?.toggleExpanded(selectedBlock);
return;
}
if (selectedBlocks.value.length) {
const selectedBlock = selectedBlocks.value[0];
if (sibling) {
store.selectBlock(sibling, null, true, true);
} else {
const parentBlock = selectedBlock.getParentBlock();
if (parentBlock) {
selectionTrail.push(selectedBlock.blockId);
maintainTrail = true;
store.selectBlock(parentBlock, null, true, true);
maintainTrail = false;
}
}
}
if (ev.shiftKey && ev.key === "ArrowRight") {
const blockId = selectionTrail.pop();
if (blockId) {
const block = findBlock(blockId);
if (block) {
maintainTrail = true;
store.selectBlock(block, null, true, true);
maintainTrail = false;
} else if (ev.key === "ArrowRight") {
const hasChildren = selectedBlock.hasChildren();
if (hasChildren) {
store.activeLayers?.toggleExpanded(selectedBlock);
// select first child
const child = selectedBlock.children[0];
if (child) {
store.selectBlock(child, null, true, true);
}
} else {
if (selectedBlocks.value.length) {
const selectedBlock = selectedBlocks.value[0];
if (selectedBlock.children && selectedBlock.isVisible()) {
let child = selectedBlock.children[0];
while (child && !child.isVisible()) {
child = child.getSiblingBlock("next") as Block;
if (!child) {
break;
}
let sibling = selectedBlock.getSiblingBlock("next");
if (sibling) {
store.selectBlock(sibling, null, true, true);
} else {
let parentBlock = selectedBlock.getParentBlock();
while (!sibling) {
if (!parentBlock) {
break;
}
sibling = parentBlock.getSiblingBlock("next");
if (sibling) {
store.selectBlock(sibling, null, true, true);
break;
} else {
parentBlock = parentBlock.getParentBlock();
}
child && store.selectBlock(child, null, true, true);
}
sibling && store.selectBlock(sibling, null, true, true);
}
}
}
if (ev.shiftKey && ev.key === "ArrowUp") {
if (selectedBlocks.value.length) {
let sibling = selectedBlocks.value[0].getSiblingBlock("previous");
if (sibling) {
store.selectBlock(sibling, null, true, true);
} else if (ev.key === "ArrowUp") {
let sibling = selectedBlock.getSiblingBlock("previous");
if (sibling) {
let isExpanded = store.activeLayers?.isExpandedInTree(sibling);
while (isExpanded) {
const lastChild = sibling.getLastChild() as Block;
if (lastChild) {
sibling = lastChild;
isExpanded = store.activeLayers?.isExpandedInTree(lastChild);
} else {
break;
}
}
store.selectBlock(sibling, null, true, true);
} else {
const parentBlock = selectedBlock.getParentBlock();
if (parentBlock) {
store.selectBlock(parentBlock, null, true, true);
}
}
}
if (ev.shiftKey && ev.key === "ArrowDown") {
if (selectedBlocks.value.length) {
let sibling = selectedBlocks.value[0].getSiblingBlock("next");
} else if (ev.key === "ArrowDown") {
const hasChildren = selectedBlock.hasChildren();
const isExpanded = store.activeLayers?.isExpandedInTree(selectedBlock);
if (hasChildren && isExpanded) {
// select first child
const child = selectedBlock.children[0];
if (child) {
store.selectBlock(child, null, true, true);
}
} else {
let sibling = selectedBlock.getSiblingBlock("next");
if (sibling) {
store.selectBlock(sibling, null, true, true);
} else {
let parentBlock = selectedBlock.getParentBlock();
while (!sibling) {
if (!parentBlock) {
break;
}
sibling = parentBlock.getSiblingBlock("next");
if (sibling) {
store.selectBlock(sibling, null, true, true);
break;
} else {
parentBlock = parentBlock.getParentBlock();
}
}
sibling && store.selectBlock(sibling, null, true, true);
}
}
}
Expand Down
10 changes: 8 additions & 2 deletions frontend/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,12 @@ const useStore = defineStore("store", {
videoBlock.attributes.src = videoSrc;
return videoBlock;
},
selectBlock(block: Block, e: MouseEvent | null, scrollLayerIntoView = true, scrollBlockIntoView = false) {
selectBlock(
block: Block,
e: MouseEvent | null,
scrollLayerIntoView: boolean | ScrollLogicalPosition = true,
scrollBlockIntoView = false,
) {
this.activeCanvas?.history?.pause();
if (this.settingPage) {
return;
Expand All @@ -220,10 +225,11 @@ const useStore = defineStore("store", {
}
if (scrollLayerIntoView) {
// TODO: move to layers?
const align = scrollLayerIntoView === true ? "center" : scrollLayerIntoView;
nextTick(() => {
document
.querySelector(`[data-block-layer-id="${block.blockId}"]`)
?.scrollIntoView({ behavior: "instant", block: "center", inline: "center" });
?.scrollIntoView({ behavior: "instant", block: align, inline: "center" });
});
}

Expand Down
6 changes: 6 additions & 0 deletions frontend/src/utils/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,12 @@ class Block implements BlockOptions {
}
return null;
}
getFirstChild() {
return this.children[0];
}
getLastChild() {
return this.children[this.children.length - 1];
}
selectSiblingBlock(direction: "next" | "previous") {
const sibling = this.getSiblingBlock(direction);
if (sibling) {
Expand Down

0 comments on commit fb69835

Please sign in to comment.