diff --git a/docs/subsystems/hotspots.md b/docs/subsystems/hotspots.md index f8a8383fca..c486c61ded 100644 --- a/docs/subsystems/hotspots.md +++ b/docs/subsystems/hotspots.md @@ -48,9 +48,7 @@ However, if you would like to fix the orientation of a hotspot popover, a To test your hotspot in the development environment, set `ALWAYS_SEND_ALL_HOTSPOTS = True` in `zproject/dev_settings.py`, and invoke `hotspots.initialize()` in your browser console. Every hotspot -should be displayed. Note that this setting has a bug that can result -in multiple copies of hotspots appearing; you can clear that by -reloading the browser. +should be displayed. Here are some visual characteristics to confirm: diff --git a/web/src/hotspots.js b/web/src/hotspots.js index ff5d1306c3..a21184cc90 100644 --- a/web/src/hotspots.js +++ b/web/src/hotspots.js @@ -261,9 +261,11 @@ function insert_hotspot_into_DOM(hotspot) { }); setTimeout(() => { - $("body").prepend(hotspot_icon_HTML); + if (!hotspot.has_trigger) { + $("body").prepend(hotspot_icon_HTML); + } $("body").prepend(hotspot_overlay_HTML); - if (place_icon(hotspot)) { + if (hotspot.has_trigger || place_icon(hotspot)) { place_popover(hotspot); } @@ -272,7 +274,7 @@ function insert_hotspot_into_DOM(hotspot) { window.addEventListener( event_name, _.debounce(() => { - if (place_icon(hotspot)) { + if (hotspot.has_trigger || place_icon(hotspot)) { place_popover(hotspot); } }, 10), @@ -286,6 +288,10 @@ export function is_open() { return meta.opened_hotspot_name !== null; } +function is_hotspot_displayed(hotspot_name) { + return $(`#hotspot_${hotspot_name}_overlay`).length; +} + export function close_hotspot_icon(elem) { $(elem).animate( {opacity: 0}, @@ -306,6 +312,7 @@ function close_read_hotspots(new_hotspots) { for (const hotspot_name of unwanted_hotspots) { close_hotspot_icon($(`#hotspot_${CSS.escape(hotspot_name)}_icon`)); + $(`#hotspot_${CSS.escape(hotspot_name)}_overlay`).remove(); } } @@ -313,7 +320,9 @@ export function load_new(new_hotspots) { close_read_hotspots(new_hotspots); for (const hotspot of new_hotspots) { hotspot.location = HOTSPOT_LOCATIONS.get(hotspot.name); - insert_hotspot_into_DOM(hotspot); + if (!is_hotspot_displayed(hotspot.name) && hotspot.location) { + insert_hotspot_into_DOM(hotspot); + } } } @@ -367,6 +376,10 @@ export function initialize() { overlays.close_overlay(overlay_name); $(`#hotspot_${CSS.escape(hotspot_name)}_icon`).remove(); + + // We are removing the hotspot overlay after it's read as it will help us avoid + // multiple copies of the hotspots when ALWAYS_SEND_ALL_HOTSPOTS is set to true. + $(`#${overlay_name}`).remove(); }); // stop propagation diff --git a/zerver/lib/hotspots.py b/zerver/lib/hotspots.py index 86e0bbb14c..cbc537dcdc 100644 --- a/zerver/lib/hotspots.py +++ b/zerver/lib/hotspots.py @@ -60,9 +60,7 @@ ALL_HOTSPOTS: Dict[str, Dict[str, Union[StrPromise, str, bool]]] = { def get_next_hotspots(user: UserProfile) -> List[Dict[str, object]]: # For manual testing, it can be convenient to set # ALWAYS_SEND_ALL_HOTSPOTS=True in `zproject/dev_settings.py` to - # make it easy to click on all of the hotspots. Note that - # ALWAYS_SEND_ALL_HOTSPOTS has some bugs; see ReadTheDocs (link - # above) for details. + # make it easy to click on all of the hotspots. # # Since this is just for development purposes, it's convenient for us to send # all the hotspots rather than any specific category.