Display mutators for popular image posting sites

This commit is contained in:
Mr. Stallion 2019-06-08 17:51:04 -05:00
parent 0107dd60a1
commit cb81610515
3 changed files with 202 additions and 11 deletions

View File

@ -1,9 +1,10 @@
<template>
<div class="image-preview-wrapper" v-if="isVisible()">
<webview class="image-preview-external" :src="isExternalUrl() ? url : null" :style="{display: isExternalUrl() ? 'flex' : 'none'}"></webview>
<!-- hiding elements instead of using 'v-if' is used here as an optimization -->
<div class="image-preview-wrapper" :style="{display: visible ? 'block' : 'none'}">
<webview webpreferences="allowRunningInsecureContent" id="image-preview-ext" ref="imagePreviewExt" class="image-preview-external" :src="externalUrl" :style="{display: externalUrlVisible ? 'flex' : 'none'}"></webview>
<div
class="image-preview-local"
:style="{backgroundImage: `url(${url})`, display: isInternalUrl() ? 'block' : 'none'}"
:style="{backgroundImage: `url(${internalUrl})`, display: internalUrlVisible ? 'block' : 'none'}"
>
</div>
</div>
@ -13,23 +14,33 @@
import {Component, Hook} from '@f-list/vue-ts';
import Vue from 'vue';
import {EventBus} from './event-bus';
import {domain } from '../bbcode/core';
import {domain} from '../bbcode/core';
import {ImagePreviewMutator} from './image-preview-mutator';
@Component
export default class ImagePreview extends Vue {
public visible: boolean = false;
public externalUrlVisible: boolean = false;
public internalUrlVisible: boolean = false;
public externalUrl: string|null = null;
public internalUrl: string|null = null;
public url: string|null = null;
public domain: string|undefined;
private jsMutator = new ImagePreviewMutator();
private interval: any = null;
private exitInterval: any = null;
private exitUrl: string|null = null;
@Hook('mounted')
onMounted() {
EventBus.$on(
'imagepreview-dismiss',
(eventData: any) => {
console.log('DIMSMISS');
this.dismiss(eventData.url);
}
);
@ -37,10 +48,39 @@
EventBus.$on(
'imagepreview-show',
(eventData: any) => {
console.log('SHOW');
this.show(eventData.url);
}
);
const webview = this.$refs.imagePreviewExt as any;
webview.addEventListener(
'dom-ready',
() => {
const url = webview.getURL();
const js = this.jsMutator.getMutatorJsForSite(url);
if (js) {
webview.executeJavaScript(js);
}
// webview.openDevTools();
/* webview.executeJavaScript(
"(() => {"
+ "$('#topbar').hide();"
+ "$('.post-header').hide();"
+ "$('#inside').css({padding: 0, margin: 0, width: '100%'});"
+ "$('#right-content').hide();"
+ "$('.post-container').css({width: '100%'});"
+ "$('.post-image img').css({width: '100%', 'min-height': 'unset'});"
+ "$('#recommendations').hide();"
+ "$('.left').css({float: 'none'});"
+ "})()"
);*/
}
);
}
@ -50,24 +90,63 @@
return;
}
this.url = null;
this.visible = false;
let due = this.visible ? 1000 : 0;
this.cancelTimer();
if (this.exitInterval) {
return;
}
this.exitUrl = this.url;
this.exitInterval = setTimeout(
() => {
this.url = null;
this.visible = false;
this.internalUrlVisible = false;
this.externalUrlVisible = false;
this.externalUrl = 'about:blank';
this.internalUrl = 'about:blank';
this.exitUrl = null;
this.exitInterval = null;
},
due
);
}
show(url: string) {
// url = 'https://imgur.com/a/2uzWx';
// url = 'http://lodash.com';
// url = 'https://rule34.xxx/index.php?page=post&s=view&id=3254983';
let due = ((url === this.exitUrl) && (this.exitInterval)) ? 0 : 100;
this.url = url;
this.domain = domain(url);
this.cancelExitTimer();
this.cancelTimer();
this.interval = setTimeout(
() => {
const isInternal = this.isInternalUrl();
this.internalUrlVisible = isInternal;
this.externalUrlVisible = !isInternal;
if (isInternal)
this.internalUrl = this.url;
else
this.externalUrl = this.url;
this.visible = true;
},
100
due
);
}
@ -81,6 +160,15 @@
}
cancelExitTimer() {
if (this.exitInterval) {
clearTimeout(this.exitInterval);
}
this.exitInterval = null;
}
isVisible() {
return this.visible;
}
@ -115,7 +203,7 @@
top: 0;
left: 0;
pointer-events: none;
background-color: black;
}
.image-preview-local {
@ -128,5 +216,6 @@
background-size: contain;
background-position: top left;
background-repeat: no-repeat;
// background-color: black;
}
</style>

View File

@ -0,0 +1,101 @@
/* tslint:disable:quotemark */
import { domain } from '../bbcode/core';
export interface ImagePreviewMutatorCollection {
[key: string]: string;
}
export class ImagePreviewMutator {
private mutators: ImagePreviewMutatorCollection = {};
constructor() {
this.init();
}
getMutatorJsForSite(url: string): string | undefined {
const urlDomain = domain(url);
if (!urlDomain)
return;
console.log('Domain is', urlDomain);
const mutatorJs = this.mutators[urlDomain];
if (!mutatorJs)
return;
return `(() => { try { ${mutatorJs} } catch (err) { console.error(err); } })()`;
}
protected add(domain: string, mutatorJs: string) {
this.mutators[domain] = mutatorJs;
}
protected init() {
this.add('e621.net', this.getBaseJsMutatorScript('#image'));
this.add('e-hentai.org', this.getBaseJsMutatorScript('#img'));
this.add('gelbooru.com', this.getBaseJsMutatorScript('#image'));
this.add('chan.sankakucomplex.com', this.getBaseJsMutatorScript('#image'));
this.add(
'gfycat.com',
`${this.getBaseJsMutatorScript('video')}
document.querySelector('video').play();
`
);
this.add(
'imgur.com',
`
const imageCount = $('.post-image-container').length;
${this.getBaseJsMutatorScript('.image.post-image img, .image.post-image video')}
if(imageCount > 1)
$('#flistWrapper').append('<div id="imageCount" style="position: absolute; bottom: 0; right: 0; background: green; border: 2px solid lightgreen; width: 5rem; height: 5rem; font-size: 2rem; font-weight: bold; color: white; border-radius: 5rem; margin: 0.75rem;"><div style="position: absolute; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%);">+' + (imageCount - 1) + '</div></div>');
`
// "$('#topbar').hide();"
// + "$('.post-header').hide();"
// + "$('#inside').css({padding: 0, margin: 0, width: '100%'});"
// + "$('#right-content').hide();"
// + "$('.post-container').css({width: '100%'});"
// + "$('.post-image img').css({width: 'auto', 'min-height': 'unset', 'max-height': '100vh'});"
// + "$('#recommendations').hide();"
// + "$('.left').css({float: 'none'});"
// + "$('body').css({overflow: 'hidden'});"
// + "const imageCount = $('.post-image-container').length;"
// + "if(imageCount > 1) {"
// + "$('body').append('<div id=\"imageCount\" style=\"position: absolute; bottom: 0; right: 0; background: green; border: 2px solid lightgreen; width: 5rem; height: 5rem; font-size: 2rem; font-weight: bold; color: white; border-radius: 5rem; margin: 0.75rem;\"><div style=\"position: absolute; top: 50%; left: 50%; transform: translateY(-50%) translateX(-50%);\">+' + (imageCount - 1) + '</div></div>');"
// + "}"
);
this.add(
'rule34.xxx',
`${this.getBaseJsMutatorScript('#image')}
const content = document.querySelector('#content');
content.remove();
`
);
}
getBaseJsMutatorScript(imageSelector: string): string {
return `const body = document.querySelector('body');
const img = document.querySelector('${imageSelector}');
const el = document.createElement('div');
el.id = 'flistWrapper';
el.style = 'width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 100000; '
+ 'background-color: black; background-size: contain; background-repeat: no-repeat; background-position: top left;';
img.remove();
el.append(img);
body.append(el);
body.style = 'padding: 0; margin: 0; overflow: hidden; width: 100%; height: 100%';
img.style = 'object-position: top left; object-fit: contain; width: 100%; height: 100%;'
`;
}
}

View File

@ -118,7 +118,8 @@ function createWindow(): Electron.BrowserWindow | undefined {
if(tabCount >= 3) return;
const lastState = windowState.getSavedWindowState();
const windowProperties: Electron.BrowserWindowConstructorOptions & {maximized: boolean} = {
...lastState, center: lastState.x === undefined, show: false
...lastState, center: lastState.x === undefined, show: false,
webPreferences: { webviewTag: true }
};
if(process.platform === 'darwin') windowProperties.titleBarStyle = 'hiddenInset';
else windowProperties.frame = false;