GitHub issue 输入修复助手(Firefox)

解决 Linux Firefox Github issue 中文输入法无法输入的问题

// ==UserScript==
// @name         GitHub issue 输入修复助手(Firefox)
// @namespace    https://github.com/
// @version      1.0
// @description  解决 Linux Firefox Github issue 中文输入法无法输入的问题
// @author       ChatGPT
// @match        https://github.com/*
// @grant        none
// @license MIT
// ==/UserScript==

(function () {
  'use strict';

  let targetInput;

  // 使用 MutationObserver 监听页面加载和输入框变化
  const observer = new MutationObserver(() => {
    targetInput = document.querySelector('input[role="combobox"][placeholder*="Search"]');

    if (targetInput && !document.getElementById('hidden-ime-input')) {
      setupRedirectInput();
    }
  });

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

  // 设置 React 输入框的值
  function setReactInputValue(input, value) {
    const nativeSetter = Object.getOwnPropertyDescriptor(
      window.HTMLInputElement.prototype, 'value'
    ).set;
    nativeSetter.call(input, value);
    const ev = new Event('input', { bubbles: true });
    input.dispatchEvent(ev);
  }

  // 创建输入框并绑定事件
  function setupRedirectInput() {
    if (!targetInput) return;
    console.log('[IME Redirect] 绑定输入框:', targetInput);

    const rect = targetInput.getBoundingClientRect();
    const style = getComputedStyle(targetInput);

    const hiddenInput = document.createElement('input');
    hiddenInput.id = 'hidden-ime-input';

    hiddenInput.style.cssText = `
      position: absolute;
      top: ${window.scrollY + rect.top - 40}px;
      left: ${window.scrollX + rect.left - 10}px;
      width: ${rect.width}px;
      height: ${rect.height}px;
      opacity: 1;
      z-index: 9999;
      resize: none;
      overflow: hidden;
      font-size: ${style.fontSize};
      border: none;
      background: white;
      outline: 1px solid #ccc;
      border-radius: 5px;
    `;

    hiddenInput.setAttribute('autocomplete', 'off');
    hiddenInput.setAttribute('autocorrect', 'off');
    hiddenInput.setAttribute('autocapitalize', 'off');
    hiddenInput.setAttribute('spellcheck', 'false');

    document.body.appendChild(hiddenInput);

    // 初始值同步
    hiddenInput.value = targetInput.value || '';

    // selection 同步
    hiddenInput.addEventListener('select', () => {
      targetInput.setSelectionRange(hiddenInput.selectionStart, hiddenInput.selectionEnd);
    });

    // 内容同步:hidden → target
    hiddenInput.addEventListener('input', () => {
      setReactInputValue(targetInput, hiddenInput.value);
    });

    // 内容同步:target → hidden(仅非 focus 状态下)
    let focus = false;
    let lastValue = targetInput.value;

    setInterval(() => {
      if (targetInput.value !== lastValue && !focus) {
        lastValue = targetInput.value;
        hiddenInput.value = targetInput.value || '';

        try {
          hiddenInput.selectionStart = targetInput.selectionStart;
          hiddenInput.selectionEnd = targetInput.selectionEnd;
        } catch {}
      }
    }, 100);

    hiddenInput.addEventListener('focus', () => {
      focus = true;
    });

    hiddenInput.addEventListener('blur', () => {
      focus = false;
    });

    // 转发回车事件
    hiddenInput.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') {
        console.log('检测到 Enter,转发到 React 输入框');
        simulateEnterKeyOnTarget(targetInput);
        e.preventDefault();
      }
    });

    // 可选:初始自动聚焦
    // hiddenInput.focus();
  }

  // 模拟在 targetInput 上按下 Enter 键
  function simulateEnterKeyOnTarget() {
    const keyboardEventInit = {
      key: 'Enter',
      code: 'Enter',
      keyCode: 13,
      which: 13,
      bubbles: true,
      cancelable: true
    };

    const down = new KeyboardEvent('keydown', keyboardEventInit);
    const up = new KeyboardEvent('keyup', keyboardEventInit);

    targetInput.dispatchEvent(down);
    targetInput.dispatchEvent(up);
  }

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址