Greasy Fork is available in English.
增强版推特搜索助手 - 右上角定位、浅色系UI、复合搜索、智能替换当前筛选
当前为
// ==UserScript==
// @name 增强版推特搜索助手-Twitter Search Assistant Enhanced
// @namespace example.twitter.enhanced
// @version 0.5
// @description 增强版推特搜索助手 - 右上角定位、浅色系UI、复合搜索、智能替换当前筛选
// @match https://twitter.com/*
// @match https://x.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// 定义搜索预设
const presets = {
"📷 图片": "filter:images -filter:retweets -filter:replies",
"🎬 视频": "filter:videos -filter:retweets -filter:replies",
"🔥 高热度": "min_faves:200 -filter:retweets",
"🈶 日语": "lang:ja -filter:retweets -filter:replies",
"🌎 英语": "lang:en -filter:retweets -filter:replies",
"💬 感想": "感想 OR 評価 lang:ja -filter:retweets -filter:replies",
"⏰ 近期": "since:2024-07-25 -filter:retweets",
"📊 热门": "min_faves:500 -filter:retweets"
};
// 主面板HTML
const panel = document.createElement('div');
panel.id = 'tw-search-assistant';
panel.innerHTML = `
<div class="panel-header">
<span>搜索助手</span>
<button class="toggle-mode" title="切换单选/多选模式">🔄</button>
</div>
<div class="mode-indicator">单选模式</div>
<input id="tw-keyword" type="text" placeholder="输入关键词(可从地址栏自动获取)">
<div class="preset-grid"></div>
<div class="action-buttons">
<button class="btn-clear">清空</button>
<button class="btn-apply">应用搜索</button>
</div>
`;
// 浅色系样式
const style = document.createElement('style');
style.textContent = `
#tw-search-assistant {
position: fixed;
top: 60px;
right: 320px;
z-index: 10000;
width: 280px;
background: #ffffff;
border: 1px solid #e1e8ed;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
font-size: 13px;
color: #0f1419;
transition: all 0.3s ease;
opacity: 0;
transform: translateY(-10px);
}
#tw-search-assistant.show {
opacity: 1;
transform: translateY(0);
}
#tw-search-assistant:hover {
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px 8px;
border-bottom: 1px solid #eff3f4;
font-weight: 600;
}
.toggle-mode {
background: none;
border: none;
cursor: pointer;
font-size: 14px;
padding: 2px 4px;
border-radius: 4px;
transition: background 0.2s;
}
.toggle-mode:hover {
background: #f7f9fa;
}
.mode-indicator {
padding: 4px 16px;
font-size: 11px;
color: #536471;
background: #f7f9fa;
margin: 0 16px 8px;
border-radius: 6px;
text-align: center;
}
#tw-keyword {
width: calc(100% - 32px);
margin: 0 16px 12px;
padding: 8px 12px;
border: 1px solid #eff3f4;
border-radius: 8px;
font-size: 14px;
outline: none;
transition: border-color 0.2s;
}
#tw-keyword:focus {
border-color: #1da1f2;
box-shadow: 0 0 0 3px rgba(29, 161, 242, 0.1);
}
.preset-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
padding: 0 16px 12px;
}
.preset-btn {
padding: 8px 12px;
background: #f7f9fa;
border: 1px solid #eff3f4;
border-radius: 8px;
color: #0f1419;
cursor: pointer;
font-size: 12px;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 4px;
}
.preset-btn:hover {
background: #e8f5fe;
border-color: #cfe5f7;
}
.preset-btn.selected {
background: #e8f5fe;
color: #1da1f2;
border-color: #1da1f2;
}
.preset-btn.selected::after {
content: '✓';
margin-left: auto;
font-size: 11px;
font-weight: bold;
}
.action-buttons {
display: flex;
gap: 8px;
padding: 0 16px 16px;
}
.btn-clear, .btn-apply {
flex: 1;
padding: 8px;
border: none;
border-radius: 8px;
font-size: 13px;
cursor: pointer;
transition: all 0.2s;
font-weight: 500;
}
.btn-clear {
background: #f7f9fa;
color: #536471;
border: 1px solid #eff3f4;
}
.btn-clear:hover {
background: #e1e8ed;
}
.btn-apply {
background: #1da1f2;
color: white;
}
.btn-apply:hover {
background: #1a91da;
}
/* 响应式调整 */
@media (max-width: 1280px) {
#tw-search-assistant {
right: 280px;
}
}
`;
document.head.appendChild(style);
document.body.appendChild(panel);
// 状态管理
let isMultiSelectMode = false;
let selectedPresets = new Set();
// 初始化按钮
function initButtons() {
const grid = document.querySelector('.preset-grid');
Object.keys(presets).forEach(name => {
const btn = document.createElement('button');
btn.className = 'preset-btn';
btn.textContent = name;
btn.onclick = () => handlePresetClick(btn, presets[name]);
grid.appendChild(btn);
});
}
// 处理预设点击
function handlePresetClick(btn, filter) {
if (isMultiSelectMode) {
if (selectedPresets.has(filter)) {
selectedPresets.delete(filter);
btn.classList.remove('selected');
} else {
selectedPresets.add(filter);
btn.classList.add('selected');
}
} else {
// 单选模式:自动执行搜索
applySearch(filter);
}
}
// 应用搜索
function applySearch(additionalFilter = null) {
const kw = document.getElementById('tw-keyword').value.trim();
let currentUrl = window.location.href;
// 获取当前搜索参数
let currentQuery = '';
if (currentUrl.includes('/search?q=')) {
const match = currentUrl.match(/\/search\?q=([^&]+)/);
if (match) {
currentQuery = decodeURIComponent(match[1]);
}
}
// 构建新搜索
let newQuery = kw || currentQuery;
if (additionalFilter) {
if (isMultiSelectMode && selectedPresets.size > 0) {
// 复合搜索
const filters = Array.from(selectedPresets).join(' ');
newQuery = newQuery ? `${newQuery} ${filters}` : filters;
} else {
// 单个筛选
newQuery = newQuery ? `${newQuery} ${additionalFilter}` : additionalFilter;
}
}
if (newQuery) {
const searchUrl = `https://twitter.com/search?q=${encodeURIComponent(newQuery)}&src=typed_query&f=top`;
window.location.href = searchUrl;
}
}
// 清空选择
function clearSelection() {
selectedPresets.clear();
document.querySelectorAll('.preset-btn.selected').forEach(btn => {
btn.classList.remove('selected');
});
}
// 切换模式
function toggleMode() {
isMultiSelectMode = !isMultiSelectMode;
document.querySelector('.mode-indicator').textContent = isMultiSelectMode ? '多选模式' : '单选模式';
clearSelection();
}
// 自动获取当前搜索词
function autoFillKeyword() {
const currentUrl = window.location.href;
if (currentUrl.includes('/search?q=')) {
const match = currentUrl.match(/\/search\?q=([^&]+)/);
if (match) {
const keyword = decodeURIComponent(match[1]).split(' ')[0]; // 只取关键词部分
document.getElementById('tw-keyword').value = keyword;
}
}
}
// 绑定事件
document.querySelector('.toggle-mode').onclick = toggleMode;
document.querySelector('.btn-clear').onclick = clearSelection;
document.querySelector('.btn-apply').onclick = () => applySearch();
// 初始化
initButtons();
autoFillKeyword();
// 显示面板(延迟显示效果)
setTimeout(() => {
panel.classList.add('show');
}, 100);
})();