Jike Compose Autofill

将 URL 中的 ?text= 参数自动写入即刻网页的“分享你的想法...”编辑框,并触发输入事件

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Jike Compose Autofill
// @namespace    popclip.jike.compose
// @version      1.1.0
// @description  将 URL 中的 ?text= 参数自动写入即刻网页的“分享你的想法...”编辑框,并触发输入事件
// @author       you
// @match        https://web.okjike.com/*
// @run-at       document-idle
// @grant        none
// ==/UserScript==

(function () {
  "use strict";

  // 1) 读取 URL 参数中的文本
  const params = new URLSearchParams(window.location.search);
  const preset = params.get("text");
  if (!preset || preset.trim() === "") {
    // 没有传文本就不做任何事
    return;
  }

  // 2) 等待编辑器渲染(即刻为 SPA,节点会延迟出现)
  function waitForEditor(timeoutMs = 15000) {
    const start = Date.now();

    return new Promise((resolve, reject) => {
      // 先快速检查一次
      let editor = findEditor();
      if (editor) return resolve(editor);

      // 用 MutationObserver 监听 DOM 变化,出现后立即填充
      const observer = new MutationObserver(() => {
        editor = findEditor();
        if (editor) {
          observer.disconnect();
          resolve(editor);
        }
      });

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

      // 超时兜底
      const timer = setInterval(() => {
        if (Date.now() - start > timeoutMs) {
          clearInterval(timer);
          observer.disconnect();
          reject(new Error("Editor not found within timeout"));
        } else {
          editor = findEditor();
          if (editor) {
            clearInterval(timer);
            observer.disconnect();
            resolve(editor);
          }
        }
      }, 500);
    });
  }

  // 3) 根据当前页面结构查找编辑器
  function findEditor() {
    // 依据当前页面提供的结构:contenteditable="true" 且 role="textbox"
    // 如果将来页面结构改变,可在此处补充其他选择器(例如类名或 data- 属性)
    const editor =
      document.querySelector("div[contenteditable='true'][role='textbox']") ||
      document.querySelector("[contenteditable='true']");

    return editor || null;
  }

  // 4) 将纯文本安全写入编辑器,并触发输入事件
  function fillEditor(editor, text) {
    if (!editor) return;

    // 聚焦到编辑器
    editor.focus();

    // 使用 Selection/Range 定位插入点(末尾),兼容 React/受控组件
    const selection = window.getSelection();
    const range = document.createRange();
    range.selectNodeContents(editor);
    range.collapse(false);
    selection.removeAllRanges();
    selection.addRange(range);

    // 优先使用 execCommand 插入文本(不少富文本编辑器仍支持)
    const before = editor.textContent || "";
    const ok = document.execCommand("insertText", false, text);

    // 回退:若 execCommand 不生效,则直接设置 textContent
    if (!ok) {
      editor.textContent = before + text;
    }

    // 触发输入事件,促使前端状态更新
    editor.dispatchEvent(new Event("input", { bubbles: true }));
    editor.dispatchEvent(new Event("change", { bubbles: true }));

    // 可选:将插入完成后把 URL 中的 text 参数移除,避免刷新重复插入
    try {
      const url = new URL(window.location.href);
      url.searchParams.delete("text");
      // 使用 history.replaceState 不会导致页面重载
      window.history.replaceState({}, document.title, url.toString());
    } catch (e) {
      // 静默失败即可
      console.warn("Jike Compose Autofill: clean URL param failed:", e);
    }
  }

  // 主流程
  waitForEditor()
    .then((editor) => {
      fillEditor(editor, preset);
    })
    .catch((e) => {
      console.warn("Jike Compose Autofill: 未找到编辑器:", e);
    });
})();