From b33fe530476f89282e1e554aecf0cfe82e6d6edd Mon Sep 17 00:00:00 2001
From: 1STEP621 <86859447+1STEP621@users.noreply.github.com>
Date: Thu, 14 Dec 2023 13:11:23 +0900
Subject: Enhance(frontend):
 MFMや絵文字が使える入力ボックスでオートコンプリートを使えるように (#12643)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* rich autocomplete for use in profiles, announcements, and channel descriptions

* implementation omissions

* add tab, apply to page editor, and fix something

* componentization

* fix nyaize doesn't working in profile preview

* detach autocomplete instance when unmounted

* fix: mismatched camelCase

* remove unused / unnecessary styles

* update CHANGELOG.md

* fix lint

* remove dump.rdb

* props.richAutocomplete -> autocomplete

* Update packages/frontend/src/scripts/autocomplete.ts

* clarify namings
メンションなども「MFM」に含まれるのか自信がなかったのでrichSyntaxなどとぼかしていましたが、含むようなので変更しました

* tweak

* Update MkFormDialog.vue

* rename

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
---
 packages/frontend/src/components/MkTextarea.vue | 29 ++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

(limited to 'packages/frontend/src/components/MkTextarea.vue')

diff --git a/packages/frontend/src/components/MkTextarea.vue b/packages/frontend/src/components/MkTextarea.vue
index 7c1ddcbbed..23fdd5bfe1 100644
--- a/packages/frontend/src/components/MkTextarea.vue
+++ b/packages/frontend/src/components/MkTextarea.vue
@@ -26,16 +26,21 @@ SPDX-License-Identifier: AGPL-3.0-only
 		></textarea>
 	</div>
 	<div :class="$style.caption"><slot name="caption"></slot></div>
+	<button style="font-size: 0.85em;" class="_textButton" type="button" @click="preview = !preview">{{ i18n.ts.preview }}</button>
+	<div v-show="preview" v-panel :class="$style.mfmPreview">
+		<Mfm :text="v"/>
+	</div>
 
 	<MkButton v-if="manualSave && changed" primary :class="$style.save" @click="updated"><i class="ti ti-device-floppy"></i> {{ i18n.ts.save }}</MkButton>
 </div>
 </template>
 
 <script lang="ts" setup>
-import { onMounted, nextTick, ref, watch, computed, toRefs, shallowRef } from 'vue';
+import { onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs, shallowRef } from 'vue';
 import { debounce } from 'throttle-debounce';
 import MkButton from '@/components/MkButton.vue';
 import { i18n } from '@/i18n.js';
+import { Autocomplete, SuggestionType } from '@/scripts/autocomplete.js';
 
 const props = defineProps<{
 	modelValue: string | null;
@@ -46,6 +51,8 @@ const props = defineProps<{
 	placeholder?: string;
 	autofocus?: boolean;
 	autocomplete?: string;
+	mfmAutocomplete?: boolean | SuggestionType[],
+	mfmPreview?: boolean;
 	spellcheck?: boolean;
 	debounce?: boolean;
 	manualSave?: boolean;
@@ -68,6 +75,8 @@ const changed = ref(false);
 const invalid = ref(false);
 const filled = computed(() => v.value !== '' && v.value != null);
 const inputEl = shallowRef<HTMLTextAreaElement>();
+const preview = ref(false);
+let autocomplete: Autocomplete;
 
 const focus = () => inputEl.value.focus();
 const onInput = (ev) => {
@@ -113,6 +122,16 @@ onMounted(() => {
 			focus();
 		}
 	});
+
+	if (props.mfmAutocomplete) {
+		autocomplete = new Autocomplete(inputEl.value, v, props.mfmAutocomplete === true ? null : props.mfmAutocomplete);
+	}
+});
+
+onUnmounted(() => {
+	if (autocomplete) {
+		autocomplete.detach();
+	}
 });
 </script>
 
@@ -194,4 +213,12 @@ onMounted(() => {
 .save {
 	margin: 8px 0 0 0;
 }
+
+.mfmPreview {
+  padding: 12px;
+  border-radius: var(--radius);
+  box-sizing: border-box;
+  min-height: 130px;
+	pointer-events: none;
+}
 </style>
-- 
cgit v1.2.3-freya

