1 line
261 KiB
Plaintext
1 line
261 KiB
Plaintext
{"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","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","prefs","scheduledAt","setScheduledAt","currentQuoteStatus","setQuoteSuggestion","checkQuoteEligibility","setLocalQuoteStatus","getPreferences","quoteApproval","isSelf","isPublic","isMineAndPrivate","isQuoteAutomaticallyAccepted","isQuoteManuallyAccepted","handlePastedLink","supportsNativeQuote","unfurledData","unfurlMastodonLink","originalURL","focusTextarea","targetElement","textBeforeInsert","spaceAfterInsert","textAfterInsert","lastFocusedFieldRef","spaceBeforeInsert","newText","focusLastFocusedField","handleFocus","composeContainerRef","lastFocusedEmojiFieldRef","composeContainer","isFormElement","spoilerText","visibility2","language2","sensitive2","m","mentions","allMentions","oninputTextarea","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","items","quote","unsupportedFiles","drafts","f","_i18n","handleItems","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__","publishing","disableQuotePolicy","openCompose","scheduledAtButtonDisabled","AccountBlock","useAvatarStatic","__COMPOSE__","previewMode","formData","pointerEvents","opacity","cancelable","FormData","fromEntries","params2","res","mediaPromises","hasNoDescriptions","v2","Promise","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","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 '#': '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 = supports('@mastodon/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 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\n const prefs = getPreferences();\n\n const currentQuoteStatus = 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 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 = () => {\n setTimeout(() => {\n if (!textareaRef.current) return;\n // status starts with newline or space, focus on first position\n if (/^\\n|\\s/.test(draftStatus?.status)) {\n textareaRef.current.selectionStart = 0;\n textareaRef.current.selectionEnd = 0;\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 if (allMentions.length > 0) {\n textareaRef.current.value = `${allMentions\n .map((m) => `@${m}`)\n .join(' ')} `;\n oninputTextarea();\n }\n focusTextarea();\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 focusTextarea();\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]);\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 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 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 ’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 ’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 (supports('@mastodon/edit-media-attributes')) {\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 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":"assets/compose-DPEmvLj7.js"} |