GitHub Style

智能高亮 GitHub 活跃仓库:集成 CSS 视觉排序、配置导入/导出,彻底解决 React 冲突与时间闪烁。

2026/07/20のページです。最新版はこちら

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name           GitHub Style
// @namespace      http://tampermonkey.net/
// @version        1.0.8
// @description    智能高亮 GitHub 活跃仓库:集成 CSS 视觉排序、配置导入/导出,彻底解决 React 冲突与时间闪烁。
// @author         XiMenChuiXue
// @license        MIT
// @icon           https://raw.githubusercontent.com/rational-stars/picgo/refs/heads/main/avatar.jpg
// @match          https://github.com/*
// @match          https://github.com/*/*
// @match          https://github.com/*/*/*
// @match          https://github.com/*/*/*/*
// @exclude        https://github.com/settings/*
// @exclude        https://github.com/notifications/*
// @exclude        https://github.com/marketplace/*
// @grant          GM_registerMenuCommand
// @grant          GM_setValue
// @grant          GM_getValue
// @grant          GM_addStyle
// @grant          GM_getResourceText
// @run-at         document-start
// @require        https://code.jquery.com/jquery-3.6.0.min.js#sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=
// @require        https://cdn.jsdelivr.net/npm/sweetalert2@11
// @require        https://cdn.jsdelivr.net/npm/@simonwep/[email protected]/dist/pickr.min.js
// @require        https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.min.js
// @resource       PICKR_CSS https://cdn.jsdelivr.net/npm/@simonwep/[email protected]/dist/themes/classic.min.css
// ==/UserScript==
 
/* global luxon, Pickr, Swal, $ */
(function () {
    'use strict';
 
    const DateTime = luxon.DateTime;
 
    const pickrCss = GM_getResourceText('PICKR_CSS');
    if (pickrCss) GM_addStyle(pickrCss);
 
    // Styles
    GM_addStyle(`
      .swal2-popup.swal2-modal.swal2-show {
          color: #FFF; border-radius: 20px; background: #31b96c;
          box-shadow: 8px 8px 16px #217e49, -8px -8px 16px #41f48f;
      }
      .formatted-date-span, .custom-time-format {
          white-space: nowrap !important; display: inline-block !important;
          font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif !important;
          font-size: 14px !important; vertical-align: middle;
      }
      div[role="row"] > div:last-child, td[role="gridcell"]:last-child {
          min-width: 135px !important; text-align: right !important; display: flex !important;
          align-items: center; justify-content: flex-end; padding-right: 10px !important;
      }
      #swal2-title a { display: inline-block; height: 40px; margin-right: 10px; border-radius: 10px; overflow: hidden; color: #fff; }
      #swal2-title { display: flex !important; justify-content: center; align-items: center; }
 
      .row-box select {
          border: 2px solid rgba(255, 255, 255, 0.3); border-radius: 8px;
          background-color: rgba(0, 0, 0, 0.2) !important; color: #fff !important;
          padding: 8px 12px; font-size: 14px; cursor: pointer; outline: none; min-width: 120px;
          -webkit-appearance: none; -moz-appearance: none; appearance: none;
          background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
          background-repeat: no-repeat; background-position: right 8px center; background-size: 16px; padding-right: 32px;
      }
      .row-box select:hover { border-color: rgba(255, 255, 255, 0.5); background-color: rgba(0, 0, 0, 0.3) !important; }
      .row-box select:focus { border-color: rgba(255, 255, 255, 0.8); background-color: rgba(0, 0, 0, 0.4) !important; box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1); }
      .row-box select option { background-color: #2d3748 !important; color: #fff !important; padding: 8px; }
      .row-box select:-moz-focusring { color: transparent; text-shadow: 0 0 0 #fff; }
 
      .row-box { display: flex; margin: 20px 25px; align-items: center; justify-content: space-between; }
      .row-box .swal2-input { height: 40px; background-color: rgba(0, 0, 0, 0.2) !important; color: #fff !important; border: 2px solid rgba(255, 255, 255, 0.3); border-radius: 8px; }
      .row-box .swal2-input:focus { border-color: rgba(255, 255, 255, 0.8); box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1); }
      .row-box label { margin-right: 10px; color: #fff; font-weight: 500; }
      .row-box main input { background: rgba(15, 172, 83, 1); width: 70px; border: unset; box-shadow: unset; text-align: right; margin: 0; }
      .row-box main { display: flex; align-items: center; gap: 10px; }
      .freshness-stars { padding: 8px; }
      .freshness-updated { margin-left: 5px; }
      .github-freshness-loading { opacity: 0.6; pointer-events: none; }
 
      input[type="checkbox"] { width: 18px; height: 18px; cursor: pointer; accent-color: #0fac53; }
      input[type="number"], input[type="password"] {
          background-color: rgba(0, 0, 0, 0.2) !important; color: #fff !important;
          border: 2px solid rgba(255, 255, 255, 0.3) !important; border-radius: 8px; padding: 8px; text-align: center;
      }
      input[type="password"] { min-width: 200px; text-align: left; padding: 8px 12px; }
      input[type="number"]:focus, input[type="password"]:focus { border-color: rgba(255, 255, 255, 0.8) !important; outline: none; box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.1); }
 
      #RESET_DEFAULTS { background-color: #e53e3e !important; color: white !important; border: none !important; padding: 10px 24px !important; border-radius: 8px !important; cursor: pointer; font-weight: 500; transition: all 0.2s; }
      #RESET_DEFAULTS:hover { background-color: #c53030 !important; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(229, 62, 62, 0.4); }
      .swal2-confirm { background-color: #0fac53 !important; border-radius: 8px !important; }
      .swal2-cancel { background-color: #718096 !important; border-radius: 8px !important; }
      
      relative-time.custom-time-replaced { display: none !important; }

      .gh-freshness-flex-sort { display: flex !important; flex-direction: column !important; }
      .gh-freshness-flex-sort > [role="row"], .gh-freshness-flex-sort > .Box-row, .gh-freshness-flex-sort > div {
          width: 100% !important; box-sizing: border-box !important; margin-left: 0 !important; margin-right: 0 !important;
      }
    `);
 
    const PanelDom = `
      <div class="row-box">
          <label for="THEME-select">主题设置:</label>
          <main>
              <select tabindex="-1" id="THEME-select" class="swal2-input">
                  <option value="light">☀️ Light</option>
                  <option value="dark">🌙 Dark</option>
              </select>
          </main>
      </div>
      <div class="row-box">
          <label id="TIME_BOUNDARY-label">时间阈值:</label>
          <main>
              <input id="TIME_BOUNDARY-number" type="number" class="swal2-input" value="" min="1" max="999" maxlength="3" pattern="\\d{1,3}">
              <select tabindex="-1" id="TIME_BOUNDARY-select" class="swal2-input">
                  <option value="day">📅 日</option>
                  <option value="week">📆 周</option>
                  <option value="month">🗓️ 月</option>
                  <option value="year">📊 年</option>
              </select>
          </main>
      </div>
      <div class="row-box">
          <div><label id="BGC-label">🎨 背景颜色:</label><input type="checkbox" id="BGC-enabled"></div>
          <main>
              <span id="BGC-highlight-color-value"><div id="BGC-highlight-color-pickr"></div></span>
              <span id="BGC-grey-color-value"><div id="BGC-grey-color-pickr"></div></span>
          </main>
      </div>
      <div class="row-box">
          <div><label id="FONT-label">🔤 字体颜色:</label><input type="checkbox" id="FONT-enabled"></div>
          <main>
              <span id="FONT-highlight-color-value"><div id="FONT-highlight-color-pickr"></div></span>
              <span id="FONT-grey-color-value"><div id="FONT-grey-color-pickr"></div></span>
          </main>
      </div>
      <div class="row-box">
          <div><label id="DIR-label">📁 文件夹颜色:</label><input type="checkbox" id="DIR-enabled"></div>
          <main>
              <span id="DIR-highlight-color-value"><div id="DIR-highlight-color-pickr"></div></span>
              <span id="DIR-grey-color-value"><div id="DIR-grey-color-pickr"></div></span>
          </main>
      </div>
      <div class="row-box">
          <div><label id="TIME_FORMAT-label">🕐 时间格式化:</label><input type="checkbox" id="TIME_FORMAT-enabled"></div>
      </div>
      <div class="row-box">
          <div><label id="SORT-label">🔀 文件排序 (CSS视觉排序):</label><input type="checkbox" id="SORT-enabled"></div>
          <main>
              <select tabindex="-1" id="SORT-select" class="swal2-input">
                  <option value="asc">⬆️ 时间正序</option>
                  <option value="desc">⬇️ 时间倒序</option>
              </select>
          </main>
      </div>
      <div class="row-box">
          <label for="CURRENT_THEME-select">🌓 当前主题:</label>
          <main>
              <select tabindex="-1" id="CURRENT_THEME-select" class="swal2-input">
                  <option value="auto">⚡ Auto</option>
                  <option value="light">☀️ Light</option>
                  <option value="dark">🌙 Dark</option>
              </select>
          </main>
      </div>
      <div class="row-box">
          <div>
              <label id="AWESOME-label"><a target="_blank" href="https://github.com/settings/tokens" style="color: #fff; text-decoration: underline;">🔑 AWESOME token:</a></label>
              <input type="checkbox" id="AWESOME-enabled">
          </div>
          <main>
              <input id="AWESOME_TOKEN" type="password" class="swal2-input" value="" placeholder="ghp_xxx 或 github_pat_xxx">
          </main>
      </div>
      
      <!-- 🚀 新增:导入/导出按钮 -->
      <div class="row-box" style="justify-content: center; gap: 15px; margin-top: 25px; flex-wrap: wrap;">
          <button type="button" id="EXPORT_CONFIG" class="swal2-styled" style="background-color: #3182ce !important; border-radius: 8px !important; margin: 5px; padding: 10px 20px !important;">📤 导出配置</button>
          <button type="button" id="IMPORT_CONFIG" class="swal2-styled" style="background-color: #805ad5 !important; border-radius: 8px !important; margin: 5px; padding: 10px 20px !important;">📥 导入配置</button>
      </div>

      <div class="row-box" style="justify-content: center; margin-top: 15px;">
          <button type="button" id="RESET_DEFAULTS" class="swal2-styled">🔄 恢复默认设置</button>
      </div>
      <p style="font-size: 0.85em; opacity: 0.9; text-align: center; margin-top: 15px; color: rgba(255,255,255,0.8);">
          💡 提示:排序采用 CSS Flex 黑科技,不破坏 React 架构。配置码包含 Token,请私密分享。
      </p>
    `;
 
    const default_THEME = {
        BGC: { highlightColor: 'rgba(15, 172, 83, 1)', greyColor: 'rgba(245, 245, 245, 0.24)', isEnabled: true },
        TIME_BOUNDARY: { number: 30, select: 'day' },
        FONT: { highlightColor: 'rgba(252, 252, 252, 1)', greyColor: 'rgba(0, 0, 0, 1)', isEnabled: true },
        DIR: { highlightColor: 'rgba(15, 172, 83, 1)', greyColor: 'rgba(154, 154, 154, 1)', isEnabled: true },
        SORT: { select: 'desc', isEnabled: true }, 
        AWESOME: { isEnabled: false },
        TIME_FORMAT: { isEnabled: true },
    };
 
    let CURRENT_THEME = GM_getValue('CURRENT_THEME', 'light');
    let AWESOME_TOKEN = GM_getValue('AWESOME_TOKEN', '');
    let THEME_TYPE = getThemeType();
    // 🚀 修改为 let 以支持运行时导入覆盖
    let config_JSON = JSON.parse(GM_getValue('config_JSON', JSON.stringify({ light: default_THEME, dark: default_THEME })));
    let THEME = config_JSON[THEME_TYPE] || JSON.parse(JSON.stringify(default_THEME));
 
    const apiCache = new Map();
    const apiQueue = [];
    let apiProcessing = false;
    const API_DELAY = 100;
 
    const configPickr = {
        theme: 'classic',
        components: {
            preview: true, opacity: true, hue: true,
            interaction: { rgba: true, input: true, clear: true, save: true },
        },
    };
 
    function getThemeType() {
        let themeType = CURRENT_THEME;
        if (CURRENT_THEME === 'auto') {
            themeType = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
        }
        return themeType;
    }
 
    function initPickr(el_default) {
        const pickr = Pickr.create({ ...configPickr, ...el_default });
        pickr.on('save', (color, instance) => {
            const hex = color.toHEXA().toString();
            instance.options.el.setAttribute('data-pickr-color', hex);
            pickr.hide();
        });
        setTimeout(() => {
            const el = document.querySelector(el_default.el + ' .pcr-button');
            if (el && el_default.default) {
                el.setAttribute('data-pickr-color', el_default.default);
            }
        }, 300);
        return pickr;
    }
 
    function getUpdatedThemeConfig() {
        let updatedTheme = {};
        for (const [themeKey, themeVal] of Object.entries(default_THEME)) {
            updatedTheme[themeKey] = {};
            for (let [key, val] of Object.entries(themeVal)) {
                if (key === 'highlightColor' || key === 'greyColor') {
                    const type = key === 'highlightColor' ? 'highlight' : 'grey';
                    const $btn = $(`#${themeKey}-${type}-color-value .pcr-button`);
                    let colorVal = $btn.attr('data-pickr-color');
                    if (!colorVal) colorVal = $btn.css('--pcr-color');
                    val = colorVal || val;
                } else if (key === 'isEnabled') {
                    val = $(`#${themeKey}-enabled`).prop('checked');
                } else if (key === 'number' || key === 'select') {
                    val = $(`#${themeKey}-${key}`).val();
                    if (key === 'number') val = parseInt(val) || 30;
                }
                updatedTheme[themeKey][key] = val;
            }
        }
        return updatedTheme;
    }
 
    function handleData(theme) {
        if (!theme) return;
        for (const [themeKey, themeVal] of Object.entries(theme)) {
            for (const [key, val] of Object.entries(themeVal)) {
                if (key === 'highlightColor' || key === 'greyColor') {
                    const type = key === 'highlightColor' ? 'highlight' : 'grey';
                    const $btn = $(`#${themeKey}-${type}-color-value .pcr-button`);
                    if ($btn.length && val) {
                        $btn.css('--pcr-color', val);
                        $btn.attr('data-pickr-color', val); 
                    }
                } else if (key === 'isEnabled') {
                    $(`#${themeKey}-enabled`).prop('checked', val);
                } else if (key === 'number' || key === 'select') {
                    $(`#${themeKey}-${key}`).val(val);
                }
            }
        }
    }
 
    function resetToDefaults() {
        handleData(default_THEME);
        initPickr({ el: '#BGC-highlight-color-pickr', default: default_THEME.BGC.highlightColor });
        initPickr({ el: '#BGC-grey-color-pickr', default: default_THEME.BGC.greyColor });
        initPickr({ el: '#FONT-highlight-color-pickr', default: default_THEME.FONT.highlightColor });
        initPickr({ el: '#FONT-grey-color-pickr', default: default_THEME.FONT.greyColor });
        initPickr({ el: '#DIR-highlight-color-pickr', default: default_THEME.DIR.highlightColor });
        initPickr({ el: '#DIR-grey-color-pickr', default: default_THEME.DIR.greyColor });
    }
 
    function createSettingsPanel() {
        Swal.fire({
            title: `<div style="display: flex; align-items: center; justify-content: center; gap: 10px;">
                <span>🎨</span>
                <span>GitHub Freshness Settings</span>
            </div>`,
            html: PanelDom,
            focusConfirm: false,
            allowOutsideClick: false,
            background: '#31b96c',
            confirmButtonColor: '#0fac53',
            cancelButtonColor: '#718096',
            preConfirm: () => {
                const updated_THEME = getUpdatedThemeConfig();
                CURRENT_THEME = $('#CURRENT_THEME-select').val();
                AWESOME_TOKEN = $('#AWESOME_TOKEN').val().trim();
 
                const tokenRegex = /^(ghp_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9_]+)$/;
                if (updated_THEME.AWESOME.isEnabled && AWESOME_TOKEN && !AWESOME_TOKEN.match(tokenRegex)) {
                    Swal.showValidationMessage('❌ Token 格式不正确 (支持 ghp_ 或 github_pat_)');
                    return false;
                }
 
                config_JSON[$('#THEME-select').val()] = updated_THEME;
                GM_setValue('config_JSON', JSON.stringify(config_JSON));
                GM_setValue('CURRENT_THEME', CURRENT_THEME);
                GM_setValue('AWESOME_TOKEN', AWESOME_TOKEN);
                THEME = updated_THEME;
                GitHub_Freshness(updated_THEME);
 
                Swal.fire({
                    position: 'top-center',
                    background: '#31b96c',
                    icon: 'success',
                    iconColor: '#fff',
                    title: '<span style="color: #fff;">✅ 保存成功!</span>',
                    showConfirmButton: false,
                    timer: 1000,
                    toast: true
                });
            },
            heightAuto: false,
            showCancelButton: true,
            confirmButtonText: '💾 保存',
            cancelButtonText: '❌ 取消',
            didOpen: () => {
                initSettings(THEME);
 
                $('#THEME-select').on('change', function () {
                    let selectedTheme = $(this).val();
                    let theme = config_JSON[selectedTheme] || JSON.parse(JSON.stringify(default_THEME));
                    handleData(theme);
 
                    initPickr({ el: '#BGC-highlight-color-pickr', default: theme.BGC.highlightColor });
                    initPickr({ el: '#BGC-grey-color-pickr', default: theme.BGC.greyColor });
                    initPickr({ el: '#FONT-highlight-color-pickr', default: theme.FONT.highlightColor });
                    initPickr({ el: '#FONT-grey-color-pickr', default: theme.FONT.greyColor });
                    initPickr({ el: '#DIR-highlight-color-pickr', default: theme.DIR.highlightColor });
                    initPickr({ el: '#DIR-grey-color-pickr', default: theme.DIR.greyColor });
                });
 
                $('#RESET_DEFAULTS').on('click', () => {
                    Swal.fire({
                        title: '🔄 确认恢复默认?',
                        text: '当前主题的设置将被重置为默认值',
                        icon: 'warning',
                        iconColor: '#f6e05e',
                        background: '#31b96c',
                        color: '#fff',
                        showCancelButton: true,
                        confirmButtonColor: '#e53e3e',
                        cancelButtonColor: '#718096',
                        confirmButtonText: '⚠️ 确认重置',
                        cancelButtonText: '✋ 取消'
                    }).then((result) => {
                        if (result.isConfirmed) {
                            resetToDefaults();
                            Swal.fire({
                                position: 'top-center',
                                background: '#31b96c',
                                icon: 'success',
                                iconColor: '#fff',
                                title: '<span style="color: #fff;">✅ 已重置为默认值</span>',
                                showConfirmButton: false,
                                timer: 800,
                                toast: true
                            });
                        }
                    });
                });

                // 🚀 导出配置逻辑
                $('#EXPORT_CONFIG').on('click', () => {
                    const exportData = {
                        config_JSON: config_JSON,
                        CURRENT_THEME: CURRENT_THEME,
                        AWESOME_TOKEN: AWESOME_TOKEN
                    };
                    const b64 = btoa(unescape(encodeURIComponent(JSON.stringify(exportData))));
                    
                    Swal.fire({
                        title: '📤 导出配置',
                        html: `
                            <p style="color: #fff; font-size: 14px; margin-bottom: 10px;">⚠️ 包含 Token 等敏感信息,请妥善保管!</p>
                            <textarea id="export-text" style="width: 100%; height: 150px; background: rgba(0,0,0,0.3); color: #fff; border: 1px solid rgba(255,255,255,0.3); border-radius: 8px; padding: 10px; font-family: monospace; resize: none;">${b64}</textarea>
                        `,
                        background: '#31b96c',
                        color: '#fff',
                        showCancelButton: true,
                        confirmButtonText: '📋 复制并关闭',
                        cancelButtonText: '❌ 关闭',
                        didOpen: () => {
                            const textarea = document.getElementById('export-text');
                            if (textarea) textarea.select();
                        },
                        preConfirm: () => {
                            const textarea = document.getElementById('export-text');
                            if (textarea) {
                                textarea.select();
                                if (navigator.clipboard) {
                                    navigator.clipboard.writeText(textarea.value).catch(() => document.execCommand('copy'));
                                } else {
                                    document.execCommand('copy');
                                }
                            }
                            return true;
                        }
                    });
                });

                // 🚀 导入配置逻辑
                $('#IMPORT_CONFIG').on('click', () => {
                    Swal.fire({
                        title: '📥 导入配置',
                        html: `
                            <p style="color: #fff; font-size: 14px; margin-bottom: 10px;">请粘贴之前导出的配置码 (Base64):</p>
                            <textarea id="import-text" style="width: 100%; height: 150px; background: rgba(0,0,0,0.3); color: #fff; border: 1px solid rgba(255,255,255,0.3); border-radius: 8px; padding: 10px; font-family: monospace; resize: none;" placeholder="粘贴配置码..."></textarea>
                        `,
                        background: '#31b96c',
                        color: '#fff',
                        showCancelButton: true,
                        confirmButtonText: '✅ 确认导入',
                        cancelButtonText: '❌ 取消',
                        preConfirm: () => {
                            const val = document.getElementById('import-text').value.trim();
                            if (!val) {
                                Swal.showValidationMessage('❌ 配置码不能为空');
                                return false;
                            }
                            try {
                                const jsonStr = decodeURIComponent(escape(atob(val)));
                                const importData = JSON.parse(jsonStr);
                                if (!importData.config_JSON) throw new Error('Invalid format');
                                return importData;
                            } catch (e) {
                                Swal.showValidationMessage('❌ 配置码解析失败,请检查格式');
                                return false;
                            }
                        }
                    }).then((result) => {
                        if (result.isConfirmed && result.value) {
                            const importData = result.value;
                            
                            config_JSON = importData.config_JSON;
                            GM_setValue('config_JSON', JSON.stringify(config_JSON));
                            
                            if (importData.CURRENT_THEME) {
                                CURRENT_THEME = importData.CURRENT_THEME;
                                GM_setValue('CURRENT_THEME', CURRENT_THEME);
                            }
                            if (importData.AWESOME_TOKEN !== undefined) {
                                AWESOME_TOKEN = importData.AWESOME_TOKEN;
                                GM_setValue('AWESOME_TOKEN', AWESOME_TOKEN);
                            }
                            
                            THEME_TYPE = getThemeType();
                            THEME = config_JSON[THEME_TYPE] || JSON.parse(JSON.stringify(default_THEME));
                            
                            Swal.fire({
                                position: 'top-center',
                                background: '#31b96c',
                                icon: 'success',
                                iconColor: '#fff',
                                title: '<span style="color: #fff;">✅ 导入成功!正在刷新...</span>',
                                showConfirmButton: false,
                                timer: 1000,
                                toast: true
                            }).then(() => {
                                Swal.close();
                                createSettingsPanel();
                                runScript();
                            });
                        }
                    });
                });
            }
        });
    }
 
    function initSettings(theme) {
        if (!theme) theme = JSON.parse(JSON.stringify(default_THEME));
 
        initPickr({ el: '#BGC-highlight-color-pickr', default: theme.BGC.highlightColor });
        initPickr({ el: '#BGC-grey-color-pickr', default: theme.BGC.greyColor });
        initPickr({ el: '#FONT-highlight-color-pickr', default: theme.FONT.highlightColor });
        initPickr({ el: '#FONT-grey-color-pickr', default: theme.FONT.greyColor });
        initPickr({ el: '#DIR-highlight-color-pickr', default: theme.DIR.highlightColor });
        initPickr({ el: '#DIR-grey-color-pickr', default: theme.DIR.greyColor });
 
        $('#THEME-select').val(THEME_TYPE);
        $('#CURRENT_THEME-select').val(CURRENT_THEME);
        $('#AWESOME_TOKEN').val(AWESOME_TOKEN);
        handleData(theme);
    }
 
    function setElementBGC(el, BGC, timeResult) {
        if (el.length && el[0] && BGC.isEnabled) {
            try { el[0].style.setProperty('background-color', timeResult ? BGC.highlightColor : BGC.greyColor, 'important'); } catch (e) {}
        }
    }
 
    function setElementDIR(el, DIR, timeResult) {
        if (el.length && DIR.isEnabled) {
            const color = timeResult ? DIR.highlightColor : DIR.greyColor;
            try {
                if (el[0]) {
                    el[0].style.setProperty('fill', color, 'important');
                    el[0].style.setProperty('stroke', color, 'important');
                }
                el.attr('fill', color); el.attr('stroke', color);
            } catch (e) {}
        }
    }
 
    function setElementFONT(el, FONT, timeResult) {
        if (el.length && el[0] && FONT.isEnabled) {
            try { el[0].style.setProperty('color', timeResult ? FONT.highlightColor : FONT.greyColor, 'important'); } catch (e) {}
        }
    }
 
    function handleTime(time, time_boundary, type = 'ISO8601') {
        if (!time) return false;
        const { number, select } = time_boundary;
        let days = 0;
        switch (select) {
            case 'day': days = parseInt(number) || 30; break;
            case 'week': days = (parseInt(number) || 4) * 7; break;
            case 'month': days = (parseInt(number) || 1) * 30; break;
            case 'year': days = (parseInt(number) || 1) * 365; break;
            default: days = 30;
        }
        const thresholdDate = new Date();
        thresholdDate.setDate(thresholdDate.getDate() - days);
        thresholdDate.setHours(0, 0, 0, 0);
 
        let inputDate = null;
        if (type === 'UTC') {
            const formats = ["yyyy年M月d日 'GMT'Z HH:mm", "MMM d, yyyy, h:mm a 'GMT'Z", "MMM d, yyyy 'GMT'Z", "yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd HH:mm:ss"];
            for (const fmt of formats) {
                try {
                    const dt = DateTime.fromFormat(time, fmt, { zone: 'UTC' });
                    if (dt.isValid) { inputDate = dt.toJSDate(); break; }
                } catch (e) { continue; }
            }
            if (!inputDate) {
                const nativeDate = new Date(time);
                if (!isNaN(nativeDate.getTime())) inputDate = nativeDate;
            }
        } else { inputDate = new Date(time); }
 
        if (!inputDate || isNaN(inputDate.getTime())) return false;
        return inputDate >= thresholdDate;
    }
 
    function toAPIUrl(href) {
        if (!href) return null;
        const match = href.match(/^https:\/\/github\.com\/([^\\/]+)\/([^\\/]+)/);
        return match ? `https://api.github.com/repos/${match[1]}/${match[2]}` : null;
    }
 
    async function processApiQueue() {
        if (apiProcessing || apiQueue.length === 0) return;
        apiProcessing = true;
        while (apiQueue.length > 0) {
            const { apiHref, callback } = apiQueue.shift();
            if (apiCache.has(apiHref)) { callback(apiCache.get(apiHref)); continue; }
            try {
                const response = await fetch(apiHref, { headers: AWESOME_TOKEN ? { 'Authorization': `token ${AWESOME_TOKEN}` } : {} });
                if (response.status === 403) { callback(null); } 
                else if (response.ok) {
                    const data = await response.json();
                    apiCache.set(apiHref, data);
                    setTimeout(() => apiCache.delete(apiHref), 5 * 60 * 1000);
                    callback(data);
                } else { callback(null); }
            } catch (error) { callback(null); }
            if (apiQueue.length > 0) await new Promise(resolve => setTimeout(resolve, API_DELAY));
        }
        apiProcessing = false;
    }
 
    function GitHub_FreshnessAwesome(theme) {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(el => {
                if (el.isIntersecting && el.target.getAttribute('data-requested') !== 'true') {
                    const href = $(el.target).attr('href');
                    const apiHref = toAPIUrl(href);
                    if (!apiHref) return;
                    el.target.setAttribute('data-requested', 'true');
                    $(el.target).addClass('github-freshness-loading');
                    apiQueue.push({
                        apiHref: apiHref,
                        callback: (data) => {
                            $(el.target).removeClass('github-freshness-loading');
                            if (!data) return;
                            const timeResult = handleTime(data.updated_at, theme.TIME_BOUNDARY);
                            if (theme.AWESOME.isEnabled) {
                                const $existing = $(el.target).parent().find('.freshness-stars, .freshness-updated');
                                if ($existing.length === 0) {
                                    $(el.target).after(
                                        `<span class="freshness-stars">★${data.stargazers_count.toLocaleString()}</span>` +
                                        `<span class="freshness-updated">📅${formatDate(data.updated_at)}</span>`
                                    );
                                    $(el.target).css('padding', '0 12px');
                                }
                            }
                            setElementBGC($(el.target), theme.BGC, timeResult);
                            setElementFONT($(el.target), theme.FONT, timeResult);
                        }
                    });
                    processApiQueue();
                }
            });
        }, { threshold: 0.1, rootMargin: '50px' });
 
        $('.Box-row a, .markdown-body a').each(function () {
            const href = $(this).attr('href');
            if (href && /^https:\/\/github\.com\/[^\\/]+\/[^\\/]+\/?$/.test(href)) {
                observer.observe(this);
            }
        });
    }
 
    function GitHub_FreshnessSearchPage(theme) {
        const elements = $('relative-time[datetime], relative-time[title]');
        if (elements.length === 0) return;
        elements.each(function () {
            const $this = $(this);
            const datetime = $this.attr('datetime');
            const title = $this.attr('title');
            const timeStr = datetime || title;
            if (!timeStr) return;
            const isISO8601 = !!datetime;
            const timeResult = handleTime(timeStr, theme.TIME_BOUNDARY, isISO8601 ? 'ISO8601' : 'UTC');
            const BGC_element = $this.closest('div[data-testid*="results-list"], div[data-testid*="results-card"], li, article, .Box-row');
            setElementBGC(BGC_element, theme.BGC, timeResult);
            setElementFONT($this, theme.FONT, timeResult);
        });
    }
 
    function GitHub_Freshness(theme) {
        if (!theme) theme = THEME;
        const matchUrl = isMatchedUrl();
        if (!matchUrl) return;
 
        if (matchUrl === 'matchSearchPage') {
            GitHub_FreshnessSearchPage(theme);
            return;
        }
 
        const timeElements = $('[data-testid="file-list-row"] relative-time, .Box-row relative-time, tr relative-time, div[role="row"] relative-time');
        if (timeElements.length === 0) return;
 
        timeElements.each(function () {
            const $this = $(this);
            const datetime = $this.attr('datetime');
            if (!datetime) return;
            const trElement = $this.closest('[data-testid="file-list-row"], .Box-row, tr, div[role="row"]');
            if (!trElement.length) return;
            const timeResult = handleTime(datetime, theme.TIME_BOUNDARY);
            let BGC_element = trElement.find('[data-testid="latest-commit-details"], td:last-child, div[role="gridcell"]:last-child').first();
            if (BGC_element.length === 0) BGC_element = $this.parent();
            const ICON_element = trElement.find('svg').first();
            setElementBGC(BGC_element, theme.BGC, timeResult);
            setElementDIR(ICON_element, theme.DIR, timeResult);
            setElementFONT($this.parent(), theme.FONT, timeResult);
        });
        
        applyCSSSortOrder(theme);
    }
 
    function applyCSSSortOrder(theme) {
        if (!theme.SORT.isEnabled) return;
        const containers = document.querySelectorAll('tbody, [role="grid"], [data-testid="file-list-row-container"], .Box');
        containers.forEach(container => {
            if (container.tagName === 'TBODY' || container.tagName === 'TABLE') return;
            const rows = container.querySelectorAll(':scope > [role="row"], :scope > .Box-row, :scope > div');
            if (rows.length <= 1) return;
            container.classList.add('gh-freshness-flex-sort');
            rows.forEach(row => {
                const timeEl = row.querySelector('relative-time[datetime]');
                if (!timeEl) return;
                const isCommitRow = row.querySelector('[data-testid="latest-commit-details"]') !== null;
                if (isCommitRow) {
                    row.style.setProperty('order', '-999999999', 'important');
                } else {
                    const datetime = timeEl.getAttribute('datetime');
                    const timestamp = new Date(datetime).getTime();
                    if (!isNaN(timestamp)) {
                        const orderVal = theme.SORT.select === 'desc' ? -timestamp : timestamp;
                        row.style.setProperty('order', String(orderVal), 'important');
                    }
                }
            });
        });
    }
 
    function isMatchedUrl() {
        const href = window.location.href;
        if (/^https:\/\/github\.com\/search\?.*$/.test(href)) return 'matchSearchPage';
        if (/^https:\/\/github\.com\/[^/]+\/[^/]+(?:\?.*)?$|^https:\/\/github\.com\/[^/]+\/[^/]+\/tree\/.+$/.test(href)) return 'matchRepoPage';
        return null;
    }
 
    function formatDate(dateStr) {
        if (!dateStr) return '';
        const date = new Date(dateStr);
        if (isNaN(date.getTime())) return dateStr;
        const Y = date.getFullYear();
        const M = String(date.getMonth() + 1).padStart(2, '0');
        const D = String(date.getDate()).padStart(2, '0');
        return `${Y}-${M}-${D}`;
    }
 
    function forceFormatRelativeTime() {
        if (!THEME.TIME_FORMAT.isEnabled) return;
        const elements = document.querySelectorAll('relative-time');
        if (elements.length === 0) return;
        elements.forEach((item) => {
            try {
                const dateStr = item.getAttribute('datetime');
                if (!dateStr) return;
                const date = new Date(dateStr);
                if (isNaN(date.getTime())) return;
                const Y = date.getFullYear();
                const M = String(date.getMonth() + 1).padStart(2, '0');
                const D = String(date.getDate()).padStart(2, '0');
                const hh = String(date.getHours()).padStart(2, '0');
                const mm = String(date.getMinutes()).padStart(2, '0');
                const str = `${Y}-${M}-${D} ${hh}:${mm}`;
 
                if (item.nextElementSibling && item.nextElementSibling.classList.contains('custom-time-format')) {
                    if (item.nextElementSibling.textContent !== str) item.nextElementSibling.textContent = str;
                    return;
                }
                item.classList.add('custom-time-replaced');
                const span = document.createElement('span');
                span.className = 'custom-time-format formatted-date-span';
                span.textContent = str;
                item.parentNode.insertBefore(span, item.nextSibling);
            } catch (e) {}
        });
    }
 
    function debounce(func, wait) {
        let timeout;
        return function (...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }
 
    const runScript = debounce(() => {
        try {
            GitHub_Freshness();
            GitHub_FreshnessAwesome(THEME); 
            forceFormatRelativeTime();
        } catch (e) { console.error('GitHub Freshness: Script execution error', e); }
    }, 350);
 
    let mutationObserver = null;
    function initMutationObserver() {
        if (mutationObserver) return;
        mutationObserver = new MutationObserver((mutations) => {
            let shouldRun = false;
            for (const mutation of mutations) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    for (const node of mutation.addedNodes) {
                        if (node.nodeType === Node.ELEMENT_NODE) {
                            if (node.matches && (node.matches('relative-time') || node.querySelector && node.querySelector('relative-time, [data-testid="file-list-row"]'))) {
                                shouldRun = true; break;
                            }
                        }
                    }
                }
            }
            if (shouldRun) runScript();
        });
        mutationObserver.observe(document.body, { childList: true, subtree: true });
    }
 
    $(function() {
        console.log('GitHub Freshness v1.0.8 (Config Sync) Loaded');
        runScript();
        initMutationObserver();
    });
 
    document.addEventListener('pjax:end', () => { runScript(); initMutationObserver(); });
    window.addEventListener('popstate', () => setTimeout(runScript, 350));
 
    const originalPush = history.pushState;
    history.pushState = function (...args) { originalPush.apply(this, args); setTimeout(runScript, 350); };
 
    const originalReplace = history.replaceState;
    history.replaceState = function (...args) { originalReplace.apply(this, args); setTimeout(runScript, 350); };
 
    let timeUpdateScheduled = false;
    function scheduleTimeUpdate() {
        if (timeUpdateScheduled) return;
        timeUpdateScheduled = true;
        requestAnimationFrame(() => {
            forceFormatRelativeTime();
            if(THEME.SORT.isEnabled) applyCSSSortOrder(THEME);
            timeUpdateScheduled = false;
        });
    }
    setInterval(scheduleTimeUpdate, 2000);
 
    GM_registerMenuCommand('⚙️ Settings', createSettingsPanel);
 
    const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
    darkModeMediaQuery.addEventListener('change', (e) => {
        if (CURRENT_THEME === 'auto') {
            THEME_TYPE = e.matches ? 'dark' : 'light';
            THEME = config_JSON[THEME_TYPE] || JSON.parse(JSON.stringify(default_THEME));
            runScript();
        }
    });
 
})();