3 ms·
I don't install extensions that require all my browsing data, but I was tempted by Dark Reader for a moment. If anyone knows a similar solution that doesn't re
by mandmandam 5y ago
I don't install extensions that require all my browsing data, but I was tempted by Dark Reader for a moment.
If anyone knows a similar solution that doesn't require such an extreme, I'd like to hear about it..
- z2h-a6n 5y agoI use the built-in darkmode settings in qutebrowser [1], which work surprisingly well for most websites, but certainly not perfect. My impression is that the implementation is mainly in Qt, or Qt Webengine, so the same functionality may be available in other browsers with the same engine. The documentation also mentions Chromium, so perhaps equivalent settings are available there. (That said, qutebrowser is great.) Anyway, my vague understanding of what is does is that it inverts all colors on the wrong side of a user-configurable brightness threshold (e.g. backgrounds that are too bright are inverted, and text that is too dark is inverted). This can make website colorschemes quite different, but most of the websites I visit regularly are still still readable, and often still reasonably nice-looking, despite having inverted colors. The relevant part of my config file looks like this: # This requests the dark version of the website if it is available. Generally when this # works, I guess brightness-based the color inversion doesn't happen. c.colors.webpage.preferred_color_scheme = 'dark' c.colors.webpage.darkmode.algorithm = 'lightness-cielab' c.colors.webpage.darkmode.contrast = 0.0 c.colors.webpage.darkmode.enabled = True c.colors.webpage.darkmode.grayscale.all = False c.colors.webpage.darkmode.grayscale.images = 0.0 c.colors.webpage.darkmode.policy.images = 'smart' c.colors.webpage.darkmode.policy.page = 'smart' c.colors.webpage.darkmode.threshold.background = 128 c.colors.webpage.darkmode.threshold.text = 128 I haven't spent any time tweaking the threshold values, but maybe some tweaking would make it even better. [1] https://qutebrowser.org/ https://qutebrowser.org/
- mandmandam 5y agoInteresting, thank you!
- aasasd 5y agoAny extension that injects JS on the page on arbitrary sites, is marked as having access to all data—because it does. But it's the only way that interface-modifying extensions can work, if you want them kick in automatically.
- mandmandam 5y agoI kinda get your point, but I feel like there needs to be a middle ground between tweaking some colors and granting full access to my passwords. Like, there is simply no way that is not a solvable issue.
- aasasd 5y agoTo redefine styling in CSS, you need to know the structure of the HTML for a specific site or page. If you don't know it, you need JS to poke in HTML, fiddle with the styles and hope that it works out alright.
- hoosieree 5y agoIt'd be nice if there was a browser permission along the lines of "this extension adds a static asset to every page" or "this extension can _write_ but can not _read_ the page".
- aasasd 5y agoTo add static CSS styles, you need to know the structure of the HTML in advance, which the extension doesn't. And to modify the DOM—even to add styles on it—you need to traverse it, i.e. read. Plus, the whole job of the extension is probably to figure out what styles are on the page already and how they can be fiddled into the darkness.
- hoosieree 5y agoDark Reader inspired me to write a similar one for myself: https://chrome.google.com/webstore/detail/obscura/nhlkgnilpmpddehjcegjpofpiiaomnen https://chrome.google.com/webstore/detail/obscura/nhlkgnilpm... Where Dark Reader is full-featured, mine is minimal. It adds a translucent tinted div overlay on every page, with mix-blend-mode:multiply to make the text come out a little sharper. No themes or querying page elements. You can audit the code yourself if you want, it's only 58 lines of JS across 2 files: // content.js (this runs on every page): 'use strict'; const C=chrome, d=document.createElement('div'), update=(o={})=>{ if('tog' in o){d.style.height = (o.tog.newValue | o.tog)+'00%';} if('color' in o){d.style.backgroundColor = o.color.newValue || o.color;} }; d.style='mix-blend-mode:multiply; z-index:2147483647; position:fixed; width:100%; top:0; right:0; pointer-events:none;'; document.documentElement.insertBefore(d, document.documentElement.firstChild); C.storage.local.get(null, update); C.runtime.onMessage.addListener(update); C.storage.onChanged.addListener(update); // popup.js: 'use strict'; let XY=[150,40]; const C=chrome, S=C.storage.local, send=x=>C.tabs.query({active:true,currentWindow:true}, t=>C.tabs.sendMessage(t[0].id, x)), torgba=x=>`rgba(${x[0]}, ${x[1]}, ${x[2]}, ${x[3]/255})`, dropper=(x,y)=>torgba(c.getImageData(x,y,1,1).data), target=(x,y)=>{c.fillStyle = 'black'; c.beginPath(); c.arc(x,y,30,0,Math.PI*2,true); c.stroke();}, touch_xy=t=>{const r=c.canvas.getBoundingClientRect(), f=(x,ox,r)=>Math.floor(Math.min(Math.max(x,ox+1),r-1)-ox); return[f(t.pageX, r.left, r.right), f(t.pageY, r.top, r.bottom)];}, init_c=()=>{ c.clearRect(0,0,c.canvas.width,c.canvas.height); c.canvas.style.backgroundColor='white'; const g1=c.createLinearGradient(0, 0, c.canvas.width, 0), // horiz, hue g2=c.createLinearGradient(0, 0, 0, c.canvas.height); // vert, lightness g1.addColorStop(0.2,'rgba(255,120,120,0)'); g1.addColorStop(1,'rgba(255,130,70,0.99)'); g2.addColorStop(0,'rgba(0,0,0,0)'); g2.addColorStop(1,'rgba(0,0,0,0.8)'); c.fillStyle = g1; c.fillRect(0,0,c.canvas.width,c.canvas.height); c.fillStyle = g2; c.fillRect(0,0,c.canvas.width,c.canvas.height);}, xy_send=(xy)=>{init_c(); target(...xy); send({xy, color:dropper(...xy)});}, xy_save=(xy)=>{init_c(); target(...xy); S.set({xy, color:dropper(...xy)});}, c=document.getElementById('c').getContext('2d'), tog=document.getElementById('tog'); window.addEventListener('load',()=>{ S.get(null, o=>{ if('tog' in o){tog.checked = o.tog;} else {S.set({tog:tog.checked});} if('xy' in o){init_c(); target(...o.xy); XY=o.xy;} else {S.set({xy:XY});} // color's xy coords in canvas if(!('color' in o)){S.set({color:dropper(...XY)});} // hardcoded default xy location }); tog.addEventListener('change', x=>{S.set({tog:tog.checked});}); c.canvas.addEventListener('mousemove', x=>{if(x.buttons!==1){return;} xy_send([x.offsetX, x.offsetY]);}); c.canvas.addEventListener('mouseup', x=>xy_save([x.offsetX, x.offsetY])); c.canvas.addEventListener('touchmove', x=>xy_send(touch_xy(x.targetTouches[0]))); c.canvas.addEventListener('touchend', x=>xy_save(touch_xy(x.changedTouches[0]))); }); window.addEventListener('keydown', e=>{ if(e.key==='x'){tog.checked = !tog.checked; S.set({tog:tog.checked});} }); Full source: https://gitlab.com/hoosieree/chrome-extension-obscura https://gitlab.com/hoosieree/chrome-extension-obscura