From cbf99f48d81d741d3a75822521b9d6b1a0f9369c Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 17 Jan 2022 01:03:43 +0000 Subject: [PATCH] FIX: Ensure floating quote button is distanced from iOS selection (#15588) Tapping within ~50px of the selection end handle on iOS doesn't trigger a click event. This commit ensures that our quote buttons are always at least 50px away from the end handle. It will try 4 positions in order of preference: 1. The original position 2. 50px to the left of the handle 3. 50px to the right of the handle 4. 50px below the handle, centered on the handle --- .../discourse/app/components/quote-button.js | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/app/assets/javascripts/discourse/app/components/quote-button.js b/app/assets/javascripts/discourse/app/components/quote-button.js index 40305a9dec4..d67cf8c6c34 100644 --- a/app/assets/javascripts/discourse/app/components/quote-button.js +++ b/app/assets/javascripts/discourse/app/components/quote-button.js @@ -233,6 +233,44 @@ export default Component.extend(KeyEnterEscape, { top = top - $quoteButton.outerHeight() - 5; } + if (isIOS) { + // The selection-handles on iOS have a hit area of ~50px radius + // so we need to make sure our buttons are outside that radius + + const safeRadius = 50; + const endHandlePosition = markerOffset; + const width = this.element.clientWidth; + + const possiblePositions = [ + { top, left }, + { top, left: endHandlePosition.left - width - safeRadius - 10 }, // move to left + { top, left: left + safeRadius }, // move to right + { top: top + safeRadius, left: endHandlePosition.left - width / 2 }, // centered below end handle + ]; + + let newPos; + for (const pos of possiblePositions) { + if (pos.left < 0 || pos.left + width + 10 > window.innerWidth) { + continue; // Offscreen + } + + const clearOfEndHandle = + pos.top - endHandlePosition.top >= safeRadius || + pos.left + width <= endHandlePosition.left - safeRadius || + pos.left >= endHandlePosition.left + safeRadius; + + if (clearOfEndHandle) { + newPos = pos; + break; + } + } + + if (newPos) { + left = newPos.left; + top = newPos.top; + } + } + $quoteButton.offset({ top, left }); }); },