// ==UserScript== // @name Autoclear ChatGPT History // @name:af Verwyder ChatGPT Geskiedenis 🕶️ // @name:am በተሻለ ChatGPT ጉዳዮ ማግኘት 🕶️ // @name:ar مسح تاريخ ChatGPT 🕶️ // @name:az ChatGPT Tarixini Təmizləyin 🕶️ // @name:be Ачысціць гісторыю ChatGPT 🕶️ // @name:bem Lekeni ChatGPT History 🕶️ // @name:bg Изчистете ChatGPT История 🕶️ // @name:bn চ্যাটজিপিটি ইতিহাস মুছে ফেলুন 🕶️ // @name:bo ChatGPT སྐད་དོན་ཚར་བཟོ། 🕶️ // @name:bs Obriši ChatGPT historiju 🕶️ // @name:ca Esborra l'historial de ChatGPT 🕶️ // @name:ceb Autoclear ChatGPT Kasaysayan 🕶️ // @name:ckb بسڕەوەی مێژووی ChatGPT 🕶️ // @name:cs Vymazat ChatGPT Historii 🕶️ // @name:cy Clirio Hanes ChatGPT 🕶️ // @name:da Ryd ChatGPT Historik 🕶️ // @name:de ChatGPT-Verlauf löschen 🕶️ // @name:dv ChatGPT ހިސްތުކުރުން ފުހެވޭނީ 🕶️ // @name:dz ChatGPT སྐད་ཆ་འབད་བཅུ་ 🕶️ // @name:el Διαγραφή Ιστορικού ChatGPT 🕶️ // @name:eo Forviŝi ChatGPT Historion 🕶️ // @name:es Borrar Historial de ChatGPT 🕶️ // @name:et Kustuta ChatGPT Ajalugu 🕶️ // @name:eu Ezabatu ChatGPT Historia 🕶️ // @name:fa پاک کردن تاریخچه ChatGPT 🕶️ // @name:fi Poista ChatGPT:n historia 🕶️ // @name:fo Strika ChatGPT Søgu 🕶️ // @name:fr Effacer l'historique de ChatGPT 🕶️ // @name:fr-CA Effacer l'historique de ChatGPT 🕶️ // @name:gd Lùghdaich Eachdraidh ChatGPT 🕶️ // @name:gl Limpar Historial de ChatGPT 🕶️ // @name:gu આપો ChatGPT ઇતિહાસ 🕶️ // @name:haw Kāpaki Kākoʻo i ka Moʻolelo o ChatGPT 🕶️ // @name:he מחק את היסטוריית ChatGPT 🕶️ // @name:hi ChatGPT इतिहास को हटाएं 🕶️ // @name:hr Izbriši ChatGPT Povijest 🕶️ // @name:ht Efase ChatGPT Istwa 🕶️ // @name:hu ChatGPT Előzmények Törlése 🕶️ // @name:hy Ջնջել ChatGPT-ի Պատմությունը 🕶️ // @name:id Hapus Riwayat ChatGPT 🕶️ // @name:is Eyða ChatGPT Saga 🕶️ // @name:it Cancella Cronologia ChatGPT 🕶️ // @name:ja ChatGPT の履歴を削除する 🕶️ // @name:jv Hapus Riwayat ChatGPT 🕶️ // @name:ka ChatGPT-ის ისტორიის გასუფთავება 🕶️ // @name:kab Sken ChatGPT Tamɣarit 🕶️ // @name:kk ChatGPT Тарихын Жою 🕶️ // @name:km លុបប្រវត្តិសាស្រ្ត ChatGPT 🕶️ // @name:kn ChatGPT ಇತಿಹಾಸವನ್ನು ಅಳಿಸಿ 🕶️ // @name:ko ChatGPT 기록 지우기 🕶️ // @name:ku Çavkaniya ChatGPTê Paqij bike 🕶️ // @name:ky ChatGPT Тарыхын Жок Кыл 🕶️ // @name:la Eximitte Historiam ChatGPT 🕶️ // @name:lb Läschen ChatGPT Geschicht 🕶️ // @name:lo ລຶບບັນດາຕິນມັກສະບັບ ChatGPT 🕶️ // @name:lt Išvalyti ChatGPT Istoriją 🕶️ // @name:lv Notīrīt ChatGPT Vēsturi 🕶️ // @name:mg Mamafa ny ChatGPT Historique 🕶️ // @name:mi Muku ChatGPT Hītori 🕶️ // @name:mk Избриши го Историјата на ChatGPT 🕶️ // @name:ml ചാറ്റ്‌ജിപിടി ചരിത്രം മായ്ക്കുക 🕶️ // @name:mn ChatGPT Түүхийг устгах 🕶️ // @name:ms Padam Sejarah ChatGPT 🕶️ // @name:mt Ħassar It-Twaħħil ChatGPT 🕶️ // @name:my ဆက်လက် ChatGPT သမိုင်းကို ဖျက်ပစ်နေပါသည် 🕶️ // @name:ne Autoclear ChatGPT इतिहास 🕶️ // @name:nl Wis ChatGPT Geschiedenis 🕶️ // @name:no Autoclear ChatGPT Historie 🕶️ // @name:ny Tikalonso ChatGPT Chisulo 🕶️ // @name:pa ਚੈਟਜੀਪੀਟੀ ਇਤਿਹਾਸ ਮਿਟਾਓ 🕶️ // @name:pap Bula Historia di ChatGPT 🕶️ // @name:pl Wyczyść Historię ChatGPT 🕶️ // @name:ps د ChatGPT د تاریخ پاکول 🕶️ // @name:pt Limpar Histórico do ChatGPT 🕶️ // @name:pt-BR Limpar Histórico do ChatGPT 🕶️ // @name:rn Kwihesha ChatGPT Byinshi 🕶️ // @name:ro Ștergeți Istoricul ChatGPT 🕶️ // @name:ru Очистить Историю ChatGPT 🕶️ // @name:rw Fata ChatGPT Itangazo 🕶️ // @name:sg Mbama ChatGPT Makumbe 🕶️ // @name:si නැවත සංවේදී ChatGPT ඉතිරිකිරීම 🕶️ // @name:sk Vymažte ChatGPT Históriu 🕶️ // @name:sl Počisti Zgodovino ChatGPT 🕶️ // @name:sm Masi ChatGPT Faʻaipoipoga 🕶️ // @name:sn Tirisa ChatGPT Chiremba 🕶️ // @name:so Ka Saar Tareenka ChatGPT 🕶️ // @name:sr Обриши историју ChatGPT-а 🕶️ // @name:sv Rensa ChatGPT Historik 🕶️ // @name:sw Futa Historia ya ChatGPT 🕶️ // @name:ta தானாகவே அழிக்க சேட்ஜிபிடி வரலாற்றை 🕶️ // @name:te ChatGPT చరిత్రను తొలగించు 🕶️ // @name:tg Тозаиши корҳои ChatGPT 🕶️ // @name:th ล้างประวัติศาสตร์ ChatGPT 🕶️ // @name:ti ምርግጋጽ ChatGPT ኣጸዓይ ፈጥር 🕶️ // @name:tk ChatGPT Tarixini Aýyr 🕶️ // @name:tn Futa ChatGPT Tlhahlobo 🕶️ // @name:to Fakatonu ChatGPT History 🕶️ // @name:tpi Kolim ChatGPT Stori 🕶️ // @name:tr ChatGPT Geçmişi Temizle 🕶️ // @name:uk Очистити Історію ChatGPT 🕶️ // @name:ur ChatGPT کی تاریخ صاف کریں 🕶️ // @name:uz ChatGPT Tarixini Tozalash 🕶️ // @name:vi Xóa Lịch Sử ChatGPT 🕶️ // @name:xh Qhipha ChatGPT Isaziso 🕶️ // @name:yi ויסמעקן טשאַטגפּט געשיכטע 🕶️ // @name:zh 自动清除 ChatGPT 历史记录 🕶️ // @name:zh-CN 自动清除 ChatGPT 历史记录 🕶️ // @name:zh-HK 自动清除 ChatGPT 历史记录 🕶️ // @name:zh-SG 自动清除 ChatGPT 历史记录 🕶️ // @name:zh-TW 自动清除 ChatGPT 历史记录 🕶️ // @name:zu Sula ChatGPT Isifundo 🕶️ // @description Auto-clears chat history when visiting chatgpt.com // @description:af Skoonmaak Chat Geskiedenis wanneer jy chatgpt.com besoek // @description:am የ chatgpt.com ጸሃይ ታክሲን በማግኘት ታከለው // @description:ar يقوم تلقائيًا بمسح سجل المحادثات عند زيارة chatgpt.com // @description:az chatgpt.com-a gedəndə avtomatik olaraq söhbət tarixini təmizləyir // @description:be Аўтаматычна ачышчае гісторыю чата пры наведванні chatgpt.com // @description:bem Chibwezache Mphindi Zochitika Pamene Kumatemba chatgpt.com // @description:bg Автоматично изчиства чат историята при посещение на chatgpt.com // @description:bn যখন chatgpt.com পরিদর্শন করা হলে অটোমেটিকভাবে চ্যাট ইতিহাস মুছে ফেলে // @description:bo དཔེར་ན་ chatgpt.com འགྲེལ་བཤད་འདི་ལུ་ སྤྱོད་ཡོད་མི་འདི་བལྟ་མི་བཟོ། // @description:bs Automatski briše istoriju chata prilikom posjete chatgpt.com // @description:ca S'elimina automàticament l'historial de xats en visitar chatgpt.com // @description:ceb Automatic gidut-ana sa kasaysayan sa chat sa pagbisita sa chatgpt.com // @description:ckb دهستکاریکردنی مێژووی گفتوگۆکان خۆکارانه بۆ سەردانی chatgpt.com // @description:cs Automaticky vymaže historii chatu při návštěvě chatgpt.com // @description:cy Mae'n glirio hanes sgwrs yn awtomatig wrth ymweld â chatgpt.com // @description:da Renser automatisk chatloggen ved besøg på chatgpt.com // @description:de Löscht den Chatverlauf automatisch beim Besuch von chatgpt.com // @description:dv chatgpt.com އެކައުންމަދުގެ ޗެކުމު ހުރިހައްދަވާނެ ޗައިންކުރޭ // @description:dz འཛུགས་མིག་འདི་ལུ་ chatgpt.com འགྲེལ་བཤད་རོགས་བསྐྱེད་ཡོད། // @description:el Αυτόματη διαγραφή ιστορικού συνομιλίας κατά την επίσκεψη στο chatgpt.com // @description:eo Memorigo de la babilado aŭtomate malaperas dum vizito ĉe chatgpt.com // @description:es Borra automáticamente el historial de chat al visitar chatgpt.com // @description:et Kustutab automaatselt vestluse ajaloo, kui külastate saiti chatgpt.com // @description:eu Berezgaitasunez ezabatzen du txataren historia chatgpt.com bisitatzen denean // @description:fa پاک کردن خودکار تاریخچه چت در هنگام بازدید از chatgpt.com // @description:fi Poistaa keskusteluhistorian automaattisesti käydessä chatgpt.comissa // @description:fo Auto-rensar spjall søguna tá tú vitjar chatgpt.com // @description:fr Efface automatiquement l'historique des discussions lors de la visite de chatgpt.com // @description:fr-CA Efface automatiquement l'historique des discussions lors de la visite de chatgpt.com // @description:gd Thoir aire bheagachaidh air eachdraidh na còmhraidh nuair a tha thu a' tadhal air chatgpt.com // @description:gl Limpa automáticamente o historial do chat ao visitar chatgpt.com // @description:gu chatgpt.com મુકે છે નાતીજે જ્ઞાનવર્ધક ચેટ નો ઇતિહાસ // @description:haw Mālama haku ʻinoʻino pāhana hoʻohānau mai ana i chatgpt.com // @description:he מנקה באופן אוטומטי את היסטוריית הצ'אט בעת ביקור ב-chatgpt.com // @description:hi chatgpt.com पर आवर्तित होने पर चैट इतिहास को स्वचालित रूप से साफ करता है // @description:hr Automatski briše povijest razgovora prilikom posjeta chatgpt.com // @description:ht Auto-efase istwa chat la lè vizite chatgpt.com // @description:hu Automatikusan törli a csevegés előzményeit a chatgpt.com látogatásakor // @description:hy Պատմությունը ինքնաշխատանքային մաքրում է chatgpt.com այցելելուն դեպի // @description:id Menghapus otomatis riwayat obrolan saat mengunjungi chatgpt.com // @description:is Hreinsar sjálfvirkt spjallshönnun þegar heimsókn er gerð á chatgpt.com // @description:it Cancella automaticamente la cronologia della chat durante la visita a chatgpt.com // @description:ja chatgpt.com を访れる际に自动的にチャット履歴を消去します // @description:jv Otomatis ngapus riwayat obrolan nalika ngunjungi chatgpt.com // @description:ka თავისითად წაშლის ჩათის ისტორიას chatgpt.com-ზე მომსახურების დროს // @description:kab Ireɣsan Ayren Tisstrir ChatGPT I yur-s achatgpt.com // @description:kk chatgpt.com-ды көруге бастап автоматты түрде чат тарихын жою // @description:km លុបសេវាកម្មប្រវត្តិការណ៍ជជែកពីព័ត៌មានមនុស្សកន្លងទៅកាន់ chatgpt.com // @description:kn chatgpt.com ಸಂದರ್ಶಿಸಿದಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಚಾಟ್ ಇತಿಹಾಸವನ್ನು ಅಳಿಸುತ್ತದೆ // @description:ko chatgpt.com 방문 시 채팅 기록을 자동으로 지웁니다 // @description:ku Çêkirina historyaya chatê di hembêzkirina chatgpt.com de // @description:ky chatgpt.com барысында түр кат жазмаларын автоматтык түрде жок этиш // @description:la Automate chat historia clearum cum chatgpt.com adibvisam // @description:lb Läscht automatesch d'Chat-Geschicht wéini een chatgpt.com besicht // @description:lo ລຶບປະວັດການສົນທະນາໃນຖ້າເຂົ້າຊົມ chatgpt.com // @description:lt Automatiškai išvalo pokalbių istoriją apsilankius chatgpt.com // @description:lv Automātiski notīra čata vēsturi, apmeklējot chatgpt.com // @description:mg Mamafa tsy ampy lalao ny tetikasa vaovao rehefa mitovy amin'ny chatgpt.com // @description:mi Auto-kōmata e whakakore i te hītori whakawhiti kōrero i te toro ki te chatgpt.com // @description:mk Автоматски брише историја на разговорот при посета на chatgpt.com // @description:ml chatgpt.com സന്ദർശിക്കുമ്പോൾ ചാറ്റ് ചരിത്രം ഓട്ടോ-പിന്തുണച്ച് അഴിച്ചുവയ്ക്കുന്നു // @description:mn chatgpt.com-оос орж ирэх үед чатын түүхийг автоматаар цэвэрлэнэ // @description:ms Membersihkan sejarah perbualan secara automatik apabila melawat chatgpt.com // @description:mt Jħassar awtomatikament il-kronoloġija tal-chat meta żżur chatgpt.com // @description:my chatgpt.com ကိုသွားဖို့အတွက် စကားဝှက်မှတ်တမ်းကို အလိုလိုရွေးချယ်ရန် အလွယ်တကူပြန်ဖွင့်ထားသည် // @description:ne chatgpt.com मा आएकोमा च्याट इतिहास स्वचालित रूपमा हटाउँछ // @description:nl Wis automatisch de chatgeschiedenis bij een bezoek aan chatgpt.com // @description:no Sletter automatisk samtalehistorikk ved besøk på chatgpt.com // @description:ny Kwatsa makina m'chipatala cha chat pamene kuwona chatgpt.com // @description:pa chatgpt.com ਦੇ ਦੌਰਾਨ ਚੈਟ ਇਤਿਹਾਸ ਆਟੋਮੈਟਿਕ ਕਲੀਅਰ ਹੋ ਜਾਂਦਾ ਹੈ // @description:pap Limpieza automático di historial di chat na bishita chatgpt.com // @description:pl Automatycznie czyści historię czatu podczas odwiedzania chatgpt.com // @description:ps خودکار تاریخچه چت پاک کول په chatgpt.com کښې // @description:pt Limpa automaticamente o histórico de bate-papo ao visitar chatgpt.com // @description:pt-BR Limpa automaticamente o histórico de bate-papo ao visitar chatgpt.com // @description:rn Guteza inkuru y'ikarita y'imibare igihe utanga chatgpt.com // @description:ro Șterge automat istoricul chat-ului la vizitarea chatgpt.com // @description:ru Автоматически очищает историю чата при посещении chatgpt.com // @description:rw Inyunganira amakuru ya chat inyuma yuko umaze guhamagara chatgpt.com // @description:sg Auto-kura kolibatalu ya misamba wakari karika kutɔbɔ chatgpt.com // @description:si chatgpt.com වෙත පැය සඳහා ස්වයංක්‍රීයතාවයින් චැට් ඉතිරිකිරීම මකා දැමුම // @description:sk Automaticky vymazáva históriu chatu pri návšteve chatgpt.com // @description:sl Samodejno izbriše zgodovino klepeta ob obisku spletnega mesta chatgpt.com // @description:sm Automa i le malologa o le sootaga i luma i le chatgpt.com // @description:sn Inongorora chat history chinayo ipapo uchi chiri kunochinja chatgpt.com // @description:so Wax ka qaad chatka markii la booqdo chatgpt.com // @description:sr Аутоматски брише историју чата при посети chatgpt.com // @description:sv Rensar automatiskt chattens historik vid besök på chatgpt.com // @description:sw Inaondoa historia ya mazungumzo moja kwa moja wakati wa kutembelea chatgpt.com // @description:ta chatgpt.com அடுத்தடுத்தப்படும் நேரத்தில் உரையாடல் வரலாறை தானியங்கே நீக்குகிறது // @description:te chatgpt.com సందర్శించినప్పుడు స్వయంచాలకంగా చాట్ చరిత్రను తొలగిస్తుంది // @description:tg Тарихи чатро худкор ҷоба кунед, ки chatgpt.com равед // @description:th ล้างประวัติการสนทนาโดยอัตโนมัติเมื่อเข้าชม chatgpt.com // @description:ti ኮምፕዩተር እየጠበቀ ጊዜ chatgpt.com የተሰኘውን ችግርን አስፈልጋል // @description:tk chatgpt.com-a ugradykda çat görnüşini awtomatiki biçimde boşaltýar // @description:tn Emucisha chat chinyakanyaka nga uwonawo chatgpt.com // @description:to 'Oku fa'a kovi 'e he ngaahi sipoti fakamatala 'i he falelotu ki he chatgpt.com // @description:tpi Autometik klia chat histeri long bisitim long chatgpt.com // @description:tr chatgpt.com'u ziyaret ettiğinizde sohbet geçmişini otomatik olarak temizler // @description:uk Автоматично очищає історію чату при відвідуванні chatgpt.com // @description:ur chatgpt.com کے دورے پر چیٹ تاریخ خودکار طور پر صاف کرتا ہے // @description:uz chatgpt.com saytini tashrif buyurganda chat tarixini avtomatik ravishda o'chiradi // @description:vi Xóa lịch sử trò chuyện tự động khi ghé thăm chatgpt.com // @description:xh Ingqalasela ihisitela le-chat uma uzithola chatgpt.com // @description:yi רומט די פֿונען דער שאַט היסטאָריע ביי בעזוך בקוקן chatgpt.com // @description:zh 访问 chatgpt.com 时自动清除聊天记录 // @description:zh-CN 访问 chatgpt.com 时自动清除聊天记录 // @description:zh-HK 访问 chatgpt.com 时自动清除聊天记录 // @description:zh-SG 访问 chatgpt.com 时自动清除聊天记录 // @description:zh-TW 访问 chatgpt.com 时自动清除聊天记录 // @description:zu Ziba itshala lokucabanga okuzoshintshwa ngokuzenzakalelayo uma ukubuka chatgpt.com // @author Adam Lui // @namespace https://github.com/adamlui // @version 2026.3.5 // @license MIT // @icon data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22180%22%20height=%22180%22%20fill=%22none%22%3E%3Cstyle%3E:root%7B--primary-fill:%23000;--secondary-fill:%23fff;%7D@media%20(prefers-color-scheme:dark)%7B:root%7B--primary-fill:%23fff;--secondary-fill:%23000;%7D%7D%3C/style%3E%3Cg%20clip-path=%22url(%23a)%22%3E%3Crect%20width=%22180%22%20height=%22180%22%20fill=%22var(--primary-fill)%22%20rx=%2290%22/%3E%3Cg%20clip-path=%22url(%23b)%22%3E%3Cpath%20fill=%22var(--secondary-fill)%22%20d=%22M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z%22/%3E%3C/g%3E%3C/g%3E%3Cdefs%3E%3CclipPath%20id=%22a%22%3E%3Cpath%20d=%22M0%200h180v180H0z%22/%3E%3C/clipPath%3E%3CclipPath%20id=%22b%22%3E%3Cpath%20d=%22M29.487%2029.964h121.035v119.954H29.487z%22/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E // @icon64 data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22180%22%20height=%22180%22%20fill=%22none%22%3E%3Cstyle%3E:root%7B--primary-fill:%23000;--secondary-fill:%23fff;%7D@media%20(prefers-color-scheme:dark)%7B:root%7B--primary-fill:%23fff;--secondary-fill:%23000;%7D%7D%3C/style%3E%3Cg%20clip-path=%22url(%23a)%22%3E%3Crect%20width=%22180%22%20height=%22180%22%20fill=%22var(--primary-fill)%22%20rx=%2290%22/%3E%3Cg%20clip-path=%22url(%23b)%22%3E%3Cpath%20fill=%22var(--secondary-fill)%22%20d=%22M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z%22/%3E%3C/g%3E%3C/g%3E%3Cdefs%3E%3CclipPath%20id=%22a%22%3E%3Cpath%20d=%22M0%200h180v180H0z%22/%3E%3C/clipPath%3E%3CclipPath%20id=%22b%22%3E%3Cpath%20d=%22M29.487%2029.964h121.035v119.954H29.487z%22/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E // @compatible chrome // @compatible edge // @compatible firefox // @compatible opera // @compatible brave // @compatible vivaldi // @compatible librewolf // @compatible ghost // @compatible qq // @match *://chatgpt.com/* // @connect cdn.jsdelivr.net // @connect gm.autoclearchatgpt.com // @connect raw.githubusercontent.com // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.9.0/dist/chatgpt.min.js#sha256-XyrLEk81vg4/zgOeYDWtugRQKJvrWEefACp0EfwMVHE= // @require https://cdn.jsdelivr.net/gh/adamlui/userscripts@ff2baba/assets/js/lib/css.js/dist/css.min.js#sha256-zf9s8C0cZ/i+gnaTIUxa0+RpDYpsJVlyuV5L2q4KUdA= // @require https://cdn.jsdelivr.net/gh/adamlui/userscripts@ff2baba/assets/js/lib/dom.js/dist/dom.min.js#sha256-nTc2by3ZAz6AR7B8fOqjloJNETvjAepe15t2qlghMDo= // @resource rpgCSS https://cdn.jsdelivr.net/gh/adamlui/ai-web-extensions@727feff/assets/styles/rising-particles/dist/gray.min.css#sha256-48sEWzNUGUOP04ur52G5VOfGZPSnZQfrF3szUr4VaRs= // @resource rpwCSS https://cdn.jsdelivr.net/gh/adamlui/ai-web-extensions@727feff/assets/styles/rising-particles/dist/white.min.css#sha256-6xBXczm7yM1MZ/v0o1KVFfJGehHk47KJjq8oTktH4KE= // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_getResourceText // @grant GM_xmlhttpRequest // @grant GM.xmlHttpRequest // @noframes // @downloadURL https://gm.autoclearchatgpt.com // @updateURL https://gm.autoclearchatgpt.com // @homepageURL https://autoclearchatgpt.com // @supportURL https://support.autoclearchatgpt.com // @contributionURL https://ko-fi.com/adamlui // ==/UserScript== // Documentation: https://docs.autoclearchatgpt.com // NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org // © 2023–2026 KudoAI & contributors under the MIT license. (async () => { 'use strict' // Init DATA window.env = { browser: { language: chatgpt.getUserLanguage(), isMobile: chatgpt.browser.isMobile() }, scriptManager: { name: (() => { try { return GM_info.scriptHandler } catch (err) { return 'unknown' }})(), version: (() => { try { return GM_info.version } catch (err) { return 'unknown' }})() }, ui: { scheme: getScheme() } } Object.assign(env.browser, { get isCompact() { return innerWidth <= 480 }}) env.scriptManager.supportsTooltips = env.scriptManager.name == 'Tampermonkey' && parseInt(env.scriptManager.version.split('.')[0]) >= 5 window.xhr = typeof GM != 'undefined' && GM.xmlHttpRequest || GM_xmlhttpRequest window.app = { version: GM_info.script.version, chatgptjsVer: /chatgpt\.js@([\d.]+)/.exec(GM_info.scriptMetaStr)[1], commitHashes: { app: '5367fdd' } // for cached .json + navicon in toggles.sidebar.insert() } app.urls = { resourceHost: `https://cdn.jsdelivr.net/gh/adamlui/autoclear-chatgpt-history@${app.commitHashes.app}` } const remoteData = { app: await new Promise(resolve => xhr({ method: 'GET', url: `${app.urls.resourceHost}/assets/data/app.json`, onload: ({ responseText }) => resolve(JSON.parse(responseText)) })), msgs: await new Promise(resolve => { const msgBaseURL = `${app.urls.resourceHost}/greasemonkey/_locales`, locale = `${ env.browser.language ? env.browser.language.replace('-', '_') : 'en' }` let msgURL = `${msgBaseURL}/${locale}/messages.json`, msgFetchesTried = 0 function fetchMsgs() { xhr({ method: 'GET', url: msgURL, onload: handleMsgs })} function handleMsgs(resp) { try { // to return localized messages.json const msgs = JSON.parse(resp.responseText), flatMsgs = {} for (const key in msgs) // remove need to ref nested keys if (typeof msgs[key] == 'object' && 'message' in msgs[key]) flatMsgs[key] = msgs[key].message resolve(flatMsgs) } catch (err) { // if bad response msgFetchesTried++ ; if (msgFetchesTried == 3) return resolve({}) // try original/region-stripped/EN only msgURL = env.browser.language.includes('-') && msgFetchesTried == 1 ? // if regional lang on 1st try... msgURL.replace(/(_locales\/[^_]+)_[^_]+(\/)/, '$1$2') // ...strip region before retrying : `${msgBaseURL}/en/messages.json` // else use default English messages fetchMsgs() } } fetchMsgs() }) } Object.assign(app, { ...remoteData.app, urls: { ...app.urls, ...remoteData.app.urls }, msgs: remoteData.msgs }) // Init SETTINGS app.config ??= {} const settings = { controls: { // displays top-to-bottom in toolbar menu autoclear: { type: 'toggle', defaultVal: false, label: app.msgs.menuLabel_autoclear, helptip: app.msgs.appDesc }, toggleHidden: { type: 'toggle', defaultVal: false, label: app.msgs.menuLabel_toggleVis, helptip: app.msgs.helptip_toggleVis }, notifDisabled: { type: 'toggle', defaultVal: false, label: app.msgs.menuLabel_modeNotifs, helptip: app.msgs.helptip_modeNotifs }, clearNow: { type: 'action', symbol: '🧹', label: app.msgs.menuLabel_clearNow, helptip: app.msgs.helptip_clearNow } }, load(...keys) { keys.flat().forEach(key => app.config[key] = processKey(key, GM_getValue(`${app.configKeyPrefix}_${key}`, undefined))) function processKey(key, val) { const ctrl = settings.controls?.[key] if (val != undefined && ( // validate stored val (ctrl?.type == 'toggle' && typeof val != 'boolean') || (ctrl?.type == 'slider' && isNaN(parseFloat(val))) )) val = undefined return val ?? (ctrl?.defaultVal ?? (ctrl?.type == 'slider' ? 100 : false)) } }, save(key, val) { GM_setValue(`${app.configKeyPrefix}_${key}`, val) ; app.config[key] = val }, typeIsEnabled(key) { // for menu labels + notifs to return ON/OFF const reInvertSuffixes = /disabled|hidden/i return reInvertSuffixes.test(key) // flag in control key name && !reInvertSuffixes.test(this.controls[key]?.label || '') // but not in label msg key name ? !app.config[key] : app.config[key] // so invert since flag reps opposite type state, else don't } } settings.load(Object.keys(settings.controls)) // Define MENU functions const toolbarMenu = { state: { symbols: ['❌', '✔️'], separator: env.scriptManager.name == 'Tampermonkey' ? ' — ' : ': ', words: [app.msgs.state_off.toUpperCase(), app.msgs.state_on.toUpperCase()] }, refresh() { if (typeof GM_unregisterMenuCommand == 'undefined') return this.entryIDs.forEach(id => GM_unregisterMenuCommand(id)) this.register() }, register() { // Add toggles this.entryIDs = Object.keys(settings.controls).map(key => { const entryData = settings.controls[key] const menuLabel = `${ entryData.symbol || this.state.symbols[+settings.typeIsEnabled(key)] } ${entryData.label} ${ entryData.type == 'toggle' ? this.state.separator + this.state.words[+settings.typeIsEnabled(key)] : entryData.type == 'slider' ? ': ' + app.config[key] + entryData.labelSuffix || '' : entryData.status ? ` — ${entryData.status}` : '' }` return GM_registerMenuCommand(menuLabel, () => { if (entryData.type == 'toggle') { settings.save(key, !app.config[key]) ; syncConfigToUI({ updatedKey: key }) notify(`${entryData.label}: ${this.state.words[+settings.typeIsEnabled(key)]}`) } else // Clear Now action clearChatsAndGoHome() }, env.scriptManager.supportsTooltips ? { title: entryData.helptip || ' ' } : undefined) }) // Add About entry this.entryIDs.push(GM_registerMenuCommand( `💡 ${app.msgs.menuLabel_about} ${app.msgs.appName}`, () => modals.open('about'), env.scriptManager.supportsTooltips ? { title: ' ' } : undefined )) } } window.updateCheck = () => { xhr({ method: 'GET', url: `${app.urls.update.gm}?t=${Date.now()}`, headers: { 'Cache-Control': 'no-cache' }, onload: ({ responseText }) => { // Compare versions, alert if update found app.latestVer = /@version +(.*)/.exec(responseText)?.[1] if (app.latestVer) for (let i = 0 ; i < 4 ; i++) { // loop thru subver's const currentSubVer = parseInt(app.version.split('.')[i], 10) || 0, latestSubVer = parseInt(app.latestVer.split('.')[i], 10) || 0 if (currentSubVer > latestSubVer) break // out of comparison since not outdated else if (latestSubVer > currentSubVer) // if outdated return modals.open('update', 'available') } // Alert to no update found, nav back to About modals.open('update', 'unavailable') ; modals.open('about') }}) } // Define FEEDBACK functions function notify(msg, pos = '', notifDuration = '', shadow = '') { if (app.config.notifDisabled && !msg.includes(app.msgs.menuLabel_modeNotifs)) return // Strip state word to append colored one later const foundState = toolbarMenu.state.words.find(word => msg.includes(word)) if (foundState) msg = msg.replace(foundState, '') // Show notification chatgpt.notify(`${app.symbol} ${msg}`, pos, notifDuration, shadow || env.ui.scheme == 'light') const notif = document.querySelector('.chatgpt-notif:last-child') // Append styled state word if (foundState) { const stateStyles = { on: { light: 'color: #5cef48 ; text-shadow: rgba(255,250,169,0.38) 2px 1px 5px', dark: 'color: #5cef48 ; text-shadow: rgb(55,255,0) 3px 0 10px' }, off: { light: 'color: #ef4848 ; text-shadow: rgba(255,169,225,0.44) 2px 1px 5px', dark: 'color: #ef4848 ; text-shadow: rgba(255, 116, 116, 0.87) 3px 0 9px' } } const styledStateSpan = dom.create.elem('span') styledStateSpan.style.cssText = stateStyles[ foundState == toolbarMenu.state.words[0] ? 'off' : 'on'][env.ui.scheme] styledStateSpan.append(foundState) ; notif.append(styledStateSpan) } } // Define MODAL functions const modals = { stack: [], // of types of undismissed modals class: `${app.slug}-modal`, about() { // Show modal const labelStyles = 'text-transform: uppercase ; font-size: 17px ; font-weight: bold ;' + `color: ${ env.ui.scheme == 'dark' ? 'white' : '#494141' }` const aboutModal = modals.alert( `${app.symbol} ${app.msgs.appName}`, // title `🧠 ${app.msgs.about_author}: ` + `${app.msgs.appAuthor} ` + `${app.msgs.about_and} ` + `${app.msgs.about_contributors}\n` + `🏷️ ${app.msgs.about_version}: ` + `${app.version}\n` + `📜 ${app.msgs.about_openSourceCode}: ` + `` + app.urls.github + '\n' + `🚀 ${app.msgs.about_latestChanges}: ` + `` + `${app.urls.github}/commits\n` + `⚡ ${app.msgs.about_poweredBy}: ` + `chatgpt.js` + ` v${app.chatgptjsVer}`, [ // buttons function checkForUpdates() { updateCheck() }, function getSupport(){}, function discuss(){}, function moreAIextensions(){} ], '', 747 // set width ) // Format text aboutModal.querySelector('h2').style.cssText = ` text-align: center ; font-size: 51px ; line-height: 46px ; padding: 15px 0` aboutModal.querySelector('p').style.cssText = ` text-align: center ; overflow-wrap: anywhere ; margin: ${ env.browser.isCompact ? '6px 0 -16px' : '3px 0 29px' }` // Hack buttons aboutModal.querySelectorAll('button').forEach(btn => { btn.style.cssText = 'height: 58px ; min-width: 136px ; text-align: center' // Replace link buttons w/ clones that don't dismiss modal if (/support|discuss|extensions/i.test(btn.textContent)) { btn.replaceWith(btn = btn.cloneNode(true)) btn.onclick = () => modals.safeWinOpen(app.urls[ btn.textContent.includes(app.msgs.btnLabel_getSupport) ? 'support' : btn.textContent.includes(app.msgs.btnLabel_discuss) ? 'discuss' : 'relatedExtensions' ]) } // Prepend emoji + localize labels if (/updates/i.test(btn.textContent)) btn.textContent = `🚀 ${app.msgs.btnLabel_checkForUpdates}` else if (/support/i.test(btn.textContent)) btn.textContent = `🧠 ${app.msgs.btnLabel_getSupport}` else if (/discuss/i.test(btn.textContent)) btn.textContent = `⭐ ${app.msgs.btnLabel_discuss}` else if (/extensions/i.test(btn.textContent)) btn.textContent = `🤖 ${app.msgs.btnLabel_moreAIextensions}` // Hide Dismiss button else btn.style.display = 'none' // hide Dismiss button }) return aboutModal }, alert(title = '', msg = '', btns = '', checkbox = '', width = '') { // generic one from chatgpt.alert() const alertID = chatgpt.alert(title, msg, btns, checkbox, width), alert = document.getElementById(alertID).firstChild this.init(alert) // add classes + rising particles bg return alert }, init(modal) { this.stylize() modal.classList.add(this.class) ; modal.parentNode.classList.add(`${this.class}-bg`) css.addRisingParticles(modal) }, observeRemoval(modal, modalType, modalSubType) { // to maintain stack for proper nav const modalBG = modal.parentNode new MutationObserver(([mutation], obs) => { mutation.removedNodes.forEach(removedNode => { if (removedNode == modalBG) { if (modals.stack[0].includes(modalSubType || modalType)) { // new modal not launched so nav back modals.stack.shift() // remove this modal type from stack 1st const prevModalType = modals.stack[0] if (prevModalType) { // open it modals.stack.shift() // remove type from stack since re-added on open modals.open(prevModalType) } } obs.disconnect() }}) }).observe(modalBG.parentNode, { childList: true, subtree: true }) }, open(modalType, modalSubType) { const modal = modalSubType ? this[modalType][modalSubType]() : this[modalType]() // show modal if (!modal) return // since no div returned this.stack.unshift(modalSubType ? `${modalType}_${modalSubType}` : modalType) // add to stack this.init(modal) // add classes + rising particles bg this.observeRemoval(modal, modalType, modalSubType) // to maintain stack for proper nav }, safeWinOpen(url) { open(url, '_blank', 'noopener') }, // to prevent backdoor vulnerabilities stylize() { const { scheme } = env.ui if (!this.styles?.isConnected) document.head.append(this.styles ||= dom.create.style()) this.styles.textContent = ` .${this.class} { /* modals */ user-select: none ; -webkit-user-select: none ; -moz-user-select: none ; -ms-user-select: none ; font-family: -apple-system, system-ui, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif ; padding: 20px 25px 24px 25px !important ; font-size: 20px ; color: ${ scheme == 'dark' ? 'white' : 'black' } !important ; background-image: linear-gradient(180deg, ${ scheme == 'dark' ? '#99a8a6 -200px, black 200px' : '#b6ebff -296px, white 171px' }) } .${this.class} [class*=modal-close-btn] { position: absolute !important ; float: right ; top: 14px !important ; right: 16px !important ; cursor: pointer ; width: 33px ; height: 33px ; border-radius: 20px } .${this.class} [class*=modal-close-btn] svg { height: 10px } .${this.class} [class*=modal-close-btn] path { ${ scheme == 'dark' ? 'stroke: white ; fill: white' : 'stroke: #9f9f9f ; fill: #9f9f9f' }} ${ scheme == 'dark' ? // invert dark mode hover paths `.${this.class} [class*=modal-close-btn]:hover path { stroke: black ; fill: black }` : '' } .${this.class} [class*=modal-close-btn]:hover { background-color: #f2f2f2 } /* hover underlay */ .${this.class} [class*=modal-close-btn] svg { margin: 11.5px } /* center SVG for hover underlay */ .${this.class} a { color: #${ scheme == 'dark' ? '00cfff' : '1e9ebb' } !important } .${this.class} h2 { font-weight: bold } .${this.class} button { --btn-transition: transform 0.1s ease-in-out, box-shadow 0.1s ease-in-out ; font-size: 14px ; text-transform: uppercase ; /* shrink/uppercase labels */ border-radius: 0 !important ; /* square borders */ transition: var(--btn-transition) ; /* smoothen hover fx */ -webkit-transition: var(--btn-transition) ; -moz-transition: var(--btn-transition) ; -o-transition: var(--btn-transition) ; -ms-transition: var(--btn-transition) ; cursor: pointer !important ; /* add finger cursor */ border: 1px solid ${ scheme == 'dark' ? 'white' : 'black' } !important ; padding: 8px !important ; min-width: 102px /* resize */ } .${this.class} button:not([class*=primary]) { background: none } .${this.class} button:hover { ${ scheme == 'light' ? // reduce intensity of light scheme hover glow '--btn-shadow: 2px 1px 43px #00cfff70 ;' : '' } color: inherit !important ; /* remove color hack */ background-color: rgb(${ scheme == 'light' ? '192 223 227 / 5%' : '43 156 171 / 43%' }) } ${ env.browser.isMobile ? '' : `.${this.class} .modal-buttons { margin-left: -13px !important }` } .about-em { color: ${ scheme == 'dark' ? 'white' : 'green' } !important }` }, update: { width: 377, available() { // Show modal const updateAvailModal = modals.alert(`🚀 ${app.msgs.alert_updateAvail}!`, // title `${app.msgs.alert_newerVer} ${app.msgs.appName} ` // msg + `(v${app.latestVer}) ${app.msgs.alert_isAvail}! ` + '${app.msgs.link_viewChanges}`, function update() { // button modals.safeWinOpen(`${app.urls.update.gm}?t=${Date.now()}`) }, '', modals.update.width ) // Localize button labels if needed if (!env.browser.language.startsWith('en')) { const updateBtns = updateAvailModal.querySelectorAll('button') updateBtns[1].textContent = app.msgs.btnLabel_update updateBtns[0].textContent = app.msgs.btnLabel_dismiss } return updateAvailModal }, unavailable() { return modals.alert(`${app.msgs.alert_upToDate}!`, // title `${app.msgs.appName} (v${app.version}) ${app.msgs.alert_isUpToDate}!`, // msg '', '', modals.update.width ) } } } // Define UI functions function clearChatsAndGoHome() { chatgpt.clearChats() // Hide history from DOM since chatgpt.clearChats() works back-end only (front-end updates on reload otherwise) new Promise(resolve => setTimeout(resolve, 1000)).then(() => { document.querySelectorAll('div#history > a').forEach(chatEntry => chatEntry.style.display = 'none') if (!clearChatsAndGoHome.historyObserver) { // monitor sidebar to restore temporal headings on new chats clearChatsAndGoHome.historyObserver = new MutationObserver(mutations => mutations.forEach(mutation => { if (mutation.type == 'childList') mutation.addedNodes.forEach(node => { if (node.tagName == 'LI') node.closest('ol').previousElementSibling.style.display = 'inherit' })})) clearChatsAndGoHome.historyObserver.observe( document.querySelector('nav'), { childList: true, subtree: true }) } }) if (location.pathname != '/') chatgpt.startNewChat() // return home from potential ghost chat notify(app.msgs.notif_chatsCleared, 'bottom-right', 2.5) } function getScheme() { return /\b(light|dark)\b/.exec(document.documentElement.className)?.[1] || ( window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' ) } function syncConfigToUI({ updatedKey } = {}) { if (updatedKey == 'autoclear' && app.config.autoclear) clearChatsAndGoHome() if (/autoclear|toggleHidden/.test(updatedKey)) toggles.sidebar.update.state() toolbarMenu.refresh() // prefixes/suffixes } const toggles = { sidebar: { class: `${app.slug}-sidebar-toggle`, create() { // Init toggle elems this.div = dom.create.elem('div', { class: this.class }) this.navicon = dom.create.elem('img') this.toggleLabel = dom.create.elem('label') this.switchSpan = dom.create.elem('span') this.knobSpan = dom.create.elem('span') // Assemble elems into parent div this.switchSpan.append(this.knobSpan) this.div.append(this.navicon, this.toggleLabel, this.switchSpan) // Stylize elems this.stylize() // create/append stylesheet // Update scheme/state this.update.scheme() ; this.update.state() // Add hover/click listeners this.div.onmouseover = this.div.onmouseout = ({ type }) => // trigger OpenAI hover overlay this.div.style.setProperty('--item-background-color', `var(--sidebar-surface-${ type == 'mouseover' ? 'secondary' : 'primary' })`) this.div.onclick = () => { settings.save('autoclear', !app.config.autoclear) ; syncConfigToUI({ updatedKey: 'autoclear' }) notify(`${app.msgs.mode_autoclear}: ${toolbarMenu.state.words[+app.config.autoclear]}`) } }, insert() { // requires lib/.min.js const sidebar = document.querySelector(chatgpt.selectors.sidebar) if (!sidebar || this.status?.startsWith('insert') || document.querySelector(`.${this.class}`)) return this.status = 'inserting' ; if (!this.div) this.create() const sidebarHeader = sidebar.querySelector('div#sidebar-header') if (sidebarHeader) { sidebarHeader.after(this.div) ; this.status = 'inserted' } else { this.status = 'waitingForSidebar' dom.get.loadedElem('div#sidebar-header').then(header => { header.after(this.div) ; this.stylize() ; this.status = 'inserted' }).catch((err) => { this.status = 'failed' ; console.error('toggles.sidebar.insert()', err) }) } }, stylize() { // requires lib/.js + env const firstLink = chatgpt.getNewChatLink() if (firstLink && !this.classesBorrowed) { // borrow/assign classes from sidebar elems const firstIcon = firstLink.querySelector('div:first-child'), firstLabel = firstLink.querySelector('div:nth-child(2)') this.div.classList.add(...firstLink.classList, ...(firstLabel?.classList || [])) this.div.querySelector('img')?.classList.add(...(firstIcon?.classList || [])) this.classesBorrowed = true } this.styles ||= dom.create.style( `:root { /* vars */ --switch-enabled-bg-color: #ad68ff ; --switch-disabled-bg-color: #ccc ; --switch-enabled-box-shadow: 1px 2px 8px #d8a9ff ; --switch-enabled-hover-box-shadow: 0 1px 10px #9b5ad1 ; --knob-box-shadow: rgba(0,0,0,0.3) 0 1px 2px 0 ; --knob-box-shadow-dark: rgba(0,0,0,0.3) 0 1px 2px 0, rgba(0,0,0,0.15) 0 3px 6px 2px }` // Element styles + `.${this.class} { /* parent div */ width: auto ; max-height: 37px ; padding: 0 5px ; user-select: none ; cursor: pointer } .${this.class} > img { /* navicon */ width: 1.25rem ; height: 1.25rem ; margin-left: 2px ; margin-right: 4px } .${this.class} > span { /* switch span */ position: relative ; width: 30px ; height: 15px ; border-radius: 28px ; background-color: var(--switch-disabled-bg-color) ; bottom: ${ firstLink ? '0.5px' : '-0.15em' } ; transition: 0.4s ; -webkit-transition: 0.4s ; -moz-transition: 0.4s ; -o-transition: 0.4s ; -ms-transition: 0.4s } .${this.class} > span.enabled { /* switch on */ background-color: var(--switch-enabled-bg-color) ; box-shadow: var(--switch-enabled-box-shadow) ; -webkit-box-shadow: var(--switch-enabled-box-shadow) ; -moz-box-shadow: var(--switch-enabled-box-shadow) ; transition: 0.15s ; -webkit-transition: 0.15s ; -moz-transition: 0.15s ; -o-transition: 0.15s ; -ms-transition: 0.15s } .${this.class}:hover > span.enabled { /* switch on when hover on parent div */ box-shadow: var(--switch-enabled-hover-box-shadow) ; -webkit-box-shadow: var(--switch-enabled-hover-box-shadow) ; -moz-box-shadow: var(--switch-enabled-hover-box-shadow) } .${this.class} > span.disabled { /* switch off */ background-color: var(--switch-disabled-bg-color) ; box-shadow: none } .${this.class} > span > span { /* knob span */ position: absolute ; width: 12px ; height: 12px ; content: "" ; border-radius: 28px ; background-color: white ; left: 2px ; bottom: 1.25px ; box-shadow: var(--knob-box-shadow) ; -webkit-box-shadow: var(--knob-box-shadow) ; -moz-box-shadow: var(--knob-box-shadow) ; transition: 0.4s ; -webkit-transition: 0.4s ; -moz-transition: 0.4s ; -o-transition: 0.4s ; -ms-transition: 0.4s } .${this.class} > label { /* toggle label */ cursor: pointer ; overflow: hidden ; text-overflow: ellipsis ; white-space: nowrap ; color: black ; padding: 0 3px ; flex-grow: 1 ; font-size: var(--text-sm) }` // Dark scheme mods + `.${this.class}.dark > span.enabled { /* switch on */ background-color: var(--switch-enabled-bg-color) ; box-shadow: var(--switch-enabled-hover-box-shadow) ; /* use hover style instead */ -webkit-box-shadow: var(--switch-enabled-hover-box-shadow) ; -moz-box-shadow: var(--switch-enabled-hover-box-shadow) } .${this.class}.dark:hover > span.enabled { /* switch on when hover on parent div */ box-shadow: var(--switch-enabled-box-shadow) ; /* use regular style instead */ -webkit-box-shadow: var(--switch-enabled-box-shadow) ; -moz-box-shadow: var(--switch-enabled-box-shadow) } .${this.class}.dark > span > span { /* knob span */ box-shadow: var(--knob-box-shadow-dark) ; /* make 3D-er */ -webkit-box-shadow: var(--knob-box-shadow-dark) ; -moz-box-shadow: var(--knob-box-shadow-dark) } .${this.class}.dark > label { color: white } /* toggle label */` ) if (!this.styles.isConnected) document.head.append(this.styles) }, update: { navicon({ preload } = {}) { const baseURL = `${ app.urls.resourceHost.replace(/@\w+/, '@4a52452')}/assets/images/icons/incognito` const schemeMap = { light: 'black', dark: 'white' }, fileName = 'icon32.png' if (preload) Object.keys(schemeMap).forEach(scheme => new Image().src = `${baseURL}/${schemeMap[scheme]}/${fileName}`) else toggles.sidebar.navicon.src = `${baseURL}/${schemeMap[env.ui.scheme]}/${fileName}` }, scheme() { // to match UI scheme toggles.sidebar.div.classList.remove('dark', 'light') toggles.sidebar.div.classList.add(env.ui.scheme) toggles.sidebar.update.navicon() }, state() { if (!toggles.sidebar.div) return // since toggle never created = sidebar missing toggles.sidebar.div.style.display = app.config.toggleHidden ? 'none' : 'flex' const isOn = app.config.autoclear toggles.sidebar.toggleLabel.textContent = `${app.msgs.mode_autoclear} ` + app.msgs[`state_${ isOn ? 'enabled' : 'disabled' }`] requestAnimationFrame(() => { toggles.sidebar.switchSpan.className = isOn ? 'enabled' : 'disabled' toggles.sidebar.knobSpan.style.transform = `translateX(${ isOn ? 13 : 0 }px)` }) // to trigger 1st transition fx } } } } // Run MAIN routine toolbarMenu.register() // create browser toolbar menu toggles.sidebar.update.navicon({ preload: true }) // preload sidebar NAVICON variants await Promise.race([chatgpt.isLoaded(), new Promise(resolve => setTimeout(resolve, 5000))]) // initial UI loaded ;['rpg', 'rpw'].forEach(cssType => // add Rising Particles styles document.head.append(dom.create.style(GM_getResourceText(`${cssType}CSS`)))) toggles.sidebar.insert() // AUTO-CLEAR on first visit if enabled if (app.config.autoclear) clearChatsAndGoHome() // Monitor NODE CHANGES to maintain sidebar toggle visibility new MutationObserver(() => { if (!app.config.toggleHidden && document.querySelector(chatgpt.selectors.sidebar) && !document.querySelector(`.${toggles.sidebar.class}`) && toggles.sidebar.status != 'inserting' ) { toggles.sidebar.status = 'missing' ; toggles.sidebar.insert() } }).observe(document.body, { attributes: true, subtree: true }) // Monitor SCHEME PREF changes to update sidebar toggle + modal colors new MutationObserver(handleSchemePrefChange).observe( // for site scheme pref changes document.documentElement, { attributes: true, attributeFilter: ['class'] }) window.matchMedia('(prefers-color-scheme: dark)').addEventListener( // for browser/system scheme pref changes 'change', () => requestAnimationFrame(handleSchemePrefChange)) function handleSchemePrefChange() { const displayedScheme = getScheme() if (env.ui.scheme != displayedScheme) { env.ui.scheme = displayedScheme ; toggles.sidebar.update.scheme() ; modals.stylize() } } })()