Feat: アバターデコレーションの検索機能
This commit is contained in:
parent
be2626ea0d
commit
5320e6db77
|
@ -28,7 +28,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<MkButton danger @click="detachAllDecorations">{{ i18n.ts.detachAll }}</MkButton>
|
<MkButton danger @click="detachAllDecorations">{{ i18n.ts.detachAll }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
|
<MkInput v-model="q" :placeholder="i18n.ts.search"/>
|
||||||
|
<div v-if="searchResult.length > 0" :class="$style.decorations">
|
||||||
|
<span> {{ i18n.ts.searchResult }}</span><br>
|
||||||
|
<XDecoration
|
||||||
|
v-for="avatarDecoration in searchResult"
|
||||||
|
:key="avatarDecoration.name"
|
||||||
|
:decoration="avatarDecoration"
|
||||||
|
@click="openDecoration(avatarDecoration)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div v-for="category in categories">
|
<div v-for="category in categories">
|
||||||
<MkFoldableSection :defaultOpen="false">
|
<MkFoldableSection :defaultOpen="false">
|
||||||
<template #header> {{ (category !== '') ? category : i18n.ts.other }}</template>
|
<template #header> {{ (category !== '') ? category : i18n.ts.other }}</template>
|
||||||
|
@ -51,7 +60,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, defineAsyncComponent, computed } from 'vue';
|
import { ref, defineAsyncComponent, computed, watch } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
import XDecoration from './avatar-decoration.decoration.vue';
|
import XDecoration from './avatar-decoration.decoration.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
|
@ -62,12 +71,62 @@ import { signinRequired } from '@/account.js';
|
||||||
import MkInfo from '@/components/MkInfo.vue';
|
import MkInfo from '@/components/MkInfo.vue';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||||
|
import MkInput from '@/components/MkInput.vue';
|
||||||
|
|
||||||
const $i = signinRequired();
|
const $i = signinRequired();
|
||||||
|
const searchResult = ref([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const avatarDecorations = ref<Misskey.entities.GetAvatarDecorationsResponse & { category:string }>([]);
|
const avatarDecorations = ref<Misskey.entities.GetAvatarDecorationsResponse & { category:string }>([]);
|
||||||
|
const q = ref<string>('');
|
||||||
|
watch(() => q.value, () => {
|
||||||
|
const searchCustom = () => {
|
||||||
|
const max = 100;
|
||||||
|
const matches = new Set();
|
||||||
|
const decos = avatarDecorations.value;
|
||||||
|
const exactMatch = decos.find(avatarDecoration => avatarDecoration.name === q.value);
|
||||||
|
if (exactMatch) matches.add(exactMatch);
|
||||||
|
|
||||||
|
if (decos.includes(' ')) { // AND検索
|
||||||
|
const keywords = q.value.split(' ');
|
||||||
|
|
||||||
|
// 名前にキーワードが含まれている
|
||||||
|
for (const deco of decos) {
|
||||||
|
if (keywords.every(keyword => deco.name.includes(keyword))) {
|
||||||
|
matches.add(deco);
|
||||||
|
if (matches.size >= max) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matches.size >= max) return matches;
|
||||||
|
|
||||||
|
// 名前またはエイリアスにキーワードが含まれている
|
||||||
|
for (const deco of decos) {
|
||||||
|
if (keywords.every(keyword => deco.name.includes(keyword))) {
|
||||||
|
matches.add(deco);
|
||||||
|
if (matches.size >= max) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const deco of decos) {
|
||||||
|
if (deco.name.startsWith(q.value)) {
|
||||||
|
matches.add(deco);
|
||||||
|
if (matches.size >= max) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matches.size >= max) return matches;
|
||||||
|
|
||||||
|
for (const deco of decos) {
|
||||||
|
if (deco.name.includes(q.value)) {
|
||||||
|
matches.add(deco);
|
||||||
|
if (matches.size >= max) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matches.size >= max) return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
};
|
||||||
|
searchResult.value = Array.from(searchCustom());
|
||||||
|
});
|
||||||
misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
|
misskeyApi('get-avatar-decorations').then(_avatarDecorations => {
|
||||||
avatarDecorations.value = _avatarDecorations;
|
avatarDecorations.value = _avatarDecorations;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|
Loading…
Reference in a new issue