您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Brings back the date grouping on chatgpt.com
// ==UserScript== // @name ChatGPT bring back date grouping // @version 1 // @author tiramifue // @description Brings back the date grouping on chatgpt.com // @match https://chatgpt.com/* // @run-at document-end // @namespace https://gf.qytechs.cn/users/570213 // @license Apache-2.0 // @noframes // ==/UserScript== // updated 2025-06-08 (function () { 'use strict'; function getDateGroupLabel(isoString) { const createdDate = new Date(isoString); const now = new Date(); const msInDay = 24 * 60 * 60 * 1000; const daysAgo = Math.floor((now - createdDate) / msInDay); const createdMonth = createdDate.getMonth(); const createdYear = createdDate.getFullYear(); const nowMonth = now.getMonth(); const nowYear = now.getFullYear(); if (daysAgo === 0) return 'Today'; if (daysAgo === 1) return 'Yesterday'; if (daysAgo <= 6) return `${daysAgo} days ago`; if (daysAgo <= 13) return 'Last week'; if (daysAgo <= 20) return '2 weeks ago'; if (daysAgo <= 31) return 'Last month'; const monthsAgo = (nowYear - createdYear) * 12 + (nowMonth - createdMonth); if (monthsAgo <= 11) return `${monthsAgo} months ago`; return 'Last year'; } function getReactFiber(dom) { for (const key in dom) { if (key.startsWith('__reactFiber$')) return dom[key]; } return null; } function extractChatInfo(fiber) { const c = fiber.memoizedProps?.conversation; return c ? { id: c.id, title: c.title, created: c.create_time, updated: c.update_time, node: fiber.stateNode } : null; } const seenIds = new Set(); const chatList = []; function processNewChatNode(node) { const fiber = getReactFiber(node); if (!fiber) return; let current = fiber; while (current && !current.memoizedProps?.conversation) { current = current.return; } if (!current || !current.memoizedProps?.conversation) return; const chat = extractChatInfo(current); if (chat && !seenIds.has(chat.id)) { seenIds.add(chat.id); chat.group = getDateGroupLabel(chat.created); chat.node = node; chatList.push(chat); // console.log("New chat loaded:", { // id: chat.id, // title: chat.title, // created: chat.created, // updated: chat.updated, // group: chat.group // }); queueRender(); } } function groupChatsByGroupName() { const groups = new Map(); for (const chat of chatList) { if (!groups.has(chat.group)) groups.set(chat.group, []); groups.get(chat.group).push(chat); } return [...groups.entries()].sort((a, b) => { const aTime = new Date(a[1][0].created).getTime(); const bTime = new Date(b[1][0].created).getTime(); return bTime - aTime; }); } function clearGroupedChats(aside) { aside.querySelectorAll('a[href^="/c/"], .__chat-group-header') .forEach(el => el.remove()); } function renderGroupedChats(aside) { clearGroupedChats(aside); const groups = groupChatsByGroupName(); for (const [label, chats] of groups) { const header = document.createElement('div'); header.className = '__chat-group-header'; header.textContent = label; header.style = ` font-weight: normal; padding: 6px 10px; font-size: 0.85rem; color: #999; margin-top: ${aside.querySelector('.__chat-group-header') ? '12px' : '0'}; `; aside.appendChild(header); chats .sort((a, b) => new Date(b.created) - new Date(a.created)) .forEach(chat => aside.appendChild(chat.node)); } } let renderTimer = null; function queueRender() { if (renderTimer) clearTimeout(renderTimer); renderTimer = setTimeout(() => { const aside = document.querySelector('#history aside'); if (aside) renderGroupedChats(aside); }, 200); } function observeChatList(aside) { const observer = new MutationObserver(mutations => { for (const mutation of mutations) { for (const node of mutation.addedNodes) { if (node.nodeType === 1 && node.matches('a[href^="/c/"]')) { processNewChatNode(node); } } } }); observer.observe(aside, { childList: true, subtree: true }); aside.querySelectorAll('a[href^="/c/"]').forEach(processNewChatNode); } function waitForElement(selector, timeout = 10000) { return new Promise((resolve, reject) => { const el = document.querySelector(selector); if (el) return resolve(el); const observer = new MutationObserver(() => { const el = document.querySelector(selector); if (el) { observer.disconnect(); resolve(el); } }); observer.observe(document.body, { childList: true, subtree: true }); setTimeout(() => { observer.disconnect(); reject(new Error(`Timeout waiting for ${selector}`)); }, timeout); }); } Promise.all([ waitForElement('#history'), waitForElement('#history aside') ]) .then(([_, aside]) => { observeChatList(aside); // console.log("Chat list observer active. Scroll to load all chats."); }) .catch(err => console.warn("ChatGPT grouping script error:", err)); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址