Back to Repository

Omni Connection Count

0 upvotes
By shiva.prasad@simprogroup.com
After page load (document_end)

Description

Show the total number of connections in omni

Match Pattern

https://*.omniapp.co/connections

Script Code

(() => {
  const CONNECTIONS_SECTION_SELECTOR = "#connections";
  const BASE_CONNECTION_TEXT = "BASE CONNECTION";
  const BADGE_CLASS = "base-connection-badge";
  const COUNT_CLASS = "connections-count-badge";
  const SEARCH_WRAPPER_CLASS = "connections-search-wrapper";
  const SEARCH_INPUT_CLASS = "connections-search-input";

  let isUpdating = false;
  let scheduled = false;

  function scheduleUpdate() {
    if (scheduled || isUpdating) return;

    scheduled = true;

    requestAnimationFrame(() => {
      scheduled = false;
      updateConnectionsSection();
    });
  }

  function decorateBaseConnection(item) {
    item.style.border = "2px solid #6366f1";
    item.style.borderRadius = "12px";
    item.style.padding = "12px";
    item.style.background = "linear-gradient(135deg, rgba(99,102,241,0.10), rgba(168,85,247,0.10))";
    item.style.boxShadow = "0 4px 14px rgba(99,102,241,0.18)";

    const heading = item.querySelector("h3");
    if (!heading || heading.querySelector(`.${BADGE_CLASS}`)) return;

    const badge = document.createElement("span");
    badge.className = BADGE_CLASS;
    badge.textContent = "Base";
    badge.style.marginLeft = "8px";
    badge.style.fontSize = "12px";
    badge.style.fontWeight = "600";
    badge.style.padding = "2px 8px";
    badge.style.borderRadius = "999px";
    badge.style.background = "#6366f1";
    badge.style.color = "white";

    heading.appendChild(badge);
  }

  function resetConnectionDecoration(item) {
    item.style.border = "";
    item.style.borderRadius = "";
    item.style.padding = "";
    item.style.background = "";
    item.style.boxShadow = "";

    item.querySelector(`.${BADGE_CLASS}`)?.remove();
  }

  function getConnectionName(item) {
    const heading = item.querySelector("h3");
    if (!heading) return "";

    return Array.from(heading.childNodes)
      .filter((node) => {
        return !(node.nodeType === Node.ELEMENT_NODE && node.classList?.contains(BADGE_CLASS));
      })
      .map((node) => node.textContent ?? "")
      .join(" ")
      .trim();
  }

  function updateCount(heading, visibleCount, totalCount) {
    let countBadge = heading.querySelector(`.${COUNT_CLASS}`);

    if (!countBadge) {
      countBadge = document.createElement("span");
      countBadge.className = COUNT_CLASS;
      countBadge.style.marginLeft = "8px";
      countBadge.style.fontSize = "14px";
      countBadge.style.fontWeight = "600";
      heading.appendChild(countBadge);
    }

    const nextText = visibleCount === totalCount ? `(${totalCount})` : `(${visibleCount}/${totalCount})`;

    if (countBadge.textContent !== nextText) {
      countBadge.textContent = nextText;
    }
  }

  function ensureSearchBar(section, heading) {
    let wrapper = section.querySelector(`.${SEARCH_WRAPPER_CLASS}`);
    let input = section.querySelector(`.${SEARCH_INPUT_CLASS}`);

    if (wrapper && input) return input;

    const isDarkMode = () => {
      const bodyBg = getComputedStyle(document.body).backgroundColor;
      const rgb = bodyBg.match(/\d+/g)?.map(Number) ?? [255, 255, 255];
      const [r, g, b] = rgb;
      const brightness = (r * 299 + g * 587 + b * 114) / 1000;
      return brightness < 128;
    };

    wrapper = document.createElement("div");
    wrapper.className = SEARCH_WRAPPER_CLASS;
    wrapper.style.display = "flex";
    wrapper.style.alignItems = "center";
    wrapper.style.gap = "8px";
    wrapper.style.marginTop = "12px";
    wrapper.style.marginBottom = "18px";
    wrapper.style.padding = "9px 13px";
    wrapper.style.width = "100%";
    wrapper.style.maxWidth = "420px";
    wrapper.style.borderRadius = "999px";
    wrapper.style.backdropFilter = "blur(8px)";
    wrapper.style.transition = "border-color 140ms ease, background 140ms ease, box-shadow 140ms ease";

    const icon = document.createElement("span");
    icon.textContent = "⌕";
    icon.style.fontSize = "16px";
    icon.style.lineHeight = "1";
    icon.style.pointerEvents = "none";

    input = document.createElement("input");
    input.className = SEARCH_INPUT_CLASS;
    input.type = "search";
    input.placeholder = "Search connections";
    input.autocomplete = "off";

    input.style.flex = "1";
    input.style.width = "100%";
    input.style.border = "0";
    input.style.outline = "0";
    input.style.background = "transparent";
    input.style.fontSize = "14px";
    input.style.fontWeight = "500";
    input.style.caretColor = "#6366f1";

    const applyIdleStyles = () => {
      const dark = isDarkMode();

      wrapper.style.border = dark ? "1px solid rgba(129,140,248,0.45)" : "1px solid rgba(99,102,241,0.28)";

      wrapper.style.background = dark ? "rgba(255,255,255,0.06)" : "rgba(255,255,255,0.9)";

      wrapper.style.boxShadow = dark ? "0 4px 18px rgba(0,0,0,0.18)" : "0 4px 18px rgba(15,23,42,0.08)";

      input.style.color = dark ? "rgba(255,255,255,0.92)" : "rgba(15,23,42,0.92)";

      icon.style.color = dark ? "rgba(255,255,255,0.55)" : "rgba(15,23,42,0.45)";
    };

    const applyFocusStyles = () => {
      const dark = isDarkMode();

      wrapper.style.border = "1px solid rgba(129,140,248,0.9)";
      wrapper.style.background = dark ? "rgba(99,102,241,0.14)" : "rgba(238,242,255,0.95)";

      wrapper.style.boxShadow = dark
        ? "0 0 0 3px rgba(99,102,241,0.18), 0 6px 22px rgba(0,0,0,0.24)"
        : "0 0 0 3px rgba(99,102,241,0.14), 0 6px 22px rgba(15,23,42,0.10)";
    };

    input.addEventListener("input", scheduleUpdate);
    input.addEventListener("focus", applyFocusStyles);
    input.addEventListener("blur", applyIdleStyles);

    wrapper.appendChild(icon);
    wrapper.appendChild(input);

    heading.insertAdjacentElement("afterend", wrapper);

    applyIdleStyles();

    return input;
  }

  function updateConnectionsSection() {
    if (isUpdating) return;

    isUpdating = true;

    try {
      const section = document.querySelector(CONNECTIONS_SECTION_SELECTOR);
      if (!section) return;

      const heading = section.querySelector("h2");
      const list = section.querySelector("ol");
      if (!heading || !list) return;

      const input = ensureSearchBar(section, heading);
      const searchText = input.value.trim().toUpperCase();

      const items = Array.from(list.querySelectorAll(":scope > li.list-item"));
      let visibleCount = 0;

      for (const item of items) {
        const name = getConnectionName(item);
        const matchesSearch = !searchText || name.toUpperCase().includes(searchText);

        item.style.display = matchesSearch ? "" : "none";

        if (matchesSearch) visibleCount += 1;

        const isBaseConnection = name.toUpperCase().includes(BASE_CONNECTION_TEXT);

        if (isBaseConnection) {
          decorateBaseConnection(item);
        } else {
          resetConnectionDecoration(item);
        }
      }

      updateCount(heading, visibleCount, items.length);
    } finally {
      isUpdating = false;
    }
  }

  const observer = new MutationObserver(scheduleUpdate);

  function attachObserver() {
    observer.disconnect();

    const section = document.querySelector(CONNECTIONS_SECTION_SELECTOR);

    observer.observe(section ?? document.body, {
      childList: true,
      subtree: true,
    });
  }

  function runDelayedUpdate() {
    attachObserver();
    scheduleUpdate();
  }

  runDelayedUpdate();

  setTimeout(runDelayedUpdate, 500);
  setTimeout(runDelayedUpdate, 1500);
  setTimeout(runDelayedUpdate, 3000);
})();
Install requires the InjectJS Chrome extension. Scripts run only on sites matching the pattern above. Review code before installing any community script.