From 0a79a747730bb4a10eb2544412dab68a10602240 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Mon, 29 Aug 2022 18:46:41 -0400 Subject: Use dedicated indicator for non-ascii domain names --- src/components/emoji_input/emoji_input.js | 4 +++- src/components/emoji_input/emoji_input.vue | 16 +++++++++++++++- src/components/emoji_input/suggestor.js | 11 ++++++----- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 5ba3907f..b664d6b3 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -1,5 +1,6 @@ import Completion from '../../services/completion/completion.js' import EmojiPicker from '../emoji_picker/emoji_picker.vue' +import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue' import { take } from 'lodash' import { findOffset } from '../../services/offset_finder/offset_finder.service.js' @@ -120,7 +121,8 @@ const EmojiInput = { } }, components: { - EmojiPicker + EmojiPicker, + UnicodeDomainIndicator }, computed: { padEmoji () { diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 7d95ab7e..81b81913 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -50,7 +50,21 @@ {{ suggestion.replacement }}
- {{ suggestion.displayText }} + + {{ suggestion.displayText }} + + + {{ suggestion.displayText }} + {{ suggestion.detailText }}
diff --git a/src/components/emoji_input/suggestor.js b/src/components/emoji_input/suggestor.js index e8efbd1e..0ddb4d68 100644 --- a/src/components/emoji_input/suggestor.js +++ b/src/components/emoji_input/suggestor.js @@ -116,11 +116,12 @@ export const suggestUsers = ({ dispatch, state }) => { return diff + nameAlphabetically + screenNameAlphabetically /* eslint-disable camelcase */ - }).map(({ screen_name, screen_name_ui, name, profile_image_url_original }) => ({ - displayText: screen_name_ui, - detailText: name, - imageUrl: profile_image_url_original, - replacement: '@' + screen_name + ' ' + }).map((user) => ({ + user, + displayText: user.screen_name_ui, + detailText: user.name, + imageUrl: user.profile_image_url_original, + replacement: '@' + user.screen_name + ' ' })) /* eslint-enable camelcase */ -- cgit v1.2.3-70-g09d2 From 8777b6eadd7deadf010dc36bb90514f75fc0da16 Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Fri, 8 Oct 2021 01:02:16 -0400 Subject: Clean up legacy code in emoji picker Ref: grouped-emoji-picker --- src/components/emoji_input/emoji_input.js | 1 - src/components/emoji_picker/emoji_picker.js | 130 ++++++--------------------- src/components/emoji_picker/emoji_picker.vue | 3 +- src/directives/lazy_image_container.js | 13 --- 4 files changed, 28 insertions(+), 119 deletions(-) delete mode 100644 src/directives/lazy_image_container.js (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index b664d6b3..fb2096c9 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -207,7 +207,6 @@ const EmojiInput = { }, triggerShowPicker () { this.showPicker = true - this.$refs.picker.startEmojiLoad() this.$nextTick(() => { this.scrollIntoView() this.focusPickerInput() diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index 82e5ad0b..b0162479 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -1,6 +1,6 @@ import { defineAsyncComponent } from 'vue' import Checkbox from '../checkbox/checkbox.vue' -import LazyImageContainer from '../../directives/lazy_image_container' +import lozad from 'lozad' import { library } from '@fortawesome/fontawesome-svg-core' import { faBoxOpen, @@ -54,7 +54,6 @@ const EmojiPicker = { showingStickers: false, groupsScrolledClass: 'scrolled-top', keepOpen: false, - customEmojiBufferSlice: LOAD_EMOJI_BY, customEmojiTimeout: null, customEmojiLoadAllConfirmed: false, groupLoadedCount: {}, @@ -65,9 +64,6 @@ const EmojiPicker = { StickerPicker: defineAsyncComponent(() => import('../sticker_picker/sticker_picker.vue')), Checkbox }, - directives: { - LazyImageContainer - }, methods: { onStickerUploaded (e) { this.$emit('sticker-uploaded', e) @@ -82,10 +78,6 @@ const EmojiPicker = { onScroll (e) { const target = (e && e.target) || this.$refs['emoji-groups'] this.updateScrolledClass(target) - this.scrolledGroup(target) - this.$nextTick(() => { - this.triggerLoadMore(target) - }) }, highlight (key) { const ref = this.$refs['group-' + key] @@ -94,7 +86,6 @@ const EmojiPicker = { this.activeGroup = key this.$nextTick(() => { this.$refs['emoji-groups'].scrollTop = top + 1 - this.loadEmoji(key) }) }, updateScrolledClass (target) { @@ -106,101 +97,48 @@ const EmojiPicker = { this.groupsScrolledClass = 'scrolled-middle' } }, - triggerLoadMore (target) { - Object.keys(this.allCustomGroups) - .filter(id => this.filteredEmojiGroups.filter(group => group.id === id).length > 0) - .map(groupId => { - const ref = this.$refs[`group-end-${groupId}`][0] - if (!ref) return undefined - - const bottom = ref.offsetTop + ref.offsetHeight - - const group = this.$refs[`group-${groupId}`][0] - const top = group.offsetTop - - const scrollerBottom = target.scrollTop + target.clientHeight - const scrollerTop = target.scrollTop - const scrollerMax = target.scrollHeight - - // Loads more emoji when they come into view - const approachingBottom = bottom - scrollerBottom < LOAD_EMOJI_MARGIN - // Always load when at the very top in case there's no scroll space yet - const atTop = scrollerTop < top + target.clientHeight / 2 && top < scrollerBottom - const unscrollable = top - bottom < target.clientHeight - // Don't load when looking at unicode category or at the very bottom - const bottomAboveViewport = bottom < scrollerTop || scrollerBottom === scrollerMax - if (!bottomAboveViewport && (approachingBottom || atTop || unscrollable)) { - return groupId - } - return undefined - }) - .filter(k => k) - .map(k => { - this.loadEmoji(k) - }) - }, - scrolledGroup (target) { - const top = target.scrollTop + 5 - this.$nextTick(() => { - this.allEmojiGroups.forEach(group => { - const ref = this.$refs['group-' + group.id] - if (ref.offsetTop <= top) { - this.activeGroup = group.id - } - }) - }) - }, - loadEmoji (loadGroup) { - if (!this.allCustomGroups[loadGroup]) { - return - } - - const allLoaded = this.loadedCount[loadGroup] >= this.allCustomGroups[loadGroup].emojis.length - - if (allLoaded) { - return - } - - this.groupLoadedCount = { - ...this.groupLoadedCount, - [loadGroup]: this.loadedCount[loadGroup] + LOAD_EMOJI_BY - } - }, - startEmojiLoad (forceUpdate = false) { - if (!forceUpdate) { - this.keyword = '' - } - this.$nextTick(() => { - this.$refs['emoji-groups'].scrollTop = 0 - this.$nextTick(() => { - if (this.firstLoaded) { - return - } - this.triggerLoadMore(this.$refs['emoji-groups']) - this.firstLoaded = true - }) - }) - }, toggleStickers () { this.showingStickers = !this.showingStickers }, setShowStickers (value) { this.showingStickers = value }, - limitedEmojis (list, groupId) { - return list // list.slice(0, this.loadedCount[groupId]) - }, filterByKeyword (list, keyword) { return filterByKeyword(list, keyword) + }, + initializeLazyLoad () { + this.destroyLazyLoad() + this.$lozad = lozad('img', {}) + this.$lozad.observe() + }, + destroyLazyLoad () { + if (this.$lozad) { + if (this.$lozad.observer) { + this.$lozad.observer.disconnect() + } + if (this.$lozad.mutationObserver) { + this.$lozad.mutationObserver.disconnect() + } + } } }, watch: { keyword () { this.customEmojiLoadAllConfirmed = false this.onScroll() - this.startEmojiLoad(true) + // Wait for the dom to change + this.$nextTick(() => this.initializeLazyLoad()) + }, + allCustomGroups () { + this.$nextTick(() => this.initializeLazyLoad()) } }, + mounted () { + this.initializeLazyLoad() + }, + destroyed () { + this.destroyLazyLoad() + }, computed: { activeGroupView () { return this.showingStickers ? '' : this.activeGroup @@ -214,10 +152,6 @@ const EmojiPicker = { allCustomGroups () { return this.$store.getters.groupedCustomEmojis }, - sensibleInitialAmountForAGroup () { - const groupCount = Object.keys(this.allCustomGroups).length - return Math.max(Math.floor(LOAD_EMOJI_BY / Math.max(groupCount, 1)), 1) - }, allEmojiGroups () { const standardEmojis = this.$store.state.instance.emoji || [] return Object.entries(this.allCustomGroups) @@ -237,16 +171,6 @@ const EmojiPicker = { })) .filter(group => group.emojis.length > 0) }, - loadedCount () { - return Object.keys(this.allCustomGroups) - .reduce((res, groupId) => { - res[groupId] = this.groupLoadedCount[groupId] || this.sensibleInitialAmountForAGroup - return res - }, {}) - }, - lastNonUnicodeGroupId () { - return this.emojis[this.emojis.length - 2].id - }, stickerPickerEnabled () { return (this.$store.state.instance.stickers || []).length !== 0 } diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue index 0e6c7e41..0df33c24 100644 --- a/src/components/emoji_picker/emoji_picker.vue +++ b/src/components/emoji_picker/emoji_picker.vue @@ -62,7 +62,6 @@
Date: Fri, 8 Oct 2021 15:09:24 -0400 Subject: Lazy-load emoji picker in post form When clicking the reply button, we used to load the whole emoji picker. This causes a considerable delay even if the user is not going to use the emoji picker. Now the content of the emoji picker is loaded only after the user has explicitly opened the emoji picker. Ref: grouped-emoji-picker --- src/components/emoji_input/emoji_input.vue | 1 + src/components/emoji_picker/emoji_picker.js | 24 +++++++++++++++++++----- src/components/emoji_picker/emoji_picker.vue | 9 +++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 81b81913..eedde9aa 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -19,6 +19,7 @@ v-if="enableEmojiPicker" ref="picker" :class="{ hide: !showPicker }" + :showing="showPicker" :enable-sticker-picker="enableStickerPicker" class="emoji-picker-panel" @emoji="insert" diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index 5b90c31e..8b4f302f 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -39,6 +39,10 @@ const EmojiPicker = { required: false, type: Boolean, default: false + }, + showing: { + required: true, + type: Boolean } }, data () { @@ -48,7 +52,9 @@ const EmojiPicker = { showingStickers: false, groupsScrolledClass: 'scrolled-top', keepOpen: false, - customEmojiTimeout: null + customEmojiTimeout: null, + // Lazy-load only after the first time `showing` becomes true. + contentLoaded: false } }, components: { @@ -115,6 +121,9 @@ const EmojiPicker = { this.$lozad = lozad('img', {}) this.$lozad.observe() }, + waitForDomAndInitializeLazyLoad() { + this.$nextTick(() => this.initializeLazyLoad()) + }, destroyLazyLoad () { if (this.$lozad) { if (this.$lozad.observer) { @@ -129,18 +138,23 @@ const EmojiPicker = { watch: { keyword () { this.onScroll() - // Wait for the dom to change - this.$nextTick(() => this.initializeLazyLoad()) + this.waitForDomAndInitializeLazyLoad() }, allCustomGroups () { - this.$nextTick(() => this.initializeLazyLoad()) + this.waitForDomAndInitializeLazyLoad() + }, + showing (val) { + if (val) { + this.contentLoaded = true + this.waitForDomAndInitializeLazyLoad() + } } }, mounted () { if (this.defaultGroup) { this.highlight(this.defaultGroup) } - this.initializeLazyLoad() + this.waitForDomAndInitializeLazyLoad() }, destroyed () { this.destroyLazyLoad() diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue index ed196066..b92bccd7 100644 --- a/src/components/emoji_picker/emoji_picker.vue +++ b/src/components/emoji_picker/emoji_picker.vue @@ -1,5 +1,7 @@ @@ -102,6 +110,7 @@ color: var(--text, $fallback--text); } } + .emoji-picker-panel { position: absolute; z-index: 20; @@ -115,31 +124,6 @@ .autocomplete { &-panel { position: absolute; - z-index: 20; - margin-top: 2px; - - &.hide { - display: none - } - - &-body { - margin: 0 0.5em 0 0.5em; - border-radius: $fallback--tooltipRadius; - border-radius: var(--tooltipRadius, $fallback--tooltipRadius); - box-shadow: 1px 2px 4px rgba(0, 0, 0, 0.5); - box-shadow: var(--popupShadow); - min-width: 75%; - background-color: $fallback--bg; - background-color: var(--popover, $fallback--bg); - color: $fallback--link; - color: var(--popoverText, $fallback--link); - --faint: var(--popoverFaintText, $fallback--faint); - --faintLink: var(--popoverFaintLink, $fallback--faint); - --lightText: var(--popoverLightText, $fallback--lightText); - --postLink: var(--popoverPostLink, $fallback--link); - --postFaintLink: var(--popoverPostFaintLink, $fallback--link); - --icon: var(--popoverIcon, $fallback--icon); - } } &-item { @@ -196,5 +180,25 @@ input, textarea { flex: 1 0 auto; } + + .hidden-overlay { + opacity: 0; + pointer-events: none; + position: absolute; + top: 0; + bottom: 0; + right: 0; + left: 0; + overflow: hidden; + /* DEBUG STUFF */ + color: red; + /* set opacity to non-zero to see the overlay */ + + .caret { + width: 0; + margin-right: calc(-1ch - 1px); + border: 1px solid red; + } + } } diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index dd332c35..60c42f0f 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -51,6 +51,10 @@ const Popover = { // lockReEntry is a flag that is set when mouse cursor is leaving the popover's content // so that if mouse goes back into popover it won't be re-shown again to prevent annoyance // with popovers refusing to be hidden when user wants to interact with something in below popover + anchorEl: null, + // There's an issue where having teleport enabled by default causes things just... + // not render at all, i.e. main post status form and its emoji inputs + teleport: false, lockReEntry: false, hidden: true, styles: {}, @@ -63,6 +67,10 @@ const Popover = { } }, methods: { + setAnchorEl (el) { + this.anchorEl = el + this.updateStyles() + }, containerBoundingClientRect () { const container = this.boundToSelector ? this.$el.closest(this.boundToSelector) : this.$el.offsetParent return container.getBoundingClientRect() @@ -75,7 +83,7 @@ const Popover = { // Popover will be anchored around this element, trigger ref is the container, so // its children are what are inside the slot. Expect only one v-slot:trigger. - const anchorEl = (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el + const anchorEl = this.anchorEl || (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el // SVGs don't have offsetWidth/Height, use fallback const anchorHeight = anchorEl.offsetHeight || anchorEl.clientHeight const anchorWidth = anchorEl.offsetWidth || anchorEl.clientWidth @@ -319,6 +327,7 @@ const Popover = { } }, mounted () { + this.teleport = true let scrollable = this.$refs.trigger.closest('.column.-scrollable') || this.$refs.trigger.closest('.mobile-notifications') if (!scrollable) scrollable = window diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue index 623af8d2..217eba7c 100644 --- a/src/components/popover/popover.vue +++ b/src/components/popover/popover.vue @@ -11,7 +11,7 @@ > - +
Date: Sun, 9 Oct 2022 23:02:39 +0300 Subject: cleanup --- src/components/emoji_input/emoji_input.js | 22 +--------------------- .../post_status_form/post_status_form.js | 3 --- 2 files changed, 1 insertion(+), 24 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index b365043c..46f04c60 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -139,8 +139,6 @@ const EmojiInput = { return this.modelValue.slice(this.caret) }, showSuggestions () { - console.log(this.focused) - console.log(this.suggestions) return this.focused && this.suggestions && this.suggestions.length > 0 && @@ -227,11 +225,8 @@ const EmojiInput = { input.addEventListener('click', this.onClickInput) input.addEventListener('transitionend', this.onTransition) input.addEventListener('input', this.onInput) + // FIXME LEAK input.addEventListener('scroll', (e) => { - console.log({ - top: this.input.scrollTop, - left: this.input.scrollLeft - }) this.$refs.hiddenOverlay.scrollTo({ top: this.input.scrollTop, left: this.input.scrollLeft @@ -278,12 +273,6 @@ const EmojiInput = { img: imageUrl || '' })) this.$refs.suggestorPopover.updateStyles() - }, - suggestions: { - handler (newValue) { - this.$nextTick(this.resize) - }, - deep: true } }, methods: { @@ -450,16 +439,12 @@ const EmojiInput = { } }) }, - onTransition (e) { - this.resize() - }, onBlur (e) { // Clicking on any suggestion removes focus from autocomplete, // preventing click handler ever executing. this.blurTimeout = setTimeout(() => { this.focused = false this.setCaret(e) - this.resize() }, 200) }, onClick (e, suggestion) { @@ -476,13 +461,11 @@ const EmojiInput = { } this.focused = true this.setCaret(e) - this.resize() this.temporarilyHideSuggestions = false }, onKeyUp (e) { const { key } = e this.setCaret(e) - this.resize() // Setting hider in keyUp to prevent suggestions from blinking // when moving away from suggested spot @@ -494,7 +477,6 @@ const EmojiInput = { }, onPaste (e) { this.setCaret(e) - this.resize() }, onKeyDown (e) { const { ctrlKey, shiftKey, key } = e @@ -541,12 +523,10 @@ const EmojiInput = { } this.showPicker = false - this.resize() }, onInput (e) { this.showPicker = false this.setCaret(e) - this.resize() this.$emit('update:modelValue', e.target.value) }, onClickInput (e) { diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index 5c536b74..eb55cfcc 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -501,7 +501,6 @@ const PostStatusForm = { if (target.value === '') { target.style.height = null this.$emit('resize') - this.$refs['emoji-input'].resize() return } @@ -588,8 +587,6 @@ const PostStatusForm = { } else { scrollerRef.scrollTop = targetScroll } - - this.$refs['emoji-input'].resize() }, showEmojiPicker () { this.$refs.textarea.focus() -- cgit v1.2.3-70-g09d2 From 2469415809c7bff4dac97c469fd4aa74f9191a75 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sun, 9 Oct 2022 23:02:42 +0300 Subject: fix css --- src/components/emoji_input/emoji_input.vue | 111 ++++++++++++++--------------- 1 file changed, 55 insertions(+), 56 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 8a4bc244..68498ef0 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -121,62 +121,6 @@ } } - .autocomplete { - &-panel { - position: absolute; - } - - &-item { - display: flex; - cursor: pointer; - padding: 0.2em 0.4em; - border-bottom: 1px solid rgba(0, 0, 0, 0.4); - height: 32px; - - .image { - width: 32px; - height: 32px; - line-height: 32px; - text-align: center; - font-size: 32px; - - margin-right: 4px; - - img { - width: 32px; - height: 32px; - object-fit: contain; - } - } - - .label { - display: flex; - flex-direction: column; - justify-content: center; - margin: 0 0.1em 0 0.2em; - - .displayText { - line-height: 1.5; - } - - .detailText { - font-size: 9px; - line-height: 9px; - } - } - - &.highlighted { - background-color: $fallback--fg; - background-color: var(--selectedMenuPopover, $fallback--fg); - color: var(--selectedMenuPopoverText, $fallback--text); - --faint: var(--selectedMenuPopoverFaintText, $fallback--faint); - --faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint); - --lightText: var(--selectedMenuPopoverLightText, $fallback--lightText); - --icon: var(--selectedMenuPopoverIcon, $fallback--icon); - } - } - } - input, textarea { flex: 1 0 auto; } @@ -201,4 +145,59 @@ } } } +.autocomplete { + &-panel { + position: absolute; + } + + &-item { + display: flex; + cursor: pointer; + padding: 0.2em 0.4em; + border-bottom: 1px solid rgba(0, 0, 0, 0.4); + height: 32px; + + .image { + width: 32px; + height: 32px; + line-height: 32px; + text-align: center; + font-size: 32px; + + margin-right: 4px; + + img { + width: 32px; + height: 32px; + object-fit: contain; + } + } + + .label { + display: flex; + flex-direction: column; + justify-content: center; + margin: 0 0.1em 0 0.2em; + + .displayText { + line-height: 1.5; + } + + .detailText { + font-size: 9px; + line-height: 9px; + } + } + + &.highlighted { + background-color: $fallback--fg; + background-color: var(--selectedMenuPopover, $fallback--fg); + color: var(--selectedMenuPopoverText, $fallback--text); + --faint: var(--selectedMenuPopoverFaintText, $fallback--faint); + --faintLink: var(--selectedMenuPopoverFaintLink, $fallback--faint); + --lightText: var(--selectedMenuPopoverLightText, $fallback--lightText); + --icon: var(--selectedMenuPopoverIcon, $fallback--icon); + } + } +} -- cgit v1.2.3-70-g09d2 From 518fcf856a63c5b50745a6549e10b228d27c10d3 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sun, 9 Oct 2022 23:09:31 +0300 Subject: fix blinking popup --- src/components/emoji_input/emoji_input.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 46f04c60..5131e699 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -258,7 +258,9 @@ const EmojiInput = { textAtCaret: async function (newWord) { const firstchar = newWord.charAt(0) if (newWord === firstchar) { - this.suggestions = [] + if (firstchar === ' ') { + this.suggestions = [] + } return } const matchedSuggestions = await this.suggest(newWord, this.maybeLocalizedEmojiNamesAndKeywords) -- cgit v1.2.3-70-g09d2 From 296a6fa4e3d14f0c8ca091870fd4f7e85bc34df8 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sun, 9 Oct 2022 23:42:36 +0300 Subject: some shitty initial implementation of emoji picker with popover --- src/components/emoji_input/emoji_input.js | 36 ++--- src/components/emoji_input/emoji_input.vue | 5 +- src/components/emoji_picker/emoji_picker.js | 32 ++-- src/components/emoji_picker/emoji_picker.scss | 8 +- src/components/emoji_picker/emoji_picker.vue | 210 +++++++++++++------------- src/components/popover/popover.js | 6 + 6 files changed, 150 insertions(+), 147 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 5131e699..635251be 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -115,12 +115,12 @@ const EmojiInput = { caret: 0, focused: false, blurTimeout: null, - showPicker: false, temporarilyHideSuggestions: false, keepOpen: false, disableClickOutside: false, suggestions: [], - overlayStyle: {} + overlayStyle: {}, + pickerShown: false } }, components: { @@ -142,7 +142,6 @@ const EmojiInput = { return this.focused && this.suggestions && this.suggestions.length > 0 && - !this.showPicker && !this.temporarilyHideSuggestions }, textAtCaret () { @@ -285,8 +284,8 @@ const EmojiInput = { if (pickerInput) pickerInput.focus() }, triggerShowPicker () { - this.showPicker = true this.$nextTick(() => { + this.$refs.picker.showPicker() this.scrollIntoView() this.focusPickerInput() }) @@ -299,12 +298,16 @@ const EmojiInput = { }, 0) }, togglePicker () { + console.log('piick') this.input.focus() - this.showPicker = !this.showPicker - if (this.showPicker) { + if (!this.pickerShown) { + console.log('pick') this.scrollIntoView() + this.$refs.picker.showPicker() this.$refs.picker.startEmojiLoad() this.$nextTick(this.focusPickerInput) + } else { + this.$refs.picker.hidePicker() } }, replace (replacement) { @@ -441,6 +444,12 @@ const EmojiInput = { } }) }, + onPickerShown () { + this.pickerShown = true + }, + onPickerClosed () { + this.pickerShown = false + }, onBlur (e) { // Clicking on any suggestion removes focus from autocomplete, // preventing click handler ever executing. @@ -458,9 +467,6 @@ const EmojiInput = { this.blurTimeout = null } - if (!this.keepOpen) { - this.showPicker = false - } this.focused = true this.setCaret(e) this.temporarilyHideSuggestions = false @@ -523,27 +529,15 @@ const EmojiInput = { this.input.focus() } } - - this.showPicker = false }, onInput (e) { - this.showPicker = false this.setCaret(e) this.$emit('update:modelValue', e.target.value) }, - onClickInput (e) { - this.showPicker = false - }, - onClickOutside (e) { - if (this.disableClickOutside) return - this.showPicker = false - }, onStickerUploaded (e) { - this.showPicker = false this.$emit('sticker-uploaded', e) }, onStickerUploadFailed (e) { - this.showPicker = false this.$emit('sticker-upload-Failed', e) }, setCaret ({ target: { selectionStart } }) { diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 68498ef0..63bf856e 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -1,7 +1,6 @@ import('../sticker_picker/sticker_picker.vue')), Checkbox, - StillImage + StillImage, + Popover }, methods: { + showPicker () { + console.log('pick') + this.$refs.popover.showPopover() + this.onShowing() + }, + hidePicker () { + this.$refs.popover.hidePopover() + }, setGroupRef (name) { return el => { this.groupRefs[name] = el } }, setEmojiRef (name) { return el => { this.emojiRefs[name] = el } }, + onPopoverShown () { + this.$emit('show') + }, + onPopoverClosed () { + this.$emit('close') + }, onStickerUploaded (e) { this.$emit('sticker-uploaded', e) }, @@ -251,16 +263,6 @@ const EmojiPicker = { allCustomGroups () { this.waitForDomAndInitializeLazyLoad() this.filteredEmojiGroups = this.getFilteredEmojiGroups() - }, - showing (val) { - if (val) { - this.onShowing() - } - } - }, - mounted () { - if (this.showing) { - this.onShowing() } }, destroyed () { diff --git a/src/components/emoji_picker/emoji_picker.scss b/src/components/emoji_picker/emoji_picker.scss index 016c46d7..53363ec1 100644 --- a/src/components/emoji_picker/emoji_picker.scss +++ b/src/components/emoji_picker/emoji_picker.scss @@ -6,14 +6,10 @@ $emoji-picker-header-picture-height: 32px; $emoji-picker-emoji-size: 32px; .emoji-picker { + width: 25em; + max-width: 100vw; display: flex; flex-direction: column; - position: absolute; - right: 0; - left: 0; - margin: 0 !important; - // TODO: actually use popover in emoji picker - z-index: var(--ZI_popovers); background-color: $fallback--bg; background-color: var(--popover, $fallback--bg); color: $fallback--link; diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue index 57bb0037..ccd45bc1 100644 --- a/src/components/emoji_picker/emoji_picker.vue +++ b/src/components/emoji_picker/emoji_picker.vue @@ -1,129 +1,135 @@ diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 60c42f0f..3474d354 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -63,6 +63,7 @@ const Popover = { // used to avoid blinking if hovered onto popover graceTimeout: null, parentPopover: null, + disableClickOutside: false, childrenShown: new Set() } }, @@ -234,6 +235,10 @@ const Popover = { }, showPopover () { if (this.disabled) return + this.disableClickOutside = true + setTimeout(() => { + this.disableClickOutside = false + }, 0) const wasHidden = this.hidden this.hidden = false this.parentPopover && this.parentPopover.onChildPopoverState(this, true) @@ -294,6 +299,7 @@ const Popover = { } }, onClickOutside (e) { + if (this.disableClickOutside) return if (this.hidden) return if (this.$refs.content && this.$refs.content.contains(e.target)) return if (this.$el.contains(e.target)) return -- cgit v1.2.3-70-g09d2 From 8fa1f0b50dcf51e976330163b819dfaf82d30a53 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 10 Oct 2022 00:33:58 +0300 Subject: move keepOpen to picker --- src/components/emoji_input/emoji_input.js | 2 -- src/components/emoji_picker/emoji_picker.js | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 635251be..6532654f 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -116,7 +116,6 @@ const EmojiInput = { focused: false, blurTimeout: null, temporarilyHideSuggestions: false, - keepOpen: false, disableClickOutside: false, suggestions: [], overlayStyle: {}, @@ -344,7 +343,6 @@ const EmojiInput = { spaceAfter, after ].join('') - this.keepOpen = keepOpen this.$emit('update:modelValue', newValue) const position = this.caret + (insertion + spaceAfter + spaceBefore).length if (!keepOpen) { diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index d70abf5b..3fad4601 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -140,6 +140,9 @@ const EmojiPicker = { }, onEmoji (emoji) { const value = emoji.imageUrl ? `:${emoji.displayText}:` : emoji.replacement + if (!this.keepOpen) { + this.$refs.popover.hidePopover() + } this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen }) }, onScroll (e) { -- cgit v1.2.3-70-g09d2 From d2fabe1a71207f92e10283fc5a881d883cb52ae1 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 10 Oct 2022 00:37:59 +0300 Subject: use anchor for picker --- src/components/emoji_input/emoji_input.js | 2 ++ src/components/emoji_picker/emoji_picker.js | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 6532654f..eb64e054 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -141,6 +141,7 @@ const EmojiInput = { return this.focused && this.suggestions && this.suggestions.length > 0 && + !this.pickerShown && !this.temporarilyHideSuggestions }, textAtCaret () { @@ -205,6 +206,7 @@ const EmojiInput = { this.input = input this.caretEl = hiddenOverlayCaret suggestorPopover.setAnchorEl(this.caretEl) + this.$refs.picker.setAnchorEl(this.caretEl) const style = getComputedStyle(this.input) this.overlayStyle.padding = style.padding this.overlayStyle.border = style.border diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index 3fad4601..e907def9 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -113,13 +113,15 @@ const EmojiPicker = { }, methods: { showPicker () { - console.log('pick') this.$refs.popover.showPopover() this.onShowing() }, hidePicker () { this.$refs.popover.hidePopover() }, + setAnchorEl (el) { + this.$refs.popover.setAnchorEl(el) + }, setGroupRef (name) { return el => { this.groupRefs[name] = el } }, -- cgit v1.2.3-70-g09d2 From 692342a77f1b91a88a30aadfd20994c293ad65e0 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 10 Oct 2022 20:11:04 +0300 Subject: focus search input when opening emoji picker --- src/components/emoji_input/emoji_input.js | 8 -------- src/components/emoji_picker/emoji_picker.js | 1 + src/components/emoji_picker/emoji_picker.vue | 1 + 3 files changed, 2 insertions(+), 8 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index eb64e054..92c10f09 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -278,17 +278,10 @@ const EmojiInput = { } }, methods: { - focusPickerInput () { - const pickerEl = this.$refs.picker.$el - if (!pickerEl) return - const pickerInput = pickerEl.querySelector('input') - if (pickerInput) pickerInput.focus() - }, triggerShowPicker () { this.$nextTick(() => { this.$refs.picker.showPicker() this.scrollIntoView() - this.focusPickerInput() }) // This temporarily disables "click outside" handler // since external trigger also means click originates @@ -306,7 +299,6 @@ const EmojiInput = { this.scrollIntoView() this.$refs.picker.showPicker() this.$refs.picker.startEmojiLoad() - this.$nextTick(this.focusPickerInput) } else { this.$refs.picker.hidePicker() } diff --git a/src/components/emoji_picker/emoji_picker.js b/src/components/emoji_picker/emoji_picker.js index e907def9..d1372c4a 100644 --- a/src/components/emoji_picker/emoji_picker.js +++ b/src/components/emoji_picker/emoji_picker.js @@ -245,6 +245,7 @@ const EmojiPicker = { this.filteredEmojiGroups = this.getFilteredEmojiGroups() if (!oldContentLoaded) { this.$nextTick(() => { + this.$refs.search.focus() if (this.defaultGroup) { this.highlight(this.defaultGroup) } diff --git a/src/components/emoji_picker/emoji_picker.vue b/src/components/emoji_picker/emoji_picker.vue index ccd45bc1..a2c99c16 100644 --- a/src/components/emoji_picker/emoji_picker.vue +++ b/src/components/emoji_picker/emoji_picker.vue @@ -71,6 +71,7 @@ class="form-control" :placeholder="$t('emoji.search_emoji')" @input="$event.target.composing = false" + ref="search" >
Date: Mon, 10 Oct 2022 20:26:32 +0300 Subject: better autocomplete handling, fix leak --- src/components/emoji_input/emoji_input.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 92c10f09..144b7c72 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -145,7 +145,7 @@ const EmojiInput = { !this.temporarilyHideSuggestions }, textAtCaret () { - return (this.wordAtCaret || {}).word || '' + return this.wordAtCaret?.word }, wordAtCaret () { if (this.modelValue && this.caret) { @@ -197,6 +197,12 @@ const EmojiInput = { return emoji.displayText } + }, + onInputScroll () { + this.$refs.hiddenOverlay.scrollTo({ + top: this.input.scrollTop, + left: this.input.scrollLeft + }) } }, mounted () { @@ -225,13 +231,7 @@ const EmojiInput = { input.addEventListener('click', this.onClickInput) input.addEventListener('transitionend', this.onTransition) input.addEventListener('input', this.onInput) - // FIXME LEAK - input.addEventListener('scroll', (e) => { - this.$refs.hiddenOverlay.scrollTo({ - top: this.input.scrollTop, - left: this.input.scrollLeft - }) - }) + input.addEventListener('scroll', this.onInputScroll) }, unmounted () { const { input } = this @@ -244,6 +244,7 @@ const EmojiInput = { input.removeEventListener('click', this.onClickInput) input.removeEventListener('transitionend', this.onTransition) input.removeEventListener('input', this.onInput) + input.removeEventListener('scroll', this.onInputScroll) } }, watch: { @@ -256,11 +257,10 @@ const EmojiInput = { } }, textAtCaret: async function (newWord) { + if (newWord === undefined) return const firstchar = newWord.charAt(0) if (newWord === firstchar) { - if (firstchar === ' ') { - this.suggestions = [] - } + this.suggestions = [] return } const matchedSuggestions = await this.suggest(newWord, this.maybeLocalizedEmojiNamesAndKeywords) @@ -292,10 +292,8 @@ const EmojiInput = { }, 0) }, togglePicker () { - console.log('piick') this.input.focus() if (!this.pickerShown) { - console.log('pick') this.scrollIntoView() this.$refs.picker.showPicker() this.$refs.picker.startEmojiLoad() -- cgit v1.2.3-70-g09d2 From 4a1ffced44c41be5c4ba60c5b8678b200c328a40 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 10 Oct 2022 22:04:49 +0300 Subject: fix unit tests --- src/components/emoji_input/emoji_input.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 144b7c72..3d3c58ac 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -211,8 +211,12 @@ const EmojiInput = { if (!input) return this.input = input this.caretEl = hiddenOverlayCaret - suggestorPopover.setAnchorEl(this.caretEl) - this.$refs.picker.setAnchorEl(this.caretEl) + if (suggestorPopover.setAnchorEl) { + suggestorPopover.setAnchorEl(this.caretEl) // unit test compat + this.$refs.picker.setAnchorEl(this.caretEl) + } else { + console.warn('setAnchorEl not found, are we in a unit test?') + } const style = getComputedStyle(this.input) this.overlayStyle.padding = style.padding this.overlayStyle.border = style.border -- cgit v1.2.3-70-g09d2 From 11f9a7ba2719ff4ddb84be39d9e83519c1d0f534 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 17 Oct 2022 21:23:25 +0300 Subject: update popover styles when caret updates --- src/components/emoji_input/emoji_input.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.js b/src/components/emoji_input/emoji_input.js index 3d3c58ac..ba5f7552 100644 --- a/src/components/emoji_input/emoji_input.js +++ b/src/components/emoji_input/emoji_input.js @@ -278,7 +278,6 @@ const EmojiInput = { ...rest, img: imageUrl || '' })) - this.$refs.suggestorPopover.updateStyles() } }, methods: { @@ -536,6 +535,9 @@ const EmojiInput = { }, setCaret ({ target: { selectionStart } }) { this.caret = selectionStart + this.$nextTick(() => { + this.$refs.suggestorPopover.updateStyles() + }) }, resize () { } -- cgit v1.2.3-70-g09d2 From 3c0e7882b10989424c3ec98413b555373efa1719 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 21 Nov 2022 22:17:33 +0200 Subject: lint --- src/components/emoji_input/emoji_input.vue | 13 ++++++++++--- src/components/emoji_picker/emoji_picker.vue | 4 ++-- src/components/mobile_nav/mobile_nav.vue | 6 +++--- src/components/notifications/notifications.vue | 2 +- src/components/popover/popover.vue | 5 ++++- .../quick_filter_settings/quick_filter_settings.vue | 2 +- src/components/quick_view_settings/quick_view_settings.vue | 2 +- src/components/search/search.js | 4 ++-- src/components/timeline/timeline.vue | 14 ++++++++++---- 9 files changed, 34 insertions(+), 18 deletions(-) (limited to 'src/components/emoji_input') diff --git a/src/components/emoji_input/emoji_input.vue b/src/components/emoji_input/emoji_input.vue index 63bf856e..c9bbc18f 100644 --- a/src/components/emoji_input/emoji_input.vue +++ b/src/components/emoji_input/emoji_input.vue @@ -6,9 +6,16 @@ > -
+
{{ preText }} - x + x {{ postText }}