Add Analytics Nav Item for X

Adds an Analytics nav item below Premium in the X.com sidebar

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Add Analytics Nav Item for X
// @namespace    https://github.com/Johnson1602/tampermonkey-scripts
// @version      0.0.2
// @description  Adds an Analytics nav item below Premium in the X.com sidebar
// @author       Weiyi Xu
// @license      MIT
// @match        https://x.com/*
// @match        https://twitter.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=x.com
// @grant        none
// ==/UserScript==

;(function () {
  'use strict'

  const ANALYTICS_URL = '/i/account_analytics'
  const ANALYTICS_LABEL = 'Analytics'

  // Analytics chart icon SVG path
  const ANALYTICS_ICON_PATH =
    'M8.75 21V3h2v18h-2zM18 21V8.5h2V21h-2zM4 21l.004-10h2L6 21H4zm9.248 0v-7h2v7h-2z'

  let analyticsTextContainer = null

  function createAnalyticsNavItem(referenceItem) {
    const analyticsItem = document.createElement('a')
    analyticsItem.href = ANALYTICS_URL
    analyticsItem.setAttribute('aria-label', ANALYTICS_LABEL)
    analyticsItem.setAttribute('role', 'link')
    analyticsItem.className = referenceItem.className
    analyticsItem.setAttribute('data-testid', 'AppTabBar_Analytics_Link')

    // Clone the inner structure from reference item
    const innerDiv = referenceItem.querySelector('div')
    if (innerDiv) {
      const clonedDiv = innerDiv.cloneNode(true)

      // Update the SVG icon
      const svg = clonedDiv.querySelector('svg')
      if (svg) {
        svg.innerHTML = `<g><path d="${ANALYTICS_ICON_PATH}"></path></g>`
      }

      // Update the text and store reference to text container
      const textSpans = clonedDiv.querySelectorAll('span')
      if (textSpans.length > 0) {
        textSpans[0].textContent = ANALYTICS_LABEL
        // The text container is the parent div of the spans
        analyticsTextContainer = textSpans[0].parentElement
      }

      // Add hover state handlers using inline styles
      analyticsItem.addEventListener('mouseenter', () => {
        const isDarkMode = document.documentElement.dataset.theme === 'dark'
        clonedDiv.style.backgroundColor = isDarkMode
          ? 'rgba(231, 233, 234, 0.1)'
          : 'rgba(15, 20, 25, 0.1)'
      })
      analyticsItem.addEventListener('mouseleave', () => {
        clonedDiv.style.backgroundColor = ''
      })

      analyticsItem.appendChild(clonedDiv)
    }

    return analyticsItem
  }

  function syncTextVisibility(referenceItem) {
    if (!analyticsTextContainer) return

    // Check if the reference item has visible text (has span elements)
    const refTextSpan = referenceItem.querySelector('span')
    const hasText = refTextSpan !== null

    if (hasText) {
      analyticsTextContainer.style.display = ''
    } else {
      analyticsTextContainer.style.display = 'none'
    }
  }

  function addAnalyticsNavItem() {
    // Find the Premium nav item, fallback to Home
    const premiumItem = document.querySelector(
      '[data-testid="premium-hub-tab"]'
    )
    const homeItem = document.querySelector(
      '[data-testid="AppTabBar_Home_Link"]'
    )
    const referenceItem = premiumItem || homeItem

    if (!referenceItem) {
      return
    }

    // Check if already added
    const existingItem = document.querySelector(
      '[data-testid="AppTabBar_Analytics_Link"]'
    )
    if (existingItem) {
      const refHasText = referenceItem.querySelector('span') !== null

      // If reference now has text but we don't have a text container, recreate the item
      if (refHasText && !analyticsTextContainer) {
        existingItem.remove()
        analyticsTextContainer = null
      } else {
        // Sync text visibility with reference item
        syncTextVisibility(referenceItem)
        return
      }
    }

    // Create and insert the Analytics nav item
    const analyticsItem = createAnalyticsNavItem(referenceItem)
    referenceItem.insertAdjacentElement('afterend', analyticsItem)
  }

  // Use MutationObserver to handle SPA navigation and responsive changes
  const observer = new MutationObserver(() => {
    addAnalyticsNavItem()
  })

  // Start observing
  observer.observe(document.body, {
    childList: true,
    subtree: true,
  })

  // Initial attempt
  addAnalyticsNavItem()
})()