From 2727fb8f20bbb04a0258f3ae0e53f31eef60cb79 Mon Sep 17 00:00:00 2001 From: ewwwwwwww Date: Wed, 22 Jun 2022 08:41:04 -0700 Subject: [PATCH 01/76] lint fixes --- .../components/emoji_picker_dropdown.js | 331 ++++++++++-------- app/soapbox/features/emoji/emoji.js | 9 +- .../components/icon_picker_dropdown.js | 3 +- .../features/ui/util/async-components.ts | 6 +- package.json | 5 +- yarn.lock | 59 ++-- 6 files changed, 220 insertions(+), 193 deletions(-) diff --git a/app/soapbox/features/compose/components/emoji_picker_dropdown.js b/app/soapbox/features/compose/components/emoji_picker_dropdown.js index ca1fff018..7419f0edf 100644 --- a/app/soapbox/features/compose/components/emoji_picker_dropdown.js +++ b/app/soapbox/features/compose/components/emoji_picker_dropdown.js @@ -1,7 +1,9 @@ +import EmojiData from '@emoji-mart/data'; import classNames from 'classnames'; import { supportsPassiveEvents } from 'detect-passive-events'; +import { Picker } from 'emoji-mart'; import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useRef, useEffect } from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { defineMessages, injectIntl } from 'react-intl'; import Overlay from 'react-overlays/lib/Overlay'; @@ -9,7 +11,7 @@ import Overlay from 'react-overlays/lib/Overlay'; import { IconButton } from 'soapbox/components/ui'; import { buildCustomEmojis } from '../../emoji/emoji'; -import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; +// import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; const messages = defineMessages({ emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' }, @@ -28,127 +30,141 @@ const messages = defineMessages({ flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' }, }); -let EmojiPicker, Emoji; // load asynchronously +function EmojiPicker({ customEmojis }) { + const ref = useRef(); -const backgroundImageFn = () => require('emoji-datasource/img/twitter/sheets/32.png'); + useEffect(() => { + const emojis = buildCustomEmojis(customEmojis); + const input = { data: EmojiData, ref, custom: [{ emojis }] }; + + // console.log(input); + + new Picker(input); + }, []); + + return
; +} +// let EmojiPicker, Emoji; // load asynchronously + +// const backgroundImageFn = () => require('emoji-datasource/img/twitter/sheets/32.png'); const listenerOptions = supportsPassiveEvents ? { passive: true } : false; -const categoriesSort = [ - 'recent', - 'custom', - 'people', - 'nature', - 'foods', - 'activity', - 'places', - 'objects', - 'symbols', - 'flags', -]; +// const categoriesSort = [ +// 'recent', +// 'custom', +// 'people', +// 'nature', +// 'foods', +// 'activity', +// 'places', +// 'objects', +// 'symbols', +// 'flags', +// ]; -class ModifierPickerMenu extends React.PureComponent { +// class ModifierPickerMenu extends React.PureComponent { +// +// static propTypes = { +// active: PropTypes.bool, +// onSelect: PropTypes.func.isRequired, +// onClose: PropTypes.func.isRequired, +// }; +// +// handleClick = e => { +// this.props.onSelect(e.currentTarget.getAttribute('data-index') * 1); +// } +// +// componentDidUpdate(prevProps) { +// if (this.props.active) { +// this.attachListeners(); +// } else { +// this.removeListeners(); +// } +// } +// +// componentWillUnmount() { +// this.removeListeners(); +// } +// +// handleDocumentClick = e => { +// if (this.node && !this.node.contains(e.target)) { +// this.props.onClose(); +// } +// } +// +// attachListeners() { +// document.addEventListener('click', this.handleDocumentClick, false); +// document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); +// } +// +// removeListeners() { +// document.removeEventListener('click', this.handleDocumentClick, false); +// document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); +// } +// +// setRef = c => { +// this.node = c; +// } +// +// render() { +// const { active } = this.props; +// +// return ( +//
+// +// +// +// +// +// +//
+// ); +// } +// +// } - static propTypes = { - active: PropTypes.bool, - onSelect: PropTypes.func.isRequired, - onClose: PropTypes.func.isRequired, - }; - - handleClick = e => { - this.props.onSelect(e.currentTarget.getAttribute('data-index') * 1); - } - - componentDidUpdate(prevProps) { - if (this.props.active) { - this.attachListeners(); - } else { - this.removeListeners(); - } - } - - componentWillUnmount() { - this.removeListeners(); - } - - handleDocumentClick = e => { - if (this.node && !this.node.contains(e.target)) { - this.props.onClose(); - } - } - - attachListeners() { - document.addEventListener('click', this.handleDocumentClick, false); - document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); - } - - removeListeners() { - document.removeEventListener('click', this.handleDocumentClick, false); - document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); - } - - setRef = c => { - this.node = c; - } - - render() { - const { active } = this.props; - - return ( -
- - - - - - -
- ); - } - -} - -class ModifierPicker extends React.PureComponent { - - static propTypes = { - active: PropTypes.bool, - modifier: PropTypes.number, - onChange: PropTypes.func, - onClose: PropTypes.func, - onOpen: PropTypes.func, - }; - - handleClick = () => { - if (this.props.active) { - this.props.onClose(); - } else { - this.props.onOpen(); - } - } - - handleSelect = modifier => { - this.props.onChange(modifier); - this.props.onClose(); - } - - render() { - const { active, modifier } = this.props; - - return ( -
- - -
- ); - } - -} +// class ModifierPicker extends React.PureComponent { +// +// static propTypes = { +// active: PropTypes.bool, +// modifier: PropTypes.number, +// onChange: PropTypes.func, +// onClose: PropTypes.func, +// onOpen: PropTypes.func, +// }; +// +// handleClick = () => { +// if (this.props.active) { +// this.props.onClose(); +// } else { +// this.props.onOpen(); +// } +// } +// +// handleSelect = modifier => { +// this.props.onChange(modifier); +// this.props.onClose(); +// } +// +// render() { +// const { active, modifier } = this.props; +// +// return ( +//
+// +// +//
+// ); +// } +// +// } @injectIntl class EmojiPickerMenu extends React.PureComponent { static propTypes = { custom_emojis: ImmutablePropTypes.list, - frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string), + // frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string), loading: PropTypes.bool, onClose: PropTypes.func.isRequired, onPick: PropTypes.func.isRequired, @@ -157,7 +173,7 @@ class EmojiPickerMenu extends React.PureComponent { arrowOffsetLeft: PropTypes.string, arrowOffsetTop: PropTypes.string, intl: PropTypes.object.isRequired, - skinTone: PropTypes.number.isRequired, + // skinTone: PropTypes.number.isRequired, onSkinTone: PropTypes.func.isRequired, }; @@ -236,46 +252,53 @@ class EmojiPickerMenu extends React.PureComponent { } render() { - const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props; + // const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props; + const { loading, style, custom_emojis } = this.props; if (loading) { return
; } - const title = intl.formatMessage(messages.emoji); + // const title = intl.formatMessage(messages.emoji); const { modifierOpen } = this.state; return (
- - - +
); + + // return ( + //
+ // + // + // + //
+ // ); } } @@ -306,18 +329,18 @@ class EmojiPickerDropdown extends React.PureComponent { this.setState({ active: true }); - if (!EmojiPicker) { - this.setState({ loading: true }); - - EmojiPickerAsync().then(EmojiMart => { - EmojiPicker = EmojiMart.Picker; - Emoji = EmojiMart.Emoji; - - this.setState({ loading: false }); - }).catch(() => { - this.setState({ loading: false }); - }); - } + // if (!EmojiPicker) { + // this.setState({ loading: true }); + // + // EmojiPickerAsync().then(EmojiMart => { + // EmojiPicker = EmojiMart.Picker; + // Emoji = EmojiMart.Emoji; + // + // this.setState({ loading: false }); + // }).catch(() => { + // this.setState({ loading: false }); + // }); + // } const { top } = e.target.getBoundingClientRect(); this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' }); diff --git a/app/soapbox/features/emoji/emoji.js b/app/soapbox/features/emoji/emoji.js index 0ce74c4de..909629979 100644 --- a/app/soapbox/features/emoji/emoji.js +++ b/app/soapbox/features/emoji/emoji.js @@ -90,12 +90,13 @@ export const buildCustomEmojis = (customEmojis, autoplay = false) => { emojis.push({ id: name, name, - short_names: [name], - text: '', - emoticons: [], keywords: [name], + skins: [{ src: url }], imageUrl: url, - custom: true, + // short_names: [name], + // text: '', + // emoticons: [], + // custom: true, }); }); diff --git a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js index 8c2bdf473..9a75ed32f 100644 --- a/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js +++ b/app/soapbox/features/soapbox_config/components/icon_picker_dropdown.js @@ -1,6 +1,7 @@ +// import EmojiData from '@emoji-mart/data'; import classNames from 'classnames'; import { supportsPassiveEvents } from 'detect-passive-events'; -import Picker from 'emoji-mart/dist-es/components/picker/picker'; +import { Picker } from 'emoji-mart'; import PropTypes from 'prop-types'; import React from 'react'; import { defineMessages, injectIntl } from 'react-intl'; diff --git a/app/soapbox/features/ui/util/async-components.ts b/app/soapbox/features/ui/util/async-components.ts index a6379b130..ffb3d9ed2 100644 --- a/app/soapbox/features/ui/util/async-components.ts +++ b/app/soapbox/features/ui/util/async-components.ts @@ -1,6 +1,6 @@ -export function EmojiPicker() { - return import(/* webpackChunkName: "emoji_picker" */'../../emoji/emoji_picker'); -} +// export function EmojiPicker() { +// return import(/* webpackChunkName: "emoji_picker" */'../../emoji/emoji_picker'); +// } export function Notifications() { return import(/* webpackChunkName: "features/notifications" */'../../notifications'); diff --git a/package.json b/package.json index cb9ab4481..8fdbe6fe4 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@babel/preset-react": "^7.17.12", "@babel/preset-typescript": "^7.17.12", "@babel/runtime": "^7.18.3", + "@emoji-mart/data": "^1.0.2", "@fontsource/inter": "^4.5.1", "@fontsource/roboto": "^4.5.0", "@gamestdio/websocket": "^0.3.2", @@ -113,7 +114,7 @@ "detect-passive-events": "^2.0.0", "dotenv": "^8.0.0", "emoji-datasource": "5.0.0", - "emoji-mart": "npm:emoji-mart-lazyload", + "emoji-mart": "^5.1.0", "entities": "^3.0.1", "es6-symbol": "^3.1.1", "escape-html": "^1.0.3", @@ -196,7 +197,7 @@ "webpack": "^5.72.1", "webpack-assets-manifest": "^5.1.0", "webpack-bundle-analyzer": "^4.5.0", - "webpack-cli": "^4.9.2", + "webpack-cli": "^4.10.0", "webpack-deadcode-plugin": "^0.1.16", "webpack-merge": "^5.8.0", "wicg-inert": "^3.1.1" diff --git a/yarn.lock b/yarn.lock index 8d2248152..5cc86ff0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1271,7 +1271,7 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== @@ -1382,6 +1382,11 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz#9283c9ce5b289a3c4f61c12757469e59377f81f3" integrity sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA== +"@emoji-mart/data@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@emoji-mart/data/-/data-1.0.2.tgz#2b94c5b5f2c79611c12238438dad9516576a09ab" + integrity sha512-+ZdzBM4llDJJvjuCEsdOYVoSlNA16MMmxKG3oF5LARkwhx6N5clr6phzneWV1qIwJsywqwG7NaBjH8DV6yzjcA== + "@es-joy/jsdoccomment@~0.29.0": version "0.29.0" resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.29.0.tgz#527c7eefadeaf5c5d0c3b2721b5fa425d2119e98" @@ -3102,22 +3107,22 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.1.1.tgz#9f53b1b7946a6efc2a749095a4f450e2932e8356" - integrity sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg== +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== -"@webpack-cli/info@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.4.1.tgz#2360ea1710cbbb97ff156a3f0f24556e0fc1ebea" - integrity sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA== +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== dependencies: envinfo "^7.7.3" -"@webpack-cli/serve@^1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe" - integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw== +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== "@xtuc/ieee754@^1.2.0": version "1.2.0" @@ -5038,14 +5043,10 @@ emoji-datasource@5.0.0: resolved "https://registry.yarnpkg.com/emoji-datasource/-/emoji-datasource-5.0.0.tgz#1522fdba3c52223a1cf5a1c1fc282935400eaa06" integrity sha512-LuvLWFnxznTH++GytEzpzOPUo1SB+6CUFqIlVETJJ3x9fpyMCKFfyqberbhMLOpT1qcNe+km+zoyBeUSC3u5Rw== -"emoji-mart@npm:emoji-mart-lazyload": - version "3.0.1-j" - resolved "https://registry.yarnpkg.com/emoji-mart-lazyload/-/emoji-mart-lazyload-3.0.1-j.tgz#87a90d30b79d9145ece078d53e3e683c1a10ce9c" - integrity sha512-0wKF7MR0/iAeCIoiBLY+JjXCugycTgYRC2SL0y9/bjNSQlbeMdzILmPQJAufU/mgLFDUitOvjxLDhOZ9yxZ48g== - dependencies: - "@babel/runtime" "^7.0.0" - intersection-observer "^0.12.0" - prop-types "^15.6.0" +emoji-mart@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/emoji-mart/-/emoji-mart-5.1.0.tgz#8a36a872e1297747342d1385bd7b7141ac2f4365" + integrity sha512-ytXgeemyw4FormPQqWd35Vh06ZSnQFhVUqW51kASZzzjhQOPSGtiN3VCC7vDq94Pkxmsbet+Gps/qj5N90mEnw== emoji-regex@^8.0.0: version "8.0.0" @@ -11822,18 +11823,18 @@ webpack-bundle-analyzer@^4.5.0: sirv "^1.0.7" ws "^7.3.1" -webpack-cli@^4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.2.tgz#77c1adaea020c3f9e2db8aad8ea78d235c83659d" - integrity sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ== +webpack-cli@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== dependencies: "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.1.1" - "@webpack-cli/info" "^1.4.1" - "@webpack-cli/serve" "^1.6.1" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" colorette "^2.0.14" commander "^7.0.0" - execa "^5.0.0" + cross-spawn "^7.0.3" fastest-levenshtein "^1.0.12" import-local "^3.0.2" interpret "^2.2.0" From 170d3f748ec35408733209a24af8baf3fceb3516 Mon Sep 17 00:00:00 2001 From: ewwwwwwww Date: Thu, 23 Jun 2022 18:36:42 -0700 Subject: [PATCH 02/76] more emoji fixes --- .../components/emoji_picker_dropdown.js | 182 +++--------------- app/soapbox/features/emoji/emoji.js | 5 - app/soapbox/features/emoji/emoji_picker.js | 4 +- 3 files changed, 31 insertions(+), 160 deletions(-) diff --git a/app/soapbox/features/compose/components/emoji_picker_dropdown.js b/app/soapbox/features/compose/components/emoji_picker_dropdown.js index 7419f0edf..de4e29387 100644 --- a/app/soapbox/features/compose/components/emoji_picker_dropdown.js +++ b/app/soapbox/features/compose/components/emoji_picker_dropdown.js @@ -30,26 +30,7 @@ const messages = defineMessages({ flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' }, }); -function EmojiPicker({ customEmojis }) { - const ref = useRef(); - - useEffect(() => { - const emojis = buildCustomEmojis(customEmojis); - const input = { data: EmojiData, ref, custom: [{ emojis }] }; - - // console.log(input); - - new Picker(input); - }, []); - - return
; -} -// let EmojiPicker, Emoji; // load asynchronously - -// const backgroundImageFn = () => require('emoji-datasource/img/twitter/sheets/32.png'); -const listenerOptions = supportsPassiveEvents ? { passive: true } : false; - -// const categoriesSort = [ +// const categories = [ // 'recent', // 'custom', // 'people', @@ -62,109 +43,29 @@ const listenerOptions = supportsPassiveEvents ? { passive: true } : false; // 'flags', // ]; -// class ModifierPickerMenu extends React.PureComponent { -// -// static propTypes = { -// active: PropTypes.bool, -// onSelect: PropTypes.func.isRequired, -// onClose: PropTypes.func.isRequired, -// }; -// -// handleClick = e => { -// this.props.onSelect(e.currentTarget.getAttribute('data-index') * 1); -// } -// -// componentDidUpdate(prevProps) { -// if (this.props.active) { -// this.attachListeners(); -// } else { -// this.removeListeners(); -// } -// } -// -// componentWillUnmount() { -// this.removeListeners(); -// } -// -// handleDocumentClick = e => { -// if (this.node && !this.node.contains(e.target)) { -// this.props.onClose(); -// } -// } -// -// attachListeners() { -// document.addEventListener('click', this.handleDocumentClick, false); -// document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); -// } -// -// removeListeners() { -// document.removeEventListener('click', this.handleDocumentClick, false); -// document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); -// } -// -// setRef = c => { -// this.node = c; -// } -// -// render() { -// const { active } = this.props; -// -// return ( -//
-// -// -// -// -// -// -//
-// ); -// } -// -// } +function EmojiPicker(props) { + const ref = useRef(); + + useEffect(() => { + const input = { ...props, data: EmojiData, ref }; + + new Picker(input); + }, []); + + return
; +} +// let EmojiPicker, Emoji; // load asynchronously + +// const backgroundImageFn = () => require('emoji-datasource/img/twitter/sheets/32.png'); +const listenerOptions = supportsPassiveEvents ? { passive: true } : false; -// class ModifierPicker extends React.PureComponent { -// -// static propTypes = { -// active: PropTypes.bool, -// modifier: PropTypes.number, -// onChange: PropTypes.func, -// onClose: PropTypes.func, -// onOpen: PropTypes.func, -// }; -// -// handleClick = () => { -// if (this.props.active) { -// this.props.onClose(); -// } else { -// this.props.onOpen(); -// } -// } -// -// handleSelect = modifier => { -// this.props.onChange(modifier); -// this.props.onClose(); -// } -// -// render() { -// const { active, modifier } = this.props; -// -// return ( -//
-// -// -//
-// ); -// } -// -// } @injectIntl class EmojiPickerMenu extends React.PureComponent { static propTypes = { custom_emojis: ImmutablePropTypes.list, - // frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string), + frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string), loading: PropTypes.bool, onClose: PropTypes.func.isRequired, onPick: PropTypes.func.isRequired, @@ -173,7 +74,7 @@ class EmojiPickerMenu extends React.PureComponent { arrowOffsetLeft: PropTypes.string, arrowOffsetTop: PropTypes.string, intl: PropTypes.object.isRequired, - // skinTone: PropTypes.number.isRequired, + skinTone: PropTypes.number.isRequired, onSkinTone: PropTypes.func.isRequired, }; @@ -231,6 +132,8 @@ class EmojiPickerMenu extends React.PureComponent { } handleClick = emoji => { + console.log(emoji); + if (!emoji.native) { emoji.native = emoji.colons; } @@ -252,53 +155,26 @@ class EmojiPickerMenu extends React.PureComponent { } render() { - // const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props; - const { loading, style, custom_emojis } = this.props; + const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props; if (loading) { return
; } - // const title = intl.formatMessage(messages.emoji); + const title = intl.formatMessage(messages.emoji); const { modifierOpen } = this.state; return (
- +
); - - // return ( - //
- // - // - // - //
- // ); } } diff --git a/app/soapbox/features/emoji/emoji.js b/app/soapbox/features/emoji/emoji.js index 909629979..2607c91a9 100644 --- a/app/soapbox/features/emoji/emoji.js +++ b/app/soapbox/features/emoji/emoji.js @@ -92,11 +92,6 @@ export const buildCustomEmojis = (customEmojis, autoplay = false) => { name, keywords: [name], skins: [{ src: url }], - imageUrl: url, - // short_names: [name], - // text: '', - // emoticons: [], - // custom: true, }); }); diff --git a/app/soapbox/features/emoji/emoji_picker.js b/app/soapbox/features/emoji/emoji_picker.js index 8725d39ec..d9947568b 100644 --- a/app/soapbox/features/emoji/emoji_picker.js +++ b/app/soapbox/features/emoji/emoji_picker.js @@ -1,5 +1,5 @@ -import Emoji from 'emoji-mart/dist-es/components/emoji/emoji'; -import Picker from 'emoji-mart/dist-es/components/picker/picker'; +import Emoji from '@emoji-mart/data'; +import { Picker } from 'emoji-mart'; export { Picker, From 4b7876f1a6ca9ee1657332a7f75ec590d925c403 Mon Sep 17 00:00:00 2001 From: ewwwwwwww Date: Thu, 23 Jun 2022 19:41:48 -0700 Subject: [PATCH 03/76] enabled async component --- .../components/emoji_picker_dropdown.js | 70 +++++++------------ app/soapbox/features/emoji/emoji_picker.js | 33 +++++++-- .../features/ui/util/async-components.ts | 6 +- app/soapbox/reducers/compose.ts | 2 + 4 files changed, 56 insertions(+), 55 deletions(-) diff --git a/app/soapbox/features/compose/components/emoji_picker_dropdown.js b/app/soapbox/features/compose/components/emoji_picker_dropdown.js index de4e29387..bec0261aa 100644 --- a/app/soapbox/features/compose/components/emoji_picker_dropdown.js +++ b/app/soapbox/features/compose/components/emoji_picker_dropdown.js @@ -1,9 +1,7 @@ -import EmojiData from '@emoji-mart/data'; import classNames from 'classnames'; import { supportsPassiveEvents } from 'detect-passive-events'; -import { Picker } from 'emoji-mart'; import PropTypes from 'prop-types'; -import React, { useRef, useEffect } from 'react'; +import React from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { defineMessages, injectIntl } from 'react-intl'; import Overlay from 'react-overlays/lib/Overlay'; @@ -11,7 +9,7 @@ import Overlay from 'react-overlays/lib/Overlay'; import { IconButton } from 'soapbox/components/ui'; import { buildCustomEmojis } from '../../emoji/emoji'; -// import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; +import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; const messages = defineMessages({ emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' }, @@ -30,36 +28,10 @@ const messages = defineMessages({ flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' }, }); -// const categories = [ -// 'recent', -// 'custom', -// 'people', -// 'nature', -// 'foods', -// 'activity', -// 'places', -// 'objects', -// 'symbols', -// 'flags', -// ]; +let EmojiPicker; // load asynchronously -function EmojiPicker(props) { - const ref = useRef(); - - useEffect(() => { - const input = { ...props, data: EmojiData, ref }; - - new Picker(input); - }, []); - - return
; -} -// let EmojiPicker, Emoji; // load asynchronously - -// const backgroundImageFn = () => require('emoji-datasource/img/twitter/sheets/32.png'); const listenerOptions = supportsPassiveEvents ? { passive: true } : false; - @injectIntl class EmojiPickerMenu extends React.PureComponent { @@ -132,10 +104,8 @@ class EmojiPickerMenu extends React.PureComponent { } handleClick = emoji => { - console.log(emoji); - if (!emoji.native) { - emoji.native = emoji.colons; + emoji.native = emoji.shortcodes; } this.props.onClose(); @@ -163,6 +133,7 @@ class EmojiPickerMenu extends React.PureComponent { const title = intl.formatMessage(messages.emoji); const { modifierOpen } = this.state; + const theme = 'dark'; return (
@@ -172,6 +143,14 @@ class EmojiPickerMenu extends React.PureComponent { onEmojiSelect={this.handleClick} recent={frequentlyUsedEmojis} skin={skinTone} + perLine={8} + emojiSize={38} + emojiButtonSize={50} + navPosition={'bottom'} + theme={theme} + set={'twitter'} + previewEmoji={false} + autoFocus />
); @@ -205,18 +184,17 @@ class EmojiPickerDropdown extends React.PureComponent { this.setState({ active: true }); - // if (!EmojiPicker) { - // this.setState({ loading: true }); - // - // EmojiPickerAsync().then(EmojiMart => { - // EmojiPicker = EmojiMart.Picker; - // Emoji = EmojiMart.Emoji; - // - // this.setState({ loading: false }); - // }).catch(() => { - // this.setState({ loading: false }); - // }); - // } + if (!EmojiPicker) { + this.setState({ loading: true }); + + EmojiPickerAsync().then(EmojiMart => { + EmojiPicker = EmojiMart; + + this.setState({ loading: false }); + }).catch(() => { + this.setState({ loading: false }); + }); + } const { top } = e.target.getBoundingClientRect(); this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' }); diff --git a/app/soapbox/features/emoji/emoji_picker.js b/app/soapbox/features/emoji/emoji_picker.js index d9947568b..4dda1de07 100644 --- a/app/soapbox/features/emoji/emoji_picker.js +++ b/app/soapbox/features/emoji/emoji_picker.js @@ -1,7 +1,28 @@ -import Emoji from '@emoji-mart/data'; -import { Picker } from 'emoji-mart'; +import data from '@emoji-mart/data'; +import { Picker as EmojiPicker } from 'emoji-mart'; +import React, { useRef, useEffect } from 'react'; -export { - Picker, - Emoji, -}; +// const categories = [ +// 'recent', +// 'custom', +// 'people', +// 'nature', +// 'foods', +// 'activity', +// 'places', +// 'objects', +// 'symbols', +// 'flags', +// ]; + +export default function Picker(props) { + const ref = useRef(); + + useEffect(() => { + const input = { ...props, data, ref }; + + new EmojiPicker(input); + }, []); + + return
; +} diff --git a/app/soapbox/features/ui/util/async-components.ts b/app/soapbox/features/ui/util/async-components.ts index ffb3d9ed2..a6379b130 100644 --- a/app/soapbox/features/ui/util/async-components.ts +++ b/app/soapbox/features/ui/util/async-components.ts @@ -1,6 +1,6 @@ -// export function EmojiPicker() { -// return import(/* webpackChunkName: "emoji_picker" */'../../emoji/emoji_picker'); -// } +export function EmojiPicker() { + return import(/* webpackChunkName: "emoji_picker" */'../../emoji/emoji_picker'); +} export function Notifications() { return import(/* webpackChunkName: "features/notifications" */'../../notifications'); diff --git a/app/soapbox/reducers/compose.ts b/app/soapbox/reducers/compose.ts index 3b861fb58..d56307a25 100644 --- a/app/soapbox/reducers/compose.ts +++ b/app/soapbox/reducers/compose.ts @@ -222,6 +222,8 @@ const insertEmoji = (state: State, position: number, emojiData: Emoji, needsSpac const oldText = state.text; const emoji = needsSpace ? ' ' + emojiData.native : emojiData.native; + console.log(emojiData, emoji); + return state.merge({ text: `${oldText.slice(0, position)}${emoji} ${oldText.slice(position)}`, focusDate: new Date(), From eeb30b54924e3a12c6424f6960b78941a860b63b Mon Sep 17 00:00:00 2001 From: ewwwwwwww Date: Sat, 25 Jun 2022 20:55:17 -0700 Subject: [PATCH 04/76] migrated emoji picker to typescript --- .../components/emoji_picker_dropdown.js | 270 ------------------ .../components/emoji_picker_dropdown.tsx | 188 ++++++++++++ .../{emoji_picker.js => emoji_picker.tsx} | 13 +- app/styles/emoji_picker.scss | 1 - types/emoji-mart/index.d.ts | 26 ++ 5 files changed, 223 insertions(+), 275 deletions(-) delete mode 100644 app/soapbox/features/compose/components/emoji_picker_dropdown.js create mode 100644 app/soapbox/features/compose/components/emoji_picker_dropdown.tsx rename app/soapbox/features/emoji/{emoji_picker.js => emoji_picker.tsx} (63%) create mode 100644 types/emoji-mart/index.d.ts diff --git a/app/soapbox/features/compose/components/emoji_picker_dropdown.js b/app/soapbox/features/compose/components/emoji_picker_dropdown.js deleted file mode 100644 index bec0261aa..000000000 --- a/app/soapbox/features/compose/components/emoji_picker_dropdown.js +++ /dev/null @@ -1,270 +0,0 @@ -import classNames from 'classnames'; -import { supportsPassiveEvents } from 'detect-passive-events'; -import PropTypes from 'prop-types'; -import React from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import { defineMessages, injectIntl } from 'react-intl'; -import Overlay from 'react-overlays/lib/Overlay'; - -import { IconButton } from 'soapbox/components/ui'; - -import { buildCustomEmojis } from '../../emoji/emoji'; -import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; - -const messages = defineMessages({ - emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' }, - emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search…' }, - emoji_not_found: { id: 'emoji_button.not_found', defaultMessage: 'No emoji\'s found.' }, - custom: { id: 'emoji_button.custom', defaultMessage: 'Custom' }, - recent: { id: 'emoji_button.recent', defaultMessage: 'Frequently used' }, - search_results: { id: 'emoji_button.search_results', defaultMessage: 'Search results' }, - people: { id: 'emoji_button.people', defaultMessage: 'People' }, - nature: { id: 'emoji_button.nature', defaultMessage: 'Nature' }, - food: { id: 'emoji_button.food', defaultMessage: 'Food & Drink' }, - activity: { id: 'emoji_button.activity', defaultMessage: 'Activity' }, - travel: { id: 'emoji_button.travel', defaultMessage: 'Travel & Places' }, - objects: { id: 'emoji_button.objects', defaultMessage: 'Objects' }, - symbols: { id: 'emoji_button.symbols', defaultMessage: 'Symbols' }, - flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' }, -}); - -let EmojiPicker; // load asynchronously - -const listenerOptions = supportsPassiveEvents ? { passive: true } : false; - -@injectIntl -class EmojiPickerMenu extends React.PureComponent { - - static propTypes = { - custom_emojis: ImmutablePropTypes.list, - frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string), - loading: PropTypes.bool, - onClose: PropTypes.func.isRequired, - onPick: PropTypes.func.isRequired, - style: PropTypes.object, - placement: PropTypes.string, - arrowOffsetLeft: PropTypes.string, - arrowOffsetTop: PropTypes.string, - intl: PropTypes.object.isRequired, - skinTone: PropTypes.number.isRequired, - onSkinTone: PropTypes.func.isRequired, - }; - - static defaultProps = { - style: {}, - loading: true, - frequentlyUsedEmojis: [], - }; - - state = { - modifierOpen: false, - placement: null, - }; - - handleDocumentClick = e => { - if (this.node && !this.node.contains(e.target)) { - this.props.onClose(); - } - } - - componentDidMount() { - document.addEventListener('click', this.handleDocumentClick, false); - document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); - } - - componentWillUnmount() { - document.removeEventListener('click', this.handleDocumentClick, false); - document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); - } - - setRef = c => { - this.node = c; - } - - getI18n = () => { - const { intl } = this.props; - - return { - search: intl.formatMessage(messages.emoji_search), - notfound: intl.formatMessage(messages.emoji_not_found), - categories: { - search: intl.formatMessage(messages.search_results), - recent: intl.formatMessage(messages.recent), - people: intl.formatMessage(messages.people), - nature: intl.formatMessage(messages.nature), - foods: intl.formatMessage(messages.food), - activity: intl.formatMessage(messages.activity), - places: intl.formatMessage(messages.travel), - objects: intl.formatMessage(messages.objects), - symbols: intl.formatMessage(messages.symbols), - flags: intl.formatMessage(messages.flags), - custom: intl.formatMessage(messages.custom), - }, - }; - } - - handleClick = emoji => { - if (!emoji.native) { - emoji.native = emoji.shortcodes; - } - - this.props.onClose(); - this.props.onPick(emoji); - } - - handleModifierOpen = () => { - this.setState({ modifierOpen: true }); - } - - handleModifierClose = () => { - this.setState({ modifierOpen: false }); - } - - handleModifierChange = modifier => { - this.props.onSkinTone(modifier); - } - - render() { - const { loading, style, intl, custom_emojis, skinTone, frequentlyUsedEmojis } = this.props; - - if (loading) { - return
; - } - - const title = intl.formatMessage(messages.emoji); - const { modifierOpen } = this.state; - const theme = 'dark'; - - return ( -
- -
- ); - } - -} - -export default @injectIntl -class EmojiPickerDropdown extends React.PureComponent { - - static propTypes = { - custom_emojis: ImmutablePropTypes.list, - frequentlyUsedEmojis: PropTypes.arrayOf(PropTypes.string), - intl: PropTypes.object.isRequired, - onPickEmoji: PropTypes.func.isRequired, - onSkinTone: PropTypes.func.isRequired, - skinTone: PropTypes.number.isRequired, - }; - - state = { - active: false, - loading: false, - }; - - setRef = (c) => { - this.dropdown = c; - } - - onShowDropdown = (e) => { - e.stopPropagation(); - - this.setState({ active: true }); - - if (!EmojiPicker) { - this.setState({ loading: true }); - - EmojiPickerAsync().then(EmojiMart => { - EmojiPicker = EmojiMart; - - this.setState({ loading: false }); - }).catch(() => { - this.setState({ loading: false }); - }); - } - - const { top } = e.target.getBoundingClientRect(); - this.setState({ placement: top * 2 < innerHeight ? 'bottom' : 'top' }); - } - - onHideDropdown = () => { - this.setState({ active: false }); - } - - onToggle = (e) => { - if (!this.state.loading && (!e.key || e.key === 'Enter')) { - if (this.state.active) { - this.onHideDropdown(); - } else { - this.onShowDropdown(e); - } - } - } - - handleKeyDown = e => { - if (e.key === 'Escape') { - this.onHideDropdown(); - } - } - - setTargetRef = c => { - this.target = c; - } - - findTarget = () => { - return this.target; - } - - render() { - const { intl, onPickEmoji, onSkinTone, skinTone, frequentlyUsedEmojis } = this.props; - const title = intl.formatMessage(messages.emoji); - const { active, loading, placement } = this.state; - - return ( -
- - - - - -
- ); - } - -} diff --git a/app/soapbox/features/compose/components/emoji_picker_dropdown.tsx b/app/soapbox/features/compose/components/emoji_picker_dropdown.tsx new file mode 100644 index 000000000..5704f8f61 --- /dev/null +++ b/app/soapbox/features/compose/components/emoji_picker_dropdown.tsx @@ -0,0 +1,188 @@ +import classNames from 'classnames'; +import React, { useRef, useEffect, useState } from 'react'; +import { usePopper } from 'react-popper'; +import { defineMessages, useIntl } from 'react-intl'; +import { createPortal } from 'react-dom'; +import { supportsPassiveEvents } from 'detect-passive-events'; + +import { IconButton, Toggle } from 'soapbox/components/ui'; +import { useSettings, useSystemTheme } from 'soapbox/hooks'; +import type { List } from 'immutable'; + +import { buildCustomEmojis } from '../../emoji/emoji'; +import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; +// import EmojiPicker from '../../emoji/emoji_picker'; + +let EmojiPicker: any; // load asynchronously + +const messages = defineMessages({ + emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' }, + emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search…' }, + emoji_not_found: { id: 'emoji_button.not_found', defaultMessage: 'No emoji\'s found.' }, + custom: { id: 'emoji_button.custom', defaultMessage: 'Custom' }, + recent: { id: 'emoji_button.recent', defaultMessage: 'Frequently used' }, + search_results: { id: 'emoji_button.search_results', defaultMessage: 'Search results' }, + people: { id: 'emoji_button.people', defaultMessage: 'People' }, + nature: { id: 'emoji_button.nature', defaultMessage: 'Nature' }, + food: { id: 'emoji_button.food', defaultMessage: 'Food & Drink' }, + activity: { id: 'emoji_button.activity', defaultMessage: 'Activity' }, + travel: { id: 'emoji_button.travel', defaultMessage: 'Travel & Places' }, + objects: { id: 'emoji_button.objects', defaultMessage: 'Objects' }, + symbols: { id: 'emoji_button.symbols', defaultMessage: 'Symbols' }, + flags: { id: 'emoji_button.flags', defaultMessage: 'Flags' }, +}); + +interface IEmojiPickerDropdown { + custom_emojis: any, + frequentlyUsedEmojis: string[], + intl: any, + onPickEmoji: (emoji: any) => void, + onSkinTone: () => void, + skinTone: () => void, +} + +const listenerOptions = supportsPassiveEvents ? { passive: true } : false; + +const EmojiPickerDropdown: React.FC = ({ custom_emojis, frequentlyUsedEmojis, onPickEmoji, onSkinTone, skinTone }) => { + const intl = useIntl(); + const settings = useSettings(); + const title = intl.formatMessage(messages.emoji); + const userTheme = settings.get('themeMode'); + const theme = (userTheme === 'dark' || userTheme === 'light') ? userTheme : 'auto'; + + const [popperElement, setPopperElement] = useState(null); + const [referenceElement, setReferenceElement] = useState(null); + const [containerElement, setContainerElement] = useState(null); + + const [visible, setVisible] = useState(false); + const [loading, setLoading] = useState(false); + + const { styles, attributes } = usePopper(referenceElement, popperElement, { + placement: 'top-start', + }); + + const handleToggle = () => { + setVisible(!visible); + }; + + const handleHide = () => { + setVisible(false); + }; + + const handleDocClick = (e: any) => { + if (!containerElement?.contains(e.target) && !popperElement?.contains(e.target)) { + setVisible(false); + } + } + + const handlePick = (emoji: any) => { + if (!emoji.native) { + emoji.native = emoji.shortcodes; + } + + setVisible(false); + onPickEmoji(emoji); + } + + const getI18n = () => { + return { + search: intl.formatMessage(messages.emoji_search), + notfound: intl.formatMessage(messages.emoji_not_found), + categories: { + search: intl.formatMessage(messages.search_results), + recent: intl.formatMessage(messages.recent), + people: intl.formatMessage(messages.people), + nature: intl.formatMessage(messages.nature), + foods: intl.formatMessage(messages.food), + activity: intl.formatMessage(messages.activity), + places: intl.formatMessage(messages.travel), + objects: intl.formatMessage(messages.objects), + symbols: intl.formatMessage(messages.symbols), + flags: intl.formatMessage(messages.flags), + custom: intl.formatMessage(messages.custom), + }, + }; + }; + + useEffect(() => { + document.addEventListener('click', handleDocClick, false); + document.addEventListener('touchend', handleDocClick, listenerOptions); + + return function cleanup() { + document.removeEventListener('click', handleDocClick); + document.removeEventListener('touchend', handleDocClick); + } + }); + + useEffect(() => { + if (!EmojiPicker) { + setLoading(true); + + EmojiPickerAsync().then(EmojiMart => { + EmojiPicker = EmojiMart.Picker; + + setLoading(false); + }).catch(() => { + setLoading(false); + }); + } + }, [visible]); + + let Popup; + + if (loading) { + Popup = () =>
; + } else { + Popup = () =>
+ +
+ } + + return ( +
+ + + {createPortal( +
+ {visible && ()} +
, + document.body + )} +
+ ); +}; + +export default EmojiPickerDropdown; diff --git a/app/soapbox/features/emoji/emoji_picker.js b/app/soapbox/features/emoji/emoji_picker.tsx similarity index 63% rename from app/soapbox/features/emoji/emoji_picker.js rename to app/soapbox/features/emoji/emoji_picker.tsx index 4dda1de07..691af4a13 100644 --- a/app/soapbox/features/emoji/emoji_picker.js +++ b/app/soapbox/features/emoji/emoji_picker.tsx @@ -1,5 +1,5 @@ -import data from '@emoji-mart/data'; -import { Picker as EmojiPicker } from 'emoji-mart'; +import data from '@emoji-mart/data/sets/14/twitter.json' +import { Picker as EmojiPicker, PickerProps } from 'emoji-mart'; import React, { useRef, useEffect } from 'react'; // const categories = [ @@ -14,9 +14,10 @@ import React, { useRef, useEffect } from 'react'; // 'symbols', // 'flags', // ]; +// -export default function Picker(props) { - const ref = useRef(); +function Picker(props: PickerProps) { + const ref = useRef(null); useEffect(() => { const input = { ...props, data, ref }; @@ -26,3 +27,7 @@ export default function Picker(props) { return
; } + +export { + Picker +} diff --git a/app/styles/emoji_picker.scss b/app/styles/emoji_picker.scss index 7bef34d27..0b94fcfb7 100644 --- a/app/styles/emoji_picker.scss +++ b/app/styles/emoji_picker.scss @@ -1,4 +1,3 @@ -.emoji-mart, .emoji-mart * { box-sizing: border-box; line-height: 1.15; diff --git a/types/emoji-mart/index.d.ts b/types/emoji-mart/index.d.ts new file mode 100644 index 000000000..2f0daf1ab --- /dev/null +++ b/types/emoji-mart/index.d.ts @@ -0,0 +1,26 @@ +declare module 'emoji-mart' { + export type PickerProps = { + custom?: { emojis: any[] }[], + set?: string, + title?: string, + theme?: string, + onEmojiSelect?: any, + recent?: any, + skin?: any, + perLine?: number, + emojiSize?: number, + emojiButtonSize?: number, + navPosition?: string, + set?: string, + theme?: string, + autoFocus?: boolean, + i18n?: any, + } + + export class Picker { + + constructor(props: PickerProps); + + } + +} From f8bd30a5f7354950ebb58928db87b61065dd11f7 Mon Sep 17 00:00:00 2001 From: ewwwwwwww Date: Sat, 25 Jun 2022 21:08:44 -0700 Subject: [PATCH 05/76] remove consolelog --- app/soapbox/reducers/compose.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/soapbox/reducers/compose.ts b/app/soapbox/reducers/compose.ts index d56307a25..3b861fb58 100644 --- a/app/soapbox/reducers/compose.ts +++ b/app/soapbox/reducers/compose.ts @@ -222,8 +222,6 @@ const insertEmoji = (state: State, position: number, emojiData: Emoji, needsSpac const oldText = state.text; const emoji = needsSpace ? ' ' + emojiData.native : emojiData.native; - console.log(emojiData, emoji); - return state.merge({ text: `${oldText.slice(0, position)}${emoji} ${oldText.slice(position)}`, focusDate: new Date(), From 89bba0e2e3427d46601a72cd67c1d1fd9deab0ed Mon Sep 17 00:00:00 2001 From: ewwwwwwww Date: Wed, 29 Jun 2022 01:25:57 -0700 Subject: [PATCH 06/76] lint fixes --- .../components/emoji_picker_dropdown.tsx | 63 +++++++++---------- app/soapbox/features/emoji/emoji_picker.tsx | 6 +- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/app/soapbox/features/compose/components/emoji_picker_dropdown.tsx b/app/soapbox/features/compose/components/emoji_picker_dropdown.tsx index 5704f8f61..31722a533 100644 --- a/app/soapbox/features/compose/components/emoji_picker_dropdown.tsx +++ b/app/soapbox/features/compose/components/emoji_picker_dropdown.tsx @@ -1,18 +1,19 @@ import classNames from 'classnames'; -import React, { useRef, useEffect, useState } from 'react'; -import { usePopper } from 'react-popper'; -import { defineMessages, useIntl } from 'react-intl'; -import { createPortal } from 'react-dom'; import { supportsPassiveEvents } from 'detect-passive-events'; +import React, { useEffect, useState } from 'react'; +import { createPortal } from 'react-dom'; +import { defineMessages, useIntl } from 'react-intl'; +import { usePopper } from 'react-popper'; -import { IconButton, Toggle } from 'soapbox/components/ui'; -import { useSettings, useSystemTheme } from 'soapbox/hooks'; -import type { List } from 'immutable'; +import { IconButton } from 'soapbox/components/ui'; +import { useSettings } from 'soapbox/hooks'; import { buildCustomEmojis } from '../../emoji/emoji'; import { EmojiPicker as EmojiPickerAsync } from '../../ui/util/async-components'; // import EmojiPicker from '../../emoji/emoji_picker'; +import type { List } from 'immutable'; + let EmojiPicker: any; // load asynchronously const messages = defineMessages({ @@ -33,8 +34,8 @@ const messages = defineMessages({ }); interface IEmojiPickerDropdown { - custom_emojis: any, - frequentlyUsedEmojis: string[], + custom_emojis: List, + frequentlyUsedEmojis: string[], intl: any, onPickEmoji: (emoji: any) => void, onSkinTone: () => void, @@ -65,15 +66,11 @@ const EmojiPickerDropdown: React.FC = ({ custom_emojis, fr setVisible(!visible); }; - const handleHide = () => { - setVisible(false); - }; - const handleDocClick = (e: any) => { if (!containerElement?.contains(e.target) && !popperElement?.contains(e.target)) { setVisible(false); } - } + }; const handlePick = (emoji: any) => { if (!emoji.native) { @@ -82,7 +79,7 @@ const EmojiPickerDropdown: React.FC = ({ custom_emojis, fr setVisible(false); onPickEmoji(emoji); - } + }; const getI18n = () => { return { @@ -111,7 +108,7 @@ const EmojiPickerDropdown: React.FC = ({ custom_emojis, fr return function cleanup() { document.removeEventListener('click', handleDocClick); document.removeEventListener('touchend', handleDocClick); - } + }; }); useEffect(() => { @@ -133,21 +130,23 @@ const EmojiPickerDropdown: React.FC = ({ custom_emojis, fr if (loading) { Popup = () =>
; } else { - Popup = () =>
- -
+ Popup = () => ( +
+ +
+ ); } return ( @@ -179,7 +178,7 @@ const EmojiPickerDropdown: React.FC = ({ custom_emojis, fr > {visible && ()}
, - document.body + document.body, )}
); diff --git a/app/soapbox/features/emoji/emoji_picker.tsx b/app/soapbox/features/emoji/emoji_picker.tsx index 691af4a13..d76eec506 100644 --- a/app/soapbox/features/emoji/emoji_picker.tsx +++ b/app/soapbox/features/emoji/emoji_picker.tsx @@ -1,4 +1,4 @@ -import data from '@emoji-mart/data/sets/14/twitter.json' +import data from '@emoji-mart/data/sets/14/twitter.json'; import { Picker as EmojiPicker, PickerProps } from 'emoji-mart'; import React, { useRef, useEffect } from 'react'; @@ -29,5 +29,5 @@ function Picker(props: PickerProps) { } export { - Picker -} + Picker, +}; From a8e7e10f6100e17928008df0e4fb51201f296682 Mon Sep 17 00:00:00 2001 From: ewwwwwwww Date: Sun, 3 Jul 2022 01:12:57 -0700 Subject: [PATCH 07/76] new emojifier --- app/soapbox/features/emoji/emoji.js | 99 -------- app/soapbox/features/emoji/emoji.ts | 165 +++++++++++++ .../features/emoji/emoji_compressed.js | 6 +- package.json | 5 +- types/emoji-mart/index.d.ts | 12 + yarn.lock | 228 +++++++++++++++--- 6 files changed, 372 insertions(+), 143 deletions(-) delete mode 100644 app/soapbox/features/emoji/emoji.js create mode 100644 app/soapbox/features/emoji/emoji.ts diff --git a/app/soapbox/features/emoji/emoji.js b/app/soapbox/features/emoji/emoji.js deleted file mode 100644 index 2607c91a9..000000000 --- a/app/soapbox/features/emoji/emoji.js +++ /dev/null @@ -1,99 +0,0 @@ -import Trie from 'substring-trie'; - -import { joinPublicPath } from 'soapbox/utils/static'; - -import unicodeMapping from './emoji_unicode_mapping_light'; - -const trie = new Trie(Object.keys(unicodeMapping)); - -const emojify = (str, customEmojis = {}, autoplay = false) => { - const tagCharsWithoutEmojis = '<&'; - const tagCharsWithEmojis = Object.keys(customEmojis).length ? '<&:' : '<&'; - let rtn = '', tagChars = tagCharsWithEmojis, invisible = 0; - for (;;) { - let match, i = 0, tag; - while (i < str.length && (tag = tagChars.indexOf(str[i])) === -1 && (invisible || !(match = trie.search(str.slice(i))))) { - i += str.codePointAt(i) < 65536 ? 1 : 2; - } - let rend, replacement = ''; - if (i === str.length) { - break; - } else if (str[i] === ':') { - // FIXME: This is insane. - /* eslint-disable no-loop-func */ - if (!(() => { - rend = str.indexOf(':', i + 1) + 1; - if (!rend) return false; // no pair of ':' - const lt = str.indexOf('<', i + 1); - if (!(lt === -1 || lt >= rend)) return false; // tag appeared before closing ':' - const shortname = str.slice(i, rend); - // now got a replacee as ':shortname:' - // if you want additional emoji handler, add statements below which set replacement and return true. - if (shortname in customEmojis) { - const filename = autoplay ? customEmojis[shortname].url : customEmojis[shortname].static_url; - replacement = `${shortname}`; - return true; - } - return false; - })()) rend = ++i; - /* eslint-enable no-loop-func */ - } else if (tag >= 0) { // <, & - rend = str.indexOf('>;'[tag], i + 1) + 1; - if (!rend) { - break; - } - if (tag === 0) { - if (invisible) { - if (str[i + 1] === '/') { // closing tag - if (!--invisible) { - tagChars = tagCharsWithEmojis; - } - } else if (str[rend - 2] !== '/') { // opening tag - invisible++; - } - } else { - if (str.startsWith('