diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 561e1ed2f..741a5a619 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -718,6 +718,7 @@ fullView: "フルビュー"
quitFullView: "フルビュー解除"
addDescription: "説明を追加"
userPagePinTip: "個々のノートのメニューから「ピン留め」を選択することで、ここにノートを表示しておくことができます。"
+notSpecifiedMentionWarning: "宛先に含まれていないメンションがあります"
_email:
_follow:
diff --git a/src/client/components/post-form.vue b/src/client/components/post-form.vue
index ce79f34d6..4c6a9ebc9 100644
--- a/src/client/components/post-form.vue
+++ b/src/client/components/post-form.vue
@@ -34,6 +34,7 @@
+ {{ $ts.notSpecifiedMentionWarning }} -
@@ -71,12 +72,14 @@ import { selectFile } from '@client/scripts/select-file';
import { notePostInterruptors, postFormActions } from '@client/store';
import { isMobile } from '@client/scripts/is-mobile';
import { throttle } from 'throttle-debounce';
+import MkInfo from '@client/components/ui/info.vue';
export default defineComponent({
components: {
XNotePreview,
XPostFormAttaches: defineAsyncComponent(() => import('./post-form-attaches.vue')),
- XPollEditor: defineAsyncComponent(() => import('./poll-editor.vue'))
+ XPollEditor: defineAsyncComponent(() => import('./poll-editor.vue')),
+ MkInfo,
},
inject: ['modal'],
@@ -143,6 +146,7 @@ export default defineComponent({
autocomplete: null,
draghover: false,
quoteId: null,
+ hasNotSpecifiedMentions: false,
recentHashtags: JSON.parse(localStorage.getItem('hashtags') || '[]'),
imeText: '',
typing: throttle(3000, () => {
@@ -214,6 +218,18 @@ export default defineComponent({
}
},
+ watch: {
+ text() {
+ this.checkMissingMention();
+ },
+ visibleUsers: {
+ handler() {
+ this.checkMissingMention();
+ },
+ deep: true
+ }
+ },
+
mounted() {
if (this.initialText) {
this.text = this.initialText;
@@ -338,6 +354,32 @@ export default defineComponent({
this.$watch('localOnly', () => this.saveDraft());
},
+ checkMissingMention() {
+ if (this.visibility === 'specified') {
+ const ast = mfm.parse(this.text);
+
+ for (const x of extractMentions(ast)) {
+ if (!this.visibleUsers.some(u => (u.username === x.username) && (u.host == x.host))) {
+ this.hasNotSpecifiedMentions = true;
+ return;
+ }
+ }
+ this.hasNotSpecifiedMentions = false;
+ }
+ },
+
+ addMissingMention() {
+ const ast = mfm.parse(this.text);
+
+ for (const x of extractMentions(ast)) {
+ if (!this.visibleUsers.some(u => (u.username === x.username) && (u.host == x.host))) {
+ os.api('users/show', { username: x.username, host: x.host }).then(user => {
+ this.visibleUsers.push(user);
+ });
+ }
+ }
+ },
+
togglePoll() {
if (this.poll) {
this.poll = null;
@@ -741,6 +783,10 @@ export default defineComponent({
}
}
+ > .hasNotSpecifiedMentions {
+ margin: 0 20px 16px 20px;
+ }
+
> .cw,
> .text {
display: block;