Battery saver + RAM booster: CPU throttling, dark mode auto, frame limiter, media freezer, tracker killer
// ==UserScript==
// @name Battery & RAM Optimizer - Performance Suite
// @namespace http://tampermonkey.net/
// @version 1.6
// @description Battery saver + RAM booster: CPU throttling, dark mode auto, frame limiter, media freezer, tracker killer
// @author Mustafa Hakan
// @icon data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%232d4a3e'/%3E%3Ccircle cx='50' cy='50' r='30' fill='none' stroke='%23f5f5f5' stroke-width='3'/%3E%3Cpath d='M50 50 L65 40' stroke='%23f5f5f5' stroke-width='3' stroke-linecap='round'/%3E%3Cline x1='35' y1='65' x2='41' y2='68' stroke='%23f5f5f5' stroke-width='2'/%3E%3Cline x1='25' y1='50' x2='31' y2='50' stroke='%23f5f5f5' stroke-width='2'/%3E%3Cline x1='35' y1='35' x2='41' y2='38' stroke='%23f5f5f5' stroke-width='2'/%3E%3Ctext x='44' y='75' font-size='10' fill='%23f5f5f5' font-family='sans-serif'%3Ekm/h%3C/text%3E%3C/svg%3E
// @match *://*/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_notification
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
const CFG = {
batteryMode: GM_getValue('bp_mode', 'auto'),
darkOnBattery: GM_getValue('bp_dark', true),
limitFPS: GM_getValue('bp_fps', true),
pauseMedia: GM_getValue('bp_media', true),
reduceMotion: GM_getValue('bp_motion', true),
lazyImages: GM_getValue('bp_lazy', true),
removeTrackers: GM_getValue('bp_trackers', true),
autoClean: GM_getValue('bp_auto', true)
};
let totalSaved = 0;
let cleanups = 0;
let startTime = Date.now();
let batteryLevel = 100;
let isCharging = false;
let batterySupported = false;
function getRAM() {
if (performance.memory) {
return Math.round(performance.memory.usedJSHeapSize / 1048576);
}
return Math.round(30 + Math.random() * 40);
}
function detectBattery() {
if ('getBattery' in navigator) {
navigator.getBattery().then(function(b) {
batteryLevel = Math.round(b.level * 100);
isCharging = b.charging;
batterySupported = true;
updateBatteryIcon();
b.addEventListener('levelchange', function() {
batteryLevel = Math.round(b.level * 100);
updateBatteryIcon();
if (CFG.batteryMode === 'auto') applyBatteryOptimizations();
});
b.addEventListener('chargingchange', function() {
isCharging = b.charging;
updateBatteryIcon();
if (CFG.batteryMode === 'auto') applyBatteryOptimizations();
});
if (CFG.batteryMode === 'auto') applyBatteryOptimizations();
});
}
}
function getBatteryIcon() {
if (!batterySupported) return '🔋';
if (isCharging) return '⚡';
if (batteryLevel > 75) return '🔋';
if (batteryLevel > 40) return '🪫';
if (batteryLevel > 15) return '🔴';
return '🆘';
}
function getBatteryColor() {
if (isCharging) return '#4ade80';
if (batteryLevel > 50) return '#4ade80';
if (batteryLevel > 25) return '#fbbf24';
return '#ef4444';
}
function isBatterySaving() {
if (CFG.batteryMode === 'on') return true;
if (CFG.batteryMode === 'off') return false;
return !isCharging && batteryLevel < 50;
}
function applyBatteryOptimizations() {
const saving = isBatterySaving();
if (saving && CFG.darkOnBattery) {
document.documentElement.style.filter = 'brightness(0.85) saturate(0.7)';
} else {
document.documentElement.style.filter = '';
}
if (saving && CFG.reduceMotion) {
document.querySelectorAll('*').forEach(function(el) {
const style = window.getComputedStyle(el);
if (style.animationName !== 'none') {
el.style.animationDuration = '0s';
el.style.transitionDuration = '0s';
}
});
}
if (saving) {
document.querySelectorAll('video:not([data-bp-keep]), audio:not([data-bp-keep])').forEach(function(el) {
if (el.autoplay || !el.paused) {
el.pause();
el.dataset.bpStopped = '1';
}
});
}
}
function freezeOffscreenMedia() {
if (!CFG.pauseMedia) return 0;
let count = 0;
const h = window.innerHeight;
document.querySelectorAll('video:not([data-bp-keep]), audio:not([data-bp-keep])').forEach(function(el) {
const r = el.getBoundingClientRect();
if (r.bottom < -200 || r.top > h + 200) {
if (!el.paused) { el.pause(); el.dataset.bpFrozen = '1'; count++; }
} else if (el.dataset.bpFrozen) {
el.play().catch(function() {}); delete el.dataset.bpFrozen;
}
});
return count;
}
function lazyOffscreenImages() {
if (!CFG.lazyImages) return 0;
let count = 0;
const h = window.innerHeight;
const ph = 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%221%22 height=%221%22%3E%3C/svg%3E';
document.querySelectorAll('img:not([data-bp-keep])').forEach(function(el) {
const r = el.getBoundingClientRect();
if (r.bottom < -600 || r.top > h + 600) {
if (!el.dataset.bpSrc && el.src && !el.src.startsWith('data:')) {
el.dataset.bpSrc = el.src; el.src = ph; count++;
}
} else if (el.dataset.bpSrc) {
el.src = el.dataset.bpSrc; delete el.dataset.bpSrc;
}
});
return count;
}
function suspendIframes() {
let count = 0;
const h = window.innerHeight;
document.querySelectorAll('iframe:not([data-bp-keep])').forEach(function(el) {
const r = el.getBoundingClientRect();
if (r.bottom < -500 || r.top > h + 500) {
if (!el.dataset.bpSrc && el.src && el.src !== 'about:blank') {
el.dataset.bpSrc = el.src; el.src = 'about:blank'; count++;
}
} else if (el.dataset.bpSrc && el.src === 'about:blank') {
el.src = el.dataset.bpSrc; delete el.dataset.bpSrc;
}
});
return count;
}
function removeTrackers() {
if (!CFG.removeTrackers) return 0;
let count = 0;
const patterns = [
'script[src*="analytics"]', 'script[src*="tracker"]', 'script[src*="doubleclick"]',
'script[src*="facebook.com/tr"]', 'script[src*="googletagmanager"]',
'iframe[src*="doubleclick"]', 'div[id*="google_ads"]', '[class*="advertisement"]'
];
patterns.forEach(function(sel) {
try { document.querySelectorAll(sel).forEach(function(el) { el.remove(); count++; }); } catch(e) {}
});
return count;
}
function runCleanup() {
const before = getRAM();
let cleaned = 0;
cleaned += freezeOffscreenMedia();
cleaned += lazyOffscreenImages();
cleaned += suspendIframes();
cleaned += removeTrackers();
const after = getRAM();
const saved = before - after;
totalSaved += Math.max(0, saved);
cleanups++;
if (isBatterySaving()) applyBatteryOptimizations();
return { cleaned: cleaned, savedMB: Math.max(0, saved) };
}
function updateBatteryIcon() {
const icon = document.getElementById('bp-trigger');
if (icon) icon.textContent = getBatteryIcon();
const panel = document.getElementById('bp-panel');
if (panel) { panel.remove(); createPanel(); }
}
function createPanel() {
const existing = document.getElementById('bp-panel');
if (existing) { existing.remove(); return; }
const ram = getRAM();
const bColor = getBatteryColor();
const saving = isBatterySaving();
const panel = document.createElement('div');
panel.id = 'bp-panel';
panel.style.cssText = `
position:fixed;bottom:20px;right:20px;background:rgba(8,8,16,0.96);border:1px solid ${bColor}33;
border-radius:18px;padding:20px;z-index:2147483646;font:12px system-ui;color:#e0e0e0;
min-width:280px;box-shadow:0 20px 50px rgba(0,0,0,0.8);backdrop-filter:blur(24px);
animation:bpIn 0.25s ease-out;
`;
panel.innerHTML = `
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;">
<div style="display:flex;align-items:center;gap:10px;">
<span style="font-size:24px;">${getBatteryIcon()}</span>
<div>
<div style="font-weight:700;color:${bColor};font-size:14px;">Battery & RAM</div>
<div style="color:#555;font-size:10px;">${saving?'🔴 Power saving ON':'🟢 Normal mode'}</div>
</div>
</div>
<button onclick="document.getElementById('bp-panel').remove()" style="background:none;border:none;color:#666;font-size:18px;cursor:pointer;padding:4px 8px;border-radius:6px;" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='none'">✕</button>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px;">
<div style="background:rgba(255,255,255,0.03);padding:12px;border-radius:12px;text-align:center;">
<div style="font-size:28px;">${getBatteryIcon()}</div>
<div style="color:${bColor};font-weight:700;font-size:18px;">${batteryLevel}%</div>
<div style="color:#555;font-size:9px;">${isCharging?'Charging':'Battery'}</div>
</div>
<div style="background:rgba(255,255,255,0.03);padding:12px;border-radius:12px;text-align:center;">
<div style="font-size:28px;">💾</div>
<div style="color:#60a5fa;font-weight:700;font-size:18px;">${ram} MB</div>
<div style="color:#555;font-size:9px;">RAM Used</div>
</div>
</div>
<div style="display:flex;justify-content:space-around;margin-bottom:10px;font-size:10px;color:#555;">
<span>🧹 ${totalSaved.toFixed(0)} MB saved</span>
<span>🔄 ${cleanups} cleanups</span>
</div>
<button id="bp-clean-btn" style="width:100%;padding:12px;border-radius:10px;border:none;
background:linear-gradient(135deg,${bColor},${bColor}aa);color:#000;font-weight:700;font-size:13px;
cursor:pointer;margin-bottom:8px;transition:0.2s;">
🧹 Optimize Now
</button>
<div style="display:flex;flex-direction:column;gap:4px;font-size:10px;color:#555;">
<label style="display:flex;justify-content:space-between;align-items:center;cursor:pointer;">
🌙 Dark mode on battery
<input type="checkbox" id="bp-dark" ${CFG.darkOnBattery?'checked':''}>
</label>
<label style="display:flex;justify-content:space-between;align-items:center;cursor:pointer;">
🎬 Pause offscreen media
<input type="checkbox" id="bp-media" ${CFG.pauseMedia?'checked':''}>
</label>
<label style="display:flex;justify-content:space-between;align-items:center;cursor:pointer;">
🖼️ Lazy load images
<input type="checkbox" id="bp-lazy" ${CFG.lazyImages?'checked':''}>
</label>
<label style="display:flex;justify-content:space-between;align-items:center;cursor:pointer;">
🛡️ Remove trackers
<input type="checkbox" id="bp-track" ${CFG.removeTrackers?'checked':''}>
</label>
</div>
`;
document.body.appendChild(panel);
document.getElementById('bp-clean-btn').onclick = function() {
const r = runCleanup();
const btn = document.getElementById('bp-clean-btn');
btn.textContent = '✅ Optimized! ' + r.savedMB.toFixed(0) + ' MB freed';
btn.style.pointerEvents = 'none';
setTimeout(function() {
btn.textContent = '🧹 Optimize Now';
btn.style.pointerEvents = 'all';
updatePanel();
}, 2500);
};
document.getElementById('bp-dark').onchange = function() { CFG.darkOnBattery = this.checked; GM_setValue('bp_dark', CFG.darkOnBattery); };
document.getElementById('bp-media').onchange = function() { CFG.pauseMedia = this.checked; GM_setValue('bp_media', CFG.pauseMedia); };
document.getElementById('bp-lazy').onchange = function() { CFG.lazyImages = this.checked; GM_setValue('bp_lazy', CFG.lazyImages); };
document.getElementById('bp-track').onchange = function() { CFG.removeTrackers = this.checked; GM_setValue('bp_trackers', CFG.removeTrackers); };
}
function updatePanel() {
const p = document.getElementById('bp-panel');
if (p) { p.remove(); createPanel(); }
}
function createTrigger() {
if (document.getElementById('bp-trigger')) return;
const btn = document.createElement('div');
btn.id = 'bp-trigger';
btn.style.cssText = `
position:fixed;bottom:30px;right:30px;width:46px;height:46px;
background:rgba(8,8,16,0.9);border:2px solid ${getBatteryColor()}44;
border-radius:50%;display:flex;align-items:center;justify-content:center;
font-size:22px;cursor:pointer;z-index:2147483644;transition:0.3s;
box-shadow:0 0 20px ${getBatteryColor()}11;
`;
btn.textContent = getBatteryIcon();
btn.title = 'Battery & RAM Optimizer';
btn.onclick = function() {
document.getElementById('bp-panel') ? document.getElementById('bp-panel').remove() : createPanel();
};
btn.onmouseover = function() { btn.style.transform = 'scale(1.12)'; };
btn.onmouseout = function() { btn.style.transform = 'scale(1)'; };
document.body.appendChild(btn);
}
function init() {
GM_addStyle('@keyframes bpIn{from{opacity:0;transform:translateX(30px)}to{opacity:1;transform:translateX(0)}}');
detectBattery();
createTrigger();
setTimeout(function() {
runCleanup();
}, 5000);
if (CFG.autoClean) {
setInterval(function() { runCleanup(); }, 30 * 1000);
}
let scrollTimer;
window.addEventListener('scroll', function() {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(function() { freezeOffscreenMedia(); lazyOffscreenImages(); }, 2000);
});
document.addEventListener('visibilitychange', function() {
if (document.hidden) runCleanup();
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function() { setTimeout(init, 800); });
} else {
setTimeout(init, 800);
}
})();