您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Toggleable filter to show only those Bluesky posts containing media
// ==UserScript== // @name Bluesky Media Only Toggle // @description Toggleable filter to show only those Bluesky posts containing media // @author @plonked.bsky.social // @match *://bsky.app/* // @namespace plonked // @version 1.0.0 // @grant GM_setValue // @grant GM_getValue // ==/UserScript== (function() { 'use strict'; const FILTER_BUTTON_ID = 'bsky-media-filter-btn'; const HIDDEN_CLASS = 'bsky-hidden-post'; const HAS_MEDIA_CLASS = 'bsky-has-media'; const STORAGE_KEY = 'bsky-media-filter-active'; const POST_SELECTORS = { feedItem: '[data-testid^="feedItem-by-"]', postPage: '[data-testid^="postThreadItem-by-"]', searchItem: 'div[role="link"][tabindex="0"]' }; const styles = ` .${HIDDEN_CLASS} { display: none !important; } `; let isFilterActive = GM_getValue(STORAGE_KEY, false); const findVideoInPost = (post) => { return post.querySelector('video[poster^="https://video.bsky.app/"], video[src^="https://t.gifs.bsky.app/"]'); }; const findImagesInPost = (post) => { return Array.from(post.querySelectorAll('img[src^="https://cdn.bsky.app/img/feed_thumbnail/"]')); }; const hasMedia = (post) => { if (post.classList.contains(HAS_MEDIA_CLASS)) { return true; } const video = findVideoInPost(post); const images = findImagesInPost(post); const containsMedia = video || images.length > 0; if (containsMedia) { post.classList.add(HAS_MEDIA_CLASS); } return containsMedia; }; const processPost = (post) => { if (post.classList.contains(HAS_MEDIA_CLASS)) { post.classList.toggle(HIDDEN_CLASS, false); return; } const containsMedia = hasMedia(post); if (containsMedia) { post.classList.toggle(HIDDEN_CLASS, false); return; } post.classList.toggle(HIDDEN_CLASS, isFilterActive); }; const toggleFilter = () => { isFilterActive = !isFilterActive; GM_setValue(STORAGE_KEY, isFilterActive); const button = document.querySelector(`#${FILTER_BUTTON_ID}`); const text = button.querySelector('.filter-text'); text.textContent = isFilterActive ? 'All Posts' : 'Media Only'; document.querySelectorAll(Object.values(POST_SELECTORS).join(',')).forEach(post => { if (post.classList.contains(HAS_MEDIA_CLASS)) { post.classList.remove(HIDDEN_CLASS); } else { post.classList.toggle(HIDDEN_CLASS, isFilterActive); } }); }; const createFilterButton = () => { const navMenu = document.querySelector('nav[role="navigation"]'); if (!navMenu) return; const settingsLink = Array.from(navMenu.querySelectorAll('a')).find(a => a.getAttribute('aria-label') === 'Settings'); if (!settingsLink) return; const button = document.createElement('a'); button.id = FILTER_BUTTON_ID; button.className = 'css-175oi2r r-1loqt21 r-1otgn73'; button.role = 'button'; button.style.cssText = ` flex-direction: row; align-items: center; padding: 12px; border-radius: 8px; gap: 8px; outline-offset: -1px; transition-property: color, background-color; transition-timing-function: cubic-bezier(0.17, 0.73, 0.14, 1); transition-duration: 100ms; cursor: pointer; `; const iconContainer = document.createElement('div'); iconContainer.className = 'css-175oi2r'; iconContainer.style.cssText = 'align-items: center; justify-content: center; z-index: 10; width: 24px; height: 24px;'; const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute('fill', 'none'); svg.setAttribute('width', '28'); svg.setAttribute('height', '28'); svg.setAttribute('viewBox', '0 0 24 24'); svg.style.color = 'rgb(241, 243, 245)'; const path = document.createElementNS("http://www.w3.org/2000/svg", "path"); path.setAttribute('fill', 'hsl(211, 20%, 95.3%)'); path.setAttribute('d', 'M2 6a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6zm2 0v4h4V6H4zm10-2h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zm0 2v4h4V6h-4zM2 16a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-4zm2 0v4h4v-4H4zm10-2h4a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2zm0 2v4h4v-4h-4z'); svg.appendChild(path); iconContainer.appendChild(svg); const text = document.createElement('div'); text.className = 'css-146c3p1 filter-text'; text.style.cssText = ` font-size: 18.75px; letter-spacing: 0px; color: rgb(241, 243, 245); font-weight: 400; line-height: 18.75px; font-family: InterVariable, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica; `; text.textContent = isFilterActive ? 'All Posts' : 'Media Only'; button.appendChild(iconContainer); button.appendChild(text); button.addEventListener('click', toggleFilter); settingsLink.parentNode.insertBefore(button, settingsLink.nextSibling); }; const addStyles = () => { const styleSheet = document.createElement('style'); styleSheet.textContent = styles; document.head.appendChild(styleSheet); }; const initialize = () => { addStyles(); createFilterButton(); const observer = new MutationObserver((mutations) => { if (mutations.some(mutation => mutation.addedNodes.length)) { document.querySelectorAll(Object.values(POST_SELECTORS).join(',')).forEach(post => { if (!post.classList.contains(HAS_MEDIA_CLASS)) { processPost(post); } }); } if (!document.querySelector(`#${FILTER_BUTTON_ID}`)) { createFilterButton(); } }); observer.observe(document.body, { childList: true, subtree: true }); document.querySelectorAll(Object.values(POST_SELECTORS).join(',')).forEach(processPost); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址