xsanda / Strava route planner: Realistic topo maps

// ==UserScript==
// @name     Strava route planner: Realistic topo maps
// @version  0.1
// @grant    none
// @include  https://www.strava.com/routes/new*
// @include https://www.strava.com/routes/*/edit*
// @require https://openuserjs.org/src/libs/xsanda/Run_code_as_client.js
// @license MIT
// ==/UserScript==

runAsClient(() => {
  const addButton = (src, handler) => {
  	img = document.createElement("img");
    img.src = src;
    Object.assign(img.style,{
      height: "48px",
      padding: "10px",
      cursor: "pointer",
    });
    document.querySelector('header [class^="Header--actions"]').prepend(img);
    img.addEventListener('click', handler);
    return img;
  };
  
  const addHillShadeLayer = (map) => {
    if (!map.getSource('dem')) {
      map.addSource('dem', {
        'type': 'raster-dem',
        'url': 'mapbox://mapbox.terrain-rgb'
      });
    }
    if (!map.getLayer('improved-hillshading')) {
      map.addLayer({
        'id': 'improved-hillshading',
        'type': 'hillshade',
        'source': 'dem',
      }, map.getLayer('global-heatmap') ? 'global-heatmap' : undefined);
    } else map.setLayoutProperty('improved-hillshading', 'visibility', 'visible');
    map.setLayoutProperty('hillshade-greys', 'visibility', 'none');
  };
  
  const hideHillShadeLayer = (map) => {
    map.setLayoutProperty('hillshade-greys', 'visibility', 'visible');
    map.setLayoutProperty('improved-hillshading', 'visibility', 'none');
  };

  const waitFor = (f, freq = 1000) =>
    new Promise((resolve) => {
      const interval = setInterval(() => {
        const result = f();
        if (result !== undefined) {
          clearInterval(interval);
          resolve(result);
        }
      }, freq);
    });

  (async () => {
    const mapInstance = await waitFor(() => {
      const mapElem = document.querySelector(".mapboxgl-map");
      if (!mapElem) return;
      const [key, reactElement] = Object.entries(mapElem).find(([key]) => /^__reactInternalInstance/.test(key)) ?? [];
      return reactElement.memoizedProps?.children?.props?.value?.map;
      });
    window.map = mapInstance;

    let showHillShade = false;
    addButton("https://static.thenounproject.com/png/1634624-200.png", () => {
      showHillShade = !showHillShade;
      if (showHillShade) addHillShadeLayer(mapInstance);
      else hideHillShadeLayer(mapInstance);
    });
  })().catch(console.error);
});