refactor: media-caption component as composition api

This commit is contained in:
Norm 2022-07-21 23:11:17 -04:00 committed by Gitea
parent 0ae09f2e80
commit b64f266483

View file

@ -1,137 +1,111 @@
<template> <template>
<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')"> <MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
<div class="container"> <div class="container">
<div class="fullwidth top-caption"> <div class="fullwidth top-caption">
<div class="mk-dialog"> <div class="mk-dialog">
<header> <header>
<Mfm v-if="title" class="title" :text="title"/> <Mfm v-if="title" class="title" :text="title"/>
<span class="text-count" :class="{ over: remainingLength < 0 }">{{ remainingLength }}</span> <span class="text-count" :class="{ over: remainingLength < 0 }">{{ remainingLength }}</span>
</header> </header>
<textarea v-model="inputValue" autofocus :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea> <textarea v-model="inputValue" autofocus :placeholder="input.placeholder" @keydown="onInputKeydown"></textarea>
<div v-if="(showOkButton || showCancelButton)" class="buttons"> <div v-if="(showOkButton || showCancelButton)" class="buttons">
<MkButton inline primary :disabled="remainingLength < 0" @click="ok">{{ $ts.ok }}</MkButton> <MkButton inline primary :disabled="remainingLength < 0" @click="ok">{{ $ts.ok }}</MkButton>
<MkButton inline @click="cancel" >{{ $ts.cancel }}</MkButton> <MkButton inline @click="cancel">{{ $ts.cancel }}</MkButton>
</div>
</div> </div>
</div> </div>
<div class="hdrwpsaf fullwidth">
<header>{{ image.name }}</header>
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="$refs.modal.close()"/>
<footer>
<span>{{ image.type }}</span>
<span>{{ bytes(image.size) }}</span>
<span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span>
</footer>
</div>
</div> </div>
</MkModal> <div class="hdrwpsaf fullwidth">
<header>{{ image.name }}</header>
<img :src="image.url" :alt="image.comment" :title="image.comment" @click="modal.close()"/>
<footer>
<span>{{ image.type }}</span>
<span>{{ bytes(image.size) }}</span>
<span v-if="image.properties && image.properties.width">{{ number(image.properties.width) }}px × {{ number(image.properties.height) }}px</span>
</footer>
</div>
</div>
</MkModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { onBeforeUnmount, onMounted, computed } from 'vue';
import { length } from 'stringz'; import { length } from 'stringz';
import * as misskey from 'misskey-js';
import MkModal from '@/components/ui/modal.vue'; import MkModal from '@/components/ui/modal.vue';
import MkButton from '@/components/ui/button.vue'; import MkButton from '@/components/ui/button.vue';
import bytes from '@/filters/bytes'; import bytes from '@/filters/bytes';
import number from '@/filters/number'; import number from '@/filters/number';
export default defineComponent({ type Input = {
components: { placeholder?: string;
MkModal, default?: any;
MkButton, };
},
props: { const props = withDefaults(defineProps<{
image: { image: misskey.entities.DriveFile;
type: Object, title?: string;
required: true, input: Input;
}, showOkButton: boolean;
title: { showCancelButton: boolean;
type: String, cancelableByBgClick: boolean;
required: false }>(), {
}, title: undefined,
input: { showOkButton: true,
required: true showCancelButton: true,
}, cancelableByBgClick: true,
showOkButton: { });
type: Boolean,
default: true
},
showCancelButton: {
type: Boolean,
default: true
},
cancelableByBgClick: {
type: Boolean,
default: true
},
},
emits: ['done', 'closed'], const emit = defineEmits<{
(ev: 'done', v: { canceled: boolean, result?: string }): void,
(ev: 'closed'): void,
}>();
data() { let inputValue: string | undefined = $ref(props.input.default ?? undefined);
return { let modal = $ref<InstanceType<typeof MkModal>>();
inputValue: this.input.default ? this.input.default : null
};
},
computed: { function done(canceled: boolean, result?: string): void {
remainingLength(): number { emit('done', { canceled, result });
if (typeof this.inputValue !== "string") return 512; modal.close();
return 512 - length(this.inputValue); }
}
},
mounted() { async function ok(): Promise<void> {
document.addEventListener('keydown', this.onKeydown); if (!props.showOkButton) return;
},
beforeUnmount() { const result = inputValue;
document.removeEventListener('keydown', this.onKeydown); done(false, result);
}, }
methods: { function cancel(): void {
bytes, done(true);
number, }
done(canceled, result?) { function onKeydown(evt: KeyboardEvent): void {
this.$emit('done', { canceled, result }); if (evt.key === 'Escape') {
this.$refs.modal.close(); cancel();
}, }
}
async ok() { function onInputKeydown(evt: KeyboardEvent): void {
if (!this.showOkButton) return; if (evt.key === 'Enter') {
if (evt.ctrlKey) {
const result = this.inputValue; evt.preventDefault();
this.done(false, result); evt.stopPropagation();
}, ok();
cancel() {
this.done(true);
},
onBgClick() {
if (this.cancelableByBgClick) {
this.cancel();
}
},
onKeydown(evt) {
if (evt.which === 27) { // ESC
this.cancel();
}
},
onInputKeydown(evt) {
if (evt.which === 13) { // Enter
if (evt.ctrlKey) {
evt.preventDefault();
evt.stopPropagation();
this.ok();
}
}
} }
} }
}
const remainingLength = computed((): number => {
if (typeof inputValue !== 'string') return 512;
return 512 - length(inputValue);
});
onMounted(() => {
document.addEventListener('keydown', onKeydown);
});
onBeforeUnmount(() => {
document.removeEventListener('keydown', onKeydown);
}); });
</script> </script>