kopia lustrzana https://github.com/cheeaun/phanpy
Make custom emoji picker work for poll fields
rodzic
a7bb3e49f7
commit
0128524970
|
@ -42,6 +42,7 @@ function ComposePoll({
|
|||
lang={lang}
|
||||
spellCheck="true"
|
||||
dir="auto"
|
||||
data-allow-custom-emoji="true"
|
||||
onInput={(e) => {
|
||||
const { value } = e.target;
|
||||
options[i] = value;
|
||||
|
|
|
@ -184,6 +184,59 @@ function Compose({
|
|||
textareaRef.current?.focus();
|
||||
}, 300);
|
||||
};
|
||||
const insertTextAtCursor = ({ targetElement, text }) => {
|
||||
if (!targetElement) return;
|
||||
|
||||
const { selectionStart, selectionEnd, value } = targetElement;
|
||||
let textBeforeInsert = value.slice(0, selectionStart);
|
||||
|
||||
// Remove zero-width space from end of text
|
||||
textBeforeInsert = textBeforeInsert.replace(/\u200B$/, '');
|
||||
|
||||
const spaceBeforeInsert = textBeforeInsert
|
||||
? /[\s\t\n\r]$/.test(textBeforeInsert)
|
||||
? ''
|
||||
: ' '
|
||||
: '';
|
||||
|
||||
const textAfterInsert = value.slice(selectionEnd);
|
||||
const spaceAfterInsert = /^[\s\t\n\r]/.test(textAfterInsert) ? '' : ' ';
|
||||
|
||||
const newText =
|
||||
textBeforeInsert +
|
||||
spaceBeforeInsert +
|
||||
text +
|
||||
spaceAfterInsert +
|
||||
textAfterInsert;
|
||||
|
||||
targetElement.value = newText;
|
||||
targetElement.selectionStart = targetElement.selectionEnd =
|
||||
selectionEnd + text.length + spaceAfterInsert.length;
|
||||
targetElement.focus();
|
||||
targetElement.dispatchEvent(new Event('input'));
|
||||
};
|
||||
|
||||
const lastFocusedEmojiFieldRef = useRef(null);
|
||||
const composeContainerRef = useRef(null);
|
||||
useEffect(() => {
|
||||
const handleFocus = (e) => {
|
||||
const target = e.target;
|
||||
if (target.hasAttribute('data-allow-custom-emoji')) {
|
||||
lastFocusedEmojiFieldRef.current = target;
|
||||
}
|
||||
};
|
||||
|
||||
const composeContainer = composeContainerRef.current;
|
||||
if (composeContainer) {
|
||||
composeContainer.addEventListener('focusin', handleFocus);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (composeContainer) {
|
||||
composeContainer.removeEventListener('focusin', handleFocus);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (replyToStatus) {
|
||||
|
@ -693,7 +746,7 @@ function Compose({
|
|||
};
|
||||
|
||||
return (
|
||||
<div id="compose-container-outer">
|
||||
<div id="compose-container-outer" ref={composeContainerRef}>
|
||||
<div id="compose-container" class={standalone ? 'standalone' : ''}>
|
||||
<div class="compose-top">
|
||||
{currentAccountInfo?.avatarStatic && (
|
||||
|
@ -1180,6 +1233,7 @@ function Compose({
|
|||
</div>
|
||||
<Textarea
|
||||
ref={textareaRef}
|
||||
data-allow-custom-emoji="true"
|
||||
placeholder={
|
||||
replyToStatus
|
||||
? t`Post your reply`
|
||||
|
@ -1208,6 +1262,7 @@ function Compose({
|
|||
onTrigger={(action) => {
|
||||
if (action?.name === 'custom-emojis') {
|
||||
setShowEmoji2Picker({
|
||||
targetElement: lastFocusedEmojiFieldRef,
|
||||
defaultSearchTerm: action?.defaultSearchTerm || null,
|
||||
});
|
||||
} else if (action?.name === 'mention') {
|
||||
|
@ -1372,7 +1427,9 @@ function Compose({
|
|||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setShowEmoji2Picker(true);
|
||||
setShowEmoji2Picker({
|
||||
targetElement: lastFocusedEmojiFieldRef,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Icon icon="emoji2" />{' '}
|
||||
|
@ -1453,7 +1510,9 @@ function Compose({
|
|||
class="toolbar-button"
|
||||
disabled={uiState === 'loading'}
|
||||
onClick={() => {
|
||||
setShowEmoji2Picker(true);
|
||||
setShowEmoji2Picker({
|
||||
targetElement: lastFocusedEmojiFieldRef,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Icon icon="emoji2" alt={_(ADD_LABELS.customEmoji)} />
|
||||
|
@ -1588,36 +1647,12 @@ function Compose({
|
|||
defaultSearchTerm={showMentionPicker?.defaultSearchTerm}
|
||||
onSelect={(socialAddress) => {
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) return;
|
||||
const { selectionStart, selectionEnd } = textarea;
|
||||
const text = textarea.value;
|
||||
let textBeforeMention = text.slice(0, selectionStart);
|
||||
// Remove zero-width space from end of text
|
||||
textBeforeMention = textBeforeMention.replace(/\u200B$/, '');
|
||||
const spaceBeforeMention = textBeforeMention
|
||||
? /[\s\t\n\r]$/.test(textBeforeMention)
|
||||
? ''
|
||||
: ' '
|
||||
: '';
|
||||
const textAfterMention = text.slice(selectionEnd);
|
||||
const spaceAfterMention = /^[\s\t\n\r]/.test(textAfterMention)
|
||||
? ''
|
||||
: ' ';
|
||||
const newText =
|
||||
textBeforeMention +
|
||||
spaceBeforeMention +
|
||||
'@' +
|
||||
socialAddress +
|
||||
spaceAfterMention +
|
||||
textAfterMention;
|
||||
textarea.value = newText;
|
||||
textarea.selectionStart = textarea.selectionEnd =
|
||||
selectionEnd +
|
||||
1 +
|
||||
socialAddress.length +
|
||||
spaceAfterMention.length;
|
||||
textarea.focus();
|
||||
textarea.dispatchEvent(new Event('input'));
|
||||
if (textarea) {
|
||||
insertTextAtCursor({
|
||||
targetElement: textarea,
|
||||
text: '@' + socialAddress,
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
|
@ -1636,33 +1671,11 @@ function Compose({
|
|||
}}
|
||||
defaultSearchTerm={showEmoji2Picker?.defaultSearchTerm}
|
||||
onSelect={(emojiShortcode) => {
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) return;
|
||||
const { selectionStart, selectionEnd } = textarea;
|
||||
const text = textarea.value;
|
||||
let textBeforeEmoji = text.slice(0, selectionStart);
|
||||
// Remove zero-width space from end of text
|
||||
textBeforeEmoji = textBeforeEmoji.replace(/\u200B$/, '');
|
||||
const spaceBeforeEmoji = textBeforeEmoji
|
||||
? /[\s\t\n\r]$/.test(textBeforeEmoji)
|
||||
? ''
|
||||
: ' '
|
||||
: '';
|
||||
const textAfterEmoji = text.slice(selectionEnd);
|
||||
const spaceAfterEmoji = /^[\s\t\n\r]/.test(textAfterEmoji)
|
||||
? ''
|
||||
: ' ';
|
||||
const newText =
|
||||
textBeforeEmoji +
|
||||
spaceBeforeEmoji +
|
||||
emojiShortcode +
|
||||
spaceAfterEmoji +
|
||||
textAfterEmoji;
|
||||
textarea.value = newText;
|
||||
textarea.selectionStart = textarea.selectionEnd =
|
||||
selectionEnd + emojiShortcode.length + spaceAfterEmoji.length;
|
||||
textarea.focus();
|
||||
textarea.dispatchEvent(new Event('input'));
|
||||
const targetElement =
|
||||
showEmoji2Picker?.targetElement?.current || textareaRef.current;
|
||||
if (targetElement) {
|
||||
insertTextAtCursor({ targetElement, text: emojiShortcode });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
|
|
|
@ -248,7 +248,7 @@ msgstr "View post stats"
|
|||
|
||||
#: src/components/account-sheet.jsx:38
|
||||
#: src/components/add-remove-lists-sheet.jsx:45
|
||||
#: src/components/compose.jsx:779
|
||||
#: src/components/compose.jsx:832
|
||||
#: src/components/custom-emojis-modal.jsx:234
|
||||
#: src/components/drafts.jsx:57
|
||||
#: src/components/edit-profile-sheet.jsx:87
|
||||
|
@ -358,7 +358,7 @@ msgstr "Add to thread"
|
|||
msgid "Choice {0}"
|
||||
msgstr "Choice {0}"
|
||||
|
||||
#: src/components/compose-poll.jsx:60
|
||||
#: src/components/compose-poll.jsx:61
|
||||
#: src/components/media-attachment.jsx:300
|
||||
#: src/components/shortcuts-settings.jsx:726
|
||||
#: src/pages/catchup.jsx:1081
|
||||
|
@ -366,15 +366,15 @@ msgstr "Choice {0}"
|
|||
msgid "Remove"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose-poll.jsx:88
|
||||
#: src/components/compose-poll.jsx:89
|
||||
msgid "Multiple choices"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose-poll.jsx:91
|
||||
#: src/components/compose-poll.jsx:92
|
||||
msgid "Duration"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose-poll.jsx:122
|
||||
#: src/components/compose-poll.jsx:123
|
||||
msgid "Remove poll"
|
||||
msgstr ""
|
||||
|
||||
|
@ -408,152 +408,152 @@ msgstr ""
|
|||
msgid "Schedule post"
|
||||
msgstr "Schedule post"
|
||||
|
||||
#: src/components/compose.jsx:304
|
||||
#: src/components/compose.jsx:357
|
||||
msgid "You have unsaved changes. Discard this post?"
|
||||
msgstr "You have unsaved changes. Discard this post?"
|
||||
|
||||
#. placeholder {0}: unsupportedFiles.length
|
||||
#. placeholder {1}: unsupportedFiles[0].name
|
||||
#. placeholder {2}: lf.format( unsupportedFiles.map((f) => f.name), )
|
||||
#: src/components/compose.jsx:542
|
||||
#: src/components/compose.jsx:595
|
||||
msgid "{0, plural, one {File {1} is not supported.} other {Files {2} are not supported.}}"
|
||||
msgstr "{0, plural, one {File {1} is not supported.} other {Files {2} are not supported.}}"
|
||||
|
||||
#: src/components/compose.jsx:552
|
||||
#: src/components/compose.jsx:570
|
||||
#: src/components/compose.jsx:1682
|
||||
#: src/components/compose.jsx:605
|
||||
#: src/components/compose.jsx:623
|
||||
#: src/components/compose.jsx:1695
|
||||
#: src/components/file-picker-input.jsx:38
|
||||
msgid "{maxMediaAttachments, plural, one {You can only attach up to 1 file.} other {You can only attach up to # files.}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:760
|
||||
#: src/components/compose.jsx:813
|
||||
msgid "Pop out"
|
||||
msgstr "Pop out"
|
||||
|
||||
#: src/components/compose.jsx:767
|
||||
#: src/components/compose.jsx:820
|
||||
msgid "Minimize"
|
||||
msgstr "Minimize"
|
||||
|
||||
#: src/components/compose.jsx:803
|
||||
#: src/components/compose.jsx:856
|
||||
msgid "Looks like you closed the parent window."
|
||||
msgstr "Looks like you closed the parent window."
|
||||
|
||||
#: src/components/compose.jsx:810
|
||||
#: src/components/compose.jsx:863
|
||||
msgid "Looks like you already have a compose field open in the parent window and currently publishing. Please wait for it to be done and try again later."
|
||||
msgstr "Looks like you already have a compose field open in the parent window and currently publishing. Please wait for it to be done and try again later."
|
||||
|
||||
#: src/components/compose.jsx:815
|
||||
#: src/components/compose.jsx:868
|
||||
msgid "Looks like you already have a compose field open in the parent window. Popping in this window will discard the changes you made in the parent window. Continue?"
|
||||
msgstr "Looks like you already have a compose field open in the parent window. Popping in this window will discard the changes you made in the parent window. Continue?"
|
||||
|
||||
#: src/components/compose.jsx:858
|
||||
#: src/components/compose.jsx:911
|
||||
msgid "Pop in"
|
||||
msgstr "Pop in"
|
||||
|
||||
#. placeholder {0}: replyToStatus.account.acct || replyToStatus.account.username
|
||||
#. placeholder {1}: rtf.format(-replyToStatusMonthsAgo, 'month')
|
||||
#: src/components/compose.jsx:868
|
||||
#: src/components/compose.jsx:921
|
||||
msgid "Replying to @{0}’s post (<0>{1}</0>)"
|
||||
msgstr ""
|
||||
|
||||
#. placeholder {0}: replyToStatus.account.acct || replyToStatus.account.username
|
||||
#: src/components/compose.jsx:878
|
||||
#: src/components/compose.jsx:931
|
||||
msgid "Replying to @{0}’s post"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:891
|
||||
#: src/components/compose.jsx:944
|
||||
msgid "Editing source post"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:944
|
||||
#: src/components/compose.jsx:997
|
||||
msgid "Poll must have at least 2 options"
|
||||
msgstr "Poll must have at least 2 options"
|
||||
|
||||
#: src/components/compose.jsx:948
|
||||
#: src/components/compose.jsx:1001
|
||||
msgid "Some poll choices are empty"
|
||||
msgstr "Some poll choices are empty"
|
||||
|
||||
#: src/components/compose.jsx:961
|
||||
#: src/components/compose.jsx:1014
|
||||
msgid "Some media have no descriptions. Continue?"
|
||||
msgstr "Some media have no descriptions. Continue?"
|
||||
|
||||
#: src/components/compose.jsx:1013
|
||||
#: src/components/compose.jsx:1066
|
||||
msgid "Attachment #{i} failed"
|
||||
msgstr "Attachment #{i} failed"
|
||||
|
||||
#: src/components/compose.jsx:1109
|
||||
#: src/components/compose.jsx:1162
|
||||
#: src/components/status.jsx:2103
|
||||
#: src/components/timeline.jsx:1015
|
||||
msgid "Content warning"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1125
|
||||
#: src/components/compose.jsx:1178
|
||||
msgid "Content warning or sensitive media"
|
||||
msgstr "Content warning or sensitive media"
|
||||
|
||||
#: src/components/compose.jsx:1161
|
||||
#: src/components/compose.jsx:1214
|
||||
#: src/components/status.jsx:87
|
||||
#: src/pages/settings.jsx:318
|
||||
msgid "Public"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1166
|
||||
#: src/components/compose.jsx:1219
|
||||
#: src/components/nav-menu.jsx:349
|
||||
#: src/components/shortcuts-settings.jsx:165
|
||||
#: src/components/status.jsx:88
|
||||
msgid "Local"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1170
|
||||
#: src/components/compose.jsx:1223
|
||||
#: src/components/status.jsx:89
|
||||
#: src/pages/settings.jsx:321
|
||||
msgid "Unlisted"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1173
|
||||
#: src/components/compose.jsx:1226
|
||||
#: src/components/status.jsx:90
|
||||
#: src/pages/settings.jsx:324
|
||||
msgid "Followers only"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1176
|
||||
#: src/components/compose.jsx:1229
|
||||
#: src/components/status.jsx:91
|
||||
#: src/components/status.jsx:1983
|
||||
msgid "Private mention"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1185
|
||||
#: src/components/compose.jsx:1239
|
||||
msgid "Post your reply"
|
||||
msgstr "Post your reply"
|
||||
|
||||
#: src/components/compose.jsx:1187
|
||||
#: src/components/compose.jsx:1241
|
||||
msgid "Edit your post"
|
||||
msgstr "Edit your post"
|
||||
|
||||
#: src/components/compose.jsx:1188
|
||||
#: src/components/compose.jsx:1242
|
||||
msgid "What are you doing?"
|
||||
msgstr "What are you doing?"
|
||||
|
||||
#: src/components/compose.jsx:1267
|
||||
#: src/components/compose.jsx:1322
|
||||
msgid "Mark media as sensitive"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1304
|
||||
#: src/components/compose.jsx:1359
|
||||
msgid "Posting on <0/>"
|
||||
msgstr "Posting on <0/>"
|
||||
|
||||
#: src/components/compose.jsx:1335
|
||||
#: src/components/compose.jsx:1390
|
||||
#: src/components/mention-modal.jsx:220
|
||||
#: src/components/shortcuts-settings.jsx:715
|
||||
#: src/pages/list.jsx:388
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1563
|
||||
#: src/components/compose.jsx:1622
|
||||
msgid "Schedule"
|
||||
msgstr "Schedule"
|
||||
|
||||
#: src/components/compose.jsx:1565
|
||||
#: src/components/compose.jsx:1624
|
||||
#: src/components/keyboard-shortcuts-help.jsx:155
|
||||
#: src/components/status.jsx:965
|
||||
#: src/components/status.jsx:1751
|
||||
|
@ -562,20 +562,20 @@ msgstr "Schedule"
|
|||
msgid "Reply"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/compose.jsx:1567
|
||||
#: src/components/compose.jsx:1626
|
||||
msgid "Update"
|
||||
msgstr "Update"
|
||||
|
||||
#: src/components/compose.jsx:1568
|
||||
#: src/components/compose.jsx:1627
|
||||
msgctxt "Submit button in composer"
|
||||
msgid "Post"
|
||||
msgstr "Post"
|
||||
|
||||
#: src/components/compose.jsx:1694
|
||||
#: src/components/compose.jsx:1707
|
||||
msgid "Downloading GIF…"
|
||||
msgstr "Downloading GIF…"
|
||||
|
||||
#: src/components/compose.jsx:1722
|
||||
#: src/components/compose.jsx:1735
|
||||
msgid "Failed to download GIF"
|
||||
msgstr "Failed to download GIF"
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue