- // ==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 phong 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.result).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);
-
- })();