Cookie Manager PRO (Optimized + Import/Export)

Faster startup, optimized DOM, draggable UI, import/export, stable deletion.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

You will need to install an extension such as Tampermonkey to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         Cookie Manager PRO (Optimized + Import/Export)
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  Faster startup, optimized DOM, draggable UI, import/export, stable deletion.
// @match        *://*/*
// @run-at       document-idle
// @grant        none
// ==/UserScript==

(function(){
'use strict';

const ready = f => /complete|interactive/.test(document.readyState) ? f() : document.addEventListener("DOMContentLoaded", f,{once:true});

ready(()=> setTimeout(()=> new CookieManager().init(),150));

class CookieManager {

    constructor(){
        this.cookies=[];
        this.filtered=[];
        this.shadow=null;
        this.panel=null;
    }

    init(){
        this.loadCookies();
        this.buildUI();
    }

    loadCookies(){
        const raw=document.cookie;
        if(!raw){ this.cookies=[]; this.filtered=[]; return; }

        this.cookies = raw.split(";").map(pair=>{
            const i = pair.indexOf("=");
            const name = decodeURIComponent(pair.slice(0,i).trim());
            const value = decodeURIComponent(pair.slice(i+1));
            return {name,value,domain:location.hostname,path:"/"};
        });

        this.filtered=[...this.cookies];
    }

    buildUI(){
        if(document.getElementById("cookieManagerHost")) return;

        const host = document.createElement("div");
        host.id="cookieManagerHost";
        document.body.appendChild(host);

        const shadow = host.attachShadow({mode:"open"});
        this.shadow = shadow;

        // STYLE
        shadow.innerHTML = `
        <style>
            :host{all:initial;}
            .btn-main{
                position:fixed;top:20px;right:20px;width:60px;height:60px;
                border-radius:50%;border:none;background:#673ab7d4;color:#fff;
                cursor:grab;display:flex;align-items:center;justify-content:center;
                font-size:28px;z-index:999999;box-shadow:0 4px 15px #0003;
                user-select:none;touch-action:none;
            }
            .btn-main:active{cursor:grabbing;}
            .panel{
                position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);
                width:95vw;max-width:900px;background:#222e;color:#fff;
                border-radius:16px;padding:12px;display:none;z-index:9999999;
                font-family:sans-serif;box-sizing:border-box;
            }
            .hdr{padding:8px;background:#fff2;border-radius:10px;margin-bottom:10px;cursor:move;}
            .search{width:100%;padding:7px;margin-bottom:8px;border:1px solid #fff4;background:#fff1;color:#fff;border-radius:5px;}
            .btn{padding:6px 8px;background:#fff3;border:none;border-radius:5px;color:#fff;cursor:pointer;margin:2px;}
            .btn:hover{background:#fff5;}
            table{width:100%;border-collapse:collapse;table-layout:fixed;margin-top:10px;}
            th,td{padding:6px;border-bottom:1px solid #fff3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
            tr:hover{background:#fff1;}
        </style>
        `;

        // BUTTON
        const toggle = document.createElement("button");
        toggle.className="btn-main"; toggle.textContent="🍪";
        shadow.appendChild(toggle);

        // PANEL
        const panel = document.createElement("div");
        panel.className="panel";
        panel.innerHTML = `
            <div class="hdr" id="hdr"><h2 style="margin:0;">Cookie Manager</h2></div>
            <input class="search" id="search" placeholder="Search cookies...">
            <div>
                <button class="btn" id="add">Add</button>
                <button class="btn" id="refresh">Refresh</button>
                <button class="btn" id="export">Export</button>
                <button class="btn" id="import">Import</button>
                <button class="btn" id="delAll" style="background:#e055;">Delete All</button>
            </div>
            <table><thead><tr><th>Name</th><th>Value</th><th>Action</th></tr></thead>
            <tbody id="list"></tbody></table>
        `;
        shadow.appendChild(panel);
        this.panel=panel;

        // DRAG
        this.makeDraggable(toggle);
        this.makeDraggable(panel, panel.querySelector("#hdr"));

        // EVENTS
        toggle.onclick = (e)=> !toggle._dragged && (panel.style.display= panel.style.display==="block"?"none":"block", this.refresh());
        toggle.onmousedown = ()=> toggle._dragged=false;

        shadow.getElementById("add").onclick = ()=> this.addPrompt();
        shadow.getElementById("refresh").onclick = ()=> this.refresh();
        shadow.getElementById("delAll").onclick = ()=> this.deleteAll();
        shadow.getElementById("search").oninput = ()=> this.search();
        shadow.getElementById("export").onclick = ()=> this.exportCookies();
        shadow.getElementById("import").onclick = ()=> this.importPrompt();

        this.render();
    }

    makeDraggable(el, handle=null){
        let drag=false, moved=false, ox=0, oy=0, sx=0, sy=0;
        const h = handle||el;

        const start = e=>{
            const t = e.touches? e.touches[0]:e;
            sx=t.clientX; sy=t.clientY; moved=false; drag=true;

            const r = el.getBoundingClientRect();
            ox = t.clientX - r.left;
            oy = t.clientY - r.top;

            el.style.transform="none";
            document.addEventListener("mousemove",move);
            document.addEventListener("mouseup",end);
            document.addEventListener("touchmove",move);
            document.addEventListener("touchend",end);
        };

        const move = e=>{
            if(!drag) return;
            const t = e.touches? e.touches[0]:e;

            if(Math.abs(t.clientX-sx)>5||Math.abs(t.clientY-sy)>5) moved=true;

            const x = Math.max(0, Math.min(window.innerWidth - el.offsetWidth, t.clientX-ox));
            const y = Math.max(0, Math.min(window.innerHeight - el.offsetHeight, t.clientY-oy));
            el.style.left=x+"px"; el.style.top=y+"px"; el.style.right="auto";
        };

        const end = ()=>{
            drag=false;
            if(moved) el._dragged=true;
            document.removeEventListener("mousemove",move);
            document.removeEventListener("mouseup",end);
            document.removeEventListener("touchmove",move);
            document.removeEventListener("touchend",end);
        };

        h.addEventListener("mousedown",start);
        h.addEventListener("touchstart",start,{passive:false});
    }

    refresh(){ this.loadCookies(); this.render(); }

    search(){
        const q = this.shadow.getElementById("search").value.toLowerCase();
        this.filtered = this.cookies.filter(c=> c.name.toLowerCase().includes(q) || c.value.toLowerCase().includes(q) );
        this.render();
    }

    render(){
        const list = this.shadow.getElementById("list");
        if(!list) return;
        if(!this.filtered.length){
            list.innerHTML = `<tr><td colspan="3" style="text-align:center;">No cookies.</td></tr>`;
            return;
        }

        const rows=[];
        for(const c of this.filtered){
            const name=this.escape(c.name);
            const val=this.escape(c.value);
            rows.push(`
                <tr><td>${name}</td><td>${val.slice(0,40)}${c.value.length>40?'…':''}</td>
                <td><button class="btn edit" data-name="${name}">✎</button>
                    <button class="btn del" data-name="${name}">×</button></td></tr>
            `);
        }
        list.innerHTML=rows.join("");

        list.querySelectorAll(".del").forEach(b=>{
            const name=this.unescapeHTML(b.dataset.name);
            b.onclick=()=> this.delete(name);
        });

        list.querySelectorAll(".edit").forEach(b=>{
            const name=this.unescapeHTML(b.dataset.name);
            b.onclick=()=> this.editPrompt(name);
        });
    }

    addPrompt(){
        const n=prompt("Name:"); if(!n) return;
        const v=prompt("Value:")||"";
        document.cookie = `${encodeURIComponent(n)}=${encodeURIComponent(v)};path=/`;
        this.refresh();
    }

    editPrompt(name){
        const c = this.cookies.find(x=>x.name===name);
        const v = prompt("New value:", c?.value||"");
        if(v===null) return;
        document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(v)};path=/`;
        this.refresh();
    }

    delete(name){
        const paths=[];
        for(let p=location.pathname; p; ){
            paths.push(p);
            p=p.substring(0,p.lastIndexOf('/'))|| (p.length>1?'/':'');
        }
        if(!paths.includes('/')) paths.push('/');

        const domains=[];
        const parts=location.hostname.split('.');
        for(let i=0;i<parts.length-1;i++) domains.push('.'+parts.slice(i).join('.'));
        if(!domains.includes(location.hostname)) domains.push(location.hostname);

        const exp="Thu, 01 Jan 1970 00:00:00 GMT";

        for(const path of paths){
            for(const d of domains){
                const opts=[
                    `;domain=${d};path=${path};expires=${exp}`,
                    `;path=${path};expires=${exp}`
                ];
                for(const o of opts)
                    document.cookie = `${encodeURIComponent(name)}=;${o}`;
            }
        }
        this.refresh();
    }

    deleteAll(){
        if(!confirm(`Delete ALL ${this.cookies.length} cookies?`)) return;
        for(const c of this.cookies) this.delete(c.name);
    }

    exportCookies(){
        const blob = new Blob([JSON.stringify(this.cookies,null,2)],{type:"application/json"});
        const a=document.createElement("a");
        a.href=URL.createObjectURL(blob);
        a.download="cookies.json";
        a.click();
    }

    importPrompt(){
        const inp=document.createElement("input");
        inp.type="file"; inp.accept="application/json";
        inp.onchange = ()=>{
            const file=inp.files[0];
            if(!file) return;
            const r=new FileReader();
            r.onload = ()=>{
                try{
                    const arr=JSON.parse(r.result);
                    arr.forEach(c=>{
                        document.cookie=`${encodeURIComponent(c.name)}=${encodeURIComponent(c.value)};path=/`;
                    });
                    this.refresh();
                }catch(e){ alert("Invalid JSON."); }
            };
            r.readAsText(file);
        };
        inp.click();
    }

    escape(s){ return s.replace(/[&<>"']/g,m=>({"&":"&amp;","<":"&lt;",">":"&gt;","\"":"&quot;","'":"&#39;"}[m])); }
    unescapeHTML(s){
        return s.replace(/&amp;/g,"&").replace(/&lt;/g,"<").replace(/&gt;/g,">")
                .replace(/&quot;/g,'"').replace(/&#39;/g,"'");
    }
}

})();