pages refactoring, fix bug (#7066)

* pages refactoring

* pages: fix if block

* fix code format

* remove passing of the page parameter

* remove comment

* fix indent

* replace with unref

* fix conditions of isVarBlock()

* Update src/client/scripts/hpml/block.ts

use includes() instead of find()

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
marihachi
2021-01-30 10:59:05 +09:00
committed by GitHub
parent 7fc3e7dd8b
commit 100a131913
24 changed files with 600 additions and 348 deletions

View File

@ -1,9 +1,9 @@
<template>
<component :is="'x-' + value.type" :value="value" :page="page" :hpml="hpml" :key="value.id" :h="h"/>
<component :is="'x-' + block.type" :block="block" :hpml="hpml" :key="block.id" :h="h"/>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, PropType } from 'vue';
import XText from './page.text.vue';
import XSection from './page.section.vue';
import XImage from './page.image.vue';
@ -19,22 +19,24 @@ import XCounter from './page.counter.vue';
import XRadioButton from './page.radio-button.vue';
import XCanvas from './page.canvas.vue';
import XNote from './page.note.vue';
import { Hpml } from '@/scripts/hpml/evaluator';
import { Block } from '@/scripts/hpml/block';
export default defineComponent({
components: {
XText, XSection, XImage, XButton, XNumberInput, XTextInput, XTextareaInput, XTextarea, XPost, XSwitch, XIf, XCounter, XRadioButton, XCanvas, XNote
},
props: {
value: {
block: {
type: Object as PropType<Block>,
required: true
},
hpml: {
required: true
},
page: {
type: Object as PropType<Hpml>,
required: true
},
h: {
type: Number,
required: true
}
},

View File

@ -1,51 +1,55 @@
<template>
<div>
<MkButton class="kudkigyw" @click="click()" :primary="value.primary">{{ hpml.interpolate(value.text) }}</MkButton>
<MkButton class="kudkigyw" @click="click()" :primary="block.primary">{{ hpml.interpolate(block.text) }}</MkButton>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, PropType, unref } from 'vue';
import MkButton from '../ui/button.vue';
import * as os from '@/os';
import { ButtonBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
MkButton
},
props: {
value: {
block: {
type: Object as PropType<ButtonBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
methods: {
click() {
if (this.value.action === 'dialog') {
if (this.block.action === 'dialog') {
this.hpml.eval();
os.dialog({
text: this.hpml.interpolate(this.value.content)
text: this.hpml.interpolate(this.block.content)
});
} else if (this.value.action === 'resetRandom') {
} else if (this.block.action === 'resetRandom') {
this.hpml.updateRandomSeed(Math.random());
this.hpml.eval();
} else if (this.value.action === 'pushEvent') {
} else if (this.block.action === 'pushEvent') {
os.api('page-push', {
pageId: this.hpml.page.id,
event: this.value.event,
...(this.value.var ? {
var: this.hpml.vars[this.value.var]
event: this.block.event,
...(this.block.var ? {
var: unref(this.hpml.vars)[this.block.var]
} : {})
});
os.dialog({
type: 'success',
text: this.hpml.interpolate(this.value.message)
text: this.hpml.interpolate(this.block.message)
});
} else if (this.value.action === 'callAiScript') {
this.hpml.callAiScript(this.value.fn);
} else if (this.block.action === 'callAiScript') {
this.hpml.callAiScript(this.block.fn);
}
}
}

View File

@ -1,24 +1,36 @@
<template>
<div class="ysrxegms">
<canvas ref="canvas" :width="value.width" :height="value.height"/>
<canvas ref="canvas" :width="block.width" :height="block.height"/>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, onMounted, PropType, Ref, ref } from 'vue';
import * as os from '@/os';
import { CanvasBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
props: {
value: {
block: {
type: Object as PropType<CanvasBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
mounted() {
this.hpml.registerCanvas(this.value.name, this.$refs.canvas);
setup(props, ctx) {
const canvas: Ref<any> = ref(null);
onMounted(() => {
props.hpml.registerCanvas(props.block.name, canvas.value);
});
return {
canvas
};
}
});
</script>

View File

@ -1,41 +1,43 @@
<template>
<div>
<MkButton class="llumlmnx" @click="click()">{{ hpml.interpolate(value.text) }}</MkButton>
<MkButton class="llumlmnx" @click="click()">{{ hpml.interpolate(block.text) }}</MkButton>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { computed, defineComponent, PropType } from 'vue';
import MkButton from '../ui/button.vue';
import * as os from '@/os';
import { CounterVarBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
MkButton
},
props: {
value: {
block: {
type: Object as PropType<CounterVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function click() {
props.hpml.updatePageVar(props.block.name, value.value + (props.block.inc || 1));
props.hpml.eval();
}
return {
v: 0,
click
};
},
watch: {
v() {
this.hpml.updatePageVar(this.value.name, this.v);
this.hpml.eval();
}
},
methods: {
click() {
this.v = this.v + (this.value.inc || 1);
}
}
});
</script>

View File

@ -1,27 +1,29 @@
<template>
<div v-show="hpml.vars[value.var]">
<XBlock v-for="child in value.children" :value="child" :page="page" :hpml="hpml" :key="child.id" :h="h"/>
<div v-show="hpml.vars.value[block.var]">
<XBlock v-for="child in block.children" :block="child" :hpml="hpml" :key="child.id" :h="h"/>
</div>
</template>
<script lang="ts">
import { defineComponent, defineAsyncComponent } from 'vue';
import { IfBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
import { defineComponent, defineAsyncComponent, PropType } from 'vue';
export default defineComponent({
components: {
XBlock: defineAsyncComponent(() => import('./page.block.vue'))
},
props: {
value: {
block: {
type: Object as PropType<IfBlock>,
required: true
},
hpml: {
required: true
},
page: {
type: Object as PropType<Hpml>,
required: true
},
h: {
type: Number,
required: true
}
},

View File

@ -5,25 +5,28 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, PropType } from 'vue';
import * as os from '@/os';
import { ImageBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
props: {
value: {
block: {
type: Object as PropType<ImageBlock>,
required: true
},
page: {
hpml: {
type: Object as PropType<Hpml>,
required: true
},
}
},
data() {
setup(props, ctx) {
const image = props.hpml.page.attachedFiles.find(x => x.id === props.block.fileId);
return {
image: null,
image
};
},
created() {
this.image = this.page.attachedFiles.find(x => x.id === this.value.fileId);
}
});
</script>

View File

@ -1,15 +1,16 @@
<template>
<div class="voxdxuby">
<XNote v-if="note && !value.detailed" v-model:note="note" :key="note.id + ':normal'"/>
<XNoteDetailed v-if="note && value.detailed" v-model:note="note" :key="note.id + ':detail'"/>
<XNote v-if="note && !block.detailed" v-model:note="note" :key="note.id + ':normal'"/>
<XNoteDetailed v-if="note && block.detailed" v-model:note="note" :key="note.id + ':detail'"/>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, onMounted, PropType, Ref, ref } from 'vue';
import XNote from '@/components/note.vue';
import XNoteDetailed from '@/components/note-detailed.vue';
import * as os from '@/os';
import { NoteBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
@ -17,20 +18,24 @@ export default defineComponent({
XNoteDetailed,
},
props: {
value: {
required: true
},
hpml: {
block: {
type: Object as PropType<NoteBlock>,
required: true
}
},
data() {
setup(props, ctx) {
const note: Ref<Record<string, any> | null> = ref(null);
onMounted(() => {
os.api('notes/show', { noteId: props.block.note })
.then(result => {
note.value = result;
});
});
return {
note: null,
note
};
},
async mounted() {
this.note = await os.api('notes/show', { noteId: this.value.note });
}
});
</script>

View File

@ -1,36 +1,44 @@
<template>
<div>
<MkInput class="kudkigyw" v-model:value="v" type="number">{{ hpml.interpolate(value.text) }}</MkInput>
<MkInput class="kudkigyw" :value="value" @update:value="updateValue($event)" type="number">{{ hpml.interpolate(block.text) }}</MkInput>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { computed, defineComponent, PropType } from 'vue';
import MkInput from '../ui/input.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { NumberInputVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkInput
},
props: {
value: {
block: {
type: Object as PropType<NumberInputVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
v: this.value.default,
};
},
watch: {
v() {
this.hpml.updatePageVar(this.value.name, this.v);
this.hpml.eval();
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>

View File

@ -6,12 +6,14 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, PropType } from 'vue';
import { faCheck, faPaperPlane } from '@fortawesome/free-solid-svg-icons';
import MkTextarea from '../ui/textarea.vue';
import MkButton from '../ui/button.vue';
import { apiUrl } from '@/config';
import * as os from '@/os';
import { PostBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
@ -19,16 +21,18 @@ export default defineComponent({
MkButton,
},
props: {
value: {
block: {
type: Object as PropType<PostBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
text: this.hpml.interpolate(this.value.text),
text: this.hpml.interpolate(this.block.text),
posted: false,
posting: false,
faCheck, faPaperPlane
@ -37,7 +41,7 @@ export default defineComponent({
watch: {
'hpml.vars': {
handler() {
this.text = this.hpml.interpolate(this.value.text);
this.text = this.hpml.interpolate(this.block.text);
},
deep: true
}
@ -45,7 +49,7 @@ export default defineComponent({
methods: {
upload() {
const promise = new Promise((ok) => {
const canvas = this.hpml.canvases[this.value.canvasId];
const canvas = this.hpml.canvases[this.block.canvasId];
canvas.toBlob(blob => {
const data = new FormData();
data.append('file', blob);
@ -69,7 +73,7 @@ export default defineComponent({
},
async post() {
this.posting = true;
const file = this.value.attachCanvasImage ? await this.upload() : null;
const file = this.block.attachCanvasImage ? await this.upload() : null;
os.apiWithDialog('notes/create', {
text: this.text === '' ? null : this.text,
fileIds: file ? [file.id] : undefined,

View File

@ -1,37 +1,45 @@
<template>
<div>
<div>{{ hpml.interpolate(value.title) }}</div>
<MkRadio v-for="x in value.values" v-model="v" :value="x" :key="x">{{ x }}</MkRadio>
<div>{{ hpml.interpolate(block.title) }}</div>
<MkRadio v-for="item in block.values" :modelValue="value" @update:modelValue="updateValue($event)" :value="item" :key="item">{{ item }}</MkRadio>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { computed, defineComponent, PropType } from 'vue';
import MkRadio from '../ui/radio.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { RadioButtonVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkRadio
},
props: {
value: {
block: {
type: Object as PropType<RadioButtonVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
v: this.value.default,
};
},
watch: {
v() {
this.hpml.updatePageVar(this.value.name, this.v);
this.hpml.eval();
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue: string) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>

View File

@ -1,29 +1,30 @@
<template>
<section class="sdgxphyu">
<component :is="'h' + h">{{ value.title }}</component>
<component :is="'h' + h">{{ block.title }}</component>
<div class="children">
<XBlock v-for="child in value.children" :value="child" :page="page" :hpml="hpml" :key="child.id" :h="h + 1"/>
<XBlock v-for="child in block.children" :block="child" :hpml="hpml" :key="child.id" :h="h + 1"/>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, defineAsyncComponent } from 'vue';
import { defineComponent, defineAsyncComponent, PropType } from 'vue';
import * as os from '@/os';
import { SectionBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
export default defineComponent({
components: {
XBlock: defineAsyncComponent(() => import('./page.block.vue'))
},
props: {
value: {
block: {
type: Object as PropType<SectionBlock>,
required: true
},
hpml: {
required: true
},
page: {
type: Object as PropType<Hpml>,
required: true
},
h: {

View File

@ -1,36 +1,44 @@
<template>
<div class="hkcxmtwj">
<MkSwitch v-model:value="v">{{ hpml.interpolate(value.text) }}</MkSwitch>
<MkSwitch :value="value" @update:value="updateValue($event)">{{ hpml.interpolate(block.text) }}</MkSwitch>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { computed, defineComponent, PropType } from 'vue';
import MkSwitch from '../ui/switch.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { SwitchVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkSwitch
},
props: {
value: {
block: {
type: Object as PropType<SwitchVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
v: this.value.default,
};
},
watch: {
v() {
this.hpml.updatePageVar(this.value.name, this.v);
this.hpml.eval();
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue: boolean) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>

View File

@ -1,36 +1,44 @@
<template>
<div>
<MkInput class="kudkigyw" v-model:value="v" type="text">{{ hpml.interpolate(value.text) }}</MkInput>
<MkInput class="kudkigyw" :value="value" @update:value="updateValue($event)" type="text">{{ hpml.interpolate(block.text) }}</MkInput>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { computed, defineComponent, PropType } from 'vue';
import MkInput from '../ui/input.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { TextInputVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkInput
},
props: {
value: {
block: {
type: Object as PropType<TextInputVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
v: this.value.default,
};
},
watch: {
v() {
this.hpml.updatePageVar(this.value.name, this.v);
this.hpml.eval();
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>

View File

@ -6,7 +6,9 @@
</template>
<script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue';
import { TextBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
import { defineAsyncComponent, defineComponent, PropType } from 'vue';
import { parse } from '../../../mfm/parse';
import { unique } from '../../../prelude/array';
@ -15,16 +17,18 @@ export default defineComponent({
MkUrlPreview: defineAsyncComponent(() => import('@/components/url-preview.vue')),
},
props: {
value: {
block: {
type: Object as PropType<TextBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
text: this.hpml.interpolate(this.value.text),
text: this.hpml.interpolate(this.block.text),
};
},
computed: {
@ -43,7 +47,7 @@ export default defineComponent({
watch: {
'hpml.vars': {
handler() {
this.text = this.hpml.interpolate(this.value.text);
this.text = this.hpml.interpolate(this.block.text);
},
deep: true
}

View File

@ -1,36 +1,45 @@
<template>
<div>
<MkTextarea v-model:value="v">{{ hpml.interpolate(value.text) }}</MkTextarea>
<MkTextarea :value="value" @update:value="updateValue($event)">{{ hpml.interpolate(block.text) }}</MkTextarea>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { computed, defineComponent, PropType } from 'vue';
import MkTextarea from '../ui/textarea.vue';
import * as os from '@/os';
import { Hpml } from '@/scripts/hpml/evaluator';
import { HpmlTextInput } from '@/scripts/hpml';
import { TextInputVarBlock } from '@/scripts/hpml/block';
export default defineComponent({
components: {
MkTextarea
},
props: {
value: {
block: {
type: Object as PropType<TextInputVarBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
v: this.value.default,
};
},
watch: {
v() {
this.hpml.updatePageVar(this.value.name, this.v);
this.hpml.eval();
setup(props, ctx) {
const value = computed(() => {
return props.hpml.vars.value[props.block.name];
});
function updateValue(newValue) {
props.hpml.updatePageVar(props.block.name, newValue);
props.hpml.eval();
}
return {
value,
updateValue
};
}
});
</script>

View File

@ -3,7 +3,9 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { TextBlock } from '@/scripts/hpml/block';
import { Hpml } from '@/scripts/hpml/evaluator';
import { defineComponent, PropType } from 'vue';
import MkTextarea from '../ui/textarea.vue';
export default defineComponent({
@ -11,22 +13,24 @@ export default defineComponent({
MkTextarea
},
props: {
value: {
block: {
type: Object as PropType<TextBlock>,
required: true
},
hpml: {
type: Object as PropType<Hpml>,
required: true
}
},
data() {
return {
text: this.hpml.interpolate(this.value.text),
text: this.hpml.interpolate(this.block.text),
};
},
watch: {
'hpml.vars': {
handler() {
this.text = this.hpml.interpolate(this.value.text);
this.text = this.hpml.interpolate(this.block.text);
},
deep: true
}

View File

@ -1,77 +1,72 @@
<template>
<div class="iroscrza" :class="{ center: page.alignCenter, serif: page.font === 'serif' }" v-if="hpml">
<XBlock v-for="child in page.content" :value="child" :page="page" :hpml="hpml" :key="child.id" :h="2"/>
<XBlock v-for="child in page.content" :block="child" :hpml="hpml" :key="child.id" :h="2"/>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, onMounted, nextTick, onUnmounted, PropType } from 'vue';
import { parse } from '@syuilo/aiscript';
import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons';
import { faHeart } from '@fortawesome/free-regular-svg-icons';
import XBlock from './page.block.vue';
import { Hpml } from '@/scripts/hpml/evaluator';
import { url } from '@/config';
import { $i } from '@/account';
import { defaultStore } from '@/store';
export default defineComponent({
components: {
XBlock
},
props: {
page: {
type: Object,
type: Object as PropType<Record<string, any>>,
required: true
},
},
setup(props, ctx) {
data() {
return {
hpml: null,
faHeartS, faHeart
};
},
created() {
this.hpml = new Hpml(this.page, {
const hpml = new Hpml(props.page, {
randomSeed: Math.random(),
visitor: this.$i,
visitor: $i,
url: url,
enableAiScript: !this.$store.state.disablePagesScript
enableAiScript: !defaultStore.state.disablePagesScript
});
},
mounted() {
this.$nextTick(() => {
if (this.page.script && this.hpml.aiscript) {
let ast;
try {
ast = parse(this.page.script);
} catch (e) {
console.error(e);
/*os.dialog({
type: 'error',
text: 'Syntax error :('
});*/
return;
onMounted(() => {
nextTick(() => {
if (props.page.script && hpml.aiscript) {
let ast;
try {
ast = parse(props.page.script);
} catch (e) {
console.error(e);
/*os.dialog({
type: 'error',
text: 'Syntax error :('
});*/
return;
}
hpml.aiscript.exec(ast).then(() => {
hpml.eval();
}).catch(e => {
console.error(e);
/*os.dialog({
type: 'error',
text: e
});*/
});
} else {
hpml.eval();
}
this.hpml.aiscript.exec(ast).then(() => {
this.hpml.eval();
}).catch(e => {
console.error(e);
/*os.dialog({
type: 'error',
text: e
});*/
});
} else {
this.hpml.eval();
}
});
onUnmounted(() => {
if (hpml.aiscript) hpml.aiscript.abort();
});
});
},
beforeUnmount() {
if (this.hpml.aiscript) this.hpml.aiscript.abort();
return {
hpml,
};
},
});
</script>