検索からハッシュタグのページが開けるように、users/searchに@から始まる文字列が与えられた際の処理を修正 等 (#13858)

* 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>
This commit is contained in:
Sayamame-beans
2024-07-30 19:18:43 +09:00
committed by GitHub
parent 2307849c9a
commit d0b7c74fd1
8 changed files with 159 additions and 103 deletions

View File

@@ -79,7 +79,7 @@ const props = defineProps<{
const emit = defineEmits<{
(ev: 'change', _ev: KeyboardEvent): void;
(ev: 'keydown', _ev: KeyboardEvent): void;
(ev: 'enter'): void;
(ev: 'enter', _ev: KeyboardEvent): void;
(ev: 'update:modelValue', value: string | number): void;
}>();
@@ -111,7 +111,7 @@ const onKeydown = (ev: KeyboardEvent) => {
emit('keydown', ev);
if (ev.code === 'Enter') {
emit('enter');
emit('enter', ev);
}
};

View File

@@ -6,7 +6,7 @@ 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="search">
<MkInput v-model="searchQuery" :large="true" :autofocus="true" type="search" @enter.prevent="search">
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkFoldableSection :expanded="true">
@@ -143,25 +143,55 @@ async function search() {
if (query == null || query === '') return;
//#region AP lookup
if (query.startsWith('https://')) {
const promise = misskeyApi('ap/show', {
uri: query,
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);
os.promiseDialog(promise, null, null, i18n.ts.fetchingAsApObject);
const res = await promise;
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}`);
if (res.type === 'User') {
router.push(`/@${res.object.username}@${res.object.host}`);
} else if (res.type === 'Note') {
router.push(`/notes/${res.object.id}`);
}
return;
}
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(`/tags/${encodeURIComponent(query.substring(1))}`);
return;
}
}
}
notePagination.value = {
endpoint: 'notes/search',
limit: 10,

View File

@@ -6,7 +6,7 @@ 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="search">
<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()">
@@ -39,8 +39,8 @@ 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?: string,
origin?: Endpoints['users/search']['req']['origin'],
}>(), {
query: '',
origin: 'combined',
@@ -59,25 +59,55 @@ async function search() {
if (query == null || query === '') return;
//#region AP lookup
if (query.startsWith('https://')) {
const promise = misskeyApi('ap/show', {
uri: query,
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);
os.promiseDialog(promise, null, null, i18n.ts.fetchingAsApObject);
const res = await promise;
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}`);
if (res.type === 'User') {
router.push(`/@${res.object.username}@${res.object.host}`);
} else if (res.type === 'Note') {
router.push(`/notes/${res.object.id}`);
}
return;
}
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,

View File

@@ -16,7 +16,7 @@ export async function lookup(router?: Router) {
title: i18n.ts.lookup,
});
const query = temp ? temp.trim() : '';
if (canceled) return;
if (canceled || query.length <= 1) return;
if (query.startsWith('@') && !query.includes(' ')) {
_router.push(`/${query}`);