Photopea adds remover

Remove the ads side bar on desktop, and the bottom ads banner on mobile. Also removes ad related popups.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Photopea adds remover
// @namespace    https://www.photopea.com/
// @version      4/13/2026
// @description  Remove the ads side bar on desktop, and the bottom ads banner on mobile. Also removes ad related popups.
// @author       pooiod7
// @match        https://*.photopea.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=photopea.com
// @run-at       document-end
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    window.originalVisualViewport = window.visualViewport;

    async function addCustomEvent() {
        // mobile devices get adds on the bottom, so push them out
        if (window.screen.width < 750 && /Mobile|Android|iPhone|iPad/i.test(navigator.userAgent)) {
            document.addEventListener('resizecanvas', () => {
                window.innerHeight = document.documentElement.clientHeight + (100);
                document.body.style.overflow = "hidden";
            });
        } else {
            document.addEventListener('resizecanvas', async () => {

                var app = document.querySelector('.flexrow.app');

                var viewportWidth = window.innerWidth;
                var docWidth =  document.documentElement.clientWidth;

                var target = Array.from(app.children).find(function(d) {
                    return d.querySelector('.alertcont');
                })

                Array.from(app.children).forEach(function(el) {
                    if(el !== target){
                        el.style.display = 'none';
                    }
                })

                var inner = app.querySelector('.flexrow .panelblock.mainblock');

                if(inner){
                    var rect = inner.getBoundingClientRect();

                    var offset = viewportWidth - rect.width;

                    var pageWidth = docWidth;
                    var adsWidth = offset;

                    var newWidth = pageWidth + adsWidth;

                    document.documentElement.style.width = newWidth + 'px';
                    document.body.style.width = newWidth + 'px';

                    Object.defineProperty(window, 'visualViewport', {
                        configurable: true,
                        value:new Proxy(originalVisualViewport, {
                            get: function(target, property){
                                if (property == 'width'){
                                    return pageWidth + adsWidth;
                                }
                                return target[property];
                            }
                        })
                    })

                    Object.defineProperty(window, 'innerWidth', {
                        configurable: true,
                        get: function(){
                            return pageWidth + adsWidth;
                        }
                    })

                    // imagine using intervals
                    if (rect.left != 0) document.body.style.marginLeft=(-rect.left) + 'px';
                    setTimeout(()=> {
                        rect = inner.getBoundingClientRect();
                        if (rect.left != 0) document.body.style.marginLeft=(-rect.left) + 'px';
                    }, 100);
                    setTimeout(()=> {
                        rect = inner.getBoundingClientRect();
                        if (rect.left != 0) document.body.style.marginLeft=(-rect.left) + 'px';
                    }, 500);
                    setTimeout(()=> {
                        rect = inner.getBoundingClientRect();
                        if (rect.left != 0) document.body.style.marginLeft=(-rect.left) + 'px';
                    }, 1000);
                }
            });
        }
    }

    document.documentElement.setAttribute('onreset', `(${addCustomEvent})()`);
    document.documentElement.dispatchEvent(new CustomEvent('reset'));
    document.documentElement.removeAttribute('onreset');

    function resize(event = {}) {
        if (!event.skip) {
            document.dispatchEvent(new CustomEvent('resizecanvas'));
            var resizeEvent = new Event('resize');
            resizeEvent.skip = true;
            window.dispatchEvent(resizeEvent);
        }
    }

    let debounce;
    window.addEventListener('resize', event => {
        clearTimeout(debounce);
        debounce = setTimeout(() => resize(event), 100);
    });

    function doresizewhenready() {
        new Promise((resolve) => {
          const observer = new MutationObserver(() => {
            const element = document.querySelector(".flexrow.app .flexrow .panelblock.mainblock");

            if (element) {
              observer.disconnect();
              resolve(element);
              window.dispatchEvent(new Event("resize"));
            }
          });

          observer.observe(document.documentElement, {
            childList: true,
            subtree: true,
          });
        });
    } doresizewhenready();
    setTimeout(doresizewhenready, 1000);
    setTimeout(doresizewhenready, 2000);

    document.querySelectorAll("div.alertpanel.tpanel").forEach(removeAlert);

    // remove the "something is changing our source code" popup
    const observer = new MutationObserver(mutations => {
      for (const m of mutations) {
        for (const node of m.addedNodes) {
          if (node.nodeType !== 1) continue;

          if (node.matches?.("div.alertpanel.tpanel")) {
              if (node.textContent.includes("changing our source")) {
                node.remove();
              }
          }

          node.querySelectorAll?.("div.alertpanel.tpanel").forEach(removeAlert);
        }
      }
    });

    observer.observe(document.body, {
      childList: true,
      subtree: true
    });

    setTimeout(() => observer.disconnect(), 10000);

    // Hide adblocker popup
    const check = () => {
        const els = Array.from(document.querySelectorAll("*"));
        for (const el of els) {
            if (el.innerText && el.innerText.includes("Are you using an ad blocker")) {
                console.log("Detected target text");

                const btn = el.parentElement?.parentElement?.querySelector("button");
                if (btn) {
                    setTimeout(() => {
                        btn.click();
                    }, 200);
                }
            }
        }
    };

    const obs = new MutationObserver(check);
    obs.observe(document.body, { childList: true, subtree: true });
    check();
})();