From 5262676e0e501332f79c0f36d2a063290212b2f8 Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Wed, 12 Feb 2020 19:22:40 +0200 Subject: [PATCH 01/11] rewrite popover because v-tooltip is slow as heck --- src/App.js | 4 +- src/App.vue | 1 + src/components/extra_buttons/extra_buttons.js | 3 + .../extra_buttons/extra_buttons.vue | 14 +- src/components/popover/popover.js | 113 ++++++++++ src/components/popover/popover.vue | 195 ++++++++++++++++++ src/components/popover/popover_target.js | 23 +++ src/components/popover/popover_target.vue | 25 +++ src/components/popper/popper.scss | 147 ------------- .../status_popover/status_popover.js | 3 +- .../status_popover/status_popover.vue | 22 +- src/main.js | 4 +- src/modules/popover.js | 31 +++ 13 files changed, 417 insertions(+), 168 deletions(-) create mode 100644 src/components/popover/popover.js create mode 100644 src/components/popover/popover.vue create mode 100644 src/components/popover/popover_target.js create mode 100644 src/components/popover/popover_target.vue create mode 100644 src/modules/popover.js diff --git a/src/App.js b/src/App.js index 61b5eec1c..041e131a5 100644 --- a/src/App.js +++ b/src/App.js @@ -12,6 +12,7 @@ import MobilePostStatusButton from './components/mobile_post_status_button/mobil import MobileNav from './components/mobile_nav/mobile_nav.vue' import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue' import PostStatusModal from './components/post_status_modal/post_status_modal.vue' +import PopoverTarget from './components/popover/popover_target.vue' import { windowWidth } from './services/window_utils/window_utils' export default { @@ -30,7 +31,8 @@ export default { MobilePostStatusButton, MobileNav, UserReportingModal, - PostStatusModal + PostStatusModal, + PopoverTarget }, data: () => ({ mobileActivePanel: 'timeline', diff --git a/src/App.vue b/src/App.vue index 1b1c2648c..de15802fa 100644 --- a/src/App.vue +++ b/src/App.vue @@ -123,6 +123,7 @@ + diff --git a/src/components/extra_buttons/extra_buttons.js b/src/components/extra_buttons/extra_buttons.js index 5ac73e975..374853832 100644 --- a/src/components/extra_buttons/extra_buttons.js +++ b/src/components/extra_buttons/extra_buttons.js @@ -1,5 +1,8 @@ +import Popover from '../popover/popover.vue' + const ExtraButtons = { props: [ 'status' ], + components: { Popover }, methods: { deleteStatus () { const confirmed = window.confirm(this.$t('status.delete_confirm')) diff --git a/src/components/extra_buttons/extra_buttons.vue b/src/components/extra_buttons/extra_buttons.vue index 746f1c917..3f0034252 100644 --- a/src/components/extra_buttons/extra_buttons.vue +++ b/src/components/extra_buttons/extra_buttons.vue @@ -1,11 +1,11 @@ @@ -59,6 +59,10 @@ @import '../../_variables.scss'; @import '../popper/popper.scss'; +.dropdown-menu { + flex-shrink: 0; +} + .icon-ellipsis { cursor: pointer; diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js new file mode 100644 index 000000000..4ee083232 --- /dev/null +++ b/src/components/popover/popover.js @@ -0,0 +1,113 @@ + +const Popover = { + name: 'Popover', + props: [ + 'trigger', + 'placement', + 'show' + ], + data () { + return { + hidden: true, + styles: { opacity: 0 } + } + }, + computed: { + display () { + return !this.hidden + } + }, + methods: { + /* + registerPopover (e) { + if (!this.targetId) { + this.$store.dispatch('registerPopover', e.target).then(id => this.targetId = id) + } + }, + unregisterPopover () { + if (this.targetId) { + this.$store.dispatch('unregisterPopover', this.targetId) + this.targetId = null + } + }, + */ + showPopover () { + this.hidden = false + this.$nextTick(function () { + if (this.hidden) return { opacity: 0 } + + const anchorEl = this.$refs.trigger || this.$el + console.log(anchorEl) + const screenBox = anchorEl.getBoundingClientRect() + const origin = { x: screenBox.left + screenBox.width * 0.5, y: screenBox.top} + const content = this.$refs.content + let horizOffset = 0 + + if ((origin.x - content.offsetWidth * 0.5) < 25) { + horizOffset += -(origin.x - content.offsetWidth * 0.5) + 25 + } + + console.log((origin.x + content.offsetWidth * 0.5), (window.innerWidth - 25)) + if ((origin.x + content.offsetWidth * 0.5) > window.innerWidth - 25) { + horizOffset -= (origin.x + content.offsetWidth * 0.5) - (window.innerWidth - 25) + } + // Default to whatever user wished with placement prop + let usingTop = this.placement !== 'bottom' + + // Handle special cases, first force to displaying on top if there's not space on bottom, + // regardless of what placement value was. Then check if there's not space on top, and + // force to bottom, again regardless of what placement value was. + if (origin.y + content.offsetHeight > (window.innerHeight - 25)) usingTop = true + if (origin.y - content.offsetHeight < 50) usingTop = false + + const vertAlign = usingTop ? + { + bottom: `${anchorEl.offsetHeight}px` + } : + { + top: `${anchorEl.offsetHeight}px` + } + this.styles = { + opacity: '100%', + left: `${(anchorEl.offsetLeft + anchorEl.offsetWidth * 0.5) - content.offsetWidth * 0.5 + horizOffset}px`, + ...vertAlign + } + }) + }, + hidePopover () { + this.hidden = true + this.styles = { opacity: 0 } + }, + onMouseenter (e) { + console.log(this.trigger) + if (this.trigger === 'hover') this.showPopover() + }, + onMouseleave (e) { + if (this.trigger === 'hover') this.hidePopover() + }, + onClick (e) { + if (this.trigger === 'click') { + if (this.hidden) { + this.showPopover() + } else { + this.hidePopover() + } + } + }, + onClickOutside (e) { + if (this.hidden) return + if (this.$el.contains(e.target)) return + console.log(e.target) + this.hidePopover() + } + }, + created () { + document.addEventListener("click", this.onClickOutside) + }, + destroyed () { + document.removeEventListener("click", this.onClickOutside) + this.hidePopover() + } +} + +export default Popover diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue new file mode 100644 index 000000000..273a0a69f --- /dev/null +++ b/src/components/popover/popover.vue @@ -0,0 +1,195 @@ + + + @@ -29,11 +25,11 @@ From 0723c0757198d5dcb3b54e1cdd362cb4d2bf52ef Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Mon, 17 Feb 2020 12:03:29 +0200 Subject: [PATCH 08/11] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c011835c3..1598e93ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Registration fixed - Deactivation of remote accounts from frontend - Fixed NSFW unhiding not working with videos when using one-click unhiding/displaying +- Improved performance of anything that uses popovers (most notably statuses) ## [1.1.7 and earlier] - 2019-12-14 ### Added From 813d121cdd6e03ea9d56d6d63ba34cbf949a893f Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Tue, 18 Feb 2020 11:47:34 +0200 Subject: [PATCH 09/11] fix centering of certain dropdowns --- src/components/extra_buttons/extra_buttons.vue | 8 +++----- src/components/popover/popover.js | 7 ++++--- src/components/react_button/react_button.vue | 12 +++++------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/components/extra_buttons/extra_buttons.vue b/src/components/extra_buttons/extra_buttons.vue index 8dc37d2b6..3a7f1283a 100644 --- a/src/components/extra_buttons/extra_buttons.vue +++ b/src/components/extra_buttons/extra_buttons.vue @@ -47,12 +47,10 @@ -
- -
+ class="icon-ellipsis button-icon" + /> diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 3732c42ef..064016662 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -25,8 +25,9 @@ const Popover = { updateStyles () { if (this.hidden) return { opacity: 0 } - // Popover will be anchored around this element - const anchorEl = this.$refs.trigger || this.$el + // Popover will be anchored around this element, trigger ref is the container, so + // its children are what are inside the slot. Expect only one slot="trigger". + const anchorEl = (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el const screenBox = anchorEl.getBoundingClientRect() // Screen position of the origin point for popover const origin = { x: screenBox.left + screenBox.width * 0.5, y: screenBox.top } @@ -86,7 +87,7 @@ const Popover = { this.styles = { opacity: 1, - transform: `translate(${Math.floor(translateX)}px, ${Math.floor(translateY)}px)` + transform: `translate(${Math.floor(translateX)}px) translateY(${Math.floor(translateY)}px)` } }, showPopover () { diff --git a/src/components/react_button/react_button.vue b/src/components/react_button/react_button.vue index 8613143fd..ab4b4fcd0 100644 --- a/src/components/react_button/react_button.vue +++ b/src/components/react_button/react_button.vue @@ -2,6 +2,7 @@
-
- -
+ class="icon-smile button-icon add-reaction-button" + :title="$t('tool_tip.add_reaction')" + />
From 16302b563013ebc10e3161e8ff72ebe1410f6685 Mon Sep 17 00:00:00 2001 From: Shpuld Shpuldson Date: Wed, 19 Feb 2020 08:49:04 +0200 Subject: [PATCH 10/11] clean up and fixes, change popover padding -> margin --- .../account_actions/account_actions.vue | 4 +- .../emoji_reactions/emoji_reactions.vue | 22 ++++--- src/components/popover/popover.js | 64 +++++++++++-------- src/components/popover/popover.vue | 2 +- 4 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/components/account_actions/account_actions.vue b/src/components/account_actions/account_actions.vue index 7b1f5cdae..483783cfb 100644 --- a/src/components/account_actions/account_actions.vue +++ b/src/components/account_actions/account_actions.vue @@ -69,12 +69,10 @@ margin: 0 .8em; } -.account-tools-popover { -} - .account-actions button.dropdown-item { margin-left: 0; } + .account-actions .trigger-button { color: $fallback--lightText; color: var(--lightText, $fallback--lightText); diff --git a/src/components/emoji_reactions/emoji_reactions.vue b/src/components/emoji_reactions/emoji_reactions.vue index 1a00054c9..47054db0a 100644 --- a/src/components/emoji_reactions/emoji_reactions.vue +++ b/src/components/emoji_reactions/emoji_reactions.vue @@ -23,7 +23,12 @@ :compact="true" />
- + + + {{ account.screen_name }}
@@ -44,15 +49,14 @@ - {{ showAll ? $t('general.show_less') : showMoreString }} - + v-if="tooManyReactions" + class="emoji-reaction-expand faint" + href="javascript:void(0)" + @click="toggleShowAll" + > + {{ showAll ? $t('general.show_less') : showMoreString }} + - diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 064016662..597e22cd2 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -1,14 +1,24 @@ const Popover = { name: 'Popover', - props: [ - 'trigger', - 'placement', - 'boundTo', - 'padding', - 'offset', - 'popoverClass' - ], + props: { + // Action to trigger popover: either 'hover' or 'click' + trigger: String, + // Either 'top' or 'bottom' + placement: String, + // Takes object with properties 'x' and 'y', values of these can be + // 'container' for using offsetParent as boundaries for either axis + // or 'viewport' + boundTo: Object, + // Takes a top/bottom/left/right object, how much space to leave + // between boundary and popover element + margin: Object, + // Takes a x/y object and tells how many pixels to offset from + // anchor point on either axis + offset: Object, + // Additional styles you may want for the popover container + popoverClass: String + }, data () { return { hidden: true, @@ -16,14 +26,14 @@ const Popover = { oldSize: { width: 0, height: 0 } } }, - computed: { - display () { - return !this.hidden - } - }, methods: { updateStyles () { - if (this.hidden) return { opacity: 0 } + if (this.hidden) { + this.styles = { + opacity: 0 + } + return + } // Popover will be anchored around this element, trigger ref is the container, so // its children are what are inside the slot. Expect only one slot="trigger". @@ -36,31 +46,31 @@ const Popover = { const parentBounds = this.boundTo && (this.boundTo.x === 'container' || this.boundTo.y === 'container') && this.$el.offsetParent.getBoundingClientRect() - const padding = this.padding || {} + const margin = this.margin || {} // What are the screen bounds for the popover? Viewport vs container - // when using viewport, using default padding values to dodge the navbar + // when using viewport, using default margin values to dodge the navbar const xBounds = this.boundTo && this.boundTo.x === 'container' ? { - min: parentBounds.left + (padding.left || 0), - max: parentBounds.right - (padding.right || 0) + min: parentBounds.left + (margin.left || 0), + max: parentBounds.right - (margin.right || 0) } : { - min: 0 + (padding.left || 10), - max: window.innerWidth - (padding.right || 10) + min: 0 + (margin.left || 10), + max: window.innerWidth - (margin.right || 10) } const yBounds = this.boundTo && this.boundTo.y === 'container' ? { - min: parentBounds.top + (padding.top || 0), - max: parentBounds.bottom - (padding.bottom || 0) + min: parentBounds.top + (margin.top || 0), + max: parentBounds.bottom - (margin.bottom || 0) } : { - min: 0 + (padding.top || 50), - max: window.innerHeight - (padding.bottom || 5) + min: 0 + (margin.top || 50), + max: window.innerHeight - (margin.bottom || 5) } let horizOffset = 0 // If overflowing from left, move it so that it doesn't if ((origin.x - content.offsetWidth * 0.5) < xBounds.min) { - horizOffset = -(origin.x - content.offsetWidth * 0.5) + xBounds.min + horizOffset += -(origin.x - content.offsetWidth * 0.5) + xBounds.min } // If overflowing from right, move it so that it doesn't @@ -85,9 +95,11 @@ const Popover = { const xOffset = (this.offset && this.offset.x) || 0 const translateX = (anchorEl.offsetWidth * 0.5) - content.offsetWidth * 0.5 + horizOffset + xOffset + // Note, separate translateX and translateY avoids blurry text on chromium, + // single translate or translate3d resulted in blurry text. this.styles = { opacity: 1, - transform: `translate(${Math.floor(translateX)}px) translateY(${Math.floor(translateY)}px)` + transform: `translateX(${Math.floor(translateX)}px) translateY(${Math.floor(translateY)}px)` } }, showPopover () { diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue index 2d1219f28..bbf6dbadf 100644 --- a/src/components/popover/popover.vue +++ b/src/components/popover/popover.vue @@ -10,7 +10,7 @@
Date: Wed, 19 Feb 2020 08:51:55 +0200 Subject: [PATCH 11/11] fix offset Y bug --- src/components/popover/popover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 597e22cd2..5881d266b 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -90,7 +90,7 @@ const Popover = { const yOffset = (this.offset && this.offset.y) || 0 const translateY = usingTop ? -anchorEl.offsetHeight - yOffset - content.offsetHeight - : yOffset + yOffset + : yOffset const xOffset = (this.offset && this.offset.x) || 0 const translateX = (anchorEl.offsetWidth * 0.5) - content.offsetWidth * 0.5 + horizOffset + xOffset