Skip to content

Commit

Permalink
add feature for editable alt condition
Browse files Browse the repository at this point in the history
  • Loading branch information
dontry committed Feb 18, 2024
1 parent c694b29 commit ef4766e
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ export default {
const store = useStore();
const intersectionTop = useIntersectionTop();
const [scrollTop] = useDocumentScroll();
if (store.state.mode === RenderMode.static)
return { translate: 0, RenderMode };
const mode = computed(() => store.state.mode);
if (mode.value === RenderMode.static) return { translate: 0, RenderMode };
const translate = computed(() => {
let top = intersectionTop.value + scrollTop.value;
Expand All @@ -94,7 +94,7 @@ export default {
participantOffsetTop
);
});
return { translate, RenderMode };
return { translate, RenderMode, mode };
},
computed: {
...mapGetters([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,23 @@
<div :class="{ hidden: collapsed }">
<div class="segment">
<div class="text-skin-fragment flex">
<label class="condition px-1 text-sm inline-block"
>[{{ condition }}]</label
<label
class="condition px-1 text-sm inline-block"
:class="{
'px-2': editableMap.get(ifBlock),
'mx-1': editableMap.get(ifBlock),
}"
:contenteditable="editableMap.get(ifBlock)"
@dblclick="(e) => handleDblClick.call(ifBlock, e)"
@blur="(e) => handleBlur.call(ifBlock, e)"
@keyup="(e) => handleKeyup.call(ifBlock, e)"
>
{{
editableMap.get(ifBlock)
? conditionTextFromIfElseBlock(ifBlock)
: `[${conditionTextFromIfElseBlock(ifBlock)}]`
}}
</label>
</div>
<block
v-if="blockInIfBlock"
Expand All @@ -41,16 +55,27 @@
incremental
></block>
</div>
<template
v-for="(elseIfBlock, index) in alt.elseIfBlock()"
:key="index + 500"
>
<template v-for="(elseIfBlock, index) in elseIfBlocks" :key="index + 500">
<div class="segment mt-2 border-t border-solid">
<div class="text-skin-fragment" :key="index + 1000">
<label class="else-if hidden">else if</label>
<label class="condition px-1"
>[{{ conditionFromIfElseBlock(elseIfBlock) }}]</label
<label
class="condition px-1"
:class="{
'px-2': editableMap.get(elseIfBlock),
'mx-1': editableMap.get(elseIfBlock),
}"
:contenteditable="editableMap.get(elseIfBlock)"
@dblclick="(e) => handleDblClick.call(elseIfBlock, e)"
@blur="(e) => handleBlur.call(elseIfBlock, e)"
@keyup="(e) => handleKeyup.call(elseIfBlock, e)"
>
{{
editableMap.get(elseIfBlock)
? conditionTextFromIfElseBlock(elseIfBlock)
: `[${conditionTextFromIfElseBlock(elseIfBlock)}]`
}}
</label>
</div>
<block
:style="{ paddingLeft: `${offsetX}px` }"
Expand Down Expand Up @@ -83,52 +108,143 @@
</template>

<script>
import { mapState } from "vuex";
import { ref, computed, nextTick } from "vue";
import { useStore } from "vuex";
import fragment from "./FragmentMixin";
import { increaseNumber, blockLength } from "@/utils/Numbering";
export default {
name: "fragment-alt",
props: ["context", "comment", "selfCallIndent", "commentObj", "number"],
mixins: [fragment],
computed: {
...mapState(["numbering"]),
from: function () {
return this.context.Origin();
},
alt: function () {
return this.context.alt();
},
blockInIfBlock: function () {
return this.alt?.ifBlock()?.braceBlock()?.block();
},
condition: function () {
return this.conditionFromIfElseBlock(this.alt?.ifBlock());
},
elseBlock: function () {
return this.alt?.elseBlock()?.braceBlock()?.block();
},
blockLengthAcc() {
const acc = [blockLength(this.blockInIfBlock)];
if (this.alt?.elseIfBlock()) {
this.alt.elseIfBlock().forEach((block) => {
setup(props) {
const store = useStore();
const editableMap = ref(new Map());
const conditionLabel = ref(null);
const numbering = computed(() => store.state.numbering);
const from = computed(() => props.context.Origin());
const alt = computed(() => props.context.alt());
const ifBlock = computed(() => alt.value?.ifBlock());
const elseIfBlocks = computed(() => alt.value?.elseIfBlock());
const elseBlock = computed(() =>
alt.value?.elseBlock()?.braceBlock()?.block(),
);
const blockInIfBlock = computed(() =>
alt.value?.ifBlock()?.braceBlock()?.block(),
);
const blockLengthAcc = computed(() => {
const acc = [blockLength(blockInIfBlock.value)];
if (alt.value?.elseIfBlock()) {
alt.value.elseIfBlock().forEach((block) => {
acc.push(
acc[acc.length - 1] + blockLength(this.blockInElseIfBlock(block)),
acc[acc.length - 1] + blockLength(blockInElseIfBlock(block)),
);
});
}
return acc;
},
},
methods: {
conditionFromIfElseBlock(ctx) {
return ctx?.parExpr()?.condition()?.getFormattedText();
},
blockInElseIfBlock(ctx) {
});
const code = computed(() => store.getters.code);
const onContentChange = computed(
() => store.getters.onContentChange || (() => {}),
);
// Set the initial value of the editableMap
editableMap.value.set(alt.value, false);
if (alt.value?.elseIfBlock()) {
alt.value.elseIfBlock().forEach((block) => {
editableMap.value.set(block, false);
});
}
function toggleEditable(_editable) {
editableMap.value.set(this, _editable);
}
function conditionFromIfElseBlock(ctx) {
return ctx?.parExpr()?.condition();
}
function conditionTextFromIfElseBlock(ctx) {
return conditionFromIfElseBlock(ctx)?.getFormattedText();
}
function blockInElseIfBlock(ctx) {
return ctx?.braceBlock()?.block();
},
increaseNumber: increaseNumber,
blockLength: blockLength,
}
function updateCode(code) {
store.dispatch("updateCode", { code });
onContentChange.value(code);
}
async function handleDblClick(e) {
e.preventDefault();
e.stopPropagation();
toggleEditable.call(this, true);
await nextTick();
const range = document.createRange();
const sel = window.getSelection();
range.selectNodeContents(e.target);
range.collapse(false);
sel.removeAllRanges();
sel.addRange(range);
}
async function handleBlur(e) {
// avoid race condition with keyup event
await nextTick();
if (!editableMap.value.get(this)) return;
replaceConditionText(this, e);
}
function handleKeyup(e) {
if (e.key === "Enter" || e.key === "Escape" || e.key === "Tab") {
replaceConditionText(this, e);
}
}
function replaceConditionText(block, event) {
toggleEditable.call(block, false);
event.preventDefault();
event.stopPropagation();
// Remove all whitespaces and check if the text is empty
const newText = event.target.innerText.replace(/\s/g, "").trim();
if (newText === "") {
event.target.innerText = conditionTextFromIfElseBlock(this);
return;
}
const condition = conditionFromIfElseBlock(block);
const [start, end] = [condition?.start?.start, condition?.stop?.stop];
updateCode(
code.value.slice(0, start) + newText + code.value.slice(end + 1),
);
}
return {
editableMap,
numbering,
from,
alt,
blockInIfBlock,
ifBlock,
elseIfBlocks,
elseBlock,
blockLengthAcc,
conditionLabel,
toggleEditable,
conditionFromIfElseBlock,
conditionTextFromIfElseBlock,
blockInElseIfBlock,
increaseNumber,
blockLength,
handleKeyup,
handleBlur,
handleDblClick,
};
},
};
</script>
Expand Down

0 comments on commit ef4766e

Please sign in to comment.