 d0b7c74fd1
			
		
	
	d0b7c74fd1
	
	
	
		
			
			* enhance(frontend): 検索からハッシュタグのページを開けるように
* fix(frontend): 照会で入力が`#`のみの場合は`/tags/`に遷移しないように
* docs(changelog): update changelog
* enhance(frontend): ユーザー検索からもハッシュタグのページを開けるように
* docs(changelog): update changelog
* enhance(frontend): 検索範囲等が指定されている時は照会/ハッシュタグページを開かないように
* enhance(frontend): 検索内容に空白が含まれている場合は照会/ハッシュタグページを開かないように
* docs(changelog): update changelog
* Revert "enhance(frontend): 検索範囲等が指定されている時は照会/ハッシュタグページを開かないように"
This reverts commit f84eecea96.
* enhance(frontend): 検索から照会/ハッシュタグページを開くかどうか確認するように
* docs(changelog): update changelog
* chore: fix lint
* docs(changelog): update changelog insertion position
* enhance(frontend): 検索から`@user@host`の形式で照会出来るように
* fix(frontend): 照会で入力が`@`のみの場合に`/@`に遷移しないように
* fix(backend): `users/search`において`@`から始まるqueryに対する処理が正しくなかった問題を修正
* docs(changelog): update changelog
* chore(backend): fix lint error
* fix(backend): more improvements for users/search when query startswith `@`
* chore: unify common conditions
* docs(changelog): refine changelog
* chore(backend): fix lint error
* MkInputをpreventに対応させ、enterの意図せぬ伝搬を防ぐ
* chore(frontend/search.user): use .prevent to prevent the propagation of enter instead of setTimeout
---------
Co-authored-by: samunohito <46447427+samunohito@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Co-authored-by: taichanne30 <dev@taichan.site>
		
	
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <!--
 | |
| SPDX-FileCopyrightText: syuilo and misskey-project
 | |
| SPDX-License-Identifier: AGPL-3.0-only
 | |
| -->
 | |
| 
 | |
| <template>
 | |
| <div class="_gaps">
 | |
| 	<div class="_gaps">
 | |
| 		<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter.prevent="search">
 | |
| 			<template #prefix><i class="ti ti-search"></i></template>
 | |
| 		</MkInput>
 | |
| 		<MkRadios v-model="searchOrigin" @update:modelValue="search()">
 | |
| 			<option value="combined">{{ i18n.ts.all }}</option>
 | |
| 			<option value="local">{{ i18n.ts.local }}</option>
 | |
| 			<option value="remote">{{ i18n.ts.remote }}</option>
 | |
| 		</MkRadios>
 | |
| 		<MkButton large primary gradate rounded @click="search">{{ i18n.ts.search }}</MkButton>
 | |
| 	</div>
 | |
| 
 | |
| 	<MkFoldableSection v-if="userPagination">
 | |
| 		<template #header>{{ i18n.ts.searchResult }}</template>
 | |
| 		<MkUserList :key="key" :pagination="userPagination"/>
 | |
| 	</MkFoldableSection>
 | |
| </div>
 | |
| </template>
 | |
| 
 | |
| <script lang="ts" setup>
 | |
| import { ref, toRef } from 'vue';
 | |
| import type { Endpoints } from 'misskey-js';
 | |
| import type { Paging } from '@/components/MkPagination.vue';
 | |
| import MkUserList from '@/components/MkUserList.vue';
 | |
| import MkInput from '@/components/MkInput.vue';
 | |
| import MkRadios from '@/components/MkRadios.vue';
 | |
| import MkButton from '@/components/MkButton.vue';
 | |
| import { i18n } from '@/i18n.js';
 | |
| import * as os from '@/os.js';
 | |
| import MkFoldableSection from '@/components/MkFoldableSection.vue';
 | |
| import { misskeyApi } from '@/scripts/misskey-api.js';
 | |
| import { useRouter } from '@/router/supplier.js';
 | |
| 
 | |
| const props = withDefaults(defineProps<{
 | |
|   query?: string,
 | |
|   origin?: Endpoints['users/search']['req']['origin'],
 | |
| }>(), {
 | |
| 	query: '',
 | |
| 	origin: 'combined',
 | |
| });
 | |
| 
 | |
| const router = useRouter();
 | |
| 
 | |
| const key = ref('');
 | |
| const searchQuery = ref(toRef(props, 'query').value);
 | |
| const searchOrigin = ref(toRef(props, 'origin').value);
 | |
| const userPagination = ref<Paging>();
 | |
| 
 | |
| async function search() {
 | |
| 	const query = searchQuery.value.toString().trim();
 | |
| 
 | |
| 	if (query == null || query === '') return;
 | |
| 
 | |
| 	//#region AP lookup
 | |
| 	if (query.startsWith('https://') && !query.includes(' ')) {
 | |
| 		const confirm = await os.confirm({
 | |
| 			type: 'info',
 | |
| 			text: i18n.ts.lookupConfirm,
 | |
| 		});
 | |
| 		if (!confirm.canceled) {
 | |
| 			const promise = misskeyApi('ap/show', {
 | |
| 				uri: query,
 | |
| 			});
 | |
| 
 | |
| 			os.promiseDialog(promise, null, null, i18n.ts.fetchingAsApObject);
 | |
| 
 | |
| 			const res = await promise;
 | |
| 
 | |
| 			if (res.type === 'User') {
 | |
| 				router.push(`/@${res.object.username}@${res.object.host}`);
 | |
| 			} else if (res.type === 'Note') {
 | |
| 				router.push(`/notes/${res.object.id}`);
 | |
| 			}
 | |
| 
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 	//#endregion
 | |
| 
 | |
| 	if (query.length > 1 && !query.includes(' ')) {
 | |
| 		if (query.startsWith('@')) {
 | |
| 			const confirm = await os.confirm({
 | |
| 				type: 'info',
 | |
| 				text: i18n.ts.lookupConfirm,
 | |
| 			});
 | |
| 			if (!confirm.canceled) {
 | |
| 				router.push(`/${query}`);
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if (query.startsWith('#')) {
 | |
| 			const confirm = await os.confirm({
 | |
| 				type: 'info',
 | |
| 				text: i18n.ts.openTagPageConfirm,
 | |
| 			});
 | |
| 			if (!confirm.canceled) {
 | |
| 				router.push(`/user-tags/${encodeURIComponent(query.substring(1))}`);
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	userPagination.value = {
 | |
| 		endpoint: 'users/search',
 | |
| 		limit: 10,
 | |
| 		params: {
 | |
| 			query: query,
 | |
| 			origin: searchOrigin.value,
 | |
| 		},
 | |
| 	};
 | |
| 
 | |
| 	key.value = query;
 | |
| }
 | |
| </script>
 |