Greasy Fork is available in English.
Remplacez l'icône Twitter par une image personnalisée et montrez votre style.
// ==UserScript== // @name Twitter X Icon // @namespace TwitterX // @match https://twitter.com/* // @grant none // @unwrap // @inject-into page // @version 0.1.13 // @author CY Fung // @description Change Twitter X Icon // @run-at document-start // @license MIT // @description:ja Twitterアイコンをカスタマイズして個性を表現しましょう。 // @description:zh-TW 自訂 Twitter 圖示,展現獨特風格。 // @description:zh-CN 自定义 Twitter 图标,展现独特风格。 // @description:ko 트위터 아이콘을 원하는 이미지로 변경하여 개성을 표현하세요. // @description:ru Замените иконку Twitter на свое изображение и выразите свою индивидуальность. // @description:af Vervang die Twitter-ikoon met 'n persoonlike prent om jou individualiteit uit te druk. // @description:az Twitter nişanını şəxsi şəkil ilə dəyişdirin və özünüzü ifadə edin. // @description:id Ganti ikon Twitter dengan gambar pilihan Anda dan tunjukkan gaya pribadi. // @description:ms Tukar ikon Twitter dengan imej pilihan anda dan tunjukkan gaya peribadi. // @description:bs Zamijenite Twitter ikonu sa odabranom slikom i izrazite svoj stil. // @description:ca Canvieu la icona de Twitter amb una imatge personalitzada i mostreu el vostre estil. // @description:cs Změňte ikonu Twitteru na vlastní obrázek a vyjádřete svůj osobní styl. // @description:da Skift Twitter-ikonet med et personligt billede og vis din stil. // @description:de Ersetzen Sie das Twitter-Icon durch ein persönliches Bild und zeigen Sie Ihren Stil. // @description:et Asendage Twitteri ikoon isikliku pildiga ja näidake oma stiili. // @description:es Cambia el ícono de Twitter por una imagen personalizada y muestra tu estilo. // @description:eu Aldatu Twitter ikurria zure irudi pertsonal batekin eta erakutsi zure estiloa. // @description:fr Remplacez l'icône Twitter par une image personnalisée et montrez votre style. // @description:gl Cambia o icona de Twitter cunha imaxe personalizada e mostra o teu estilo. // @description:hr Zamijenite Twitter ikonu osobnom slikom i pokažite svoj stil. // @description:zu Thayela uhlobo lweTwitter ngezithombe ozokhetha ukuze uphazamise izibonelo zakho. // @description:is Skiptu út Twitter tákn með persónulegu myndi og sýndu stílinn þinn. // @description:it Sostituisci l'icona di Twitter con un'immagine personalizzata e mostra il tuo stile. // @description:sw Badilisha ishara ya Twitter na picha yako ya kibinafsi na onyesha mtindo wako. // @description:lv Mainiet Twitter ikonu ar personīgu attēlu un parādiet savu stilu. // @description:lt Pakeiskite „Twitter“ piktogramą asmeniniu vaizdu ir parodykite savo stilų. // @description:hu Cserélje le a Twitter ikont egyéni képre, és mutassa meg stílusát. // @description:nl Vervang het Twitter-pictogram door een aangepaste afbeelding en toon uw stijl. // @description:uz Twitter niqobini o'zgartiring va shaxsiy tasvir bilan o'zingizni ifodalang. // @description:pl Zmień ikonę Twittera na wybrany obraz i pokaż swój styl. // @description:pt Substitua o ícone do Twitter por uma imagem personalizada e mostre o seu estilo. // @description:pt-BR Substitua o ícone do Twitter por uma imagem personalizada e mostre o seu estilo. // @description:ro Înlocuiți iconița Twitter cu o imagine personalizată și arătați-vă stilul. // @description:sq Zëvendësoni ikonën e Twitter me një imazh të personalizuar dhe tregoni stilin tuaj. // @description:sk Nahraďte ikonu Twitteru vlastným obrázkom a ukážte svoj štýl. // @description:sl Zamenjajte ikono Twitter z izbrano sliko in izrazite svoj slog. // @description:sr Zamenite Twitter ikonu ličnom slikom i pokažite svoj stil. // @description:fi Vaihda Twitter-kuvake omalla kuvalla ja näytä oma tyyli. // @description:sv Byt ut Twitter-ikonen med en anpassad bild och visa din stil. // @description:vi Thay đổi biểu tượng Twitter bằng hình ảnh tùy chỉnh và thể hiện p#### cách của bạn. // @description:tr Twitter simgesini istediğiniz bir görüntüyle değiştirin ve tarzınızı gösterin. // @description:be Замяніце іконку Twitter на свой малюнак і выразіце свой стыль. // @description:bg Заменете иконата на Twitter с изображение по ваш избор и покажете своя стил. // @description:ky Twitter иконкасын карата муркунун издесеңиз жана стилиңизди көрсөтүңүз. // @description:kk Twitter белгісін таңдап жатқан суретпен ауыстырып, стильіңізді көрсетіңіз. // @description:mk Заменете ја иконата на Twitter со слика по ваш избор и прикажете го вашиот стил. // @description:mn Twitter хэрэглэгчийн дүрсийг өөрчил, таны ихэнх стилийг харуулна уу. // @description:uk Замініть іконку Twitter на свій малюнок і виразіть свій стиль. // @description:el Αντικαταστήστε το εικονίδιο του Twitter με εικόνα της επιλογής σας και εμφανίστε το στυλ σας. // @description:hy Փոխարինեք Twitter-ի պատկերն անձնանշանով և ցուցադրեք ձեր ոլորտը: // @description:ur ٹوئٹر آئیکن کو آپ کی منتخب تصویر سے تبدیل کریں اور اپنی شہرت کو ظاہر کریں۔ // @description:ar قم بتغيير أيقونة Twitter إلى صورة اختيارك وعرض أسلوبك الشخصي. // @description:fa آیکن Twitter را با تصویر انتخابی تغییر داده و سبک خود را نشان دهید. // @description:ne आफ्नो छवि छान्ने गरी ट्विटर चिन्ह परिवर्तन गर्नुहोस् र आफ्नो शैली प्रदर्शन गर्नुहोस्। // @description:mr Twitter चिन्हाची प्रतिनिधित्व करण्यासाठी आपली पसंतीची चित्रे वापरा. // @description:hi ट्विटर आइकन को अपनी पसंदीदा तस्वीर से बदलें और अपनी शैली दिखाएं। // @description:as আপোনাৰ বৰ্ণনাৰ সৈতে Twitter চিনত পৰিষ্কৰণ কৰক। // @description:bn আপনার পছন্দের ছবি দিয়ে Twitter চিহ্নিকা পরিবর্তন করুন এবং আপনার শৈলী প্রদর্শন করুন। // @description:pa ਆਪਣੀ ਚੋਣ ਦੀ ਤਸਵੀਰ ਨਾਲ Twitter ਚਿੰਨਕ ਨੂੰ ਬਦਲੋ ਅਤੇ ਆਪਣੀ ਸ਼ੈਲੀ ਦਿਖਾਓ। // @description:gu આપની પસંદની ચિત્રો સાથે Twitter ચિન્હ બદલો અને તમારી શૈલી બતાવો. // @description:or ଆପଣଙ୍କ ପସନ୍ଦର ଚିତ୍ରରେ Twitter ପ୍ରତିକା ବଦଳାନ୍ତୁ ଏବଂ ଆପଣଙ୍କ ସ୍ଟାଇଲ ଦର୍ଶନ ଦିଅନ୍ତୁ। // @description:ta உங்கள் ஆர்வம் உள்ள படத்தைப் பயன்படுத்தி Twitter ஐகானை மாற்றவும் உங்கள் பார்வையைக் காட்டுங்கள். // @description:te మీ ఇష్టమైన చిత్రంతో Twitter గురించిన చిహ్నాన్ని మార్చండి మరియు మీ శైలిని చూపించండి. // @description:kn ನಿಮ್ಮ ಆಸಕ್ತಿಗೆ ಅನುಗುನವಾಗಿ Twitter ಚಿಹ್ನೆಯನ್ನು ಬದಲಾಯಿಸಿ ಮತ್ತು ನಿಮ್ಮ ಶೈಲಿಯನ್ನು ತೋರಿಸಿ. // @description:ml നിങ്ങളുടെ ഇഷ്ട ചിത്രം ഉപയോഗിച്ച് Twitter ചിഹ്നം മാറ്റുകയും നിങ്ങളുടെ ശൈലി കാണിക്കുകയും ചെയ്യുക. // @description:si ඔබේ ආදරයෙන් Twitter ලකුණ වෙනස් කිරීමේදී ඔබේ ප්රධාන වෙළඳ ආකර්ෂණය පෙන්වන්ද සඳහා ඉඩදීම. // @description:th เปลี่ยนไอคอน Twitter ด้วยภาพที่คุณเลือกและแสดงสไตล์ของคุณ // @description:lo ປ່ຽນເວັບໄຊ Twitter ໂດຍຮູບພາບທີ່ເຈົ້າເລືອກແລະສະແດງສະຖານທີ່ຂ້ອຍ // @description:my Twitter အိုင်ကွန်းရွေးကို သင်ရွေးသောပုံမျှ နှင့်သင်၏အပြင်ကိုပြပေးပါ။ // @description:ka Twitter ხატულა შეიცვალეთ თქვენი რასიელი სურათით და გამოაჩინეთ თქვენი სტილი. // @description:am የጥንቃቄዎን ምስል በ Twitter አይኮን መቀየር እና ስብስቦችዎን ተማሪዎች እንዴት ያቀየረው እንደሚፈልግ ትስጋላችሁ። // @description:km ប្តូររូបក្នុង Twitter ជារូបសម្រាប់អ្នកដែលអ្នកស្រលាញ់យ៉ាងមាននងពីរបៀបផ្សេងៗ // ==/UserScript== (() => { let mIconUrl = ''; let linkCache = new Map(); let waa = new WeakSet(); let mDotUrlMap = new Map(); const op = { radius: (canvasSize) => Math.round(canvasSize.width * 0.14), x: (canvasSize, radius) => canvasSize.width - radius * 2 + radius * 0.05, y: (canvasSize, radius) => 0 + radius * 2 - radius * 0.3, }; function addRedDotToImage(dataUriBase64, op) { return new Promise((resolve, reject) => { // Create an image element to load the data URI const image = new Image(); image.onload = () => { const { width, height } = image; const canvasSize = { width, height } const radius = op.radius(canvasSize); const dotX = op.x(canvasSize, radius); const dotY = op.y(canvasSize, radius); // Convert the canvas back to a data URI base64 string let revisedDataUriBase64; if (dataUriBase64.startsWith('data:image/svg+xml')) { // For SVG, create a new SVG element and add the circle element const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svgElement.setAttribute('width', width); svgElement.setAttribute('height', height); // Create a new image element within the SVG const svgImageElement = document.createElementNS('http://www.w3.org/2000/svg', 'image'); svgImageElement.setAttribute('width', width); svgImageElement.setAttribute('height', height); svgImageElement.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', dataUriBase64); svgElement.appendChild(svgImageElement); // Create a red dot circle element const circleElement = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); circleElement.setAttribute('cx', dotX); circleElement.setAttribute('cy', dotY); circleElement.setAttribute('r', radius); circleElement.setAttribute('fill', 'red'); svgElement.appendChild(circleElement); if (typeof btoa !== 'function') return reject(); try { // Convert the modified SVG element back to a data URI base64 string const serializer = new XMLSerializer(); const svgString = serializer.serializeToString(svgElement); revisedDataUriBase64 = 'data:image/svg+xml;base64,' + btoa(svgString); } catch (e) { } } else { const canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); ctx.drawImage(image, 0, 0); // Draw a red dot on the top right corner ctx.beginPath(); ctx.arc(dotX, dotY, radius, 0, 2 * Math.PI); ctx.fillStyle = 'red'; ctx.fill(); try { revisedDataUriBase64 = canvas.toDataURL(); } catch (e) { } } if (!revisedDataUriBase64) { return reject(); } // Convert the canvas back to a data URI base64 string // const revisedDataUriBase64 = canvas.toDataURL(); resolve(revisedDataUriBase64); }; // Set the image source to the provided data URI image.src = dataUriBase64; }); } function myLink(link, dottable) { if (waa.has(link)) return; waa.add(link); let hrefDtor = Object.getOwnPropertyDescriptor(link.constructor.prototype, 'href'); if (!hrefDtor.set || !hrefDtor.get) { return; } const getHref = () => { return hrefDtor.get.call(link) } let qq = null; async function updateURL(hh) { // console.log('old href', hh, link.getAttribute('has-dot') === 'true') let nurl = mIconUrl; if (nurl && hh) { let href = hh; let isDotted = link.getAttribute('has-dot') === 'true' if (isDotted && !nurl.startsWith('http')) { nurl = await addRedDotToImage(nurl, op); } if (hh !== nurl && nurl) { let rel = link.getAttribute('rel'); if (rel === 'icon' || rel === 'shortcut icon') { const link1 = document.querySelector('link[rel="icon"]'); const link2 = document.querySelector('link[rel="shortcut icon"]'); if(link1) link1.setAttribute('has-dot', isDotted ? 'true' : 'false'); if(link2) link2.setAttribute('has-dot', isDotted ? 'true' : 'false'); if(link1) link1.href = nurl; if(link2) link2.href = nurl; } else { link.href = nurl; } } } } function ckk() { const hh = getHref(); if (qq === hh) return; qq = hh; updateURL(hh); } function updateDotState(hh2) { if (hh2 && typeof hh2 == 'string' && hh2.startsWith('http')) { let href = hh2; let isDotted = false; if (mDotUrlMap.has(href)) isDotted = mDotUrlMap.get(href); else { if (href.endsWith('/twitter-pip.3.ico')) isDotted = true; else { let q = /\?[^?.:\/\\]+/.exec(href); q = q ? q[0] : ''; if (q) { isDotted = true; } } mDotUrlMap.set(href, isDotted); } link.setAttribute('has-dot', isDotted ? 'true' : 'false') } Promise.resolve().then(ckk) } let hh2 = null; hh2 = getHref(); updateDotState(hh2); Object.defineProperty(link, 'href', { get() { return hh2; }, set(a) { if (!a || a.startsWith('http')) { hh2 = a; updateDotState(hh2); } return hrefDtor.set.call(this, a); } }); document.addEventListener('my-twitter-icon-has-changed', (evt) => { if (!evt) return; let detail = evt.detail; if (!detail) return; let mIconUrl = detail.mIconUrl; if (!mIconUrl) return; link.href = mIconUrl; // console.log('icon changed') Promise.resolve().then(ckk); }, true); } function mIconFn(iconUrl, rel, dottable) { const selector = `link[rel~="${rel}"]`; let link = document.querySelector(selector); if (!link) { /** @type {HTMLLinkElement} */ link = document.createElement("link"); link.rel = `${rel}`; link.href = iconUrl; document.head.appendChild(link); } for (const link of document.querySelectorAll(selector)) { if (waa.has(link)) continue; myLink(link, dottable); } } function replacePageIcon(iconUrl) { mIconFn(iconUrl, 'icon', 1) } function replaceAppIcon(iconUrl) { mIconFn(iconUrl, 'apple-touch-icon', 0); } const addCSS = (href) => { let p = document.querySelector('style#j8d4f'); if (!p) { p = document.createElement('style'); p.id = 'j8d4f'; document.head.appendChild(p); } let newTextContent = ` a[href][my-custom-icon] > div::before { background-image: url("${href}"); --my-custom-icon-padding: 6px; position: absolute; left: var(--my-custom-icon-padding); right: var(--my-custom-icon-padding); top: var(--my-custom-icon-padding); bottom: var(--my-custom-icon-padding); content: ''; color: #fff; display: block; background-size: cover; background-position: center; background-repeat: no-repeat; border-radius: 46%; } a[href][my-custom-icon] svg::before { display: block; position: absolute; content: ""; left: 0; right: 0; top: 0; bottom: 0; } a[href][my-custom-icon] svg path { visibility: collapse; } `; newTextContent = newTextContent.trim(); if (p.textContent !== newTextContent) p.textContent = newTextContent; } let qdd = 0; function sendMessageIconChanged(mIconUrl) { document.dispatchEvent(new CustomEvent('my-twitter-icon-has-changed', { detail: { mIconUrl } })); } function changeIconFn() { mIconUrl = localStorage.getItem('myCustomTwitterIcon'); if (!mIconUrl) return; let tid = qdd = Date.now(); if (tid !== qdd) return; addCSS(mIconUrl); replacePageIcon(mIconUrl); replaceAppIcon(mIconUrl); sendMessageIconChanged(mIconUrl) } function onImageLoaded(dataURL) { // Save the data URL to localStorage with a specific key localStorage.setItem('myCustomTwitterIcon', dataURL); // console.log('myCustomTwitterIcon - done'); changeIconFn(); } // Function to handle the image drop event function handleDrop(event) { if (!event) return; if (!(event.target instanceof HTMLElement)) return; event.preventDefault(); // Check if the target element is the desired anchor with href="/home" const targetElement = event.target.closest('a[href][my-custom-icon]'); if (!targetElement) return; // Get the dropped file (assuming only one file is dropped) const file = event.dataTransfer.files[0]; // Check if the dropped file is an image if (!file || !file.type.startsWith('image/')) return; linkCache.clear(); // Read the image file and convert to base64 data URL let reader = new FileReader(); reader.onload = function () { Promise.resolve(reader.r###lt).then(onImageLoaded); reader = null; }; reader.readAsDataURL(file); } // Function to handle the dragover event and allow dropping function handleDragOver(event) { event.preventDefault(); } if (localStorage.getItem('myCustomTwitterIcon')) { changeIconFn(); } let observer = null; // Function to check if the target element is available and hook the drag and drop functionality function hookDragAndDrop() { const targetElement = document.querySelector('a[href="/home"][aria-label="Twitter"], a[href="/home"][aria-label="X"]'); if (targetElement && observer) { targetElement.setAttribute('my-custom-icon', ''); targetElement.addEventListener('dragover', handleDragOver); targetElement.addEventListener('drop', handleDrop); // console.log('Drag and drop functionality hooked.'); document.head.appendChild(document.createElement('style')).textContent = ` a[href="/home"][aria-label="Twitter"][my-custom-icon] *, a[href="/home"][aria-label="X"][my-custom-icon] * { pointer-events: none; } `; observer.takeRecords(); // Stop and disconnect the observer since the targetElement is found observer.disconnect(); observer = null; if (localStorage.getItem('myCustomTwitterIcon')) { changeIconFn(); } } } // Use MutationObserver to observe changes in the document observer = new MutationObserver(function (mutationsList, observer) { let p = false; for (const mutation of mutationsList) { if (mutation.type === 'childList' || mutation.type === 'subtree') { p = true; } } if (p) hookDragAndDrop(); }); // Start observing the entire document observer.observe(document, { childList: true, subtree: true }); document.addEventListener('change-my-twitter-icon', () => { changeIconFn(); }, true); })();