Files
phanpy-cz/assets/compose-CUhufx8N.js.map
2025-11-09 08:49:49 +01:00

1 line
266 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"version":3,"mappings":"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","names":["ansiRegex","onlyFirst","pattern","regex","stripAnsi","string","segmenter","stringLength","countAnsiEscapeCodes","length","_","urlRegexObj","RegExp","urlRegex","source","flags","isMobileSafari","test","navigator","userAgent","CameraCaptureInput","hidden","disabled","supportedMimeTypes","setMediaAttachments","filteredSupportedMimeTypes","filter","mimeType","_jsx","type","accept","join","capture","onChange","e","files","target","mediaFile","Array","from","attachments","file","size","url","URL","createObjectURL","id","description","value","supportsCameraCapture","document","createElement","CharCountMeter","maxCharacters","charCount","useSnapshot","states","composerCharacterCount","leftChars","class","_jsxs","title","style","children","max","Combobox","input","list","tabInsertsSuggestions","defaultFirstOption","event","keyboardBindings","trackComposition","commitWithElement","_a","visible","indexDiff","focusEl","els","focusIndex","indexOfItem","newIndex","el","scrollTo","combobox","commit","fireCommitEvent","container","inViewport","element","scrollTop","containerBottom","top","bottom","boundary","query","text","key","cursor","multiWord","lookBackIndex","lastMatchPosition","keyIndex","pre","InputStyleCloneUpdateEvent","CloneRegistry","InputStyleClone","#styleObserver","#updateStyles","#resizeObserver","#requestUpdateLayout","#inputRef","#container","#cloneElement","clone","#updateText","#onDocumentScrollOrResize","#onInput","#input","#usingInput","fn","#xOffset","#yOffset","#updateLayout","inputStyle","inputRect","cloneRect","#isLayoutUpdating","prop","propertiesToCopy","InputRange","#inputElement","#startOffset","#endOffset","startOffset","endOffset","selectionStart","selectionEnd","offset","#clampOffset","toStart","#createCloneRange","#styleClone","range","textNode","TextExpander$2","expander","match","menu","_b","position","caretRect","targetPosition","currentPosition","delta","currentStyle","item","beginning","remaining","detail","suffix","found","providers","provide","result","changeEvent","x","TextExpanderElement","keysAttr","keys","multiWordAttr","globalMultiWord","state","TextExpander","_getCustomEmojis","instance","masto","visibleEmojis","v1","customEmojis","visibleInPicker","searcher","Fuse","findAllMatches","getCustomEmojis","pmem","matchesArg","cacheKeyArg","keyArg","maxAge","role","className","windowMargin","observer","IntersectionObserver","entries","forEach","entry","isIntersecting","left","width","boundingClientRect","innerWidth","window","insetInlineStart","isRTL","observe","encodeHTML","str","replace","char","charCodeAt","onTrigger","props","ref","t","_useLingui","textExpanderRef","useRef","api","searcherRef","textExpanderTextRef","hasTextExpanderRef","useImperativeHandle","setStyle","current","Object","assign","activated","useEffect","then","catch","console","textExpander","showMore","limit","results","html","emoji","shortcode","innerHTML","matched","resolve","searchResults","q","response","avatarStatic","name","displayName","username","acct","emojis","history","roles","accountInstance","displayNameWithEmoji","total","acc","cur","_t","error","more","continue","setTimeout","handleCommited","Event","handleActivate","handleDeactivate","handleChange","handleValue","addEventListener","removeEventListener","expiryOptions","i18nDuration","ComposePoll","lang","poll","onInput","maxOptions","maxExpiration","minExpiration","maxCharactersPerOption","options","expiresIn","multiple","map","option","i","required","maxlength","placeholder","values","0","spellCheck","autocomplete","dir","onClick","splice","push","checked","_Trans","label","USERNAME_RE","MENTION_RE","HASHTAG_RE","SHORTCODE_RE_FRAGMENT","SCAN_RE","Intl","Segmenter","highlightText","Infinity","withinLimitHTML","exceedLimitHTML","htmlSegments","segment","index","escapeHTML","autoResizeTextarea","textarea","offsetHeight","scrollHeight","clientHeight","innerHeight","height","detectLangs","langDetector","langs","detect","slice","detectedLanguage","detectAll","__vitePreload","Textarea","forwardRef","setText","useState","textareaProps","useThrottledResizeObserver","onResize","getBoundingClientRect","minHeight","slowHighlightPerf","composeHighlightRef","throttleHighlightText","useThrottledCallback","cancel","start","end","Date","now","debouncedAutoDetectLanguage","useDebouncedCallback","dom","mark","querySelectorAll","remove","text2","languages","autoCapitalize","autoComplete","autoCorrect","rows","cols","hasTextExpander","lastLine","textBeforeCursor","bullet","newBullet","number","preSpaces","anything","preventDefault","pos","postSpaces","setRangeText","setSelectionRange","dispatchEvent","onScroll","pastedText","CUSTOM_EMOJIS_COUNT","EMOJI_SIZE_MIN","EMOJI_SIZE_MAX","EMOJI_SIZE_STEP","CustomEmojiButton","memo","showCode","addEdges","parent","currentTarget","closest","rect","selfRect","targetClassList","classList","buffer","add","right","undefined","onPointerEnter","onFocus","staticUrl","srcSet","media","src","alt","loading","decoding","_Fragment","CustomEmojisList","onSelect","i18n","setMax","CUSTOM_EMOJI_SIZE","CustomEmojisModal","onClose","defaultSearchTerm","uiState","setUIState","customEmojisList","setCustomEmojis","recentlyUsedCustomEmojis","useMemo","store","account","get","customEmojisCatList","emojisCat","othersCat","category","scrollableRef","setMatches","onEmojiSizeDecrease","useCallback","emojiSize","setEmojiSize","newSize","Math","local","del","onEmojiSizeIncrease","onFind","onSelectEmoji","queueMicrotask","recentlyUsedCustomEmojis2","findIndex","unshift","emoji2","inputRef","focus","Icon","Loader","autocorrect","autocapitalize","matches","icon","FilePickerInput","maxMediaAttachments","mediaAttachments","mediaFiles","poweredByGiphyURL","PHANPY_GIPHY_API_KEY","GIPHY_API_KEY","import","GIFS_PER_PAGE","GIFPickerModal","setResults","formRef","qRef","currentOffset","fetchGIFs","behavior","api_key","rating","locale","r","fetch","referrerPolicy","debouncedOnInput","onSubmit","abrupt","gif","alt_text","images","fixed_height","original","fixed_height_small","fixed_height_downsampled","webp","urlObj","parse","strippedWebP","strippedURL","origin","webpObj","url2","theURL","mp4","srcset","referrerpolicy","onLoad","backgroundColor","pagination","PHANPY_IMG_ALT_API_URL","IMG_ALT_API_URL","scaleDimension","matrix","matrixLimit","scalingFactor","sqrt","newWidth","floor","newHeight","MediaAttachment","attachment","descriptionLimit","onDescriptionChange","onRemove","supportsEdit","supports","checkMaxError","imageSizeLimit","imageMatrixLimit","videoSizeLimit","videoMatrixLimit","videoFrameRateLimit","maxError","startsWith","imageMatrix","setImageMatrix","setMaxError","details","videoMatrix","setVideoMatrix","setDescription","suffixType","subtype","subTypeMap","Set","suffixTypes","debouncedOnDescriptionChange","setShowModal","timer","textareaRef","showModal","clearTimeout","descTextarea","image","video","audio","toastRef","hideToast","maxErrorText","err","maxErrorToast","imageSize","imageSizeLimit2","prettyBytes","imageMatrix2","imageMatrixLimit2","videoSize","videoSizeLimit2","videoMatrix2","videoMatrixLimit2","tabIndex","naturalHeight","naturalWidth","playsinline","muted","disablePictureInPicture","preload","onLoadedMetadata","videoHeight","videoWidth","controls","duration","Modal","Menu2","portal","zIndex","align","overflow","menuButton","MenuItem","body","method","showToast","message","params","components","MentionModal","accounts","setAccounts","relationshipsMap","setRelationshipsMap","selectedIndex","setSelectedIndex","loadRelationships","relationships","fetchRelationships","loadAccounts","term","search","debouncedLoadAccounts","useHotkeys","selectedAccount","selectAccount","enableOnFormTags","useKey","listRef","selectedItem","block","relationship","avatarSize","showStats","showActivity","QuoteSuggestion","quoteSuggestion","hasCurrentQuoteStatus","onAccept","onCancel","Status","status","readOnly","supportedLanguagesMap","supportedLanguages","reduce","l","code","common","native","expirySeconds","oneDay","expiresInFromExpiresAt","expiresAt","find","s","DEFAULT_LANG","localeMatch","getDtfLocale","usernameRegex","urlPlaceholder","countableText","inputText","LF","mem","ListFormat","ADD_LABELS","camera","customEmoji","sensitive","scheduledPost","DEFAULT_SCHEDULED_AT","MIN_SCHEDULED_AT","Compose","replyToStatus","replyMode","editStatus","draftStatus","quoteStatus","standalone","hasOpener","rtf","RTF","lf","UID","uid","currentAccount","currentAccountInfo","charactersReservedPerUrl","polls","supportedImagesVideosTypes","setQuoteApprovalPolicy","spoilerTextRef","visibility","setVisibility","quoteApprovalPolicy","prevLanguage","setSensitive","sensitiveMedia","setSensitiveMedia","language","setLanguage","scheduledAt","setScheduledAt","prefs","setQuoteSuggestion","currentQuoteStatus","setLocalQuoteStatus","checkQuoteEligibility","setQuoteCleared","getPreferences","quoteApproval","isSelf","isPublic","isMineAndPrivate","isQuoteAutomaticallyAccepted","isQuoteManuallyAccepted","handlePastedLink","supportsNativeQuote","unfurledData","unfurlMastodonLink","originalURL","focusTextarea","cursorPosition","targetElement","textBeforeInsert","spaceAfterInsert","textAfterInsert","lastFocusedFieldRef","spaceBeforeInsert","newText","focusLastFocusedField","handleFocus","composeContainerRef","lastFocusedEmojiFieldRef","composeContainer","isFormElement","spoilerText","visibility2","language2","sensitive2","mentions","authorMention","oninputTextarea","allMentions","otherMentions","m","composablePoll","o","statusSource","statuses","setPoll","postQuoteApprovalPolicy","alert","toLowerCase","policy","sensitiveMedia2","mediaAttachments2","scheduledAt2","quoteApprovalPolicy2","snapStates","beforeUnloadCopy","canClose","composerState","hasValue","hasMediaAttachments","hasOnlyAcct","confirmClose","hasIDMediaAttachments","handleBeforeUnload","sameWithSource","supportsCloseWatcher","escDownRef","yes","returnValue","hasModal","modals","hasOnlyComposer","getCharCount","useCloseWatcher","updateCharCount","draftKey","backgroundDraft","keyup","ns","deepEqual","prevBackgroundDraft","db","useInterval","saveUnsavedDraft","quote","_i18n","debug","drafts","unsupportedFiles","updatedAt","f","handleItems","querySelector","items","clipboardData","dataTransfer","allowedFiles","1","format","handleDragover","showMentionPicker","setShowMentionPicker","setShowEmoji2Picker","stopPropagation","autoDetectedLanguages","topSupportedLanguages","topLanguages","contentTranslationHideLanguages","restLanguages","codeA","commonA","codeB","commonB","replyToStatusMonthsAgo","onMinimize","cwButtonDisabled","onCWButtonClick","pollButtonDisabled","showGIFPicker","setAutoDetectedLanguages","highlightLanguageField","highlightVisibilityField","settings","showAddButton","BUTTON_WIDTH","addSubToolbarRef","scrollWidth","truncated","setShowAddButton","overTruncated","minimized","onScheduledAtClick","mediaButtonDisabled","showPollButton","onPollButtonClick","newWin","confirmText","passData","opener","__STATES__","showCompose","disableQuotePolicy","openCompose","scheduledAtButtonDisabled","AccountBlock","useAvatarStatic","__COMPOSE__","previewMode","formData","pointerEvents","opacity","cancelable","FormData","fromEntries","params2","res","mediaPromises","hasNoDescriptions","v2","Promise","publishing","newStatus","reason","e2","quote_approval_policy","action","in_reply_to_id","saveStatus","skipThreading","i2","fileID","newAttachments","poll2","newPoll","ScheduledAtField","currentValue","pastedLinkPos","lastCursorPos","newValue","getLocalTimezoneName","open","hasCurrentQuote","containerProps","MenuDivider","composerGIFPicker","setShowGIFPicker","showScheduledAt","quoteURL","currentText","quoteCleared","localQuoteStatus","linkPos","visibilityText","commonText","localeCode2Text","session","socialAddress","showCommon","showEmoji2Picker","emojiShortcode","insertTextAtCursor","newMediaAttachments","theToast","obj","log"],"ignoreList":[0,1,2,6,7],"sources":["../../node_modules/ansi-regex/index.js","../../node_modules/strip-ansi/index.js","../../node_modules/string-length/index.js","../../src/utils/url-regex.js","../../src/components/camera-capture-input.jsx","../../src/components/char-count-meter.jsx","../../node_modules/@github/combobox-nav/dist/index.js","../../node_modules/@github/text-expander-element/dist/index.js","../../src/utils/custom-emojis.js","../../src/components/text-expander.jsx","../../src/components/compose-poll.jsx","../../src/components/compose-textarea.jsx","../../src/components/custom-emojis-modal.jsx","../../src/components/file-picker-input.jsx","../../src/assets/powered-by-giphy.svg","../../src/components/gif-picker-modal.jsx","../../src/components/media-attachment.jsx","../../src/components/mention-modal.jsx","../../src/components/quote-suggestion.jsx","../../src/components/compose.jsx"],"sourcesContent":["export default function ansiRegex({onlyFirst = false} = {}) {\n\tconst pattern = [\n\t '[\\\\u001B\\\\u009B][[\\\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]+)*|[a-zA-Z\\\\d]+(?:;[-a-zA-Z\\\\d\\\\/#&.:=?%@~_]*)*)?\\\\u0007)',\n\t\t'(?:(?:\\\\d{1,4}(?:;\\\\d{0,4})*)?[\\\\dA-PR-TZcf-ntqry=><~]))'\n\t].join('|');\n\n\treturn new RegExp(pattern, onlyFirst ? undefined : 'g');\n}\n","import ansiRegex from 'ansi-regex';\n\nconst regex = ansiRegex();\n\nexport default function stripAnsi(string) {\n\tif (typeof string !== 'string') {\n\t\tthrow new TypeError(`Expected a \\`string\\`, got \\`${typeof string}\\``);\n\t}\n\n\t// Even though the regex is global, we don't need to reset the `.lastIndex`\n\t// because unlike `.exec()` and `.test()`, `.replace()` does it automatically\n\t// and doing it manually has a performance penalty.\n\treturn string.replace(regex, '');\n}\n","import stripAnsi from 'strip-ansi';\n\nconst segmenter = new Intl.Segmenter();\n\nexport default function stringLength(string, {countAnsiEscapeCodes = false} = {}) {\n\tif (string === '') {\n\t\treturn 0;\n\t}\n\n\tif (!countAnsiEscapeCodes) {\n\t\tstring = stripAnsi(string);\n\t}\n\n\tif (string === '') {\n\t\treturn 0;\n\t}\n\n\tlet length = 0;\n\n\tfor (const _ of segmenter.segment(string)) { // eslint-disable-line no-unused-vars\n\t\tlength++;\n\t}\n\n\treturn length;\n}\n","import urlRegex from '../data/url-regex';\n\nconst urlRegexObj = new RegExp(urlRegex.source, urlRegex.flags);\n\nexport default urlRegexObj;\n","const isMobileSafari =\n /iPad|iPhone|iPod/.test(navigator.userAgent) &&\n /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n\nfunction CameraCaptureInput({\n hidden,\n disabled = false,\n supportedMimeTypes,\n setMediaAttachments,\n}) {\n // If not Mobile Safari, only apply image/*\n // Chrome Android doesn't show the camera if image and video combined\n // It also can't switch between photo and video mode like iOS/Safari\n const filteredSupportedMimeTypes = isMobileSafari\n ? supportedMimeTypes\n : supportedMimeTypes?.filter((mimeType) => !/^image\\//i.test(mimeType));\n\n return (\n <input\n type=\"file\"\n hidden={hidden}\n accept={filteredSupportedMimeTypes?.join(',')}\n capture=\"environment\"\n disabled={disabled}\n onChange={(e) => {\n const files = e.target.files;\n if (!files) return;\n const mediaFile = Array.from(files)[0];\n if (!mediaFile) return;\n setMediaAttachments((attachments) => [\n ...attachments,\n {\n file: mediaFile,\n type: mediaFile.type,\n size: mediaFile.size,\n url: URL.createObjectURL(mediaFile),\n id: null, // indicate uploaded state\n description: null,\n },\n ]);\n e.target.value = null;\n }}\n />\n );\n}\n\nexport const supportsCameraCapture = (() => {\n const input = document.createElement('input');\n return 'capture' in input;\n})();\n\nexport default CameraCaptureInput;\n","import { useSnapshot } from 'valtio';\n\nimport states from '../utils/states';\n\nfunction CharCountMeter({ maxCharacters = 500, hidden }) {\n const snapStates = useSnapshot(states);\n const charCount = snapStates.composerCharacterCount;\n const leftChars = maxCharacters - charCount;\n if (hidden) {\n return <span class=\"char-counter\" hidden />;\n }\n return (\n <span\n class=\"char-counter\"\n title={`${leftChars}/${maxCharacters}`}\n style={{\n '--percentage': (charCount / maxCharacters) * 100,\n }}\n >\n <meter\n class={`${\n leftChars <= -10\n ? 'explode'\n : leftChars <= 0\n ? 'danger'\n : leftChars <= 20\n ? 'warning'\n : ''\n }`}\n value={charCount}\n max={maxCharacters}\n />\n <span class=\"counter\">{leftChars}</span>\n </span>\n );\n}\n\nexport default CharCountMeter;\n","export default class Combobox {\n constructor(input, list, { tabInsertsSuggestions, defaultFirstOption } = {}) {\n this.input = input;\n this.list = list;\n this.tabInsertsSuggestions = tabInsertsSuggestions !== null && tabInsertsSuggestions !== void 0 ? tabInsertsSuggestions : true;\n this.defaultFirstOption = defaultFirstOption !== null && defaultFirstOption !== void 0 ? defaultFirstOption : false;\n this.isComposing = false;\n if (!list.id) {\n list.id = `combobox-${Math.random().toString().slice(2, 6)}`;\n }\n this.ctrlBindings = !!navigator.userAgent.match(/Macintosh/);\n this.keyboardEventHandler = event => keyboardBindings(event, this);\n this.compositionEventHandler = event => trackComposition(event, this);\n this.inputHandler = this.clearSelection.bind(this);\n input.setAttribute('role', 'combobox');\n input.setAttribute('aria-controls', list.id);\n input.setAttribute('aria-expanded', 'false');\n input.setAttribute('aria-autocomplete', 'list');\n input.setAttribute('aria-haspopup', 'listbox');\n }\n destroy() {\n this.clearSelection();\n this.stop();\n this.input.removeAttribute('role');\n this.input.removeAttribute('aria-controls');\n this.input.removeAttribute('aria-expanded');\n this.input.removeAttribute('aria-autocomplete');\n this.input.removeAttribute('aria-haspopup');\n }\n start() {\n this.input.setAttribute('aria-expanded', 'true');\n this.input.addEventListener('compositionstart', this.compositionEventHandler);\n this.input.addEventListener('compositionend', this.compositionEventHandler);\n this.input.addEventListener('input', this.inputHandler);\n this.input.addEventListener('keydown', this.keyboardEventHandler);\n this.list.addEventListener('click', commitWithElement);\n this.indicateDefaultOption();\n }\n stop() {\n this.clearSelection();\n this.input.setAttribute('aria-expanded', 'false');\n this.input.removeEventListener('compositionstart', this.compositionEventHandler);\n this.input.removeEventListener('compositionend', this.compositionEventHandler);\n this.input.removeEventListener('input', this.inputHandler);\n this.input.removeEventListener('keydown', this.keyboardEventHandler);\n this.list.removeEventListener('click', commitWithElement);\n }\n indicateDefaultOption() {\n var _a;\n if (this.defaultFirstOption) {\n (_a = Array.from(this.list.querySelectorAll('[role=\"option\"]:not([aria-disabled=\"true\"])'))\n .filter(visible)[0]) === null || _a === void 0 ? void 0 : _a.setAttribute('data-combobox-option-default', 'true');\n }\n }\n navigate(indexDiff = 1) {\n const focusEl = Array.from(this.list.querySelectorAll('[aria-selected=\"true\"]')).filter(visible)[0];\n const els = Array.from(this.list.querySelectorAll('[role=\"option\"]')).filter(visible);\n const focusIndex = els.indexOf(focusEl);\n if ((focusIndex === els.length - 1 && indexDiff === 1) || (focusIndex === 0 && indexDiff === -1)) {\n this.clearSelection();\n this.input.focus();\n return;\n }\n let indexOfItem = indexDiff === 1 ? 0 : els.length - 1;\n if (focusEl && focusIndex >= 0) {\n const newIndex = focusIndex + indexDiff;\n if (newIndex >= 0 && newIndex < els.length)\n indexOfItem = newIndex;\n }\n const target = els[indexOfItem];\n if (!target)\n return;\n for (const el of els) {\n el.removeAttribute('data-combobox-option-default');\n if (target === el) {\n this.input.setAttribute('aria-activedescendant', target.id);\n target.setAttribute('aria-selected', 'true');\n scrollTo(this.list, target);\n }\n else {\n el.removeAttribute('aria-selected');\n }\n }\n }\n clearSelection() {\n this.input.removeAttribute('aria-activedescendant');\n for (const el of this.list.querySelectorAll('[aria-selected=\"true\"]')) {\n el.removeAttribute('aria-selected');\n }\n this.indicateDefaultOption();\n }\n}\nfunction keyboardBindings(event, combobox) {\n if (event.shiftKey || event.metaKey || event.altKey)\n return;\n if (!combobox.ctrlBindings && event.ctrlKey)\n return;\n if (combobox.isComposing)\n return;\n switch (event.key) {\n case 'Enter':\n if (commit(combobox.input, combobox.list)) {\n event.preventDefault();\n }\n break;\n case 'Tab':\n if (combobox.tabInsertsSuggestions && commit(combobox.input, combobox.list)) {\n event.preventDefault();\n }\n break;\n case 'Escape':\n combobox.clearSelection();\n break;\n case 'ArrowDown':\n combobox.navigate(1);\n event.preventDefault();\n break;\n case 'ArrowUp':\n combobox.navigate(-1);\n event.preventDefault();\n break;\n case 'n':\n if (combobox.ctrlBindings && event.ctrlKey) {\n combobox.navigate(1);\n event.preventDefault();\n }\n break;\n case 'p':\n if (combobox.ctrlBindings && event.ctrlKey) {\n combobox.navigate(-1);\n event.preventDefault();\n }\n break;\n default:\n if (event.ctrlKey)\n break;\n combobox.clearSelection();\n }\n}\nfunction commitWithElement(event) {\n if (!(event.target instanceof Element))\n return;\n const target = event.target.closest('[role=\"option\"]');\n if (!target)\n return;\n if (target.getAttribute('aria-disabled') === 'true')\n return;\n fireCommitEvent(target);\n}\nfunction commit(input, list) {\n const target = list.querySelector('[aria-selected=\"true\"], [data-combobox-option-default=\"true\"]');\n if (!target)\n return false;\n if (target.getAttribute('aria-disabled') === 'true')\n return true;\n target.click();\n return true;\n}\nfunction fireCommitEvent(target) {\n target.dispatchEvent(new CustomEvent('combobox-commit', { bubbles: true }));\n}\nfunction visible(el) {\n return (!el.hidden &&\n !(el instanceof HTMLInputElement && el.type === 'hidden') &&\n (el.offsetWidth > 0 || el.offsetHeight > 0));\n}\nfunction trackComposition(event, combobox) {\n combobox.isComposing = event.type === 'compositionstart';\n const list = document.getElementById(combobox.input.getAttribute('aria-controls') || '');\n if (!list)\n return;\n combobox.clearSelection();\n}\nfunction scrollTo(container, target) {\n if (!inViewport(container, target)) {\n container.scrollTop = target.offsetTop;\n }\n}\nfunction inViewport(container, element) {\n const scrollTop = container.scrollTop;\n const containerBottom = scrollTop + container.clientHeight;\n const top = element.offsetTop;\n const bottom = top + element.clientHeight;\n return top >= scrollTop && bottom <= containerBottom;\n}\n","import Combobox from '@github/combobox-nav';\n\nconst boundary = /\\s|\\(|\\[/;\nfunction query(text, key, cursor, { multiWord, lookBackIndex, lastMatchPosition } = {\n multiWord: false,\n lookBackIndex: 0,\n lastMatchPosition: null\n}) {\n let keyIndex = text.lastIndexOf(key, cursor - 1);\n if (keyIndex === -1)\n return;\n if (keyIndex < lookBackIndex)\n return;\n if (multiWord) {\n if (lastMatchPosition != null) {\n if (lastMatchPosition === keyIndex)\n return;\n keyIndex = lastMatchPosition - key.length;\n }\n const charAfterKey = text[keyIndex + 1];\n if (charAfterKey === ' ' && cursor >= keyIndex + key.length + 1)\n return;\n const newLineIndex = text.lastIndexOf('\\n', cursor - 1);\n if (newLineIndex > keyIndex)\n return;\n const dotIndex = text.lastIndexOf('.', cursor - 1);\n if (dotIndex > keyIndex)\n return;\n }\n else {\n const spaceIndex = text.lastIndexOf(' ', cursor - 1);\n if (spaceIndex > keyIndex)\n return;\n }\n const pre = text[keyIndex - 1];\n if (pre && !boundary.test(pre))\n return;\n const queryString = text.substring(keyIndex + key.length, cursor);\n return {\n text: queryString,\n position: keyIndex + key.length\n };\n}\n\nclass InputStyleCloneUpdateEvent extends Event {\n constructor() {\n super(\"update\");\n }\n}\nconst CloneRegistry = new WeakMap();\n/**\n * Creates an element that exactly matches an input pixel-for-pixel and automatically stays in sync with it. This\n * is a non-interactive overlay on to the input and can be used to affect the visual appearance of the input\n * without modifying its behavior. The clone element is hidden by default.\n *\n * This lower level API powers the `InputRange` but provides more advanced functionality including event updates.\n *\n * Emits `update` events whenever anything is recalculated: when the layout changes, when the user scrolls, when the\n * input is updated, etc. This event may be emitted more than once per change.\n *\n * @note There may be cases in which the clone cannot observe changes to the input and fails to automatically update.\n * For example, if the `value` property on the input is written to directly, no `input` event is emitted by the input\n * and the clone does not automatically update. In these cases, `forceUpdate` can be used to manually trigger an update.\n */\n// PRIOR ART: This approach was adapted from the following MIT-licensed sources:\n// - primer/react (Copyright (c) 2018 GitHub, Inc.): https://github.com/primer/react/blob/a0db832302702b869aa22b0c4049ad9305ef631f/src/drafts/utils/character-coordinates.ts\n// - component/textarea-caret-position (Copyright (c) 2015 Jonathan Ong me@jongleberry.com): https://github.com/component/textarea-caret-position/blob/b5db7a7e47dd149c2a66276183c69234e4dabe30/index.js\n// - koddsson/textarea-caret-position (Copyright (c) 2015 Jonathan Ong me@jongleberry.com): https://github.com/koddsson/textarea-caret-position/blob/eba40ec8488eed4d77815f109af22e1d9c0751d3/index.js\nclass InputStyleClone extends EventTarget {\n #styleObserver = new MutationObserver(() => this.#updateStyles());\n #resizeObserver = new ResizeObserver(() => this.#requestUpdateLayout());\n // This class is unique in that it will prevent itself from getting garbage collected because of the subscribed\n // observers (if never detached). Because of this, we want to avoid preventing the existence of this class from also\n // preventing the garbage collection of the associated input. This also allows us to automatically detach if the\n // input gets collected.\n #inputRef;\n #container = document.createElement(\"div\");\n #cloneElement = document.createElement(\"div\");\n /**\n * Get the clone for an input, reusing an existing one if available. This avoids creating unecessary clones, which\n * have a performance cost due to their high-frequency event-based updates. Because these elements are shared, they\n * should be mutated with caution. If you're planning to mutate the clone, consider constructing a new one instead.\n *\n * Upon initial creation the clone element will automatically be inserted into the DOM and begin observing the\n * linked input.\n * @param input The target input to clone.\n */\n static for(input) {\n let clone = CloneRegistry.get(input);\n if (!clone) {\n clone = new InputStyleClone(input);\n CloneRegistry.set(input, clone);\n }\n return clone;\n }\n /**\n * Connect this instance to a target input element and insert this instance into the DOM in the correct location.\n *\n * NOTE: calling the static `for` method is usually preferable as it will reuse an existing clone if available.\n * However, if reusing clones is problematic (ie, if the clone needs to be mutated), a clone can be constructed\n * directly with `new InputStyleClone(target)`.\n */\n constructor(input) {\n super();\n this.#inputRef = new WeakRef(input);\n // We want position:absolute so it doesn't take space in the layout, but that doesn't work with display:table-cell\n // used in the HTMLInputElement approach. So we need a wrapper.\n this.#container.style.position = \"absolute\";\n this.#container.style.pointerEvents = \"none\";\n this.#container.setAttribute(\"aria-hidden\", \"true\");\n this.#container.appendChild(this.#cloneElement);\n this.#cloneElement.style.pointerEvents = \"none\";\n this.#cloneElement.style.userSelect = \"none\";\n this.#cloneElement.style.overflow = \"hidden\";\n this.#cloneElement.style.display = \"block\";\n // Important not to use display:none which would not render the content at all\n this.#cloneElement.style.visibility = \"hidden\";\n if (input instanceof HTMLTextAreaElement) {\n this.#cloneElement.style.whiteSpace = \"pre-wrap\";\n this.#cloneElement.style.wordWrap = \"break-word\";\n }\n else {\n this.#cloneElement.style.whiteSpace = \"nowrap\";\n // text in single-line inputs is vertically centered\n this.#cloneElement.style.display = \"table-cell\";\n this.#cloneElement.style.verticalAlign = \"middle\";\n }\n input.after(this.#container);\n this.#updateStyles();\n this.#updateText();\n this.#styleObserver.observe(input, {\n attributeFilter: [\n \"style\",\n \"dir\", // users can right-click in some browsers to change the text direction dynamically\n ],\n });\n this.#resizeObserver.observe(input);\n document.addEventListener(\"scroll\", this.#onDocumentScrollOrResize, { capture: true });\n window.addEventListener(\"resize\", this.#onDocumentScrollOrResize, { capture: true });\n // capture so this happens first, so other things can respond to `input` events after this data updates\n input.addEventListener(\"input\", this.#onInput, { capture: true });\n }\n /** Get the clone element. */\n get element() {\n return this.#cloneElement;\n }\n /**\n * Force a recalculation. Will emit an `update` event. This is typically not needed unless the input has changed in\n * an unobservable way, eg by directly writing to the `value` property.\n */\n forceUpdate() {\n this.#updateStyles();\n this.#updateText();\n }\n disconnect() {\n this.#container?.remove();\n this.#styleObserver.disconnect();\n this.#resizeObserver.disconnect();\n document.removeEventListener(\"scroll\", this.#onDocumentScrollOrResize, { capture: true });\n window.removeEventListener(\"resize\", this.#onDocumentScrollOrResize, { capture: true });\n // Can't use `usingInput` here since that could infinitely recurse\n const input = this.#input;\n if (input) {\n input.removeEventListener(\"input\", this.#onInput, { capture: true });\n CloneRegistry.delete(input);\n }\n }\n // --- private ---\n get #input() {\n return this.#inputRef?.deref();\n }\n /** Perform `fn` using the `input` if it is still available. If not, clean up the clone instead. */\n #usingInput(fn) {\n const input = this.#input;\n if (!input)\n return this.disconnect();\n return fn(input);\n }\n /** Current relative x-adjustment in pixels, executed via CSS transform. */\n #xOffset = 0;\n /** Current relative y-adjustment in pixels, executed via CSS transform. */\n #yOffset = 0;\n /**\n * Update only geometric properties without recalculating styles. Typically call `#requestUpdateLayout` instead to\n * only update once per animation frame.\n */\n #updateLayout() {\n // This runs often, so keep it as fast as possible! Avoid all unecessary updates.\n this.#usingInput((input) => {\n const inputStyle = window.getComputedStyle(input);\n this.#cloneElement.style.height = inputStyle.height;\n this.#cloneElement.style.width = inputStyle.width;\n // Immediately re-adjust for browser inconsistencies in scrollbar handling, if necessary\n if (input.clientHeight !== this.#cloneElement.clientHeight)\n this.#cloneElement.style.height = `calc(${inputStyle.height} + ${input.clientHeight - this.#cloneElement.clientHeight}px)`;\n if (input.clientWidth !== this.#cloneElement.clientWidth)\n this.#cloneElement.style.width = `calc(${inputStyle.width} + ${input.clientWidth - this.#cloneElement.clientWidth}px)`;\n // Position on top of the input\n const inputRect = input.getBoundingClientRect();\n const cloneRect = this.#cloneElement.getBoundingClientRect();\n this.#xOffset = this.#xOffset + inputRect.left - cloneRect.left;\n this.#yOffset = this.#yOffset + inputRect.top - cloneRect.top;\n this.#cloneElement.style.transform = `translate(${this.#xOffset}px, ${this.#yOffset}px)`;\n this.#cloneElement.scrollTop = input.scrollTop;\n this.#cloneElement.scrollLeft = input.scrollLeft;\n this.dispatchEvent(new InputStyleCloneUpdateEvent());\n });\n }\n #isLayoutUpdating = false;\n /** Request a layout update. Will only happen once per animation frame, to avoid unecessary updates. */\n #requestUpdateLayout() {\n if (this.#isLayoutUpdating)\n return;\n this.#isLayoutUpdating = true;\n requestAnimationFrame(() => {\n this.#updateLayout();\n this.#isLayoutUpdating = false;\n });\n }\n /** Update the styles of the clone based on the styles of the input, then request a layout update. */\n #updateStyles() {\n this.#usingInput((input) => {\n const inputStyle = window.getComputedStyle(input);\n for (const prop of propertiesToCopy)\n this.#cloneElement.style[prop] = inputStyle[prop];\n this.#requestUpdateLayout();\n });\n }\n /**\n * Update the text content of the clone based on the text content of the input. Triggers a layout update in case the\n * text update caused scrolling.\n */\n #updateText() {\n this.#usingInput((input) => {\n this.#cloneElement.textContent = input.value;\n // This is often unecessary on a pure text update, but text updates could potentially cause layout updates like\n // scrolling or resizing. And we run the update on _every frame_ when scrolling, so this isn't that expensive.\n // We don't requestUpdateLayout here because this one should happen synchronously, so that clients can react\n // within their own `input` event handlers.\n this.#updateLayout();\n });\n }\n #onInput = () => this.#updateText();\n #onDocumentScrollOrResize = (event) => {\n this.#usingInput((input) => {\n if (event.target === document ||\n event.target === window ||\n (event.target instanceof Node && event.target.contains(input)))\n this.#requestUpdateLayout();\n });\n };\n}\n// Note that some browsers, such as Firefox, do not concatenate properties\n// into their shorthand (e.g. padding-top, padding-bottom etc. -> padding),\n// so we have to list every single property explicitly.\nconst propertiesToCopy = [\n // RTL / vertical writing modes support:\n \"direction\",\n \"writingMode\",\n \"unicodeBidi\",\n \"textOrientation\",\n \"boxSizing\",\n \"borderTopWidth\",\n \"borderRightWidth\",\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderStyle\",\n \"paddingTop\",\n \"paddingRight\",\n \"paddingBottom\",\n \"paddingLeft\",\n // https://developer.mozilla.org/en-US/docs/Web/CSS/font\n \"fontStyle\",\n \"fontVariant\",\n \"fontWeight\",\n \"fontStretch\",\n \"fontSize\",\n \"fontSizeAdjust\",\n \"lineHeight\",\n \"fontFamily\",\n \"textAlign\",\n \"textTransform\",\n \"textIndent\",\n \"textDecoration\",\n \"letterSpacing\",\n \"wordSpacing\",\n \"tabSize\",\n \"MozTabSize\",\n];\n\nclass InputRange {\n #inputElement;\n #startOffset;\n #endOffset;\n /**\n * Construct a new `InputRange`.\n * @param element The target input element that contains the content for the range.\n * @param startOffset The inclusive 0-based start index for the range. Will be adjusted to fit in the input contents.\n * @param endOffset The exclusive 0-based end index for the range. Will be adjusted to fit in the input contents.\n */\n constructor(element, startOffset = 0, endOffset = startOffset) {\n this.#inputElement = element;\n this.#startOffset = startOffset;\n this.#endOffset = endOffset;\n }\n /**\n * Create a new range from the current user selection. If the input is not focused, the range will just be the start\n * of the input (offsets `0` to `0`).\n *\n * This can be used to get the caret coordinates: if the resulting range is `collapsed`, the location of the\n * `getBoundingClientRect` will be the location of the caret caret (note, however, that the width will be `0` in\n * this case).\n */\n static fromSelection(input) {\n const { selectionStart, selectionEnd } = input;\n return new InputRange(input, selectionStart ?? undefined, selectionEnd ?? undefined);\n }\n /** Returns true if the start is equal to the end of this range. */\n get collapsed() {\n return this.startOffset === this.endOffset;\n }\n /** Always returns the containing input element. */\n get commonAncestorContainer() {\n return this.#inputElement;\n }\n /** Always returns the containing input element. */\n get endContainer() {\n return this.#inputElement;\n }\n /** Always returns the containing input element. */\n get startContainer() {\n return this.#inputElement;\n }\n get startOffset() {\n return this.#startOffset;\n }\n get endOffset() {\n return this.#endOffset;\n }\n /** Update the inclusive start offset. Will be adjusted to fit within the content size. */\n setStartOffset(offset) {\n this.#startOffset = this.#clampOffset(offset);\n }\n /** Update the exclusive end offset. Will be adjusted to fit within the content size. */\n setEndOffset(offset) {\n this.#endOffset = this.#clampOffset(offset);\n }\n /**\n * Collapse this range to one side.\n * @param toStart If `true`, will collapse to the start side. Otherwise, will collapse to the end.\n */\n collapse(toStart = false) {\n if (toStart)\n this.setEndOffset(this.startOffset);\n else\n this.setStartOffset(this.endOffset);\n }\n /** Returns a `DocumentFragment` containing a new `Text` node containing the content in the range. */\n cloneContents() {\n return this.#createCloneRange().cloneContents();\n }\n /** Create a copy of this range. */\n cloneRange() {\n return new InputRange(this.#inputElement, this.startOffset, this.endOffset);\n }\n /**\n * Obtain one rect that contains the entire contents of the range. If the range spans multiple lines, this box will\n * contain all pieces of the range but may also contain some space outside the range.\n * @see https://iansan5653.github.io/dom-input-range/demos/playground/\n */\n getBoundingClientRect() {\n return this.#createCloneRange().getBoundingClientRect();\n }\n /**\n * Obtain the rects that contain contents of this range. If the range spans multiple lines, there will be multiple\n * bounding boxes. These boxes can be used, for example, to draw a highlight over the range.\n * @see https://iansan5653.github.io/dom-input-range/demos/playground/\n */\n getClientRects() {\n return this.#createCloneRange().getClientRects();\n }\n /** Get the contents of the range as a string. */\n toString() {\n return this.#createCloneRange().toString();\n }\n /**\n * Get the underlying `InputStyleClone` instance powering these calculations. This can be used to listen for\n * updates to trigger layout recalculation.\n */\n getStyleClone() {\n return this.#styleClone;\n }\n // --- private ---\n get #styleClone() {\n return InputStyleClone.for(this.#inputElement);\n }\n get #cloneElement() {\n return this.#styleClone;\n }\n #clampOffset(offset) {\n return Math.max(0, Math.min(offset, this.#inputElement.value.length));\n }\n #createCloneRange() {\n // It's tempting to create a single Range and reuse it across the lifetime of the class. However, this wouldn't be\n // accurate because the contents of the input can change and the contents of the range would become stale. So we\n // must create a new range every time we need it.\n const range = document.createRange();\n const textNode = this.#cloneElement.element.childNodes[0];\n if (textNode) {\n range.setStart(textNode, this.startOffset);\n range.setEnd(textNode, this.endOffset);\n }\n return range;\n }\n}\n\nconst states = new WeakMap();\nclass TextExpander {\n constructor(expander, input) {\n this.expander = expander;\n this.input = input;\n this.combobox = null;\n this.menu = null;\n this.match = null;\n this.justPasted = false;\n this.lookBackIndex = 0;\n this.oninput = this.onInput.bind(this);\n this.onpaste = this.onPaste.bind(this);\n this.onkeydown = this.onKeydown.bind(this);\n this.oncommit = this.onCommit.bind(this);\n this.onmousedown = this.onMousedown.bind(this);\n this.onblur = this.onBlur.bind(this);\n this.interactingWithList = false;\n input.addEventListener('paste', this.onpaste);\n input.addEventListener('input', this.oninput);\n input.addEventListener('keydown', this.onkeydown);\n input.addEventListener('blur', this.onblur);\n }\n destroy() {\n this.input.removeEventListener('paste', this.onpaste);\n this.input.removeEventListener('input', this.oninput);\n this.input.removeEventListener('keydown', this.onkeydown);\n this.input.removeEventListener('blur', this.onblur);\n }\n dismissMenu() {\n if (this.deactivate()) {\n this.lookBackIndex = this.input.selectionEnd || this.lookBackIndex;\n }\n }\n activate(match, menu) {\n var _a, _b;\n if (this.input !== document.activeElement && this.input !== ((_b = (_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.shadowRoot) === null || _b === void 0 ? void 0 : _b.activeElement)) {\n return;\n }\n this.deactivate();\n this.menu = menu;\n if (!menu.id)\n menu.id = `text-expander-${Math.floor(Math.random() * 100000).toString()}`;\n this.expander.append(menu);\n this.combobox = new Combobox(this.input, menu);\n this.expander.dispatchEvent(new Event('text-expander-activate'));\n this.positionMenu(menu, match.position);\n this.combobox.start();\n menu.addEventListener('combobox-commit', this.oncommit);\n menu.addEventListener('mousedown', this.onmousedown);\n this.combobox.navigate(1);\n }\n positionMenu(menu, position) {\n const caretRect = new InputRange(this.input, position).getBoundingClientRect();\n const targetPosition = { left: caretRect.left, top: caretRect.top + caretRect.height };\n const currentPosition = menu.getBoundingClientRect();\n const delta = {\n left: targetPosition.left - currentPosition.left,\n top: targetPosition.top - currentPosition.top\n };\n if (delta.left !== 0 || delta.top !== 0) {\n const currentStyle = getComputedStyle(menu);\n menu.style.left = currentStyle.left ? `calc(${currentStyle.left} + ${delta.left}px)` : `${delta.left}px`;\n menu.style.top = currentStyle.top ? `calc(${currentStyle.top} + ${delta.top}px)` : `${delta.top}px`;\n }\n }\n deactivate() {\n const menu = this.menu;\n if (!menu || !this.combobox)\n return false;\n this.expander.dispatchEvent(new Event('text-expander-deactivate'));\n this.menu = null;\n menu.removeEventListener('combobox-commit', this.oncommit);\n menu.removeEventListener('mousedown', this.onmousedown);\n this.combobox.destroy();\n this.combobox = null;\n menu.remove();\n return true;\n }\n onCommit({ target }) {\n var _a;\n const item = target;\n if (!(item instanceof HTMLElement))\n return;\n if (!this.combobox)\n return;\n const match = this.match;\n if (!match)\n return;\n const beginning = this.input.value.substring(0, match.position - match.key.length);\n const remaining = this.input.value.substring(match.position + match.text.length);\n const detail = { item, key: match.key, value: null, continue: false };\n const canceled = !this.expander.dispatchEvent(new CustomEvent('text-expander-value', { cancelable: true, detail }));\n if (canceled)\n return;\n if (!detail.value)\n return;\n let suffix = (_a = this.expander.getAttribute('suffix')) !== null && _a !== void 0 ? _a : ' ';\n if (detail.continue) {\n suffix = '';\n }\n const value = `${detail.value}${suffix}`;\n this.input.value = beginning + value + remaining;\n const cursor = beginning.length + value.length;\n this.deactivate();\n this.input.focus({\n preventScroll: true\n });\n this.input.selectionStart = cursor;\n this.input.selectionEnd = cursor;\n if (!detail.continue) {\n this.lookBackIndex = cursor;\n this.match = null;\n }\n this.expander.dispatchEvent(new CustomEvent('text-expander-committed', { cancelable: false, detail: { input: this.input } }));\n }\n onBlur() {\n if (this.interactingWithList) {\n this.interactingWithList = false;\n return;\n }\n this.deactivate();\n }\n onPaste() {\n this.justPasted = true;\n }\n async onInput() {\n if (this.justPasted) {\n this.justPasted = false;\n return;\n }\n const match = this.findMatch();\n if (match) {\n this.match = match;\n const menu = await this.notifyProviders(match);\n if (!this.match)\n return;\n if (menu) {\n this.activate(match, menu);\n }\n else {\n this.deactivate();\n }\n }\n else {\n this.match = null;\n this.deactivate();\n }\n }\n findMatch() {\n const cursor = this.input.selectionEnd || 0;\n const text = this.input.value;\n if (cursor <= this.lookBackIndex) {\n this.lookBackIndex = cursor - 1;\n }\n for (const { key, multiWord } of this.expander.keys) {\n const found = query(text, key, cursor, {\n multiWord,\n lookBackIndex: this.lookBackIndex,\n lastMatchPosition: this.match ? this.match.position : null\n });\n if (found) {\n return { text: found.text, key, position: found.position };\n }\n }\n }\n async notifyProviders(match) {\n const providers = [];\n const provide = (result) => providers.push(result);\n const changeEvent = new CustomEvent('text-expander-change', {\n cancelable: true,\n detail: { provide, text: match.text, key: match.key }\n });\n const canceled = !this.expander.dispatchEvent(changeEvent);\n if (canceled)\n return;\n const all = await Promise.all(providers);\n const fragments = all.filter(x => x.matched).map(x => x.fragment);\n return fragments[0];\n }\n onMousedown() {\n this.interactingWithList = true;\n }\n onKeydown(event) {\n if (event.key === 'Escape') {\n this.match = null;\n if (this.deactivate()) {\n this.lookBackIndex = this.input.selectionEnd || this.lookBackIndex;\n event.stopImmediatePropagation();\n event.preventDefault();\n }\n }\n }\n}\nclass TextExpanderElement extends HTMLElement {\n get keys() {\n const keysAttr = this.getAttribute('keys');\n const keys = keysAttr ? keysAttr.split(' ') : [];\n const multiWordAttr = this.getAttribute('multiword');\n const multiWord = multiWordAttr ? multiWordAttr.split(' ') : [];\n const globalMultiWord = multiWord.length === 0 && this.hasAttribute('multiword');\n return keys.map(key => ({ key, multiWord: globalMultiWord || multiWord.includes(key) }));\n }\n set keys(value) {\n this.setAttribute('keys', value);\n }\n connectedCallback() {\n const input = this.querySelector('input[type=\"text\"], textarea');\n if (!(input instanceof HTMLInputElement || input instanceof HTMLTextAreaElement))\n return;\n const state = new TextExpander(this, input);\n states.set(this, state);\n }\n disconnectedCallback() {\n const state = states.get(this);\n if (!state)\n return;\n state.destroy();\n states.delete(this);\n }\n dismiss() {\n const state = states.get(this);\n if (!state)\n return;\n state.dismissMenu();\n }\n}\n\nif (!window.customElements.get('text-expander')) {\n window.TextExpanderElement = TextExpanderElement;\n window.customElements.define('text-expander', TextExpanderElement);\n}\n\nexport { TextExpanderElement as default };\n","import Fuse from 'fuse.js';\n\nimport pmem from './pmem';\n\nasync function _getCustomEmojis(instance, masto) {\n const emojis = await masto.v1.customEmojis.list();\n const visibleEmojis = emojis.filter((e) => e.visibleInPicker);\n const searcher = new Fuse(visibleEmojis, {\n keys: ['shortcode'],\n findAllMatches: true,\n });\n return [visibleEmojis, searcher];\n}\n\nconst getCustomEmojis = pmem(_getCustomEmojis, {\n // Limit by time to reduce memory usage\n // Cached by instance\n matchesArg: (cacheKeyArg, keyArg) => cacheKeyArg.instance === keyArg.instance,\n maxAge: 30 * 60 * 1000, // 30 minutes\n});\n\nexport { getCustomEmojis, _getCustomEmojis };\nexport default getCustomEmojis;\n","import '@github/text-expander-element';\n\nimport { useLingui } from '@lingui/react/macro';\nimport { forwardRef, useImperativeHandle } from 'preact/compat';\nimport { useEffect, useRef } from 'preact/hooks';\n\nimport { api } from '../utils/api';\nimport getCustomEmojis from '../utils/custom-emojis';\nimport emojifyText from '../utils/emojify-text';\nimport getDomain from '../utils/get-domain';\nimport isRTL from '../utils/is-rtl';\nimport shortenNumber from '../utils/shorten-number';\n\nconst menu = document.createElement('ul');\nmenu.role = 'listbox';\nmenu.className = 'text-expander-menu';\n\n// Set IntersectionObserver on menu, reposition it because text-expander doesn't handle it\nconst windowMargin = 16;\nconst observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (entry.isIntersecting) {\n const { left, width } = entry.boundingClientRect;\n const { innerWidth } = window;\n if (left + width > innerWidth) {\n const insetInlineStart = isRTL() ? 'right' : 'left';\n menu.style[insetInlineStart] = innerWidth - width - windowMargin + 'px';\n }\n }\n });\n});\nobserver.observe(menu);\n\nfunction encodeHTML(str) {\n return str.replace(/[&<>\"']/g, function (char) {\n return '&#' + char.charCodeAt(0) + ';';\n });\n}\n\nfunction TextExpander({ onTrigger = null, ...props }, ref) {\n const { t } = useLingui();\n const textExpanderRef = useRef();\n const { masto, instance } = api();\n const searcherRef = useRef();\n const textExpanderTextRef = useRef('');\n const hasTextExpanderRef = useRef(false);\n\n // Expose the activated state to parent components\n useImperativeHandle(ref, () => ({\n setStyle: (style) => {\n if (textExpanderRef.current) {\n Object.assign(textExpanderRef.current.style, style);\n }\n },\n activated: () => hasTextExpanderRef.current,\n }));\n\n // Setup emoji search if not already set up\n useEffect(() => {\n if (searcherRef.current) return; // Already set up\n\n getCustomEmojis(instance, masto)\n .then(([, searcher]) => {\n searcherRef.current = searcher;\n })\n .catch((e) => {\n console.error(e);\n });\n }, [instance, masto]);\n\n useEffect(() => {\n const textExpander = textExpanderRef.current;\n if (!textExpander) return;\n\n const handleChange = (e) => {\n const { key, provide, text } = e.detail;\n textExpanderTextRef.current = text;\n\n if (text === '') {\n provide(\n Promise.resolve({\n matched: false,\n }),\n );\n return;\n }\n\n if (key === ':') {\n const showMore = !!onTrigger;\n const results = searcherRef.current?.search(text, {\n limit: 5,\n });\n\n let html = '';\n results?.forEach(({ item: emoji }) => {\n const { shortcode, url } = emoji;\n html += `\n <li role=\"option\" data-value=\"${encodeHTML(shortcode)}\">\n <img src=\"${encodeHTML(\n url,\n )}\" width=\"16\" height=\"16\" alt=\"\" loading=\"lazy\" />\n ${encodeHTML(shortcode)}\n </li>`;\n });\n if (showMore) {\n html += `<li role=\"option\" data-value=\"\" data-more=\"${text}\">${'More…'}</li>`;\n }\n menu.innerHTML = html;\n\n provide(\n Promise.resolve({\n matched: (results?.length || 0) > 0,\n fragment: menu,\n }),\n );\n return;\n }\n\n // Handle @ mentions and # hashtags\n const type = {\n '@': 'accounts',\n '': 'accounts',\n '#': 'hashtags',\n '': 'hashtags',\n }[key];\n\n if (type) {\n provide(\n new Promise(async (resolve) => {\n try {\n let searchResults;\n if (type === 'accounts') {\n searchResults = await masto.v1.accounts.search.list({\n q: text,\n limit: 5,\n resolve: false,\n });\n } else {\n const response = await masto.v2.search.list({\n type,\n q: text,\n limit: 5,\n });\n searchResults = response[type] || response;\n }\n\n if (text !== textExpanderTextRef.current) {\n return;\n }\n\n const results = searchResults;\n let html = '';\n results.forEach((result) => {\n const {\n name,\n avatarStatic,\n displayName,\n username,\n acct,\n emojis,\n history,\n roles,\n url,\n } = result;\n const displayNameWithEmoji = emojifyText(displayName, emojis);\n const accountInstance = getDomain(url);\n\n if (acct) {\n html += `\n <li role=\"option\" data-value=\"${encodeHTML(acct)}\">\n <span class=\"avatar\">\n <img src=\"${encodeHTML(\n avatarStatic,\n )}\" width=\"16\" height=\"16\" alt=\"\" loading=\"lazy\" />\n </span>\n <span>\n <b>${displayNameWithEmoji || username}</b>\n <br><span class=\"bidi-isolate\">@${encodeHTML(\n acct,\n )}</span>\n ${\n roles?.map(\n (role) => ` <span class=\"tag collapsed\">\n ${role.name}\n ${\n !!accountInstance &&\n `<span class=\"more-insignificant\">\n ${accountInstance}\n </span>`\n }\n </span>`,\n ) || ''\n }\n </span>\n </li>\n `;\n } else {\n const total = history?.reduce?.(\n (acc, cur) => acc + +cur.uses,\n 0,\n );\n html += `\n <li role=\"option\" data-value=\"${encodeHTML(name)}\">\n <span class=\"grow\">#<b>${encodeHTML(name)}</b></span>\n ${\n total\n ? `<span class=\"count\">${shortenNumber(total)}</span>`\n : ''\n }\n </li>\n `;\n }\n });\n if (type === 'accounts') {\n html += `<li role=\"option\" data-value=\"\" data-more=\"${text}\">${t`More…`}</li>`;\n }\n menu.innerHTML = html;\n resolve({\n matched: results.length > 0,\n fragment: menu,\n });\n } catch (error) {\n console.error('Search error:', error);\n resolve({\n matched: false,\n });\n }\n }),\n );\n return;\n }\n\n // No other keys supported\n provide(\n Promise.resolve({\n matched: false,\n }),\n );\n };\n\n const handleValue = (e) => {\n const { key, item } = e.detail;\n const { value, more } = item.dataset;\n\n if (key === ':') {\n e.detail.value = value ? `:${value}:` : ''; // zero-width space\n if (more) {\n // Prevent adding space after the above value\n e.detail.continue = true;\n\n setTimeout(() => {\n // Trigger custom emoji picker modal for more options\n onTrigger?.({\n name: 'custom-emojis',\n defaultSearchTerm: more,\n });\n }, 300);\n }\n } else if (key === '@') {\n e.detail.value = value ? `@${value}` : ''; // zero-width space\n if (more) {\n e.detail.continue = true;\n setTimeout(() => {\n onTrigger?.({\n name: 'mention',\n defaultSearchTerm: more,\n });\n }, 300);\n }\n } else {\n e.detail.value = `${key}${value}`;\n }\n };\n\n const handleCommited = (e) => {\n const { input } = e.detail;\n\n if (input) {\n const event = new Event('input', { bubbles: true });\n input.dispatchEvent(event);\n }\n };\n\n const handleActivate = () => {\n hasTextExpanderRef.current = true;\n };\n\n const handleDeactivate = () => {\n hasTextExpanderRef.current = false;\n };\n\n textExpander.addEventListener('text-expander-change', handleChange);\n textExpander.addEventListener('text-expander-value', handleValue);\n textExpander.addEventListener('text-expander-committed', handleCommited);\n textExpander.addEventListener('text-expander-activate', handleActivate);\n textExpander.addEventListener('text-expander-deactivate', handleDeactivate);\n\n return () => {\n textExpander.removeEventListener('text-expander-change', handleChange);\n textExpander.removeEventListener('text-expander-value', handleValue);\n textExpander.removeEventListener(\n 'text-expander-committed',\n handleCommited,\n );\n textExpander.removeEventListener(\n 'text-expander-activate',\n handleActivate,\n );\n textExpander.removeEventListener(\n 'text-expander-deactivate',\n handleDeactivate,\n );\n };\n }, [searcherRef.current, onTrigger, t, masto]);\n\n return <text-expander ref={textExpanderRef} {...props} />;\n}\n\nexport default forwardRef(TextExpander);\n","import { Trans, useLingui } from '@lingui/react/macro';\n\nimport i18nDuration from '../utils/i18n-duration';\n\nimport Icon from './icon';\nimport TextExpander from './text-expander';\n\nexport const expiryOptions = {\n 300: i18nDuration(5, 'minute'),\n 1_800: i18nDuration(30, 'minute'),\n 3_600: i18nDuration(1, 'hour'),\n 21_600: i18nDuration(6, 'hour'),\n 86_400: i18nDuration(1, 'day'),\n 259_200: i18nDuration(3, 'day'),\n 604_800: i18nDuration(1, 'week'),\n};\n\nfunction ComposePoll({\n lang,\n poll,\n disabled,\n onInput = () => {},\n maxOptions,\n maxExpiration,\n minExpiration,\n maxCharactersPerOption,\n}) {\n const { t } = useLingui();\n const { options, expiresIn, multiple } = poll;\n\n return (\n <div class={`poll ${multiple ? 'multiple' : ''}`}>\n <div class=\"poll-choices\">\n {options.map((option, i) => (\n <div class=\"poll-choice\" key={i}>\n <TextExpander keys=\":\" class=\"poll-field-container\">\n <input\n required\n type=\"text\"\n value={option}\n disabled={disabled}\n maxlength={maxCharactersPerOption}\n placeholder={t`Choice ${i + 1}`}\n lang={lang}\n spellCheck=\"true\"\n autocomplete=\"off\"\n dir=\"auto\"\n data-allow-custom-emoji=\"true\"\n onInput={(e) => {\n const { value } = e.target;\n options[i] = value;\n onInput(poll);\n }}\n />\n </TextExpander>\n <button\n type=\"button\"\n class=\"plain4 poll-button\"\n disabled={disabled || options.length <= 1}\n onClick={() => {\n options.splice(i, 1);\n onInput(poll);\n }}\n title={t`Remove`}\n >\n \n </button>\n </div>\n ))}\n </div>\n <div class=\"poll-toolbar\">\n <button\n type=\"button\"\n class=\"plain2 poll-button\"\n disabled={disabled || options.length >= maxOptions}\n onClick={() => {\n options.push('');\n onInput(poll);\n }}\n title={t`Add`}\n >\n +\n </button>{' '}\n <div class=\"poll-config\">\n <label class=\"multiple-choices\">\n <input\n type=\"checkbox\"\n checked={multiple}\n disabled={disabled}\n onChange={(e) => {\n const { checked } = e.target;\n poll.multiple = checked;\n onInput(poll);\n }}\n />{' '}\n <Trans>Multiple choice</Trans>\n </label>\n <label class=\"expires-in\">\n <Trans>Duration</Trans>{' '}\n <select\n value={expiresIn}\n disabled={disabled}\n onChange={(e) => {\n const { value } = e.target;\n poll.expiresIn = value;\n onInput(poll);\n }}\n >\n {Object.entries(expiryOptions)\n .filter(([value]) => {\n return value >= minExpiration && value <= maxExpiration;\n })\n .map(([value, label]) => (\n <option value={value} key={value}>\n {label()}\n </option>\n ))}\n </select>\n </label>\n <div class=\"spacer\" />\n <button\n type=\"button\"\n class=\"light danger small\"\n disabled={disabled}\n onClick={() => {\n onInput(null);\n }}\n >\n <Trans>Remove poll</Trans>\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nexport default ComposePoll;\n","import { forwardRef } from 'preact/compat';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { useDebouncedCallback, useThrottledCallback } from 'use-debounce';\n\nimport { langDetector } from '../utils/browser-translator';\nimport escapeHTML from '../utils/escape-html';\nimport states from '../utils/states';\nimport urlRegexObj from '../utils/url-regex';\nimport useThrottledResizeObserver from '../utils/useThrottledResizeObserver';\n\nimport TextExpander from './text-expander';\n\n// https://github.com/mastodon/mastodon/blob/c03bd2a238741a012aa4b98dc4902d6cf948ab63/app/models/account.rb#L69\nconst USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i;\nconst MENTION_RE = new RegExp(\n `(^|[^=\\\\/\\\\w])([@]${USERNAME_RE.source}(?:@[\\\\p{L}\\\\w.-]+[\\\\w]+)?)`,\n 'uig',\n);\n\n// AI-generated, all other regexes are too complicated\nconst HASHTAG_RE = new RegExp(\n `(^|[^=\\\\/\\\\w])([#][\\\\p{L}\\\\p{N}_]+([\\\\p{L}\\\\p{N}_.]+[\\\\p{L}\\\\p{N}_]+)?)(?![\\\\/\\\\w])`,\n 'iug',\n);\n\n// https://github.com/mastodon/mastodon/blob/23e32a4b3031d1da8b911e0145d61b4dd47c4f96/app/models/custom_emoji.rb#L31\nconst SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}';\nconst SCAN_RE = new RegExp(\n `(^|[^=\\\\/\\\\w])(:${SHORTCODE_RE_FRAGMENT}:)(?=[^A-Za-z0-9_:]|$)`,\n 'g',\n);\n\nconst segmenter = new Intl.Segmenter();\n\nfunction highlightText(text, { maxCharacters = Infinity }) {\n // Exceeded characters limit\n const { composerCharacterCount } = states;\n if (composerCharacterCount > maxCharacters) {\n // Highlight exceeded characters\n let withinLimitHTML = '',\n exceedLimitHTML = '';\n const htmlSegments = segmenter.segment(text);\n for (const { segment, index } of htmlSegments) {\n if (index < maxCharacters) {\n withinLimitHTML += segment;\n } else {\n exceedLimitHTML += segment;\n }\n }\n if (exceedLimitHTML) {\n exceedLimitHTML =\n '<mark class=\"compose-highlight-exceeded\">' +\n escapeHTML(exceedLimitHTML) +\n '</mark>';\n }\n return escapeHTML(withinLimitHTML) + exceedLimitHTML;\n }\n\n return escapeHTML(text)\n .replace(urlRegexObj, '$2<mark class=\"compose-highlight-url\">$3</mark>') // URLs\n .replace(MENTION_RE, '$1<mark class=\"compose-highlight-mention\">$2</mark>') // Mentions\n .replace(HASHTAG_RE, '$1<mark class=\"compose-highlight-hashtag\">$2</mark>') // Hashtags\n .replace(\n SCAN_RE,\n '$1<mark class=\"compose-highlight-emoji-shortcode\">$2</mark>',\n ); // Emoji shortcodes\n}\n\nfunction autoResizeTextarea(textarea) {\n if (!textarea) return;\n const { value, offsetHeight, scrollHeight, clientHeight } = textarea;\n if (offsetHeight < window.innerHeight) {\n // NOTE: This check is needed because the offsetHeight return 50000 (really large number) on first render\n // No idea why it does that, will re-investigate in far future\n const offset = offsetHeight - clientHeight;\n const height = value ? scrollHeight + offset + 'px' : null;\n textarea.style.height = height;\n }\n}\n\nconst detectLangs = async (text) => {\n if (langDetector) {\n const langs = await langDetector.detect(text);\n if (langs?.length) {\n return langs.slice(0, 2).map((lang) => lang.detectedLanguage);\n }\n }\n const { detectAll } = await import('tinyld/light');\n const langs = detectAll(text);\n if (langs?.length) {\n // return max 2\n return langs.slice(0, 2).map((lang) => lang.lang);\n }\n return null;\n};\n\nconst Textarea = forwardRef((props, ref) => {\n const [text, setText] = useState(ref.current?.value || '');\n const { maxCharacters, onTrigger = null, ...textareaProps } = props;\n\n const textExpanderRef = useRef();\n\n useThrottledResizeObserver({\n ref,\n onResize: () => {\n // Get height of textarea, set height to textExpander\n if (textExpanderRef.current && ref.current) {\n const { height } = ref.current.getBoundingClientRect();\n if (height) {\n textExpanderRef.current.setStyle({ minHeight: height + 'px' });\n }\n }\n },\n });\n\n const slowHighlightPerf = useRef(0); // increment if slow\n const composeHighlightRef = useRef();\n const throttleHighlightText = useThrottledCallback((text) => {\n if (!composeHighlightRef.current) return;\n if (slowHighlightPerf.current > 3) {\n // After 3 times of lag, disable highlighting\n composeHighlightRef.current.innerHTML = '';\n composeHighlightRef.current = null; // Destroy the whole thing\n throttleHighlightText?.cancel?.();\n return;\n }\n let start;\n let end;\n if (slowHighlightPerf.current <= 3) start = Date.now();\n composeHighlightRef.current.innerHTML =\n highlightText(text, {\n maxCharacters,\n }) + '\\n';\n if (slowHighlightPerf.current <= 3) end = Date.now();\n console.debug('HIGHLIGHT PERF', { start, end, diff: end - start });\n if (start && end && end - start > 50) {\n // if slow, increment\n slowHighlightPerf.current++;\n }\n // Newline to prevent multiple line breaks at the end from being collapsed, no idea why\n }, 500);\n\n const debouncedAutoDetectLanguage = useDebouncedCallback(() => {\n // Make use of the highlightRef to get the DOM\n // Clone the dom\n const dom = composeHighlightRef.current?.cloneNode(true);\n if (!dom) return;\n // Remove mark\n dom.querySelectorAll('mark').forEach((mark) => {\n mark.remove();\n });\n const text = dom.innerText?.trim();\n if (!text) return;\n (async () => {\n const langs = await detectLangs(text);\n if (langs?.length) {\n onTrigger?.({\n name: 'auto-detect-language',\n languages: langs,\n });\n }\n })();\n }, 2000);\n\n return (\n <TextExpander\n ref={textExpanderRef}\n keys=\"@ : # \"\n class=\"compose-field-container\"\n onTrigger={onTrigger}\n >\n <textarea\n class=\"compose-field\"\n autoCapitalize=\"sentences\"\n autoComplete=\"on\"\n autoCorrect=\"on\"\n spellCheck=\"true\"\n dir=\"auto\"\n rows=\"6\"\n cols=\"50\"\n {...textareaProps}\n ref={ref}\n name=\"status\"\n value={text}\n onKeyDown={(e) => {\n // Get line before cursor position after pressing 'Enter'\n const { key, target } = e;\n const hasTextExpander = textExpanderRef.current?.activated();\n if (\n key === 'Enter' &&\n !(e.ctrlKey || e.metaKey || hasTextExpander) &&\n !e.isComposing\n ) {\n try {\n const { value, selectionStart } = target;\n const textBeforeCursor = value.slice(0, selectionStart);\n const lastLine = textBeforeCursor.split('\\n').slice(-1)[0];\n if (lastLine) {\n // If line starts with \"- \" or \"12. \"\n if (/^\\s*(-|\\d+\\.)\\s/.test(lastLine)) {\n // insert \"- \" at cursor position\n const [_, preSpaces, bullet, postSpaces, anything] =\n lastLine.match(/^(\\s*)(-|\\d+\\.)(\\s+)(.+)?/) || [];\n if (anything) {\n e.preventDefault();\n const [number] = bullet.match(/\\d+/) || [];\n const newBullet = number ? `${+number + 1}.` : '-';\n const text = `\\n${preSpaces}${newBullet}${postSpaces}`;\n target.setRangeText(text, selectionStart, selectionStart);\n const pos = selectionStart + text.length;\n target.setSelectionRange(pos, pos);\n } else {\n // trim the line before the cursor, then insert new line\n const pos = selectionStart - lastLine.length;\n target.setRangeText('', pos, selectionStart);\n }\n autoResizeTextarea(target);\n target.dispatchEvent(new Event('input'));\n }\n }\n } catch (e) {\n // silent fail\n console.error(e);\n }\n }\n if (composeHighlightRef.current) {\n composeHighlightRef.current.scrollTop = target.scrollTop;\n }\n }}\n onInput={(e) => {\n const { target } = e;\n const text = target.value;\n setText(text);\n autoResizeTextarea(target);\n props.onInput?.(e);\n throttleHighlightText(text);\n debouncedAutoDetectLanguage();\n }}\n onScroll={(e) => {\n if (composeHighlightRef.current) {\n const { scrollTop } = e.target;\n composeHighlightRef.current.scrollTop = scrollTop;\n }\n }}\n onPaste={(e) => {\n try {\n const pastedText = e.clipboardData.getData('text').trim();\n if (pastedText) {\n onTrigger?.({\n name: 'pasted-link',\n url: pastedText,\n });\n }\n } catch (error) {\n console.error(error);\n }\n }}\n />\n <div\n ref={composeHighlightRef}\n class=\"compose-highlight\"\n aria-hidden=\"true\"\n />\n </TextExpander>\n );\n});\n\nexport default Textarea;\n","import './custom-emojis-modal.css';\n\nimport { Trans, useLingui } from '@lingui/react/macro';\nimport { memo } from 'preact/compat';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'preact/hooks';\n\nimport getCustomEmojis from '../utils/custom-emojis';\nimport store from '../utils/store';\n\nimport Icon from './icon';\nimport Loader from './loader';\n\nconst CUSTOM_EMOJIS_COUNT = 100;\nconst EMOJI_SIZE_MIN = 1;\nconst EMOJI_SIZE_MAX = 2;\nconst EMOJI_SIZE_STEP = 0.5;\n\nconst CustomEmojiButton = memo(({ emoji, onClick, showCode }) => {\n const addEdges = (e) => {\n // Add edge-left or edge-right class based on self position relative to scrollable parent\n // If near left edge, add edge-left, if near right edge, add edge-right\n const buffer = 88;\n const parent = e.currentTarget.closest('main');\n if (parent) {\n const rect = parent.getBoundingClientRect();\n const selfRect = e.currentTarget.getBoundingClientRect();\n const targetClassList = e.currentTarget.classList;\n if (selfRect.left < rect.left + buffer) {\n targetClassList.add('edge-left');\n targetClassList.remove('edge-right');\n } else if (selfRect.right > rect.right - buffer) {\n targetClassList.add('edge-right');\n targetClassList.remove('edge-left');\n } else {\n targetClassList.remove('edge-left', 'edge-right');\n }\n }\n };\n\n return (\n <button\n type=\"button\"\n className=\"plain4\"\n onClick={onClick}\n data-title={showCode ? undefined : emoji.shortcode}\n onPointerEnter={addEdges}\n onFocus={addEdges}\n >\n <picture>\n {!!emoji.staticUrl && (\n <source\n srcSet={emoji.staticUrl}\n media=\"(prefers-reduced-motion: reduce)\"\n />\n )}\n <img\n className=\"shortcode-emoji\"\n src={emoji.url || emoji.staticUrl}\n alt={emoji.shortcode}\n width=\"24\"\n height=\"24\"\n loading=\"lazy\"\n decoding=\"async\"\n />\n </picture>\n {showCode && (\n <>\n {' '}\n <code>{emoji.shortcode}</code>\n </>\n )}\n </button>\n );\n});\n\nconst CustomEmojisList = memo(({ emojis, onSelect }) => {\n const { i18n } = useLingui();\n const [max, setMax] = useState(CUSTOM_EMOJIS_COUNT);\n const showMore = emojis.length > max;\n return (\n <section>\n {emojis.slice(0, max).map((emoji) => (\n <CustomEmojiButton\n key={emoji.shortcode}\n emoji={emoji}\n onClick={() => {\n onSelect(`:${emoji.shortcode}:`);\n }}\n />\n ))}\n {showMore && (\n <button\n type=\"button\"\n class=\"plain small\"\n onClick={() => setMax(max + CUSTOM_EMOJIS_COUNT)}\n >\n <Trans>{i18n.number(emojis.length - max)} more…</Trans>\n </button>\n )}\n </section>\n );\n});\n\nconst CUSTOM_EMOJI_SIZE = 'composer-customEmojiSize';\n\nfunction CustomEmojisModal({\n masto,\n instance,\n onClose = () => {},\n onSelect = () => {},\n defaultSearchTerm,\n}) {\n const { t } = useLingui();\n const [uiState, setUIState] = useState('default');\n const customEmojisList = useRef([]);\n const [customEmojis, setCustomEmojis] = useState([]);\n const recentlyUsedCustomEmojis = useMemo(\n () => store.account.get('recentlyUsedCustomEmojis') || [],\n );\n const searcherRef = useRef();\n useEffect(() => {\n setUIState('loading');\n (async () => {\n try {\n const [emojis, searcher] = await getCustomEmojis(instance, masto);\n console.log('emojis', emojis);\n searcherRef.current = searcher;\n setCustomEmojis(emojis);\n setUIState('default');\n } catch (e) {\n setUIState('error');\n console.error(e);\n }\n })();\n }, []);\n\n const customEmojisCatList = useMemo(() => {\n // Group emojis by category\n const emojisCat = {\n '--recent--': recentlyUsedCustomEmojis.filter((emoji) =>\n customEmojis.find((e) => e.shortcode === emoji.shortcode),\n ),\n };\n const othersCat = [];\n customEmojis.forEach((emoji) => {\n customEmojisList.current?.push?.(emoji);\n if (!emoji.category) {\n othersCat.push(emoji);\n return;\n }\n if (!emojisCat[emoji.category]) {\n emojisCat[emoji.category] = [];\n }\n emojisCat[emoji.category].push(emoji);\n });\n if (othersCat.length) {\n emojisCat['--others--'] = othersCat;\n }\n return emojisCat;\n }, [customEmojis]);\n\n const scrollableRef = useRef();\n const [matches, setMatches] = useState(null);\n const [emojiSize, setEmojiSize] = useState(\n store.local.get(CUSTOM_EMOJI_SIZE) || EMOJI_SIZE_MIN,\n );\n const onEmojiSizeDecrease = useCallback(() => {\n const newSize = Math.max(EMOJI_SIZE_MIN, emojiSize - EMOJI_SIZE_STEP);\n setEmojiSize(newSize);\n if (newSize === EMOJI_SIZE_MIN) {\n store.local.del(CUSTOM_EMOJI_SIZE);\n } else {\n store.local.set(CUSTOM_EMOJI_SIZE, newSize);\n }\n }, [emojiSize]);\n\n const onEmojiSizeIncrease = useCallback(() => {\n const newSize = Math.min(EMOJI_SIZE_MAX, emojiSize + EMOJI_SIZE_STEP);\n setEmojiSize(newSize);\n if (newSize === EMOJI_SIZE_MIN) {\n store.local.del(CUSTOM_EMOJI_SIZE);\n } else {\n store.local.set(CUSTOM_EMOJI_SIZE, newSize);\n }\n }, [emojiSize]);\n\n const onFind = useCallback(\n (e) => {\n const { value } = e.target;\n if (value) {\n const results = searcherRef.current?.search(value, {\n limit: CUSTOM_EMOJIS_COUNT,\n });\n setMatches(results.map((r) => r.item));\n scrollableRef.current?.scrollTo?.(0, 0);\n } else {\n setMatches(null);\n }\n },\n [customEmojis],\n );\n useEffect(() => {\n if (defaultSearchTerm && customEmojis?.length) {\n onFind({ target: { value: defaultSearchTerm } });\n }\n }, [defaultSearchTerm, onFind, customEmojis]);\n\n const onSelectEmoji = useCallback(\n (emoji) => {\n onSelect?.(emoji);\n onClose?.();\n\n queueMicrotask(() => {\n let recentlyUsedCustomEmojis =\n store.account.get('recentlyUsedCustomEmojis') || [];\n const recentlyUsedEmojiIndex = recentlyUsedCustomEmojis.findIndex(\n (e) => e.shortcode === emoji.shortcode,\n );\n if (recentlyUsedEmojiIndex !== -1) {\n // Move emoji to index 0\n recentlyUsedCustomEmojis.splice(recentlyUsedEmojiIndex, 1);\n recentlyUsedCustomEmojis.unshift(emoji);\n } else {\n recentlyUsedCustomEmojis.unshift(emoji);\n // Remove unavailable ones\n recentlyUsedCustomEmojis = recentlyUsedCustomEmojis.filter((e) =>\n customEmojisList.current?.find?.(\n (emoji) => emoji.shortcode === e.shortcode,\n ),\n );\n // Limit to 10\n recentlyUsedCustomEmojis = recentlyUsedCustomEmojis.slice(0, 10);\n }\n\n // Store back\n store.account.set('recentlyUsedCustomEmojis', recentlyUsedCustomEmojis);\n });\n },\n [onSelect],\n );\n\n const inputRef = useRef();\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n // Put cursor at the end\n if (inputRef.current.value) {\n inputRef.current.selectionStart = inputRef.current.value.length;\n inputRef.current.selectionEnd = inputRef.current.value.length;\n }\n }\n }, []);\n\n return (\n <div\n id=\"custom-emojis-sheet\"\n class=\"sheet\"\n style={{\n '--custom-emoji-size': emojiSize,\n }}\n >\n {!!onClose && (\n <button type=\"button\" class=\"sheet-close\" onClick={onClose}>\n <Icon icon=\"x\" alt={t`Close`} />\n </button>\n )}\n <header>\n <div>\n <b>\n <Trans>Custom emojis</Trans>\n </b>{' '}\n {uiState === 'loading' ? (\n <Loader />\n ) : (\n <small class=\"insignificant\"> • {instance}</small>\n )}\n </div>\n <form\n onSubmit={(e) => {\n e.preventDefault();\n const emoji = matches[0];\n if (emoji) {\n onSelectEmoji(`:${emoji.shortcode}:`);\n }\n }}\n >\n <input\n ref={inputRef}\n type=\"search\"\n placeholder={t`Search emoji`}\n onInput={onFind}\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n spellCheck=\"false\"\n dir=\"auto\"\n defaultValue={defaultSearchTerm || ''}\n />\n </form>\n </header>\n <main ref={scrollableRef}>\n {matches !== null ? (\n <ul class=\"custom-emojis-matches custom-emojis-list\">\n {matches.map((emoji) => (\n <li key={emoji.shortcode} class=\"custom-emojis-match\">\n <CustomEmojiButton\n emoji={emoji}\n onClick={() => {\n onSelectEmoji(`:${emoji.shortcode}:`);\n }}\n showCode\n />\n </li>\n ))}\n </ul>\n ) : (\n <div class=\"custom-emojis-list\">\n {uiState === 'error' && (\n <div class=\"ui-state\">\n <p>\n <Trans>Error loading custom emojis</Trans>\n </p>\n </div>\n )}\n {uiState === 'default' &&\n Object.entries(customEmojisCatList).map(\n ([category, emojis]) =>\n !!emojis?.length && (\n <div class=\"section-container\">\n <div class=\"section-header\">\n {{\n '--recent--': t`Recently used`,\n '--others--': t`Others`,\n }[category] || category}\n </div>\n <CustomEmojisList\n emojis={emojis}\n onSelect={onSelectEmoji}\n />\n </div>\n ),\n )}\n </div>\n )}\n <div class=\"size-range\">\n <button\n type=\"button\"\n class=\"plain4\"\n onClick={onEmojiSizeDecrease}\n disabled={emojiSize <= EMOJI_SIZE_MIN}\n >\n <Icon icon=\"zoom-out\" size=\"l\" alt={t`Zoom out`} />\n </button>\n <button\n type=\"button\"\n class=\"plain4\"\n onClick={onEmojiSizeIncrease}\n disabled={emojiSize >= EMOJI_SIZE_MAX}\n >\n <Icon icon=\"zoom-in\" size=\"l\" alt={t`Zoom in`} />\n </button>\n </div>\n </main>\n </div>\n );\n}\n\nexport default CustomEmojisModal;\n","import { plural } from '@lingui/core/macro';\n\nfunction FilePickerInput({\n hidden,\n supportedMimeTypes,\n maxMediaAttachments,\n mediaAttachments,\n disabled = false,\n setMediaAttachments,\n}) {\n return (\n <input\n type=\"file\"\n hidden={hidden}\n accept={supportedMimeTypes?.join(',')}\n multiple={\n maxMediaAttachments === undefined ||\n maxMediaAttachments - mediaAttachments >= 2\n }\n disabled={disabled}\n onChange={(e) => {\n const files = e.target.files;\n if (!files) return;\n\n const mediaFiles = Array.from(files).map((file) => ({\n file,\n type: file.type,\n size: file.size,\n url: URL.createObjectURL(file),\n id: null, // indicate uploaded state\n description: null,\n }));\n console.log('MEDIA ATTACHMENTS', files, mediaFiles);\n\n // Validate max media attachments\n if (mediaAttachments.length + mediaFiles.length > maxMediaAttachments) {\n alert(\n plural(maxMediaAttachments, {\n one: 'You can only attach up to 1 file.',\n other: 'You can only attach up to # files.',\n }),\n );\n } else {\n setMediaAttachments((attachments) => {\n return attachments.concat(mediaFiles);\n });\n }\n // Reset\n e.target.value = '';\n }}\n />\n );\n}\n\nexport default FilePickerInput;\n","export default \"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20version='1.0'%20viewBox='0%200%20641%20223'%3e%3cpath%20fill='%23aaa'%20d='M86%20214c-9-1-17-4-24-8l-6-3-5-5-5-4-4-6-4-6-3-8-2-8v-27l2-9%203-9%204-6%204-6%205-5%205-5%207-3%206-4%207-2%207-2%2012-1h12l7%201%208%202%207%204%207%203%205%205%205%204-10%2010-10%209-4-3-10-5-5-1H88l-5%202-6%203-3%204-4%204-2%205-2%206v6l-1%207%201%207%202%207%203%205%202%204%204%203%204%203%205%202%206%202h9l10-1%205-2%206-3v-16H91v-27h59v54l-1%203-2%203-5%204-4%204-5%203-5%202-8%202-8%202-10%201H92l-6-1zm266-62V91h34v46h44V91h34v121h-34v-46h-44v46h-34v-61zm-182-1V90h34v121h-34v-60zm59-1V90h35l36%201%205%202c3%200%208%202%2010%204l5%202%204%205%205%204%203%207%203%207%201%2013v13l-4%206-3%207-4%204-5%205-5%202-5%203-6%202-5%201-18%201h-18v32h-34v-61zm67-2%203-2%202-4%202-5v-5l-2-4-2-4-3-2-3-3h-30v31h30l3-2zm226%2039v-24l-8-12-18-28a1751%201751%200%200%200-20-31v-2h39l7%2012%2012%2021%206%209%2013-21%2013-21h38v2l-41%2061-7%2010v48h-34v-24zM109%2066l-4-1-5-5-5-4-1-5-3-9v-5l1-5c2-7%203-10%208-15l4-4%207-2%207-2h7l6%201%205%202%205%202%203%204%204%203%202%206%202%205v13l-2%205-2%206-4%204-3%203-5%202-4%202-9%201h-9l-5-2zm22-11%204-2%203-4%202-5V34l-2-4-2-4-3-2-4-3-5-1h-6l-4%202-5%202-2%204-3%205-1%203v4l1%205%202%205%202%202%205%203%204%202h10l4-2zM37%2039V11h33l3%201%203%202%204%203%203%203%201%205%201%204v5l-1%204-3%204-3%205-4%201-3%202-11%201H49v16H37V39zm31%200%203-2%201-2%201-2v-4l-1-3-3-2-2-2H49v18h15l4-1zm107%2025a512%20512%200%200%200-19-53h14l4%2014%206%2019%201%204%201-1%207-19%205-17h9l6%2019%207%2018v-1l2-6%205-17%204-13h14v1l-4%2012-16%2041v2h-5l-5-1-6-15-6-15-1%201-3%207-6%2015-2%208h-11l-1-3zm74-25V11h42v11h-29v2l-1%205v4h29v11h-28v11h2l15%201h13v11h-43V39zm55%200V11h33l5%203%205%202%202%204%202%205v10l-2%203-1%204-5%203-5%203%205%205%208%2010%203%204h-14l-7-9-8-10h-9v19h-12V39zm33-3%202-3v-6l-3-3-2-3h-18v16h1v1h17l2-2zm26%203V11h42v11h-29l-1%206v5h29v11h-28v5l-1%205%201%201v1h30v11h-43V39zm54%200V11h17l18%201%204%202%205%203%202%204%203%204%202%206%201%206v5c-1%206-3%2012-6%2015l-3%204-5%203-5%202-17%201h-16V39zm33%2014%205-5%202-3v-6l-1-6-1-3-1-3-4-3-3-2h-5l-6-1-3%201h-3v34h9l8-1%203-2zm50-14V11h34l5%202%204%202%202%203%202%203v9l-2%202-3%204-1%201%203%203%203%204%201%203%201%204-1%204-1%204-3%203-3%203-5%201-5%201h-31V39zm34%2015%202-1v-6l-2-2-2-2h-20v13h20l2-2zm-3-22%204-2v-6l-2-1-2-2h-19v12h16l4-1zm42%2024V45l-6-9-11-17-5-8h15l4%208%207%2011%202%203%207-11%207-11h14l-11%2016-11%2017v23h-12V56z'/%3e%3c/svg%3e\"","import { Trans, useLingui } from '@lingui/react/macro';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { useDebouncedCallback } from 'use-debounce';\n\nimport poweredByGiphyURL from '../assets/powered-by-giphy.svg';\n\nimport Icon from './icon';\nimport Loader from './loader';\n\nconst { PHANPY_GIPHY_API_KEY: GIPHY_API_KEY } = import.meta.env;\n\nconst GIFS_PER_PAGE = 20;\n\nfunction GIFPickerModal({ onClose = () => {}, onSelect = () => {} }) {\n const { i18n, t } = useLingui();\n const [uiState, setUIState] = useState('default');\n const [results, setResults] = useState([]);\n const formRef = useRef(null);\n const qRef = useRef(null);\n const currentOffset = useRef(0);\n const scrollableRef = useRef(null);\n\n function fetchGIFs({ offset }) {\n console.log('fetchGIFs', { offset });\n if (!qRef.current?.value) return;\n setUIState('loading');\n scrollableRef.current?.scrollTo?.({\n top: 0,\n left: 0,\n behavior: 'smooth',\n });\n (async () => {\n try {\n const query = {\n api_key: GIPHY_API_KEY,\n q: qRef.current.value,\n rating: 'g',\n limit: GIFS_PER_PAGE,\n bundle: 'messaging_non_clips',\n offset,\n lang: i18n.locale || 'en',\n };\n const response = await fetch(\n 'https://api.giphy.com/v1/gifs/search?' + new URLSearchParams(query),\n {\n referrerPolicy: 'no-referrer',\n },\n ).then((r) => r.json());\n currentOffset.current = response.pagination?.offset || 0;\n setResults(response);\n setUIState('results');\n } catch (e) {\n setUIState('error');\n console.error(e);\n }\n })();\n }\n\n useEffect(() => {\n qRef.current?.focus();\n }, []);\n\n const debouncedOnInput = useDebouncedCallback(() => {\n fetchGIFs({ offset: 0 });\n }, 1000);\n\n return (\n <div id=\"gif-picker-sheet\" class=\"sheet\">\n {!!onClose && (\n <button type=\"button\" class=\"sheet-close\" onClick={onClose}>\n <Icon icon=\"x\" alt={t`Close`} />\n </button>\n )}\n <header>\n <form\n ref={formRef}\n onSubmit={(e) => {\n e.preventDefault();\n fetchGIFs({ offset: 0 });\n }}\n >\n <input\n ref={qRef}\n type=\"search\"\n name=\"q\"\n placeholder={t`Search GIFs`}\n required\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n spellCheck=\"false\"\n dir=\"auto\"\n onInput={debouncedOnInput}\n />\n <input\n type=\"image\"\n class=\"powered-button\"\n src={poweredByGiphyURL}\n width=\"86\"\n height=\"30\"\n alt={t`Powered by GIPHY`}\n />\n </form>\n </header>\n <main ref={scrollableRef} class={uiState === 'loading' ? 'loading' : ''}>\n {uiState === 'default' && (\n <div class=\"ui-state\">\n <p class=\"insignificant\">\n <Trans>Type to search GIFs</Trans>\n </p>\n </div>\n )}\n {uiState === 'loading' && !results?.data?.length && (\n <div class=\"ui-state\">\n <Loader abrupt />\n </div>\n )}\n {results?.data?.length > 0 ? (\n <>\n <ul>\n {results.data.map((gif) => {\n const { id, images, title, alt_text } = gif;\n const {\n fixed_height_small,\n fixed_height_downsampled,\n fixed_height,\n original,\n } = images;\n const theImage = fixed_height_small?.url\n ? fixed_height_small\n : fixed_height_downsampled?.url\n ? fixed_height_downsampled\n : fixed_height;\n let { url, webp, width, height } = theImage;\n if (+height > 100) {\n width = (width / height) * 100;\n height = 100;\n }\n const urlObj = URL.parse(url);\n const strippedURL = urlObj.origin + urlObj.pathname;\n let strippedWebP;\n if (webp) {\n const webpObj = URL.parse(webp);\n strippedWebP = webpObj.origin + webpObj.pathname;\n }\n return (\n <li key={id}>\n <button\n type=\"button\"\n onClick={() => {\n const { mp4, url } = original;\n const theURL = mp4 || url;\n const urlObj = URL.parse(theURL);\n const strippedURL = urlObj.origin + urlObj.pathname;\n onClose();\n onSelect({\n url: strippedURL,\n type: mp4 ? 'video/mp4' : 'image/gif',\n alt_text: alt_text || title,\n });\n }}\n >\n <figure\n style={{\n '--figure-width': width + 'px',\n // width: width + 'px'\n }}\n >\n <picture>\n {strippedWebP && (\n <source srcset={strippedWebP} type=\"image/webp\" />\n )}\n <img\n src={strippedURL}\n width={width}\n height={height}\n loading=\"lazy\"\n decoding=\"async\"\n alt={alt_text}\n referrerpolicy=\"no-referrer\"\n onLoad={(e) => {\n e.target.style.backgroundColor = 'transparent';\n }}\n />\n </picture>\n <figcaption>{alt_text || title}</figcaption>\n </figure>\n </button>\n </li>\n );\n })}\n </ul>\n <p class=\"pagination\">\n {results.pagination?.offset > 0 && (\n <button\n type=\"button\"\n class=\"light small\"\n disabled={uiState === 'loading'}\n onClick={() => {\n fetchGIFs({\n offset: results.pagination?.offset - GIFS_PER_PAGE,\n });\n }}\n >\n <Icon icon=\"chevron-left\" />\n <span>\n <Trans>Previous</Trans>\n </span>\n </button>\n )}\n <span />\n {results.pagination?.offset + results.pagination?.count <\n results.pagination?.total_count && (\n <button\n type=\"button\"\n class=\"light small\"\n disabled={uiState === 'loading'}\n onClick={() => {\n fetchGIFs({\n offset: results.pagination?.offset + GIFS_PER_PAGE,\n });\n }}\n >\n <span>\n <Trans>Next</Trans>\n </span>{' '}\n <Icon icon=\"chevron-right\" />\n </button>\n )}\n </p>\n </>\n ) : (\n uiState === 'results' && (\n <div class=\"ui-state\">\n <p>No results</p>\n </div>\n )\n )}\n {uiState === 'error' && (\n <div class=\"ui-state\">\n <p>\n <Trans>Error loading GIFs</Trans>\n </p>\n </div>\n )}\n </main>\n </div>\n );\n}\n\nexport default GIFPickerModal;\n","import { Trans, useLingui } from '@lingui/react/macro';\nimport { MenuItem } from '@szhsin/react-menu';\nimport { useEffect, useMemo, useRef, useState } from 'preact/hooks';\nimport { useDebouncedCallback } from 'use-debounce';\n\nimport localeCode2Text from '../utils/localeCode2Text';\nimport prettyBytes from '../utils/pretty-bytes';\nimport showToast from '../utils/show-toast';\nimport states from '../utils/states';\nimport { getCurrentInstanceConfiguration } from '../utils/store-utils';\nimport supports from '../utils/supports';\n\nimport Icon from './icon';\nimport Menu2 from './menu2';\nimport Modal from './modal';\n\nconst { PHANPY_IMG_ALT_API_URL: IMG_ALT_API_URL } = import.meta.env;\n\nfunction scaleDimension(matrix, matrixLimit, width, height) {\n // matrix = number of pixels\n // matrixLimit = max number of pixels\n // Calculate new width and height, downsize to within the limit, preserve aspect ratio, no decimals\n const scalingFactor = Math.sqrt(matrixLimit / matrix);\n const newWidth = Math.floor(width * scalingFactor);\n const newHeight = Math.floor(height * scalingFactor);\n return { newWidth, newHeight };\n}\n\nfunction MediaAttachment({\n attachment,\n disabled,\n lang,\n supportedMimeTypes,\n descriptionLimit = 1500,\n onDescriptionChange = () => {},\n onRemove = () => {},\n}) {\n const { i18n, t } = useLingui();\n const [uiState, setUIState] = useState('default');\n const supportsEdit =\n supports('@mastodon/edit-media-attributes') ||\n supports('@gotosocial/edit-media-attributes');\n const { type, id, file } = attachment;\n const url = useMemo(\n () => (file ? URL.createObjectURL(file) : attachment.url),\n [file, attachment.url],\n );\n console.log({ attachment });\n\n const checkMaxError = !!file?.size;\n const configuration = checkMaxError ? getCurrentInstanceConfiguration() : {};\n const {\n mediaAttachments: {\n imageSizeLimit,\n imageMatrixLimit,\n videoSizeLimit,\n videoMatrixLimit,\n videoFrameRateLimit,\n } = {},\n } = configuration || {};\n\n const [maxError, setMaxError] = useState(() => {\n if (!checkMaxError) return null;\n if (\n type.startsWith('image') &&\n imageSizeLimit &&\n file.size > imageSizeLimit\n ) {\n return {\n type: 'imageSizeLimit',\n details: {\n imageSize: file.size,\n imageSizeLimit,\n },\n };\n } else if (\n type.startsWith('video') &&\n videoSizeLimit &&\n file.size > videoSizeLimit\n ) {\n return {\n type: 'videoSizeLimit',\n details: {\n videoSize: file.size,\n videoSizeLimit,\n },\n };\n }\n return null;\n });\n\n const [imageMatrix, setImageMatrix] = useState({});\n useEffect(() => {\n if (!checkMaxError || !imageMatrixLimit) return;\n if (imageMatrix?.matrix > imageMatrixLimit) {\n setMaxError({\n type: 'imageMatrixLimit',\n details: {\n imageMatrix: imageMatrix?.matrix,\n imageMatrixLimit,\n width: imageMatrix?.width,\n height: imageMatrix?.height,\n },\n });\n }\n }, [imageMatrix, imageMatrixLimit, checkMaxError]);\n\n const [videoMatrix, setVideoMatrix] = useState({});\n useEffect(() => {\n if (!checkMaxError || !videoMatrixLimit) return;\n if (videoMatrix?.matrix > videoMatrixLimit) {\n setMaxError({\n type: 'videoMatrixLimit',\n details: {\n videoMatrix: videoMatrix?.matrix,\n videoMatrixLimit,\n width: videoMatrix?.width,\n height: videoMatrix?.height,\n },\n });\n }\n }, [videoMatrix, videoMatrixLimit, checkMaxError]);\n\n const [description, setDescription] = useState(attachment.description);\n\n let [suffixType, subtype] = type.split('/');\n // If type is not supported, try to find a supported type with the same subtype\n // E.g. application/ogg -> audio/ogg\n const suffixTypes = new Set();\n const subTypeMap = {};\n if (supportedMimeTypes?.length) {\n supportedMimeTypes.forEach((mimeType) => {\n const [t, st] = mimeType.split('/');\n subTypeMap[st] = t;\n suffixTypes.add(t);\n });\n }\n if (!suffixTypes.has(suffixType)) {\n suffixType = subTypeMap[subtype];\n }\n\n const debouncedOnDescriptionChange = useDebouncedCallback(\n onDescriptionChange,\n 250,\n );\n useEffect(() => {\n debouncedOnDescriptionChange(description);\n }, [description, debouncedOnDescriptionChange]);\n\n const [showModal, setShowModal] = useState(false);\n const textareaRef = useRef(null);\n useEffect(() => {\n let timer;\n if (showModal && textareaRef.current) {\n timer = setTimeout(() => {\n textareaRef.current.focus();\n }, 100);\n }\n return () => {\n clearTimeout(timer);\n };\n }, [showModal]);\n\n const descTextarea = (\n <>\n {!!id && !supportsEdit ? (\n <div class=\"media-desc\">\n <span class=\"tag\">\n <Trans>Uploaded</Trans>\n </span>\n <p title={description}>\n {attachment.description || <i>No description</i>}\n </p>\n </div>\n ) : (\n <textarea\n ref={textareaRef}\n value={description || ''}\n lang={lang}\n placeholder={\n {\n image: t`Image description`,\n video: t`Video description`,\n audio: t`Audio description`,\n }[suffixType]\n }\n autoCapitalize=\"sentences\"\n autoComplete=\"on\"\n autoCorrect=\"on\"\n spellCheck=\"true\"\n dir=\"auto\"\n disabled={disabled || uiState === 'loading'}\n class={uiState === 'loading' ? 'loading' : ''}\n maxlength={descriptionLimit} // Not unicode-aware :(\n onInput={(e) => {\n const { value } = e.target;\n setDescription(value);\n // debouncedOnDescriptionChange(value);\n }}\n ></textarea>\n )}\n </>\n );\n\n const toastRef = useRef(null);\n useEffect(() => {\n return () => {\n toastRef.current?.hideToast?.();\n };\n }, []);\n\n const maxErrorToast = useRef(null);\n\n const maxErrorText = (err) => {\n const { type, details } = err;\n switch (type) {\n case 'imageSizeLimit': {\n const { imageSize, imageSizeLimit } = details;\n return t`File size too large. Uploading might encounter issues. Try reduce the file size from ${prettyBytes(\n imageSize,\n )} to ${prettyBytes(imageSizeLimit)} or lower.`;\n }\n case 'imageMatrixLimit': {\n const { imageMatrix, imageMatrixLimit, width, height } = details;\n const { newWidth, newHeight } = scaleDimension(\n imageMatrix,\n imageMatrixLimit,\n width,\n height,\n );\n return t`Dimension too large. Uploading might encounter issues. Try reduce dimension from ${i18n.number(\n width,\n )}×${i18n.number(height)}px to ${i18n.number(newWidth)}×${i18n.number(\n newHeight,\n )}px.`;\n }\n case 'videoSizeLimit': {\n const { videoSize, videoSizeLimit } = details;\n return t`File size too large. Uploading might encounter issues. Try reduce the file size from ${prettyBytes(\n videoSize,\n )} to ${prettyBytes(videoSizeLimit)} or lower.`;\n }\n case 'videoMatrixLimit': {\n const { videoMatrix, videoMatrixLimit, width, height } = details;\n const { newWidth, newHeight } = scaleDimension(\n videoMatrix,\n videoMatrixLimit,\n width,\n height,\n );\n return t`Dimension too large. Uploading might encounter issues. Try reduce dimension from ${i18n.number(\n width,\n )}×${i18n.number(height)}px to ${i18n.number(newWidth)}×${i18n.number(\n newHeight,\n )}px.`;\n }\n case 'videoFrameRateLimit': {\n // Not possible to detect this on client-side for now\n return t`Frame rate too high. Uploading might encounter issues.`;\n }\n }\n };\n\n return (\n <>\n <div class=\"media-attachment\">\n <div\n class=\"media-preview\"\n tabIndex=\"0\"\n onClick={() => {\n setShowModal(true);\n }}\n >\n {suffixType === 'image' ? (\n <img\n src={url}\n alt=\"\"\n onLoad={(e) => {\n if (!checkMaxError) return;\n const { naturalWidth, naturalHeight } = e.target;\n setImageMatrix({\n matrix: naturalWidth * naturalHeight,\n width: naturalWidth,\n height: naturalHeight,\n });\n }}\n />\n ) : suffixType === 'video' || suffixType === 'gifv' ? (\n <video\n src={url + '#t=0.1'} // Make Safari show 1st-frame preview\n playsinline\n muted\n disablePictureInPicture\n preload=\"metadata\"\n onLoadedMetadata={(e) => {\n if (!checkMaxError) return;\n const { videoWidth, videoHeight } = e.target;\n if (videoWidth && videoHeight) {\n setVideoMatrix({\n matrix: videoWidth * videoHeight,\n width: videoWidth,\n height: videoHeight,\n });\n }\n }}\n />\n ) : suffixType === 'audio' ? (\n <audio src={url} controls />\n ) : null}\n </div>\n {descTextarea}\n <div class=\"media-aside\">\n <button\n type=\"button\"\n class=\"plain close-button\"\n disabled={disabled}\n onClick={onRemove}\n >\n <Icon icon=\"x\" alt={t`Remove`} />\n </button>\n {!!maxError && (\n <button\n type=\"button\"\n class=\"media-error\"\n title={maxErrorText(maxError)}\n onClick={() => {\n if (maxErrorToast.current) {\n maxErrorToast.current.hideToast();\n }\n maxErrorToast.current = showToast({\n text: maxErrorText(maxError),\n duration: 10_000,\n });\n }}\n >\n <Icon icon=\"alert\" alt={t`Error`} />\n </button>\n )}\n </div>\n </div>\n {showModal && (\n <Modal\n onClose={() => {\n setShowModal(false);\n }}\n >\n <div id=\"media-sheet\" class=\"sheet sheet-max\">\n <button\n type=\"button\"\n class=\"sheet-close\"\n onClick={() => {\n setShowModal(false);\n }}\n >\n <Icon icon=\"x\" alt={t`Close`} />\n </button>\n <header>\n <h2>\n {\n {\n image: t`Edit image description`,\n video: t`Edit video description`,\n audio: t`Edit audio description`,\n }[suffixType]\n }\n </h2>\n </header>\n <main tabIndex=\"-1\">\n <div class=\"media-preview\">\n {suffixType === 'image' ? (\n <img src={url} alt=\"\" />\n ) : suffixType === 'video' || suffixType === 'gifv' ? (\n <video src={url} playsinline controls />\n ) : suffixType === 'audio' ? (\n <audio src={url} controls />\n ) : null}\n </div>\n <div class=\"media-form\">\n {descTextarea}\n <footer>\n {suffixType === 'image' &&\n /^(png|jpe?g|gif|webp)$/i.test(subtype) &&\n !!states.settings.mediaAltGenerator &&\n !!IMG_ALT_API_URL && (\n <Menu2\n portal={{\n target: document.body,\n }}\n containerProps={{\n style: {\n zIndex: 1001,\n },\n }}\n align=\"center\"\n position=\"anchor\"\n overflow=\"auto\"\n menuButton={\n <button type=\"button\" class=\"plain\">\n <Icon icon=\"more\" size=\"l\" alt={t`More`} />\n </button>\n }\n >\n <MenuItem\n disabled={uiState === 'loading'}\n onClick={() => {\n setUIState('loading');\n toastRef.current = showToast({\n text: t`Generating description. Please wait…`,\n duration: -1,\n });\n // POST with multipart\n (async function () {\n try {\n const body = new FormData();\n body.append('image', file);\n const response = await fetch(IMG_ALT_API_URL, {\n method: 'POST',\n body,\n }).then((r) => r.json());\n if (response.error) {\n throw new Error(response.error);\n }\n setDescription(response.description);\n } catch (e) {\n console.error(e);\n showToast(\n e.message\n ? t`Failed to generate description: ${e.message}`\n : t`Failed to generate description`,\n );\n } finally {\n setUIState('default');\n toastRef.current?.hideToast?.();\n }\n })();\n }}\n >\n <Icon icon=\"sparkles2\" />\n {lang && lang !== 'en' ? (\n <small>\n <Trans>Generate description…</Trans>\n <br />\n (English)\n </small>\n ) : (\n <span>\n <Trans>Generate description…</Trans>\n </span>\n )}\n </MenuItem>\n {!!lang && lang !== 'en' && (\n <MenuItem\n disabled={uiState === 'loading'}\n onClick={() => {\n setUIState('loading');\n toastRef.current = showToast({\n text: t`Generating description. Please wait…`,\n duration: -1,\n });\n // POST with multipart\n (async function () {\n try {\n const body = new FormData();\n body.append('image', file);\n const params = `?lang=${lang}`;\n const response = await fetch(\n IMG_ALT_API_URL + params,\n {\n method: 'POST',\n body,\n },\n ).then((r) => r.json());\n if (response.error) {\n throw new Error(response.error);\n }\n setDescription(response.description);\n } catch (e) {\n console.error(e);\n showToast(\n t`Failed to generate description${\n e?.message ? `: ${e.message}` : ''\n }`,\n );\n } finally {\n setUIState('default');\n toastRef.current?.hideToast?.();\n }\n })();\n }}\n >\n <Icon icon=\"sparkles2\" />\n <small>\n <Trans>Generate description…</Trans>\n <br />\n <Trans>\n ({localeCode2Text(lang)}){' '}\n <span class=\"more-insignificant\">\n — experimental\n </span>\n </Trans>\n </small>\n </MenuItem>\n )}\n </Menu2>\n )}\n <button\n type=\"button\"\n class=\"light block\"\n onClick={() => {\n setShowModal(false);\n }}\n disabled={uiState === 'loading'}\n >\n <Trans>Done</Trans>\n </button>\n </footer>\n </div>\n </main>\n </div>\n </Modal>\n )}\n </>\n );\n}\n\nexport default MediaAttachment;\n","import { Trans, useLingui } from '@lingui/react/macro';\nimport { useEffect, useRef, useState } from 'preact/hooks';\nimport { useHotkeys } from 'react-hotkeys-hook';\nimport { useDebouncedCallback } from 'use-debounce';\n\nimport { api } from '../utils/api';\nimport { fetchRelationships } from '../utils/relationships';\n\nimport AccountBlock from './account-block';\nimport Icon from './icon';\nimport Loader from './loader';\n\nfunction MentionModal({\n onClose = () => {},\n onSelect = () => {},\n defaultSearchTerm,\n}) {\n const { t } = useLingui();\n const { masto } = api();\n const [uiState, setUIState] = useState('default');\n const [accounts, setAccounts] = useState([]);\n const [relationshipsMap, setRelationshipsMap] = useState({});\n\n const [selectedIndex, setSelectedIndex] = useState(0);\n\n const loadRelationships = async (accounts) => {\n if (!accounts?.length) return;\n const relationships = await fetchRelationships(accounts, relationshipsMap);\n if (relationships) {\n setRelationshipsMap({\n ...relationshipsMap,\n ...relationships,\n });\n }\n };\n\n const loadAccounts = (term) => {\n if (!term) return;\n setUIState('loading');\n (async () => {\n try {\n const accounts = await masto.v1.accounts.search.list({\n q: term,\n limit: 40,\n resolve: false,\n });\n setAccounts(accounts);\n loadRelationships(accounts);\n setUIState('default');\n } catch (e) {\n setUIState('error');\n console.error(e);\n }\n })();\n };\n\n const debouncedLoadAccounts = useDebouncedCallback(loadAccounts, 1000);\n\n useEffect(() => {\n loadAccounts();\n }, [loadAccounts]);\n\n const inputRef = useRef();\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n // Put cursor at the end\n if (inputRef.current.value) {\n inputRef.current.selectionStart = inputRef.current.value.length;\n inputRef.current.selectionEnd = inputRef.current.value.length;\n }\n }\n }, []);\n\n useEffect(() => {\n if (defaultSearchTerm) {\n loadAccounts(defaultSearchTerm);\n }\n }, [defaultSearchTerm]);\n\n const selectAccount = (account) => {\n const socialAddress = account.acct;\n onSelect(socialAddress);\n onClose();\n };\n\n useHotkeys(\n 'enter',\n () => {\n const selectedAccount = accounts[selectedIndex];\n if (selectedAccount) {\n selectAccount(selectedAccount);\n }\n },\n {\n preventDefault: true,\n enableOnFormTags: ['input'],\n useKey: true,\n ignoreEventWhen: (e) => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey,\n },\n );\n\n const listRef = useRef();\n useHotkeys(\n 'down',\n () => {\n if (selectedIndex < accounts.length - 1) {\n setSelectedIndex(selectedIndex + 1);\n } else {\n setSelectedIndex(0);\n }\n setTimeout(() => {\n const selectedItem = listRef.current.querySelector('.selected');\n if (selectedItem) {\n selectedItem.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n inline: 'center',\n });\n }\n }, 1);\n },\n {\n preventDefault: true,\n enableOnFormTags: ['input'],\n useKey: true,\n ignoreEventWhen: (e) => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey,\n },\n );\n\n useHotkeys(\n 'up',\n () => {\n if (selectedIndex > 0) {\n setSelectedIndex(selectedIndex - 1);\n } else {\n setSelectedIndex(accounts.length - 1);\n }\n setTimeout(() => {\n const selectedItem = listRef.current.querySelector('.selected');\n if (selectedItem) {\n selectedItem.scrollIntoView({\n behavior: 'smooth',\n block: 'center',\n inline: 'center',\n });\n }\n }, 1);\n },\n {\n preventDefault: true,\n enableOnFormTags: ['input'],\n useKey: true,\n ignoreEventWhen: (e) => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey,\n },\n );\n\n return (\n <div id=\"mention-sheet\" class=\"sheet\">\n {!!onClose && (\n <button type=\"button\" class=\"sheet-close\" onClick={onClose}>\n <Icon icon=\"x\" alt={t`Close`} />\n </button>\n )}\n <header>\n <form\n onSubmit={(e) => {\n e.preventDefault();\n debouncedLoadAccounts.flush?.();\n // const searchTerm = inputRef.current.value;\n // debouncedLoadAccounts(searchTerm);\n }}\n >\n <input\n ref={inputRef}\n required\n type=\"search\"\n class=\"block\"\n placeholder={t`Search accounts`}\n onInput={(e) => {\n const { value } = e.target;\n debouncedLoadAccounts(value);\n }}\n autocomplete=\"off\"\n autocorrect=\"off\"\n autocapitalize=\"off\"\n spellCheck=\"false\"\n dir=\"auto\"\n defaultValue={defaultSearchTerm || ''}\n />\n </form>\n </header>\n <main>\n {accounts?.length > 0 ? (\n <ul\n ref={listRef}\n class={`accounts-list ${uiState === 'loading' ? 'loading' : ''}`}\n >\n {accounts.map((account, i) => {\n const relationship = relationshipsMap[account.id];\n return (\n <li\n key={account.id}\n class={i === selectedIndex ? 'selected' : ''}\n >\n <AccountBlock\n avatarSize=\"xxl\"\n account={account}\n relationship={relationship}\n showStats\n showActivity\n />\n <button\n type=\"button\"\n class=\"plain2\"\n onClick={() => {\n selectAccount(account);\n }}\n >\n <Icon icon=\"plus\" size=\"xl\" alt={t`Add`} />\n </button>\n </li>\n );\n })}\n </ul>\n ) : uiState === 'loading' ? (\n <div class=\"ui-state\">\n <Loader abrupt />\n </div>\n ) : uiState === 'error' ? (\n <div class=\"ui-state\">\n <p>\n <Trans>Error loading accounts</Trans>\n </p>\n </div>\n ) : null}\n </main>\n </div>\n );\n}\n\nexport default MentionModal;\n","import './quote-suggestion.css';\n\nimport { Trans } from '@lingui/react/macro';\n\nimport Status from './status';\n\nexport default function QuoteSuggestion({\n quoteSuggestion,\n hasCurrentQuoteStatus,\n onAccept,\n onCancel,\n}) {\n if (!quoteSuggestion) return null;\n\n return (\n <div class=\"quote-suggestion\">\n <div class=\"quote-suggestion-header\">\n <b>\n <Trans>Turn link into a quote?</Trans>\n </b>\n <div class=\"quote-suggestion-url\">{quoteSuggestion.url}</div>\n </div>\n <div class=\"quote-status\">\n <Status\n status={quoteSuggestion.status}\n instance={quoteSuggestion.instance}\n size=\"s\"\n readOnly\n />\n </div>\n <div class=\"quote-suggestion-actions\">\n <span class=\"spacer\" />\n <button type=\"button\" class=\"plain\" onClick={onCancel}>\n {hasCurrentQuoteStatus ? (\n <Trans>Cancel</Trans>\n ) : (\n <Trans>Keep as link</Trans>\n )}\n </button>\n <button type=\"button\" class=\"plain6\" onClick={onAccept}>\n {hasCurrentQuoteStatus ? (\n <Trans>Replace current quote</Trans>\n ) : (\n <Trans>Turn into quote</Trans>\n )}\n </button>\n </div>\n </div>\n );\n}\n","import './compose.css';\n\nimport { msg, plural } from '@lingui/core/macro';\nimport { Trans, useLingui } from '@lingui/react/macro';\nimport { MenuDivider, MenuItem } from '@szhsin/react-menu';\nimport { deepEqual } from 'fast-equals';\nimport { useEffect, useMemo, useRef, useState } from 'preact/hooks';\nimport { useHotkeys } from 'react-hotkeys-hook';\nimport stringLength from 'string-length';\nimport { uid } from 'uid/single';\nimport { useSnapshot } from 'valtio';\n\nimport supportedLanguages from '../data/status-supported-languages';\nimport { api, getPreferences } from '../utils/api';\nimport db from '../utils/db';\nimport { getDtfLocale } from '../utils/dtf-locale';\nimport localeMatch from '../utils/locale-match';\nimport localeCode2Text from '../utils/localeCode2Text';\nimport mem from '../utils/mem';\nimport openCompose from '../utils/open-compose';\nimport {\n getPostQuoteApprovalPolicy,\n supportsNativeQuote,\n} from '../utils/quote-utils';\nimport RTF from '../utils/relative-time-format';\nimport showToast from '../utils/show-toast';\nimport states, { saveStatus } from '../utils/states';\nimport store from '../utils/store';\nimport {\n getAPIVersions,\n getCurrentAccount,\n getCurrentAccountNS,\n getCurrentInstanceConfiguration,\n} from '../utils/store-utils';\nimport supports from '../utils/supports';\nimport unfurlMastodonLink from '../utils/unfurl-link';\nimport urlRegexObj from '../utils/url-regex';\nimport useCloseWatcher from '../utils/useCloseWatcher';\nimport useInterval from '../utils/useInterval';\nimport useThrottledResizeObserver from '../utils/useThrottledResizeObserver';\nimport visibilityIconsMap from '../utils/visibility-icons-map';\nimport visibilityText from '../utils/visibility-text';\n\nimport AccountBlock from './account-block';\n// import Avatar from './avatar';\nimport CameraCaptureInput, {\n supportsCameraCapture,\n} from './camera-capture-input';\nimport CharCountMeter from './char-count-meter';\nimport ComposePoll, { expiryOptions } from './compose-poll';\nimport Textarea from './compose-textarea';\nimport CustomEmojisModal from './custom-emojis-modal';\nimport FilePickerInput from './file-picker-input';\nimport GIFPickerModal from './gif-picker-modal';\nimport Icon from './icon';\nimport Loader from './loader';\nimport MediaAttachment from './media-attachment';\nimport MentionModal from './mention-modal';\nimport Menu2 from './menu2';\nimport Modal from './modal';\nimport QuoteSuggestion from './quote-suggestion';\nimport ScheduledAtField, {\n getLocalTimezoneName,\n MIN_SCHEDULED_AT,\n} from './ScheduledAtField';\nimport Status from './status';\nimport TextExpander from './text-expander';\n\nconst supportedLanguagesMap = supportedLanguages.reduce((acc, l) => {\n const [code, common, native] = l;\n acc[code] = {\n common,\n native,\n };\n return acc;\n}, {});\n\n/* NOTES:\n - Max character limit includes BOTH status text and Content Warning text\n*/\n\nconst expirySeconds = Object.keys(expiryOptions);\nconst oneDay = 24 * 60 * 60;\n\nconst expiresInFromExpiresAt = (expiresAt) => {\n if (!expiresAt) return oneDay;\n const delta = (Date.parse(expiresAt) - Date.now()) / 1000;\n return expirySeconds.find((s) => s >= delta) || oneDay;\n};\n\nconst DEFAULT_LANG = localeMatch(\n [getDtfLocale(), ...navigator.languages],\n supportedLanguages.map((l) => l[0]),\n 'en',\n);\n\n// https://github.com/mastodon/mastodon/blob/c4a429ed47e85a6bbf0d470a41cc2f64cf120c19/app/javascript/mastodon/features/compose/util/counter.js\nconst usernameRegex = /(^|[^\\/\\w])[@](([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)/gi;\nconst urlPlaceholder = '$2xxxxxxxxxxxxxxxxxxxxxxx';\nfunction countableText(inputText) {\n return inputText\n .replace(urlRegexObj, urlPlaceholder)\n .replace(usernameRegex, '$1@$3');\n}\n\n// const rtf = new Intl.RelativeTimeFormat();\nconst LF = mem((locale) => new Intl.ListFormat(locale || undefined));\n\nconst ADD_LABELS = {\n camera: msg`Take photo or video`,\n media: msg`Add media`,\n customEmoji: msg`Add custom emoji`,\n gif: msg`Add GIF`,\n poll: msg`Add poll`,\n sensitive: msg`Add content warning`,\n scheduledPost: msg`Schedule post`,\n};\n\nconst DEFAULT_SCHEDULED_AT = Math.max(10 * 60 * 1000, MIN_SCHEDULED_AT); // 10 mins\n\nfunction Compose({\n onClose,\n replyToStatus,\n replyMode = 'all',\n editStatus,\n draftStatus,\n quoteStatus,\n standalone,\n hasOpener,\n}) {\n const { i18n, _, t } = useLingui();\n const rtf = RTF(i18n.locale);\n const lf = LF(i18n.locale);\n\n console.warn('RENDER COMPOSER');\n const { masto, instance } = api();\n const [uiState, setUIState] = useState('default');\n const UID = useRef(draftStatus?.uid || uid());\n console.log('Compose UID', UID.current);\n\n const currentAccount = useMemo(getCurrentAccount, []);\n const currentAccountInfo = currentAccount.info;\n\n const configuration = getCurrentInstanceConfiguration();\n console.log('⚙️ Configuration', configuration);\n\n const {\n statuses: {\n maxCharacters,\n maxMediaAttachments, // Beware: it can be undefined!\n charactersReservedPerUrl,\n } = {},\n mediaAttachments: {\n supportedMimeTypes,\n imageSizeLimit,\n imageMatrixLimit,\n videoSizeLimit,\n videoMatrixLimit,\n videoFrameRateLimit,\n descriptionLimit,\n } = {},\n polls: {\n maxOptions,\n maxCharactersPerOption,\n maxExpiration,\n minExpiration,\n } = {},\n } = configuration || {};\n const supportedImagesVideosTypes = supportedMimeTypes?.filter((mimeType) =>\n /^(image|video)/i.test(mimeType),\n );\n\n const textareaRef = useRef();\n const spoilerTextRef = useRef();\n\n const [visibility, setVisibility] = useState('public');\n const [quoteApprovalPolicy, setQuoteApprovalPolicy] = useState('public');\n const [sensitive, setSensitive] = useState(false);\n const [sensitiveMedia, setSensitiveMedia] = useState(false);\n const [language, setLanguage] = useState(\n store.session.get('currentLanguage') || DEFAULT_LANG,\n );\n const prevLanguage = useRef(language);\n const [mediaAttachments, setMediaAttachments] = useState([]);\n const [poll, setPoll] = useState(null);\n const [scheduledAt, setScheduledAt] = useState(null);\n const [quoteSuggestion, setQuoteSuggestion] = useState(null);\n const [localQuoteStatus, setLocalQuoteStatus] = useState(quoteStatus);\n const [quoteCleared, setQuoteCleared] = useState(false);\n\n const prefs = getPreferences();\n\n const currentQuoteStatus = quoteCleared\n ? null\n : localQuoteStatus || quoteStatus;\n\n // Quote eligibility logic duplicated from status.jsx\n const checkQuoteEligibility = (status) => {\n if (!supportsNativeQuote()) return false;\n\n const { visibility, quoteApproval, account } = status;\n const isSelf = currentAccountInfo && currentAccountInfo.id === account.id;\n const isPublic = ['public', 'unlisted'].includes(visibility);\n const isMineAndPrivate = isSelf && visibility === 'private';\n\n const isQuoteAutomaticallyAccepted =\n quoteApproval?.currentUser === 'automatic' &&\n (isPublic || isMineAndPrivate);\n const isQuoteManuallyAccepted =\n quoteApproval?.currentUser === 'manual' && (isPublic || isMineAndPrivate);\n\n if (!isPublic && !isSelf) {\n return false;\n } else if (isQuoteAutomaticallyAccepted) {\n return true;\n } else if (isQuoteManuallyAccepted) {\n return true;\n } else {\n return false;\n }\n };\n\n const handlePastedLink = async (url) => {\n // Handle QP links\n if (supportsNativeQuote()) {\n // Quotes cannot coexist with media attachments or polls\n if (mediaAttachments.length > 0 || poll) {\n return;\n }\n\n // Cannot add/remove/replace current quote when editing\n if (editStatus) {\n return;\n }\n\n // Don't show quote suggestion when visibility is 'direct'\n if (visibility === 'direct') {\n return;\n }\n\n try {\n const unfurledData = await unfurlMastodonLink(instance, url);\n if (unfurledData?.id) {\n const status =\n states.statuses[`${unfurledData.instance}/${unfurledData.id}`];\n if (status && checkQuoteEligibility(status)) {\n // Don't show suggestion if it's the same as current quote\n if (currentQuoteStatus?.id === status.id) {\n return;\n }\n\n setQuoteSuggestion({\n status,\n instance: unfurledData.instance,\n url: unfurledData.originalURL,\n });\n }\n }\n } catch (error) {\n console.error(error);\n }\n }\n };\n\n const oninputTextarea = () => {\n if (!textareaRef.current) return;\n textareaRef.current.dispatchEvent(new Event('input'));\n };\n const focusTextarea = (cursorPosition) => {\n setTimeout(() => {\n if (!textareaRef.current) return;\n // If cursor position is provided, set it\n if (cursorPosition !== undefined) {\n textareaRef.current.setSelectionRange(cursorPosition, cursorPosition);\n }\n console.debug('FOCUS textarea');\n textareaRef.current?.focus();\n }, 300);\n };\n const insertTextAtCursor = ({ targetElement, text }) => {\n if (!targetElement) return;\n\n const { selectionStart, selectionEnd, value } = targetElement;\n let textBeforeInsert = value.slice(0, selectionStart);\n\n // Remove zero-width space from end of text\n textBeforeInsert = textBeforeInsert.replace(/\\u200B$/, '');\n\n const spaceBeforeInsert = textBeforeInsert\n ? /[\\s\\t\\n\\r]$/.test(textBeforeInsert)\n ? ''\n : ' '\n : '';\n\n const textAfterInsert = value.slice(selectionEnd);\n const spaceAfterInsert = /^[\\s\\t\\n\\r]/.test(textAfterInsert) ? '' : ' ';\n\n const newText =\n textBeforeInsert +\n spaceBeforeInsert +\n text +\n spaceAfterInsert +\n textAfterInsert;\n\n targetElement.value = newText;\n targetElement.selectionStart = targetElement.selectionEnd =\n selectionEnd + text.length + spaceAfterInsert.length;\n targetElement.focus();\n targetElement.dispatchEvent(new Event('input'));\n };\n\n const lastFocusedFieldRef = useRef(null);\n const lastFocusedEmojiFieldRef = useRef(null);\n const focusLastFocusedField = () => {\n setTimeout(() => {\n if (!lastFocusedFieldRef.current) return;\n lastFocusedFieldRef.current.focus();\n }, 0);\n };\n const composeContainerRef = useRef(null);\n useEffect(() => {\n const handleFocus = (e) => {\n // Toggle focused if in or out if any fields are focused\n composeContainerRef.current.classList.toggle(\n 'focused',\n e.type === 'focusin',\n );\n\n const target = e.target;\n if (target.hasAttribute('data-allow-custom-emoji')) {\n lastFocusedEmojiFieldRef.current = target;\n }\n const isFormElement = ['INPUT', 'BUTTON', 'SELECT', 'TEXTAREA'].includes(\n target.tagName,\n );\n if (isFormElement) {\n lastFocusedFieldRef.current = target;\n }\n };\n\n const composeContainer = composeContainerRef.current;\n if (composeContainer) {\n composeContainer.addEventListener('focusin', handleFocus);\n composeContainer.addEventListener('focusout', handleFocus);\n }\n\n return () => {\n if (composeContainer) {\n composeContainer.removeEventListener('focusin', handleFocus);\n composeContainer.removeEventListener('focusout', handleFocus);\n }\n };\n }, []);\n\n useEffect(() => {\n if (replyToStatus) {\n const { spoilerText, visibility, language, sensitive } = replyToStatus;\n if (spoilerText && spoilerTextRef.current) {\n spoilerTextRef.current.value = spoilerText;\n }\n const mentions = new Set([\n replyToStatus.account.acct,\n ...replyToStatus.mentions.map((m) => m.acct),\n ]);\n const allMentions = [...mentions].filter(\n (m) => m !== currentAccountInfo.acct,\n );\n\n if (allMentions.length > 0) {\n const authorMention = `@${replyToStatus.account.acct}`;\n const otherMentions = allMentions\n .filter((m) => m !== replyToStatus.account.acct)\n .map((m) => `@${m}`);\n\n if (replyMode === 'author-only') {\n // Mode 1: Only mention the author\n textareaRef.current.value = `${authorMention} `;\n oninputTextarea();\n focusTextarea();\n } else if (replyMode === 'author-first') {\n // Mode 2: Mention author first, then others at the end after 2 newlines\n if (otherMentions.length > 0) {\n textareaRef.current.value = `${authorMention} \\n\\n${otherMentions.join(' ')}`;\n oninputTextarea();\n // Set cursor position after the author mention\n const cursorPosition = authorMention.length + 1; // +1 for the space\n focusTextarea(cursorPosition);\n } else {\n // If no other mentions, just mention the author\n textareaRef.current.value = `${authorMention} `;\n oninputTextarea();\n focusTextarea();\n }\n } else {\n // Mode 3 (default 'all'): All mentions at the beginning\n textareaRef.current.value = `${allMentions\n .map((m) => `@${m}`)\n .join(' ')} `;\n oninputTextarea();\n focusTextarea();\n }\n }\n setVisibility(\n visibility === 'public' && prefs['posting:default:visibility']\n ? prefs['posting:default:visibility'].toLowerCase()\n : visibility,\n );\n setLanguage(\n language ||\n prefs['posting:default:language']?.toLowerCase() ||\n DEFAULT_LANG,\n );\n setSensitive(!!spoilerText);\n } else if (editStatus) {\n const {\n visibility,\n language,\n sensitive,\n poll,\n mediaAttachments,\n quoteApproval,\n } = editStatus;\n const composablePoll = !!poll?.options && {\n ...poll,\n options: poll.options.map((o) => o?.title || o),\n expiresIn: poll?.expiresIn || expiresInFromExpiresAt(poll.expiresAt),\n };\n setUIState('loading');\n (async () => {\n try {\n const statusSource = await masto.v1.statuses\n .$select(editStatus.id)\n .source.fetch();\n console.log({ statusSource });\n const { text, spoilerText } = statusSource;\n textareaRef.current.value = text;\n textareaRef.current.dataset.source = text;\n oninputTextarea();\n focusTextarea();\n spoilerTextRef.current.value = spoilerText;\n setVisibility(visibility);\n setLanguage(\n language ||\n prefs['posting:default:language']?.toLowerCase() ||\n DEFAULT_LANG,\n );\n if (supportsNativeQuote()) {\n const postQuoteApprovalPolicy =\n getPostQuoteApprovalPolicy(quoteApproval);\n setQuoteApprovalPolicy(postQuoteApprovalPolicy);\n }\n setSensitive(sensitive);\n if (composablePoll) setPoll(composablePoll);\n setMediaAttachments(mediaAttachments);\n setUIState('default');\n } catch (e) {\n console.error(e);\n alert(e?.reason || e);\n setUIState('error');\n }\n })();\n } else {\n focusTextarea();\n console.log('Apply prefs', prefs);\n if (prefs['posting:default:visibility']) {\n setVisibility(prefs['posting:default:visibility'].toLowerCase());\n }\n if (prefs['posting:default:language']) {\n setLanguage(prefs['posting:default:language'].toLowerCase());\n }\n if (prefs['posting:default:sensitive']) {\n setSensitive(!!prefs['posting:default:sensitive']);\n }\n if (prefs['posting:default:quote_policy']) {\n let policy = prefs['posting:default:quote_policy'].toLowerCase();\n if (prefs['posting:default:visibility']) {\n const visibility = prefs['posting:default:visibility'].toLowerCase();\n if (visibility === 'private' || visibility === 'direct') {\n policy = 'nobody';\n }\n }\n setQuoteApprovalPolicy(policy);\n }\n }\n if (draftStatus) {\n const {\n status,\n spoilerText,\n visibility,\n language,\n sensitive,\n sensitiveMedia,\n poll,\n mediaAttachments,\n scheduledAt,\n quoteApprovalPolicy,\n } = draftStatus;\n const composablePoll = !!poll?.options && {\n ...poll,\n options: poll.options.map((o) => o?.title || o),\n expiresIn: poll?.expiresIn || expiresInFromExpiresAt(poll.expiresAt),\n };\n textareaRef.current.value = status;\n oninputTextarea();\n // status starts with newline or space, focus on first position\n const cursorPos = /^\\n|\\s/.test(status) ? 0 : undefined;\n focusTextarea(cursorPos);\n if (spoilerText) spoilerTextRef.current.value = spoilerText;\n if (visibility) setVisibility(visibility);\n setLanguage(\n language ||\n prefs['posting:default:language']?.toLowerCase() ||\n DEFAULT_LANG,\n );\n if (sensitiveMedia !== null) setSensitiveMedia(sensitiveMedia);\n if (sensitive !== null) setSensitive(sensitive);\n if (composablePoll) setPoll(composablePoll);\n if (mediaAttachments) setMediaAttachments(mediaAttachments);\n if (scheduledAt) setScheduledAt(scheduledAt);\n if (quoteApprovalPolicy) setQuoteApprovalPolicy(quoteApprovalPolicy);\n }\n }, [draftStatus, editStatus, replyToStatus, replyMode]);\n\n // focus textarea when state.composerState.minimized turns false\n const snapStates = useSnapshot(states);\n useEffect(() => {\n if (!snapStates.composerState.minimized) {\n focusTextarea();\n }\n }, [snapStates.composerState.minimized]);\n\n const formRef = useRef();\n\n const beforeUnloadCopy = t`You have unsaved changes. Discard this post?`;\n const canClose = () => {\n const { value, dataset } = textareaRef.current;\n\n // check if loading\n if (uiState === 'loading') {\n console.log('canClose', { uiState });\n return false;\n }\n\n // check for status and media attachments\n const hasValue = (value || '')\n .trim()\n .replace(/^\\p{White_Space}+|\\p{White_Space}+$/gu, '');\n const hasMediaAttachments = mediaAttachments.length > 0;\n if (!hasValue && !hasMediaAttachments) {\n console.log('canClose', { value, mediaAttachments });\n return true;\n }\n\n // check if all media attachments have IDs\n const hasIDMediaAttachments =\n mediaAttachments.length > 0 &&\n mediaAttachments.every((media) => media.id);\n if (hasIDMediaAttachments) {\n console.log('canClose', { hasIDMediaAttachments });\n return true;\n }\n\n // check if status contains only \"@acct\", if replying\n const isSelf = replyToStatus?.account.id === currentAccountInfo.id;\n const hasOnlyAcct =\n replyToStatus && value.trim() === `@${replyToStatus.account.acct}`;\n // TODO: check for mentions, or maybe just generic \"@username<space>\", including multiple mentions like \"@username1<space>@username2<space>\"\n if (!isSelf && hasOnlyAcct) {\n console.log('canClose', { isSelf, hasOnlyAcct });\n return true;\n }\n\n // check if status is same with source\n const sameWithSource = value === dataset?.source;\n if (sameWithSource) {\n console.log('canClose', { sameWithSource });\n return true;\n }\n\n console.log('canClose', {\n value,\n hasMediaAttachments,\n hasIDMediaAttachments,\n poll,\n isSelf,\n hasOnlyAcct,\n sameWithSource,\n uiState,\n });\n\n return false;\n };\n\n const confirmClose = () => {\n if (!canClose()) {\n const yes = confirm(beforeUnloadCopy);\n return yes;\n }\n return true;\n };\n\n useEffect(() => {\n // Show warning if user tries to close window with unsaved changes\n const handleBeforeUnload = (e) => {\n if (!canClose()) {\n e.preventDefault();\n e.returnValue = beforeUnloadCopy;\n }\n };\n window.addEventListener('beforeunload', handleBeforeUnload, {\n capture: true,\n });\n return () =>\n window.removeEventListener('beforeunload', handleBeforeUnload, {\n capture: true,\n });\n }, []);\n\n const getCharCount = () => {\n const { value } = textareaRef.current;\n const { value: spoilerText } = spoilerTextRef.current;\n return stringLength(countableText(value)) + stringLength(spoilerText);\n };\n const updateCharCount = () => {\n const count = getCharCount();\n states.composerCharacterCount = count;\n };\n useEffect(updateCharCount, []);\n\n const supportsCloseWatcher = window.CloseWatcher;\n const escDownRef = useRef(false);\n useHotkeys(\n 'esc',\n () => {\n escDownRef.current = true;\n // This won't be true if this event is already handled and not propagated 🤞\n },\n {\n enabled: !supportsCloseWatcher,\n enableOnFormTags: true,\n useKey: true,\n ignoreEventWhen: (e) => e.metaKey || e.ctrlKey || e.altKey || e.shiftKey,\n },\n );\n useHotkeys(\n 'esc',\n () => {\n if (!standalone && escDownRef.current && confirmClose()) {\n onClose();\n }\n escDownRef.current = false;\n },\n {\n enabled: !supportsCloseWatcher,\n enableOnFormTags: true,\n // Use keyup because Esc keydown will close the confirm dialog on Safari\n keyup: true,\n ignoreEventWhen: (e) => {\n const modals = document.querySelectorAll('#modal-container > *');\n const hasModal = !!modals;\n const hasOnlyComposer =\n modals.length === 1 && modals[0].querySelector('#compose-container');\n return (\n (hasModal && !hasOnlyComposer) ||\n e.metaKey ||\n e.ctrlKey ||\n e.altKey ||\n e.shiftKey\n );\n },\n useKey: true,\n },\n );\n useCloseWatcher(() => {\n if (!standalone && confirmClose()) {\n onClose();\n }\n }, []);\n\n const prevBackgroundDraft = useRef({});\n const draftKey = () => {\n const ns = getCurrentAccountNS();\n return `${ns}#${UID.current}`;\n };\n const saveUnsavedDraft = () => {\n // Not enabling this for editing status\n // I don't think this warrant a draft mode for a status that's already posted\n // Maybe it could be a big edit change but it should be rare\n if (editStatus) return;\n if (states.composerState.minimized) return;\n const key = draftKey();\n const backgroundDraft = {\n key,\n replyTo: replyToStatus\n ? {\n /* Smaller payload of replyToStatus. Reasons:\n - No point storing whole thing\n - Could have media attachments\n - Could be deleted/edited later\n */\n id: replyToStatus.id,\n account: {\n id: replyToStatus.account.id,\n username: replyToStatus.account.username,\n acct: replyToStatus.account.acct,\n },\n }\n : null,\n draftStatus: {\n uid: UID.current,\n status: textareaRef.current.value,\n spoilerText: spoilerTextRef.current.value,\n visibility,\n language,\n sensitive,\n sensitiveMedia,\n poll,\n mediaAttachments,\n scheduledAt,\n quoteApprovalPolicy,\n },\n quote: currentQuoteStatus?.id\n ? {\n // Smaller payload, same reason as replyTo\n id: currentQuoteStatus.id,\n }\n : null,\n };\n if (\n !deepEqual(backgroundDraft, prevBackgroundDraft.current) &&\n !canClose()\n ) {\n console.debug('not equal', backgroundDraft, prevBackgroundDraft.current);\n db.drafts\n .set(key, {\n ...backgroundDraft,\n state: 'unsaved',\n updatedAt: Date.now(),\n })\n .then(() => {\n console.debug('DRAFT saved', key, backgroundDraft);\n })\n .catch((e) => {\n console.error('DRAFT failed', key, e);\n });\n prevBackgroundDraft.current = structuredClone(backgroundDraft);\n }\n };\n useInterval(saveUnsavedDraft, 5000); // background save every 5s\n useEffect(() => {\n saveUnsavedDraft();\n // If unmounted, means user discarded the draft\n // Also means pop-out 🙈, but it's okay because the pop-out will persist the ID and re-create the draft\n return () => {\n db.drafts.del(draftKey());\n };\n }, []);\n\n useEffect(() => {\n const handleItems = (e) => {\n // Ignore drops when a sheet is open\n if (document.querySelector('.sheet')) return;\n\n const { items } = e.clipboardData || e.dataTransfer;\n const files = [];\n const unsupportedFiles = [];\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (item.kind === 'file') {\n const file = item.getAsFile();\n if (\n supportedMimeTypes !== undefined &&\n !supportedMimeTypes.includes(file.type)\n ) {\n unsupportedFiles.push(file);\n } else {\n files.push(file);\n }\n }\n }\n if (unsupportedFiles.length > 0) {\n alert(\n plural(unsupportedFiles.length, {\n one: `File ${unsupportedFiles[0].name} is not supported.`,\n other: `Files ${lf.format(\n unsupportedFiles.map((f) => f.name),\n )} are not supported.`,\n }),\n );\n }\n if (files.length > 0 && mediaAttachments.length >= maxMediaAttachments) {\n alert(\n plural(maxMediaAttachments, {\n one: 'You can only attach up to 1 file.',\n other: 'You can only attach up to # files.',\n }),\n );\n return;\n }\n console.log({ files });\n if (files.length > 0) {\n e.preventDefault();\n e.stopPropagation();\n // Auto-cut-off files to avoid exceeding maxMediaAttachments\n let allowedFiles = files;\n if (maxMediaAttachments !== undefined) {\n const max = maxMediaAttachments - mediaAttachments.length;\n allowedFiles = allowedFiles.slice(0, max);\n if (allowedFiles.length <= 0) {\n alert(\n plural(maxMediaAttachments, {\n one: 'You can only attach up to 1 file.',\n other: 'You can only attach up to # files.',\n }),\n );\n return;\n }\n }\n const mediaFiles = allowedFiles.map((file) => ({\n file,\n type: file.type,\n size: file.size,\n url: URL.createObjectURL(file),\n id: null,\n description: null,\n }));\n setMediaAttachments([...mediaAttachments, ...mediaFiles]);\n }\n };\n window.addEventListener('paste', handleItems);\n const handleDragover = (e) => {\n // Prevent default if there's files\n if (e.dataTransfer.items.length > 0) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n window.addEventListener('dragover', handleDragover);\n window.addEventListener('drop', handleItems);\n return () => {\n window.removeEventListener('paste', handleItems);\n window.removeEventListener('dragover', handleDragover);\n window.removeEventListener('drop', handleItems);\n };\n }, [mediaAttachments]);\n\n const [showMentionPicker, setShowMentionPicker] = useState(false);\n const [showEmoji2Picker, setShowEmoji2Picker] = useState(false);\n const [showGIFPicker, setShowGIFPicker] = useState(false);\n\n const [autoDetectedLanguages, setAutoDetectedLanguages] = useState(null);\n const [topSupportedLanguages, restSupportedLanguages] = useMemo(() => {\n const topLanguages = [];\n const restLanguages = [];\n const { contentTranslationHideLanguages = [] } = states.settings;\n supportedLanguages.forEach((l) => {\n const [code] = l;\n if (\n code === language ||\n code === prevLanguage.current ||\n code === DEFAULT_LANG ||\n contentTranslationHideLanguages.includes(code) ||\n (autoDetectedLanguages?.length && autoDetectedLanguages.includes(code))\n ) {\n topLanguages.push(l);\n } else {\n restLanguages.push(l);\n }\n });\n topLanguages.sort(([codeA, commonA], [codeB, commonB]) => {\n if (codeA === language) return -1;\n if (codeB === language) return 1;\n return commonA.localeCompare(commonB);\n });\n restLanguages.sort(([codeA, commonA], [codeB, commonB]) =>\n commonA.localeCompare(commonB),\n );\n return [topLanguages, restLanguages];\n }, [language, autoDetectedLanguages]);\n\n const replyToStatusMonthsAgo = useMemo(\n () =>\n !!replyToStatus?.createdAt &&\n Math.floor(\n (Date.now() - Date.parse(replyToStatus.createdAt)) /\n (1000 * 60 * 60 * 24 * 30),\n ),\n [replyToStatus],\n );\n\n const onMinimize = () => {\n saveUnsavedDraft();\n states.composerState.minimized = true;\n };\n\n const mediaButtonDisabled =\n uiState === 'loading' ||\n (maxMediaAttachments !== undefined &&\n mediaAttachments.length >= maxMediaAttachments) ||\n !!poll; /* ||\n !!currentQuoteStatus?.id; */\n\n const cwButtonDisabled = uiState === 'loading' || !!sensitive;\n const onCWButtonClick = () => {\n setSensitive(true);\n setTimeout(() => {\n spoilerTextRef.current?.focus();\n }, 0);\n };\n\n // If maxOptions is not defined or defined and is greater than 1, show poll button\n const showPollButton = maxOptions == null || maxOptions > 1;\n const pollButtonDisabled =\n uiState === 'loading' || !!poll || !!mediaAttachments.length; /* ||\n !!currentQuoteStatus?.id; */\n const onPollButtonClick = () => {\n setPoll({\n options: ['', ''],\n expiresIn: 24 * 60 * 60, // 1 day\n multiple: false,\n });\n // Focus first choice field\n setTimeout(() => {\n composeContainerRef.current\n ?.querySelector('.poll-choice input[type=\"text\"]')\n ?.focus();\n }, 0);\n };\n\n const highlightLanguageField =\n language !== prevLanguage.current ||\n (autoDetectedLanguages?.length &&\n !autoDetectedLanguages.includes(language));\n const highlightVisibilityField = visibility !== 'public';\n\n const highlightQuoteApprovalPolicyField = quoteApprovalPolicy !== 'public';\n const disableQuotePolicy =\n visibility === 'private' || visibility === 'direct';\n\n const addSubToolbarRef = useRef();\n const [showAddButton, setShowAddButton] = useState(true);\n const BUTTON_WIDTH = 42; // roughly one button width\n useThrottledResizeObserver({\n ref: addSubToolbarRef,\n box: 'border-box',\n onResize: ({ width }) => {\n // If scrollable, it's truncated\n const { scrollWidth } = addSubToolbarRef.current;\n const truncated = scrollWidth > width;\n const overTruncated = width < BUTTON_WIDTH * 4;\n setShowAddButton(overTruncated || truncated);\n addSubToolbarRef.current.hidden = overTruncated;\n },\n });\n\n const showScheduledAt = !editStatus;\n const scheduledAtButtonDisabled = uiState === 'loading' || !!scheduledAt;\n const onScheduledAtClick = () => {\n const date = new Date(Date.now() + DEFAULT_SCHEDULED_AT);\n setScheduledAt(date);\n };\n\n return (\n <div id=\"compose-container-outer\" ref={composeContainerRef}>\n <div\n id=\"compose-container\"\n tabIndex={-1}\n class={standalone ? 'standalone' : ''}\n >\n <div class=\"compose-top\">\n {currentAccountInfo?.avatarStatic && (\n // <Avatar\n // url={currentAccountInfo.avatarStatic}\n // size=\"xl\"\n // alt={currentAccountInfo.username}\n // squircle={currentAccountInfo?.bot}\n // />\n <AccountBlock\n account={currentAccountInfo}\n accountInstance={currentAccount.instanceURL}\n hideDisplayName\n useAvatarStatic\n />\n )}\n {!standalone ? (\n <span class=\"compose-controls\">\n <button\n type=\"button\"\n class=\"plain4 pop-button\"\n disabled={uiState === 'loading'}\n onClick={() => {\n // If there are non-ID media attachments (not yet uploaded), show confirmation dialog because they are not going to be passed to the new window\n // const containNonIDMediaAttachments =\n // mediaAttachments.length > 0 &&\n // mediaAttachments.some((media) => !media.id);\n // if (containNonIDMediaAttachments) {\n // const yes = confirm(\n // 'You have media attachments that are not yet uploaded. Opening a new window will discard them and you will need to re-attach them. Are you sure you want to continue?',\n // );\n // if (!yes) {\n // return;\n // }\n // }\n\n // const mediaAttachmentsWithIDs = mediaAttachments.filter(\n // (media) => media.id,\n // );\n\n const newWin = openCompose({\n editStatus,\n replyToStatus,\n draftStatus: {\n uid: UID.current,\n status: textareaRef.current.value,\n spoilerText: spoilerTextRef.current.value,\n visibility,\n language,\n sensitive,\n poll,\n mediaAttachments,\n scheduledAt,\n },\n quoteStatus: currentQuoteStatus,\n });\n\n if (!newWin) {\n return;\n }\n\n onClose();\n }}\n >\n <Icon icon=\"popout\" alt={t`Pop out`} />\n </button>\n <button\n type=\"button\"\n class=\"plain4 min-button\"\n onClick={onMinimize}\n >\n <Icon icon=\"minimize\" alt={t`Minimize`} />\n </button>{' '}\n <button\n type=\"button\"\n class=\"plain4 close-button\"\n disabled={uiState === 'loading'}\n onClick={() => {\n if (confirmClose()) {\n onClose();\n }\n }}\n >\n <Icon icon=\"x\" alt={t`Close`} />\n </button>\n </span>\n ) : (\n hasOpener && (\n <button\n type=\"button\"\n class=\"light pop-button\"\n disabled={uiState === 'loading'}\n onClick={() => {\n // If there are non-ID media attachments (not yet uploaded), show confirmation dialog because they are not going to be passed to the new window\n // const containNonIDMediaAttachments =\n // mediaAttachments.length > 0 &&\n // mediaAttachments.some((media) => !media.id);\n // if (containNonIDMediaAttachments) {\n // const yes = confirm(\n // 'You have media attachments that are not yet uploaded. Opening a new window will discard them and you will need to re-attach them. Are you sure you want to continue?',\n // );\n // if (!yes) {\n // return;\n // }\n // }\n\n if (!window.opener) {\n alert(t`Looks like you closed the parent window.`);\n return;\n }\n\n if (window.opener.__STATES__.showCompose) {\n if (window.opener.__STATES__.composerState?.publishing) {\n alert(\n t`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.`,\n );\n return;\n }\n\n let confirmText = t`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?`;\n const yes = confirm(confirmText);\n if (!yes) return;\n }\n\n // const mediaAttachmentsWithIDs = mediaAttachments.filter(\n // (media) => media.id,\n // );\n\n onClose({\n fn: () => {\n const passData = {\n editStatus,\n replyToStatus,\n replyMode,\n draftStatus: {\n uid: UID.current,\n status: textareaRef.current.value,\n spoilerText: spoilerTextRef.current.value,\n visibility,\n language,\n sensitive,\n sensitiveMedia,\n poll,\n mediaAttachments,\n scheduledAt,\n },\n quoteStatus: currentQuoteStatus,\n };\n window.opener.__COMPOSE__ = passData; // Pass it here instead of `showCompose` due to some weird proxy issue again\n if (window.opener.__STATES__.showCompose) {\n window.opener.__STATES__.showCompose = false;\n setTimeout(() => {\n window.opener.__STATES__.showCompose = true;\n }, 10);\n } else {\n window.opener.__STATES__.showCompose = true;\n }\n if (window.opener.__STATES__.composerState.minimized) {\n // Maximize it\n window.opener.__STATES__.composerState.minimized = false;\n }\n },\n });\n }}\n >\n <Icon icon=\"popin\" alt={t`Pop in`} />\n </button>\n )\n )}\n </div>\n {!!replyToStatus && (\n <details class=\"status-preview\" open>\n <Status status={replyToStatus} size=\"s\" previewMode />\n <summary class=\"status-preview-legend reply-to\">\n {replyToStatusMonthsAgo > 0 ? (\n <Trans>\n Replying to @\n {replyToStatus.account.acct || replyToStatus.account.username}\n &rsquo;s post (\n <strong>\n {rtf.format(-replyToStatusMonthsAgo, 'month')}\n </strong>\n )\n </Trans>\n ) : (\n <Trans>\n Replying to @\n {replyToStatus.account.acct || replyToStatus.account.username}\n &rsquo;s post\n </Trans>\n )}\n </summary>\n </details>\n )}\n {!!editStatus && (\n <details class=\"status-preview\">\n <Status status={editStatus} size=\"s\" previewMode />\n <summary class=\"status-preview-legend\">\n <Trans>Editing source post</Trans>\n </summary>\n </details>\n )}\n <form\n ref={formRef}\n class={`form-visibility-${visibility}`}\n style={{\n pointerEvents: uiState === 'loading' ? 'none' : 'auto',\n opacity: uiState === 'loading' ? 0.5 : 1,\n }}\n onClick={() => {\n setTimeout(() => {\n if (!document.activeElement) {\n lastFocusedFieldRef.current?.focus?.();\n }\n }, 10);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {\n formRef.current.dispatchEvent(\n new Event('submit', { cancelable: true }),\n );\n }\n }}\n onSubmit={(e) => {\n e.preventDefault();\n\n const formData = new FormData(e.target);\n const entries = Object.fromEntries(formData.entries());\n console.log('ENTRIES', entries);\n let {\n status,\n visibility,\n sensitive,\n sensitiveMedia,\n spoilerText,\n scheduledAt,\n quoteApprovalPolicy,\n } = entries;\n\n // Pre-cleanup\n // checkboxes return \"on\" if checked\n sensitive = sensitive === 'on';\n sensitiveMedia = sensitiveMedia === 'on';\n\n // Convert datetime-local input value to RFC3339 Date string value\n scheduledAt = scheduledAt\n ? new Date(scheduledAt).toISOString()\n : undefined;\n\n // Validation\n /* Let the backend validate this\n if (stringLength(status) > maxCharacters) {\n alert(`Status is too long! Max characters: ${maxCharacters}`);\n return;\n }\n if (\n sensitive &&\n stringLength(status) + stringLength(spoilerText) > maxCharacters\n ) {\n alert(\n `Status and content warning is too long! Max characters: ${maxCharacters}`,\n );\n return;\n }\n */\n if (poll) {\n if (poll.options.length < 2) {\n alert(t`Poll must have at least 2 options`);\n return;\n }\n if (poll.options.some((option) => option === '')) {\n alert(t`Some poll choices are empty`);\n return;\n }\n }\n // TODO: check for URLs and use `charactersReservedPerUrl` to calculate max characters\n\n if (mediaAttachments.length > 0) {\n // If there are media attachments, check if they have no descriptions\n const hasNoDescriptions = mediaAttachments.some(\n (media) => !media.description?.trim?.(),\n );\n if (hasNoDescriptions) {\n const yes = confirm(\n t`Some media have no descriptions. Continue?`,\n );\n if (!yes) return;\n }\n }\n\n // Post-cleanup\n spoilerText = (sensitive && spoilerText) || undefined;\n status = status === '' ? undefined : status;\n\n // states.composerState.minimized = true;\n states.composerState.publishing = true;\n setUIState('loading');\n (async () => {\n try {\n console.log('MEDIA ATTACHMENTS', mediaAttachments);\n if (mediaAttachments.length > 0) {\n // Upload media attachments first\n const mediaPromises = mediaAttachments.map((attachment) => {\n const { file, description, id } = attachment;\n console.log('UPLOADING', attachment);\n if (id) {\n // If already uploaded\n return attachment;\n } else {\n const params = removeNullUndefined({\n file,\n description,\n });\n return masto.v2.media.create(params).then((res) => {\n if (res.id) {\n attachment.id = res.id;\n }\n return res;\n });\n }\n });\n const results = await Promise.allSettled(mediaPromises);\n\n // If any failed, return\n if (\n results.some((result) => {\n return result.status === 'rejected' || !result.value?.id;\n })\n ) {\n states.composerState.publishing = false;\n states.composerState.publishingError = true;\n setUIState('error');\n // Alert all the reasons\n results.forEach((result) => {\n if (result.status === 'rejected') {\n console.error(result);\n alert(result.reason || t`Attachment #${i} failed`);\n }\n });\n return;\n }\n\n console.log({ results, mediaAttachments });\n }\n\n /* NOTE:\n Using snakecase here because masto.js's `isObject` returns false for `params`, ONLY happens when opening in pop-out window. This is maybe due to `window.masto` variable being passed from the parent window. The check that failed is `x.constructor === Object`, so maybe the `Object` in new window is different than parent window's?\n Code: https://github.com/neet/masto.js/blob/dd0d649067b6a2b6e60fbb0a96597c373a255b00/src/serializers/is-object.ts#L2\n\n // TODO: Note above is no longer true in Masto.js v6. Revisit this.\n */\n let params = {\n status,\n // spoilerText,\n spoiler_text: spoilerText,\n language,\n sensitive: sensitive || sensitiveMedia,\n poll,\n // mediaIds: mediaAttachments.map((attachment) => attachment.id),\n media_ids: mediaAttachments.map(\n (attachment) => attachment.id,\n ),\n };\n if (editStatus) {\n if (supportsNativeQuote()) {\n params.quote_approval_policy = quoteApprovalPolicy;\n }\n if (\n supports('@mastodon/edit-media-attributes') ||\n supports('@gotosocial/edit-media-attributes')\n ) {\n params.media_attributes = mediaAttachments.map(\n (attachment) => {\n return {\n id: attachment.id,\n description: attachment.description,\n // focus\n // thumbnail\n };\n },\n );\n }\n } else {\n if (supportsNativeQuote() && currentQuoteStatus?.id) {\n params.quoted_status_id = currentQuoteStatus.id;\n params.quote_approval_policy = quoteApprovalPolicy;\n }\n params.visibility = visibility;\n // params.inReplyToId = replyToStatus?.id || undefined;\n params.in_reply_to_id = replyToStatus?.id || undefined;\n params.scheduled_at = scheduledAt;\n }\n params = removeNullUndefined(params);\n console.log('POST', params);\n\n let newStatus;\n if (editStatus) {\n newStatus = await masto.v1.statuses\n .$select(editStatus.id)\n .update(params);\n saveStatus(newStatus, instance, {\n skipThreading: true,\n });\n } else {\n try {\n newStatus = await masto.v1.statuses.create(params, {\n requestInit: {\n headers: {\n 'Idempotency-Key': UID.current,\n },\n },\n });\n } catch (_) {\n // If idempotency key fails, try again without it\n newStatus = await masto.v1.statuses.create(params);\n }\n }\n states.composerState.minimized = false;\n states.composerState.publishing = false;\n setUIState('default');\n\n // Close\n onClose({\n // type: post, reply, edit\n type: editStatus ? 'edit' : replyToStatus ? 'reply' : 'post',\n newStatus,\n instance,\n scheduledAt,\n });\n } catch (e) {\n states.composerState.publishing = false;\n states.composerState.publishingError = true;\n console.error(e);\n alert(e?.reason || e);\n setUIState('error');\n }\n })();\n }}\n >\n <div>\n <div class={`compose-cw-container ${sensitive ? '' : 'collapsed'}`}>\n <input\n type=\"hidden\"\n name=\"sensitive\"\n value={sensitive ? 'on' : 'off'}\n />\n {/* mimic the old checkbox */}\n <TextExpander\n keys=\":\"\n class=\"spoiler-text-field-container\"\n onTrigger={(action) => {\n if (action?.name === 'custom-emojis') {\n setShowEmoji2Picker({\n targetElement: spoilerTextRef,\n defaultSearchTerm: action?.defaultSearchTerm || null,\n });\n }\n }}\n >\n <input\n ref={spoilerTextRef}\n type=\"text\"\n name=\"spoilerText\"\n placeholder={t`Content warning`}\n data-allow-custom-emoji=\"true\"\n disabled={uiState === 'loading'}\n class=\"spoiler-text-field\"\n lang={language}\n spellCheck=\"true\"\n autocomplete=\"off\"\n dir=\"auto\"\n onInput={() => {\n updateCharCount();\n }}\n />\n </TextExpander>\n <button\n type=\"button\"\n class=\"close-button plain4 small\"\n onClick={() => {\n setSensitive(false);\n textareaRef.current.focus();\n }}\n >\n <Icon icon=\"x\" alt={t`Cancel`} />\n </button>\n </div>\n <Textarea\n ref={textareaRef}\n data-allow-custom-emoji=\"true\"\n placeholder={\n replyToStatus\n ? t`Post your reply`\n : editStatus\n ? t`Edit your post`\n : !!poll\n ? t`Ask a question`\n : t`What are you doing?`\n }\n required={mediaAttachments?.length === 0}\n disabled={uiState === 'loading'}\n lang={language}\n onInput={() => {\n updateCharCount();\n }}\n maxCharacters={maxCharacters}\n onTrigger={(action) => {\n if (action?.name === 'custom-emojis') {\n setShowEmoji2Picker({\n targetElement: lastFocusedEmojiFieldRef,\n defaultSearchTerm: action?.defaultSearchTerm || null,\n });\n } else if (action?.name === 'mention') {\n setShowMentionPicker({\n defaultSearchTerm: action?.defaultSearchTerm || null,\n });\n } else if (\n action?.name === 'auto-detect-language' &&\n action?.languages\n ) {\n setAutoDetectedLanguages(action.languages);\n } else if (action?.name === 'pasted-link' && action?.url) {\n handlePastedLink(action.url);\n }\n }}\n />\n </div>\n {mediaAttachments?.length > 0 && (\n <div class=\"media-attachments\">\n {mediaAttachments.map((attachment, i) => {\n const { id, file } = attachment;\n const fileID = file?.size + file?.type + file?.name;\n return (\n <MediaAttachment\n key={id || fileID || i}\n attachment={attachment}\n disabled={uiState === 'loading'}\n lang={language}\n supportedMimeTypes={supportedMimeTypes}\n descriptionLimit={descriptionLimit}\n onDescriptionChange={(value) => {\n setMediaAttachments((attachments) => {\n const newAttachments = [...attachments];\n newAttachments[i] = {\n ...newAttachments[i],\n description: value,\n };\n return newAttachments;\n });\n }}\n onRemove={() => {\n setMediaAttachments((attachments) => {\n return attachments.filter((_, j) => j !== i);\n });\n }}\n />\n );\n })}\n <label class=\"media-sensitive\">\n <input\n name=\"sensitiveMedia\"\n type=\"checkbox\"\n checked={sensitiveMedia}\n disabled={uiState === 'loading'}\n onChange={(e) => {\n const sensitiveMedia = e.target.checked;\n setSensitiveMedia(sensitiveMedia);\n }}\n />{' '}\n <span>\n <Trans>Mark media as sensitive</Trans>\n </span>{' '}\n <Icon icon={`eye-${sensitiveMedia ? 'close' : 'open'}`} />\n </label>\n </div>\n )}\n {!!poll && (\n <ComposePoll\n lang={language}\n maxOptions={maxOptions}\n maxExpiration={maxExpiration}\n minExpiration={minExpiration}\n maxCharactersPerOption={maxCharactersPerOption}\n poll={poll}\n disabled={uiState === 'loading'}\n onInput={(poll) => {\n if (poll) {\n const newPoll = { ...poll };\n setPoll(newPoll);\n } else {\n setPoll(null);\n focusLastFocusedField();\n }\n }}\n />\n )}\n {!!currentQuoteStatus?.id && (\n <div class=\"quote-status\">\n <Status\n status={currentQuoteStatus}\n instance={instance}\n size=\"s\"\n readOnly\n />\n </div>\n )}\n {scheduledAt && (\n <div class=\"toolbar scheduled-at\">\n <span>\n <label>\n <Trans>\n Posting on{' '}\n <ScheduledAtField\n scheduledAt={scheduledAt}\n setScheduledAt={setScheduledAt}\n />\n </Trans>\n </label>{' '}\n <small class=\"tag insignificant\">\n {getLocalTimezoneName()}\n </small>\n </span>\n <button\n type=\"button\"\n class=\"plain4 close-button small\"\n onClick={() => {\n setScheduledAt(null);\n focusLastFocusedField();\n }}\n >\n <Icon icon=\"x\" alt={t`Cancel`} />\n </button>\n </div>\n )}\n <QuoteSuggestion\n quoteSuggestion={quoteSuggestion}\n hasCurrentQuoteStatus={!!currentQuoteStatus?.id}\n onAccept={() => {\n const { status } = quoteSuggestion;\n\n // Remove the pasted link from textarea\n const currentValue = textareaRef.current?.value || '';\n // Find pasted link nearest to last cursor position\n const lastCursorPos = textareaRef.current?.selectionStart || 0;\n const pastedLinkPos = currentValue.lastIndexOf(\n quoteSuggestion.url,\n lastCursorPos,\n );\n const newValue =\n currentValue.slice(0, pastedLinkPos) +\n currentValue.slice(pastedLinkPos + quoteSuggestion.url.length);\n if (textareaRef.current) {\n textareaRef.current.value = newValue;\n textareaRef.current.dispatchEvent(new Event('input'));\n }\n\n const hasCurrentQuote = !!currentQuoteStatus?.id;\n if (hasCurrentQuote) {\n // If there's already a quote, replacement doesn't need transition\n setQuoteSuggestion(null);\n setLocalQuoteStatus(status);\n } else {\n // Transition the unfurled quote to the quote preview\n if (document.startViewTransition) {\n document.startViewTransition(() => {\n setQuoteSuggestion(null);\n setLocalQuoteStatus(status);\n });\n } else {\n setQuoteSuggestion(null);\n setLocalQuoteStatus(status);\n }\n }\n focusTextarea();\n }}\n onCancel={() => setQuoteSuggestion(null)}\n />\n <div class=\"toolbar compose-footer\">\n <span class=\"add-toolbar-button-group spacer\">\n {showAddButton && (\n <Menu2\n portal={{\n target: document.body,\n }}\n containerProps={{\n style: {\n zIndex: 1001,\n },\n }}\n menuButton={({ open }) => (\n <button\n type=\"button\"\n class={`toolbar-button add-button ${\n open ? 'active' : ''\n }`}\n >\n <Icon icon=\"plus\" title={t`Add`} />\n </button>\n )}\n >\n {supportsCameraCapture && (\n <MenuItem\n disabled={mediaButtonDisabled}\n className=\"compose-menu-add-media\"\n >\n <label class=\"compose-menu-add-media-field\">\n <CameraCaptureInput\n hidden\n supportedMimeTypes={supportedImagesVideosTypes}\n disabled={mediaButtonDisabled}\n setMediaAttachments={setMediaAttachments}\n />\n </label>\n <Icon icon=\"camera\" /> <span>{_(ADD_LABELS.camera)}</span>\n </MenuItem>\n )}\n <MenuItem\n disabled={mediaButtonDisabled}\n className=\"compose-menu-add-media\"\n >\n <label class=\"compose-menu-add-media-field\">\n <FilePickerInput\n hidden\n supportedMimeTypes={supportedMimeTypes}\n maxMediaAttachments={maxMediaAttachments}\n mediaAttachments={mediaAttachments}\n disabled={mediaButtonDisabled}\n setMediaAttachments={setMediaAttachments}\n />\n </label>\n <Icon icon=\"media\" /> <span>{_(ADD_LABELS.media)}</span>\n </MenuItem>\n <MenuItem\n disabled={cwButtonDisabled}\n onClick={onCWButtonClick}\n >\n <Icon icon={`eye-${sensitive ? 'close' : 'open'}`} />{' '}\n <span>{_(ADD_LABELS.sensitive)}</span>\n </MenuItem>\n {showPollButton && (\n <MenuItem\n disabled={pollButtonDisabled}\n onClick={onPollButtonClick}\n >\n <Icon icon=\"poll\" /> <span>{_(ADD_LABELS.poll)}</span>\n </MenuItem>\n )}\n <MenuDivider />\n <MenuItem\n onClick={() => {\n setShowEmoji2Picker({\n targetElement: lastFocusedEmojiFieldRef,\n });\n }}\n >\n <Icon icon=\"emoji2\" />{' '}\n <span>{_(ADD_LABELS.customEmoji)}</span>\n </MenuItem>\n {!!states.settings.composerGIFPicker && (\n <MenuItem\n disabled={mediaButtonDisabled}\n onClick={() => {\n setShowGIFPicker(true);\n }}\n >\n <span class=\"icon icon-gif\" role=\"img\" />\n <span>{_(ADD_LABELS.gif)}</span>\n </MenuItem>\n )}\n {showScheduledAt && (\n <>\n <MenuDivider />\n <MenuItem\n disabled={scheduledAtButtonDisabled}\n onClick={onScheduledAtClick}\n >\n <Icon icon=\"schedule\" />{' '}\n <span>{_(ADD_LABELS.scheduledPost)}</span>\n </MenuItem>\n </>\n )}\n </Menu2>\n )}\n <span\n class=\"add-sub-toolbar-button-group\"\n ref={addSubToolbarRef}\n hidden\n >\n {supportsCameraCapture && (\n <label class=\"toolbar-button\">\n <CameraCaptureInput\n supportedMimeTypes={supportedImagesVideosTypes}\n mediaAttachments={mediaAttachments}\n disabled={mediaButtonDisabled}\n setMediaAttachments={setMediaAttachments}\n />\n <Icon icon=\"camera\" alt={_(ADD_LABELS.camera)} />\n </label>\n )}\n <label class=\"toolbar-button\">\n <FilePickerInput\n supportedMimeTypes={supportedMimeTypes}\n maxMediaAttachments={maxMediaAttachments}\n mediaAttachments={mediaAttachments}\n disabled={mediaButtonDisabled}\n setMediaAttachments={setMediaAttachments}\n />\n <Icon icon=\"media\" alt={_(ADD_LABELS.media)} />\n </label>\n <button\n type=\"button\"\n class=\"toolbar-button\"\n disabled={cwButtonDisabled}\n onClick={onCWButtonClick}\n >\n <Icon\n icon={`eye-${sensitive ? 'close' : 'open'}`}\n alt={_(ADD_LABELS.sensitive)}\n />\n </button>\n {showPollButton && (\n <button\n type=\"button\"\n class=\"toolbar-button\"\n disabled={pollButtonDisabled}\n onClick={onPollButtonClick}\n >\n <Icon icon=\"poll\" alt={_(ADD_LABELS.poll)} />\n </button>\n )}\n <div class=\"toolbar-divider\" />\n {/* <button\n type=\"button\"\n class=\"toolbar-button\"\n disabled={uiState === 'loading'}\n onClick={() => {\n setShowMentionPicker(true);\n }}\n >\n <Icon icon=\"at\" />\n </button> */}\n <button\n type=\"button\"\n class=\"toolbar-button\"\n disabled={uiState === 'loading'}\n onClick={() => {\n setShowEmoji2Picker({\n targetElement: lastFocusedEmojiFieldRef,\n });\n }}\n >\n <Icon icon=\"emoji2\" alt={_(ADD_LABELS.customEmoji)} />\n </button>\n {!!states.settings.composerGIFPicker && (\n <button\n type=\"button\"\n class=\"toolbar-button gif-picker-button\"\n disabled={mediaButtonDisabled}\n onClick={() => {\n setShowGIFPicker(true);\n }}\n >\n <span\n class=\"icon icon-gif\"\n aria-label={_(ADD_LABELS.gif)}\n />\n </button>\n )}\n {showScheduledAt && (\n <>\n <div class=\"toolbar-divider\" />\n <button\n type=\"button\"\n class={`toolbar-button ${scheduledAt ? 'highlight' : ''}`}\n disabled={scheduledAtButtonDisabled}\n onClick={onScheduledAtClick}\n >\n <Icon icon=\"schedule\" alt={_(ADD_LABELS.scheduledPost)} />\n </button>\n </>\n )}\n </span>\n </span>\n {uiState === 'loading' ? (\n <Loader abrupt />\n ) : (\n <CharCountMeter\n maxCharacters={maxCharacters}\n hidden={uiState === 'loading'}\n />\n )}\n {supportsNativeQuote() && (\n <label\n class={`toolbar-button ${highlightQuoteApprovalPolicyField ? 'highlight' : ''}`}\n >\n <Icon icon=\"quote2\" alt=\"Quote settings\" />\n {quoteApprovalPolicy === 'followers' && (\n <Icon icon=\"group\" class=\"insignificant\" />\n )}\n {quoteApprovalPolicy === 'nobody' && (\n <Icon icon=\"block\" class=\"insignificant\" />\n )}\n <select\n name=\"quoteApprovalPolicy\"\n value={quoteApprovalPolicy}\n onChange={(e) => {\n setQuoteApprovalPolicy(e.target.value);\n }}\n disabled={uiState === 'loading'}\n dir=\"auto\"\n >\n <option value=\"public\" disabled={disableQuotePolicy}>\n <Trans>Anyone can quote</Trans>\n </option>\n <option value=\"followers\" disabled={disableQuotePolicy}>\n <Trans>Your followers can quote</Trans>\n </option>\n <option value=\"nobody\">\n <Trans>Only you can quote</Trans>\n </option>\n </select>\n </label>\n )}\n <label\n class={`toolbar-button ${highlightVisibilityField ? 'highlight' : ''}`}\n title={_(visibilityText[visibility])}\n >\n {visibility === 'public' || visibility === 'direct' ? (\n <Icon\n icon={visibilityIconsMap[visibility]}\n alt={_(visibilityText[visibility])}\n />\n ) : (\n <span class=\"icon-text\">{_(visibilityText[visibility])}</span>\n )}\n <select\n name=\"visibility\"\n value={visibility}\n onChange={(e) => {\n setVisibility(e.target.value);\n if (\n e.target.value === 'private' ||\n e.target.value === 'direct'\n ) {\n setQuoteApprovalPolicy('nobody');\n }\n\n if (e.target.value === 'direct' && currentQuoteStatus?.id) {\n const quoteURL = currentQuoteStatus.url;\n if (quoteURL) {\n const currentText = textareaRef.current.value;\n if (!currentText.includes(quoteURL)) {\n textareaRef.current.value =\n currentText + (currentText ? '\\n' : '') + quoteURL;\n oninputTextarea();\n }\n }\n setQuoteCleared(true);\n showToast(t`Quotes can't be embedded in private mentions.`);\n } else if (e.target.value !== 'direct' && quoteCleared) {\n const quoteURL = (localQuoteStatus || quoteStatus)?.url;\n if (quoteURL && textareaRef.current) {\n const currentValue = textareaRef.current.value;\n const linkPos = currentValue.indexOf(quoteURL);\n if (linkPos !== -1) {\n let newValue =\n currentValue.slice(0, linkPos) +\n currentValue.slice(linkPos + quoteURL.length);\n newValue = newValue.replace(/\\n+$/, '');\n textareaRef.current.value = newValue;\n oninputTextarea();\n }\n }\n setQuoteCleared(false);\n }\n }}\n disabled={uiState === 'loading' || !!editStatus}\n dir=\"auto\"\n >\n <option value=\"public\">\n <Trans>Public</Trans>\n </option>\n {(supports('@pleroma/local-visibility-post') ||\n supports('@akkoma/local-visibility-post')) && (\n <option value=\"local\">\n <Trans>Local</Trans>\n </option>\n )}\n <option value=\"unlisted\">\n <Trans>Quiet public</Trans>\n </option>\n <option value=\"private\">\n <Trans>Followers</Trans>\n </option>\n <option value=\"direct\">\n <Trans>Private mention</Trans>\n </option>\n </select>\n </label>{' '}\n <label\n class={`toolbar-button ${\n highlightLanguageField ? 'highlight' : ''\n }`}\n >\n <span class=\"icon-text\">\n {supportedLanguagesMap[language]?.native}\n </span>\n <select\n name=\"language\"\n value={language}\n onChange={(e) => {\n const { value } = e.target;\n setLanguage(value || DEFAULT_LANG);\n store.session.set('currentLanguage', value || DEFAULT_LANG);\n }}\n disabled={uiState === 'loading'}\n dir=\"auto\"\n >\n {topSupportedLanguages.map(([code, common, native]) => {\n const commonText = localeCode2Text({\n code,\n fallback: common,\n });\n const showCommon = commonText !== native;\n return (\n <option value={code} key={code}>\n {showCommon ? `${native} - ${commonText}` : commonText}\n </option>\n );\n })}\n <hr />\n {restSupportedLanguages.map(([code, common, native]) => {\n const commonText = localeCode2Text({\n code,\n fallback: common,\n });\n const showCommon = commonText !== native;\n return (\n <option value={code} key={code}>\n {showCommon ? `${native} - ${commonText}` : commonText}\n </option>\n );\n })}\n </select>\n </label>{' '}\n <button type=\"submit\" disabled={uiState === 'loading'}>\n {scheduledAt\n ? t`Schedule`\n : replyToStatus\n ? t`Reply`\n : editStatus\n ? t`Update`\n : t({\n message: 'Post',\n context: 'Submit button in composer',\n })}\n </button>\n </div>\n </form>\n </div>\n {showMentionPicker && (\n <Modal\n onClose={() => {\n setShowMentionPicker(false);\n focusLastFocusedField();\n }}\n >\n <MentionModal\n masto={masto}\n instance={instance}\n onClose={() => {\n setShowMentionPicker(false);\n }}\n defaultSearchTerm={showMentionPicker?.defaultSearchTerm}\n onSelect={(socialAddress) => {\n const textarea = textareaRef.current;\n if (textarea) {\n insertTextAtCursor({\n targetElement: textarea,\n text: '@' + socialAddress,\n });\n }\n }}\n />\n </Modal>\n )}\n {showEmoji2Picker && (\n <Modal\n onClose={() => {\n setShowEmoji2Picker(false);\n focusLastFocusedField();\n }}\n >\n <CustomEmojisModal\n masto={masto}\n instance={instance}\n onClose={() => {\n setShowEmoji2Picker(false);\n }}\n defaultSearchTerm={showEmoji2Picker?.defaultSearchTerm}\n onSelect={(emojiShortcode) => {\n const targetElement =\n showEmoji2Picker?.targetElement?.current || textareaRef.current;\n if (targetElement) {\n insertTextAtCursor({ targetElement, text: emojiShortcode });\n }\n }}\n />\n </Modal>\n )}\n {showGIFPicker && (\n <Modal\n onClose={() => {\n setShowGIFPicker(false);\n focusLastFocusedField();\n }}\n >\n <GIFPickerModal\n onClose={() => setShowGIFPicker(false)}\n onSelect={({ url, type, alt_text }) => {\n console.log('GIF URL', url);\n if (mediaAttachments.length >= maxMediaAttachments) {\n alert(\n plural(maxMediaAttachments, {\n one: 'You can only attach up to 1 file.',\n other: 'You can only attach up to # files.',\n }),\n );\n return;\n }\n // Download the GIF and insert it as media attachment\n (async () => {\n let theToast;\n try {\n theToast = showToast({\n text: t`Downloading GIF…`,\n duration: -1,\n });\n const blob = await fetch(url, {\n referrerPolicy: 'no-referrer',\n }).then((res) => res.blob());\n const file = new File(\n [blob],\n type === 'video/mp4' ? 'video.mp4' : 'image.gif',\n {\n type,\n },\n );\n const newMediaAttachments = [\n ...mediaAttachments,\n {\n file,\n type,\n size: file.size,\n id: null,\n description: alt_text || '',\n },\n ];\n setMediaAttachments(newMediaAttachments);\n theToast?.hideToast?.();\n } catch (err) {\n console.error(err);\n theToast?.hideToast?.();\n showToast(t`Failed to download GIF`);\n }\n })();\n }}\n />\n </Modal>\n )}\n </div>\n );\n}\n\nfunction removeNullUndefined(obj) {\n for (let key in obj) {\n if (obj[key] === null || obj[key] === undefined) {\n delete obj[key];\n }\n }\n return obj;\n}\n\nexport default Compose;\n"],"file":"compose-CUhufx8N.js"}