From d87488a5f054a60632f0c484c84b0c10319946dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?= <46447427+samunohito@users.noreply.github.com> Date: Wed, 26 Feb 2025 10:51:23 +0900 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=81=AE=E3=82=B5=E3=82=B8=E3=82=A7=E3=82=B9=E3=83=88=E4=B8=AD?= =?UTF-8?q?=E3=81=AB@=E3=82=92=E5=85=A5=E5=8A=9B=E3=81=97=E3=81=A6?= =?UTF-8?q?=E3=82=82=E3=82=B5=E3=82=B8=E3=82=A7=E3=82=B9=E3=83=88=E7=B5=90?= =?UTF-8?q?=E6=9E=9C=E3=81=8C=E6=B6=88=E3=81=88=E3=81=AA=E3=81=84=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=20(#15435)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + .../frontend/src/components/MkAutocomplete.vue | 6 ++++-- packages/frontend/src/scripts/autocomplete.ts | 14 ++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ffce0bee..5066b95a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - Fix: 埋め込みプレイヤーから外部ページに移動できない問題を修正 - Fix: Play の再読込時に UI が以前の状態を引き継いでしまう問題を修正 `#14378` - Fix: カスタム絵文字管理画面(beta)にてisSensitive/localOnlyの絞り込みが上手くいかない問題の修正 ( #15445 ) +- Fix: ユーザのサジェスト中に@を入力してもサジェスト結果が消えないように `#14385` - Fix: CWの注釈が100文字を超えている場合、ノート投稿ボタンを非アクティブに ### Server diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue index 685dcb86e..33495c8af 100644 --- a/packages/frontend/src/components/MkAutocomplete.vue +++ b/packages/frontend/src/components/MkAutocomplete.vue @@ -49,6 +49,7 @@ import sanitizeHtml from 'sanitize-html'; import { emojilist, getEmojiName } from '@@/js/emojilist.js'; import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@@/js/emoji-base.js'; import { MFM_TAGS, MFM_PARAMS } from '@@/js/const.js'; +import type { EmojiDef } from '@/scripts/search-emoji.js'; import contains from '@/scripts/contains.js'; import { acct } from '@/filters/user.js'; import * as os from '@/os.js'; @@ -58,7 +59,6 @@ import { i18n } from '@/i18n.js'; import { miLocalStorage } from '@/local-storage.js'; import { customEmojis } from '@/custom-emojis.js'; import { searchEmoji } from '@/scripts/search-emoji.js'; -import type { EmojiDef } from '@/scripts/search-emoji.js'; const lib = emojilist.filter(x => x.category !== 'flags'); @@ -198,8 +198,10 @@ function exec() { users.value = JSON.parse(cache); fetching.value = false; } else { + const [username, host] = props.q.toString().split('@'); misskeyApi('users/search-by-username-and-host', { - username: props.q, + username: username, + host: host, limit: 10, detail: false, }).then(searchedUsers => { diff --git a/packages/frontend/src/scripts/autocomplete.ts b/packages/frontend/src/scripts/autocomplete.ts index 55015c90f..9a603b848 100644 --- a/packages/frontend/src/scripts/autocomplete.ts +++ b/packages/frontend/src/scripts/autocomplete.ts @@ -4,9 +4,9 @@ */ import { nextTick, ref, defineAsyncComponent } from 'vue'; -import type { Ref } from 'vue'; import getCaretCoordinates from 'textarea-caret'; import { toASCII } from 'punycode.js'; +import type { Ref } from 'vue'; import { popup } from '@/os.js'; export type SuggestionType = 'user' | 'hashtag' | 'emoji' | 'mfmTag' | 'mfmParam'; @@ -98,15 +98,21 @@ export class Autocomplete { const isMention = mentionIndex !== -1; const isHashtag = hashtagIndex !== -1; - const isMfmParam = mfmParamIndex !== -1 && afterLastMfmParam?.includes('.') && !afterLastMfmParam?.includes(' '); + const isMfmParam = mfmParamIndex !== -1 && afterLastMfmParam?.includes('.') && !afterLastMfmParam.includes(' '); const isMfmTag = mfmTagIndex !== -1 && !isMfmParam; const isEmoji = emojiIndex !== -1 && text.split(/:[a-z0-9_+\-]+:/).pop()!.includes(':'); let opened = false; if (isMention && this.onlyType.includes('user')) { - const username = text.substring(mentionIndex + 1); - if (username !== '' && username.match(/^[a-zA-Z0-9_]+$/)) { + // ユーザのサジェスト中に@を入力すると、その位置から新たにユーザ名を取りなおそうとしてしまう + // この動きはリモートユーザのサジェストを阻害するので、@を検知したらその位置よりも前の@を探し、 + // ホスト名を含むリモートのユーザ名を全て拾えるようにする + const mentionIndexAlt = text.lastIndexOf('@', mentionIndex - 1); + const username = mentionIndexAlt === -1 + ? text.substring(mentionIndex + 1) + : text.substring(mentionIndexAlt + 1); + if (username !== '' && username.match(/^[a-zA-Z0-9_@.]+$/)) { this.open('user', username); opened = true; } else if (username === '') {