From 7bb43329bb20ee203020634d5df9e6a896b437da Mon Sep 17 00:00:00 2001 From: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com> Date: Wed, 13 Aug 2025 10:51:23 +0900 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20=E3=83=A1=E3=83=B3=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E8=A3=9C=E5=AE=8C=E3=81=AE=E3=81=9F=E3=82=81?= =?UTF-8?q?=E3=81=AE=E3=82=B5=E3=82=B8=E3=82=A7=E3=82=B9=E3=83=88=E3=81=8C?= =?UTF-8?q?=E6=AD=A3=E3=81=97=E3=81=8F=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=20(#16401)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): mention-syntax detection for autocomplete doesn't work properly * docs(changelog): update changelog --- CHANGELOG.md | 2 ++ packages/frontend/src/utility/autocomplete.ts | 36 ++++++++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2358bd84ac..b998dfee6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ - Fix: テーマエディタが動作しない問題を修正 - Fix: チャンネルのハイライトページにノートが表示されない問題を修正 - Fix: カラムの名前が正しくリスト/チャンネルの名前にならない問題を修正 +- Fix: 複数のメンションを1行に記述した場合に、サジェストが正しく表示されない問題を修正 +- Fix: メンションとしての条件を満たしていても、特定の条件(`-`が含まれる場合など)で正しくサジェストされない問題を一部修正 ### Server - Enhance: ノートの削除処理の効率化 diff --git a/packages/frontend/src/utility/autocomplete.ts b/packages/frontend/src/utility/autocomplete.ts index 1246c32554..82109af1a0 100644 --- a/packages/frontend/src/utility/autocomplete.ts +++ b/packages/frontend/src/utility/autocomplete.ts @@ -78,7 +78,10 @@ export class Autocomplete { const caretPos = Number(this.textarea.selectionStart); const text = this.text.substring(0, caretPos).split('\n').pop()!; - const mentionIndex = text.lastIndexOf('@'); + // メンションに含められる文字のみで構成された、最も末尾にある文字列を抽出 + const mentionCandidate = text.split(/[^a-zA-Z0-9_@.\-]+/).pop()!; + + const mentionIndex = mentionCandidate.lastIndexOf('@'); const hashtagIndex = text.lastIndexOf('#'); const emojiIndex = text.lastIndexOf(':'); const mfmTagIndex = text.lastIndexOf('$'); @@ -97,7 +100,7 @@ export class Autocomplete { const afterLastMfmParam = text.split(/\$\[[a-zA-Z]+/).pop(); - const isMention = mentionIndex !== -1; + const maybeMention = mentionIndex !== -1; const isHashtag = hashtagIndex !== -1; const isMfmParam = mfmParamIndex !== -1 && afterLastMfmParam?.includes('.') && !afterLastMfmParam.includes(' '); const isMfmTag = mfmTagIndex !== -1 && !isMfmParam; @@ -107,20 +110,27 @@ export class Autocomplete { let opened = false; - if (isMention && this.onlyType.includes('user')) { + if (maybeMention && this.onlyType.includes('user')) { // ユーザのサジェスト中に@を入力すると、その位置から新たにユーザ名を取りなおそうとしてしまう // この動きはリモートユーザのサジェストを阻害するので、@を検知したらその位置よりも前の@を探し、 // ホスト名を含むリモートのユーザ名を全て拾えるようにする - 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 === '') { - this.open('user', null); - opened = true; + const mentionIndexAlt = mentionCandidate.lastIndexOf('@', mentionIndex - 1); + + // @が連続している場合、1つ目を無視する + const mentionIndexLeft = (mentionIndexAlt !== -1 && mentionIndexAlt !== mentionIndex - 1) ? mentionIndexAlt : mentionIndex; + + // メンションを構成する条件を満たしているか確認する + const isMention = mentionIndexLeft === 0 || '_@.-'.includes(mentionCandidate[mentionIndexLeft - 1]); + + if (isMention) { + const username = mentionCandidate.substring(mentionIndexLeft + 1); + if (username !== '' && username.match(/^[a-zA-Z0-9_@.\-]+$/)) { + this.open('user', username); + opened = true; + } else if (username === '') { + this.open('user', null); + opened = true; + } } }