Link sidebar buttons and scripts

I would like to add it in the form of a button in the sidebar (hamburger menu) → More or at the bottom of the sidebar and then connect JavaScript. How do I access the Discourse sidebar to do that?

I did the following, but it didn’t work.
I put it in the of the component.

<div class="sidebar-custom-sections">
  <ul class="sidebar-more-section-links-details-content-main">
    <li data-list-item-name="Install" class="sidebar-section-link-wrapper" id="sidebar_install_wrapper">
      <a href="#" rel="noopener noreferrer" target="_self" data-link-name="Install" class="sidebar-section-link sidebar-row" id="sidebar_install_button">
        <span class="sidebar-section-link-prefix icon">
          <svg class="fa d-icon d-icon-download svg-icon prefix-icon svg-string" xmlns="http://www.w3.org/2000/svg">
            <use href="#download"></use>
          </svg>
        </span>
        <span class="sidebar-section-link-content-text">
          Install
        </span>
      </a>
    </li>
  </ul>
</div>

If you mean adding a new link here:

image

Then, you can use addCommunitySectionLink API. You have an example in the comment.

2 Likes
<script>
api.addCommunitySectionLink({
  name: "unread",
  route: "discovery.unread",
  title: I18n.t("some.unread.title"),
  text: I18n.t("some.unread.text"),
  icon: "fa-envelope"
});
</script>

I put it in the HTML body section of the component like this, but it does not seem to be added to more. Is not it possible to do it this way?

You should use the following code in Head instead:

<script type="text/discourse-plugin" version="0.8">
    api.addCommunitySectionLink({
      name: "unread",
      route: "discovery.unread",
      title: I18n.t("some.unread.title"),
      text: I18n.t("some.unread.text"),
      icon: "fa-envelope"
    });
</script>

<script type="text/discourse-plugin" version="0.8"> is important if you want to use the API.

That should work better. :+1:

1 Like
<script type="text/discourse-plugin" version="0.8">
    api.addCommunitySectionLink({
      name: "install",
      route: "/install",
      title: "install",
      text: "install",
      icon: "download"
    });
</script>

I tried to add the above code to the sidebar’s view, but it did not work, so I wrote it in the format below, referring to the existing path. However, when the button appears and I press it, the script does not seem to work properly. Oddly enough, the script works when I press the ‘Topic’ button rather than the button I created. The script to be connected was also placed in the head of the HTML.

<script type="text/discourse-plugin" version="0.8">
    api.addCommunitySectionLink({
      name: "install",
      route: "discovery.latest",
      title: "install",
      text: "install",
      icon: "download"
    });
</script>
<script type="text/discourse-plugin" version="0.8">
    api.addCommunitySectionLink({
      name: "install",
      route: "discovery.latest",
      title: "Install App",
      text: "Install App",
      icon: "download"
    });
</script>

<script>
let deferredPrompt; // Variable to store the install prompt

// Function to check if iOS app is installed
function checkIfIosAppInstalled() {
  console.log("Checking if iOS app is installed");
  return window.navigator.standalone !== undefined && window.navigator.standalone;
}

// Function to check if Android app is installed
async function checkIfAndroidAppInstalled() {
  try {
    if ('getInstalledRelatedApps' in navigator) {
      console.log("getInstalledRelatedApps supported");
      const relatedApps = await navigator.getInstalledRelatedApps();
      console.log("Related apps:", relatedApps);
      return relatedApps.length > 0;
    } else {
      console.log("getInstalledRelatedApps not supported");
    }
  } catch (error) {
    console.error("Error checking if Android app is installed:", error);
  }
  return false;
}

// Function to check if desktop app is installed
function checkIfDesktopAppInstalled() {
  console.log("Checking if desktop app is installed");
  return window.matchMedia('(display-mode: standalone)').matches;
}

// Function to check if app is installed based on platform and show/hide the button
async function checkIfAppInstalled() {
  const userAgent = navigator.userAgent;
  let isInstalled = false;

  try {
    if (/iPhone|iPad|iPod/.test(userAgent)) {
      console.log("iOS device detected");
      isInstalled = checkIfIosAppInstalled();
    } else if (/Android/.test(userAgent)) {
      console.log("Android device detected");
      isInstalled = await checkIfAndroidAppInstalled();
    } else {
      console.log("Desktop device detected");
      isInstalled = checkIfDesktopAppInstalled();
    }
  } catch (error) {
    console.error("Error checking if app is installed:", error);
  }

  console.log("Is installed:", isInstalled);
  setInstallButtonVisibility(!isInstalled);
}

// Function to show/hide the install button
function setInstallButtonVisibility(visible) {
  console.log("Setting install button visibility:", visible);
  // Show/hide the sidebar button in the "More" section
  const sidebarButton = document.querySelector('a[href="/latest"]');
  if (sidebarButton) {
    sidebarButton.parentElement.style.display = visible ? 'block' : 'none';
  }
}

// Function to set up the install button
async function setupInstallButton() {
  let beforeInstallPromptFired = false;

  if ('onbeforeinstallprompt' in window) {
    window.addEventListener("beforeinstallprompt", e => {
      console.log("beforeinstallprompt event fired");
      beforeInstallPromptFired = true;
      e.preventDefault(); // Prevent the automatic prompt from showing
      deferredPrompt = e; // Save the event to trigger it later
      setInstallButtonVisibility(true);

      // Set click event for the sidebar button in the "More" section
      const sidebarButton = document.querySelector('a[href="/latest"]');
      if (sidebarButton) {
        sidebarButton.addEventListener("click", async (event) => {
          event.preventDefault();
          console.log("Install button clicked");
          deferredPrompt.prompt(); // Show the prompt

          const choiceResult = await deferredPrompt.userChoice;
          console.log("User choice result:", choiceResult);
          if (choiceResult.outcome === "accepted") {
            setInstallButtonVisibility(false); // Hide button if install is accepted
          }
          deferredPrompt = null; // Reset deferredPrompt
        });
      }
    });

    window.addEventListener("appinstalled", evt => {
      console.log("appinstalled event fired:", evt); // Log app installed event
      setInstallButtonVisibility(false); // Hide button if app is installed
    });
  }

  // Assume already installed if beforeinstallprompt event does not fire
  document.addEventListener("DOMContentLoaded", async () => {
    console.log("DOMContentLoaded event fired");
    await checkIfAppInstalled();
    if (!beforeInstallPromptFired && !('onbeforeinstallprompt' in window)) {
      console.log("Assume app is already installed or browser does not support the event");
      setInstallButtonVisibility(false);
    }
  });
}

// Check if app is installed and set up the install button on page load
document.addEventListener("DOMContentLoaded", async () => {
  console.log("DOMContentLoaded event fired - running setupInstallButton");
  await setupInstallButton();
});
</script>

What is the problem?