diff options
| author | 1STEP621 <86859447+1STEP621@users.noreply.github.com> | 2023-12-14 13:11:23 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-14 13:11:23 +0900 |
| commit | b33fe530476f89282e1e554aecf0cfe82e6d6edd (patch) | |
| tree | fcf410283db79cdf3883a43543887a5836ed6f2f /packages/frontend/src/pages | |
| parent | refactor(frontend) $i の型情報にtokenを追加 (#12649) (diff) | |
| download | misskey-b33fe530476f89282e1e554aecf0cfe82e6d6edd.tar.gz misskey-b33fe530476f89282e1e554aecf0cfe82e6d6edd.tar.bz2 misskey-b33fe530476f89282e1e554aecf0cfe82e6d6edd.zip | |
Enhance(frontend): MFMや絵文字が使える入力ボックスでオートコンプリートを使えるように (#12643)
* 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>
Diffstat (limited to 'packages/frontend/src/pages')
6 files changed, 24 insertions, 9 deletions
diff --git a/packages/frontend/src/pages/admin/announcements.vue b/packages/frontend/src/pages/admin/announcements.vue index 92070dc6c6..e4bbe15955 100644 --- a/packages/frontend/src/pages/admin/announcements.vue +++ b/packages/frontend/src/pages/admin/announcements.vue @@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only <MkInput v-model="announcement.title"> <template #label>{{ i18n.ts.title }}</template> </MkInput> - <MkTextarea v-model="announcement.text"> + <MkTextarea v-model="announcement.text" mfmAutocomplete :mfmPreview="true"> <template #label>{{ i18n.ts.text }}</template> </MkTextarea> <MkInput v-model="announcement.imageUrl" type="url"> @@ -75,7 +75,6 @@ import { ref, computed } from 'vue'; import XHeader from './_header_.vue'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; -import MkTextarea from '@/components/MkTextarea.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import MkRadios from '@/components/MkRadios.vue'; import MkInfo from '@/components/MkInfo.vue'; @@ -83,6 +82,7 @@ import * as os from '@/os.js'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; import MkFolder from '@/components/MkFolder.vue'; +import MkTextarea from '@/components/MkTextarea.vue'; const announcements = ref<any[]>([]); diff --git a/packages/frontend/src/pages/channel-editor.vue b/packages/frontend/src/pages/channel-editor.vue index af382bb137..f16b8709f3 100644 --- a/packages/frontend/src/pages/channel-editor.vue +++ b/packages/frontend/src/pages/channel-editor.vue @@ -12,7 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template #label>{{ i18n.ts.name }}</template> </MkInput> - <MkTextarea v-model="description"> + <MkTextarea v-model="description" mfmAutocomplete :mfmPreview="true"> <template #label>{{ i18n.ts.description }}</template> </MkTextarea> @@ -70,7 +70,6 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { computed, ref, watch, defineAsyncComponent } from 'vue'; -import MkTextarea from '@/components/MkTextarea.vue'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import MkColorInput from '@/components/MkColorInput.vue'; @@ -81,6 +80,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js'; import { i18n } from '@/i18n.js'; import MkFolder from '@/components/MkFolder.vue'; import MkSwitch from '@/components/MkSwitch.vue'; +import MkTextarea from '@/components/MkTextarea.vue'; const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default)); diff --git a/packages/frontend/src/pages/clip.vue b/packages/frontend/src/pages/clip.vue index 2ea0312c7e..3c94db82d7 100644 --- a/packages/frontend/src/pages/clip.vue +++ b/packages/frontend/src/pages/clip.vue @@ -101,6 +101,7 @@ const headerActions = computed(() => clip.value && isOwned.value ? [{ type: 'string', required: false, multiline: true, + treatAsMfm: true, label: i18n.ts.description, default: clip.value.description, }, diff --git a/packages/frontend/src/pages/my-clips/index.vue b/packages/frontend/src/pages/my-clips/index.vue index 2390617954..85c016187d 100644 --- a/packages/frontend/src/pages/my-clips/index.vue +++ b/packages/frontend/src/pages/my-clips/index.vue @@ -60,6 +60,7 @@ async function create() { type: 'string', required: false, multiline: true, + treatAsMfm: true, label: i18n.ts.description, }, isPublic: { diff --git a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue index 4f47a77bdd..643e8ecdad 100644 --- a/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue +++ b/packages/frontend/src/pages/page-editor/els/page-editor.el.text.vue @@ -9,16 +9,17 @@ SPDX-License-Identifier: AGPL-3.0-only <template #header><i class="ti ti-align-left"></i> {{ i18n.ts._pages.blocks.text }}</template> <section> - <textarea v-model="text" :class="$style.textarea"></textarea> + <textarea ref="inputEl" v-model="text" :class="$style.textarea"></textarea> </section> </XContainer> </template> <script lang="ts" setup> /* eslint-disable vue/no-mutating-props */ -import { watch, ref } from 'vue'; +import { watch, ref, shallowRef, onMounted, onUnmounted } from 'vue'; import XContainer from '../page-editor.container.vue'; import { i18n } from '@/i18n.js'; +import { Autocomplete } from '@/scripts/autocomplete.js'; const props = defineProps<{ modelValue: any @@ -28,7 +29,10 @@ const emit = defineEmits<{ (ev: 'update:modelValue', value: any): void; }>(); +let autocomplete: Autocomplete; + const text = ref(props.modelValue.text ?? ''); +const inputEl = shallowRef<HTMLTextAreaElement | null>(null); watch(text, () => { emit('update:modelValue', { @@ -36,6 +40,14 @@ watch(text, () => { text: text.value, }); }); + +onMounted(() => { + autocomplete = new Autocomplete(inputEl.value, text); +}); + +onUnmounted(() => { + autocomplete.detach(); +}); </script> <style lang="scss" module> diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index 5f0d1aee51..1381042c39 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -13,11 +13,11 @@ SPDX-License-Identifier: AGPL-3.0-only <MkButton primary rounded :class="$style.bannerEdit" @click="changeBanner">{{ i18n.ts._profile.changeBanner }}</MkButton> </div> - <MkInput v-model="profile.name" :max="30" manualSave> + <MkInput v-model="profile.name" :max="30" manualSave :mfmAutocomplete="['emoji']"> <template #label>{{ i18n.ts._profile.name }}</template> </MkInput> - <MkTextarea v-model="profile.description" :max="500" tall manualSave> + <MkTextarea v-model="profile.description" :max="500" tall manualSave mfmAutocomplete :mfmPreview="true" :nyaize="$i?.isCat ? 'respect' : undefined" :author="($i as Misskey.entities.UserLite)"> <template #label>{{ i18n.ts._profile.description }}</template> <template #caption>{{ i18n.ts._profile.youCanIncludeHashtags }}</template> </MkTextarea> @@ -112,10 +112,10 @@ SPDX-License-Identifier: AGPL-3.0-only <script lang="ts" setup> import { computed, reactive, ref, watch, defineAsyncComponent } from 'vue'; +import Misskey from 'misskey-js'; import XAvatarDecoration from './profile.avatar-decoration.vue'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; -import MkTextarea from '@/components/MkTextarea.vue'; import MkSwitch from '@/components/MkSwitch.vue'; import MkSelect from '@/components/MkSelect.vue'; import FormSplit from '@/components/form/split.vue'; @@ -130,6 +130,7 @@ import { definePageMetadata } from '@/scripts/page-metadata.js'; import { claimAchievement } from '@/scripts/achievements.js'; import { defaultStore } from '@/store.js'; import MkInfo from '@/components/MkInfo.vue'; +import MkTextarea from '@/components/MkTextarea.vue'; const Sortable = defineAsyncComponent(() => import('vuedraggable').then(x => x.default)); |