mirror of
https://github.com/paricafe/misskey.git
synced 2025-02-17 13:37:29 -06:00
emojiAutoSpacing
This commit is contained in:
parent
fdd190ec75
commit
3aa0a5ea9b
2 changed files with 65 additions and 42 deletions
|
@ -996,49 +996,54 @@ function insertMention() {
|
|||
}
|
||||
|
||||
async function insertEmoji(ev: MouseEvent) {
|
||||
textAreaReadOnly.value = true;
|
||||
const target = ev.currentTarget ?? ev.target;
|
||||
if (target == null) return;
|
||||
textAreaReadOnly.value = true;
|
||||
const target = ev.currentTarget ?? ev.target;
|
||||
if (target == null) return;
|
||||
|
||||
// emojiPickerはダイアログが閉じずにtextareaとやりとりするので、
|
||||
// focustrapをかけているとinsertTextAtCursorが効かない
|
||||
// そのため、投稿フォームのテキストに直接注入する
|
||||
// See: https://github.com/misskey-dev/misskey/pull/14282
|
||||
// https://github.com/misskey-dev/misskey/issues/14274
|
||||
// emojiPickerはダイアログが閉じずにtextareaとやりとりするので、
|
||||
// focustrapをかけているとinsertTextAtCursorが効かない
|
||||
// そのため、投稿フォームのテキストに直接注入する
|
||||
// See: https://github.com/misskey-dev/misskey/pull/14282
|
||||
// https://github.com/misskey-dev/misskey/issues/14274
|
||||
|
||||
let pos = textareaEl.value?.selectionStart ?? 0;
|
||||
let posEnd = textareaEl.value?.selectionEnd ?? text.value.length;
|
||||
let pos = textareaEl.value?.selectionStart ?? 0;
|
||||
let posEnd = textareaEl.value?.selectionEnd ?? text.value.length;
|
||||
|
||||
const addSpacing = (before: string, emoji: string) => {
|
||||
let result = emoji;
|
||||
const needSpaceBefore = before.length > 0 && !before.endsWith(' ');
|
||||
const addSpacing = (before: string, after: string, emoji: string) => {
|
||||
let result = emoji;
|
||||
const needSpaceBefore = before.length > 0 && !before.endsWith(' ');
|
||||
const needSpaceAfter = !after.startsWith(' ');
|
||||
|
||||
if (needSpaceBefore) result = ' ' + result;
|
||||
result = result + ' ';
|
||||
if (needSpaceBefore) result = ' ' + result;
|
||||
if (needSpaceAfter) result = result + ' ';
|
||||
|
||||
return result;
|
||||
return {
|
||||
text: result,
|
||||
addedSpaces: (needSpaceBefore ? 1 : 0) + (needSpaceAfter ? 1 : 0),
|
||||
};
|
||||
};
|
||||
|
||||
emojiPicker.show(
|
||||
target as HTMLElement,
|
||||
emoji => {
|
||||
const textBefore = text.value.substring(0, pos);
|
||||
const textAfter = text.value.substring(posEnd);
|
||||
emojiPicker.show(
|
||||
target as HTMLElement,
|
||||
(emoji) => {
|
||||
const textBefore = text.value.substring(0, pos);
|
||||
const textAfter = text.value.substring(posEnd);
|
||||
|
||||
const processedEmoji = defaultStore.state.emojiAutoSpacing
|
||||
? addSpacing(textBefore, emoji)
|
||||
: emoji + ' ';
|
||||
const processed = defaultStore.state.emojiAutoSpacing
|
||||
? addSpacing(textBefore, textAfter, emoji)
|
||||
: { text: emoji + ' ', addedSpaces: 1 };
|
||||
|
||||
text.value = textBefore + processedEmoji + textAfter;
|
||||
text.value = textBefore + processed.text + textAfter;
|
||||
|
||||
pos += processedEmoji.length;
|
||||
posEnd += processedEmoji.length;
|
||||
},
|
||||
() => {
|
||||
textAreaReadOnly.value = false;
|
||||
nextTick(() => focus());
|
||||
},
|
||||
);
|
||||
const newPos = pos + emoji.length + processed.addedSpaces;
|
||||
pos = newPos;
|
||||
posEnd = newPos;
|
||||
},
|
||||
() => {
|
||||
textAreaReadOnly.value = false;
|
||||
nextTick(() => focus());
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async function insertMfmFunction(ev: MouseEvent) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import { nextTick, Ref, ref, defineAsyncComponent } from 'vue';
|
|||
import getCaretCoordinates from 'textarea-caret';
|
||||
import { toASCII } from 'punycode/';
|
||||
import { popup } from '@/os.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
|
||||
export type SuggestionType = 'user' | 'hashtag' | 'emoji' | 'mfmTag' | 'mfmParam';
|
||||
|
||||
|
@ -265,20 +266,37 @@ export class Autocomplete {
|
|||
});
|
||||
} else if (type === 'emoji') {
|
||||
const source = this.text;
|
||||
|
||||
const before = source.substring(0, caret);
|
||||
const trimmedBefore = before.substring(0, before.lastIndexOf(':'));
|
||||
const after = source.substring(caret);
|
||||
|
||||
// 挿入
|
||||
this.text = trimmedBefore + value + after;
|
||||
if (defaultStore.state.emojiAutoSpacing) {
|
||||
const needSpaceBefore = trimmedBefore.length > 0 && !trimmedBefore.endsWith(' ');
|
||||
const needSpaceAfter = !after.startsWith(' ');
|
||||
|
||||
// キャレットを戻す
|
||||
nextTick(() => {
|
||||
this.textarea.focus();
|
||||
const pos = trimmedBefore.length + value.length;
|
||||
this.textarea.setSelectionRange(pos, pos);
|
||||
});
|
||||
this.text = trimmedBefore +
|
||||
(needSpaceBefore ? ' ' : '') +
|
||||
value +
|
||||
(needSpaceAfter ? ' ' : '') +
|
||||
after;
|
||||
|
||||
nextTick(() => {
|
||||
this.textarea.focus();
|
||||
const pos = trimmedBefore.length +
|
||||
(needSpaceBefore ? 1 : 0) +
|
||||
value.length +
|
||||
(needSpaceAfter ? 1 : 0);
|
||||
this.textarea.setSelectionRange(pos, pos);
|
||||
});
|
||||
} else {
|
||||
this.text = trimmedBefore + value + after;
|
||||
|
||||
nextTick(() => {
|
||||
this.textarea.focus();
|
||||
const pos = trimmedBefore.length + value.length;
|
||||
this.textarea.setSelectionRange(pos, pos);
|
||||
});
|
||||
}
|
||||
} else if (type === 'mfmTag') {
|
||||
const source = this.text;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue