Instagram Image Context Menu

Custom context menu untuk Open New Tab & Save Image As di IG

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği yüklemek için Tampermonkey gibi bir uzantı yüklemeniz gerekir.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği indirebilmeniz için ayrıca Tampermonkey gibi bir eklenti kurmanız gerekmektedir.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

Bu stili yüklemek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için Stylus gibi bir uzantı kurmanız gerekir.

Bu stili yükleyebilmek için Stylus gibi bir uzantı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

Bu stili yüklemek için bir kullanıcı stili yöneticisi uzantısı kurmanız gerekir.

Bu stili yükleyebilmek için bir kullanıcı stili yöneticisi uzantısı yüklemeniz gerekir.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         Instagram Image Context Menu
// @namespace    http://tampermonkey.net/
// @version      4.0
// @description  Custom context menu untuk Open New Tab & Save Image As di IG
// @author       XIREN
// @match        *://*.instagram.com/*
// @grant        GM_download
// @grant        GM_openInTab
// ==/UserScript==

(function() {
    'use strict';

    // 1. Setup UI untuk Custom Context Menu
    const menu = document.createElement('div');
    menu.id = 'ig-custom-context-menu';
    menu.style.position = 'fixed';
    menu.style.backgroundColor = '#262626'; // Warna dark mode IG
    menu.style.border = '1px solid #363636';
    menu.style.borderRadius = '8px';
    menu.style.padding = '5px 0';
    menu.style.zIndex = '9999999';
    menu.style.display = 'none';
    menu.style.boxShadow = '0 4px 12px rgba(0,0,0,0.5)';
    menu.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';

    const createOption = (text) => {
        const opt = document.createElement('div');
        opt.innerText = text;
        opt.style.padding = '10px 20px';
        opt.style.color = '#fff';
        opt.style.cursor = 'pointer';
        opt.style.fontSize = '14px';
        opt.style.fontWeight = '500';
        opt.onmouseover = () => opt.style.backgroundColor = '#363636';
        opt.onmouseout = () => opt.style.backgroundColor = 'transparent';
        return opt;
    };

    const openBtn = createOption('🔎 Fullscreen View');
    const saveBtn = createOption('💾 Unduh Gambar JPG');

    menu.appendChild(openBtn);
    menu.appendChild(saveBtn);
    document.body.appendChild(menu);

    let currentImgUrl = '';

    // 2. Event Listener buat nangkap Klik Kanan (Context Menu)
    document.addEventListener('contextmenu', function(e) {
        let target = e.target;
        let img = null;

        // Cek target yang diklik, cari elemen <img> di level atasnya (buat nembus overlay IG)
        if (target.tagName.toLowerCase() === 'img') {
            img = target;
        } else {
            let parent = target.parentElement;
            // Naik maksimal 4 level DOM buat nyari gambar yang ditamengin
            for (let i = 0; i < 4; i++) {
                if (!parent) break;
                img = parent.querySelector('img');
                if (img) break;
                parent = parent.parentElement;
            }
        }

        // Kalau ketemu gambar dan bukan sekadar icon/foto profil kecil
        if (img && img.src && !img.src.includes('profile_pic')) {
            e.preventDefault(); // Blokir context menu bawaan browser
            currentImgUrl = img.src;

            // Atur posisi menu pas di koordinat mouse
            menu.style.left = `${e.clientX}px`;
            menu.style.top = `${e.clientY}px`;
            menu.style.display = 'block';
        } else {
            menu.style.display = 'none'; // Sembunyiin kalau klik di luar gambar
        }
    });

    // 3. Ilangin menu kalau klik kiri di sembarang tempat
    document.addEventListener('click', function(e) {
        if (e.target !== openBtn && e.target !== saveBtn) {
            menu.style.display = 'none';
        }
    });

    // 4. Aksi: Open in New Tab
    openBtn.addEventListener('click', function() {
        if (currentImgUrl) {
            GM_openInTab(currentImgUrl, { active: true });
            menu.style.display = 'none';
        }
    });

    // 5. Aksi: Save Image As (Otomatis force download)
    saveBtn.addEventListener('click', function() {
        if (currentImgUrl) {
            // Ekstrak ID/Nama file dari URL asli IG
            let rawUrl = currentImgUrl.split('?')[0];
            let fileName = rawUrl.substring(rawUrl.lastIndexOf('/') + 1) || `IG_IMG_${Date.now()}.jpg`;

            // Panggil API Tampermonkey buat maksa buka dialog download
            GM_download({
                url: currentImgUrl,
                name: fileName,
                saveAs: true // Mancing munculnya dialog "Save As..."
            });
            menu.style.display = 'none';
        }
    });

})();