Move playback setting extras to ExtrasMenu; New mod: Filterworks / Anime4K
This commit is contained in:
parent
e67a71ab3e
commit
d42172174a
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
/priv/
|
||||
/.vscode/
|
||||
update.sh
|
||||
mods_dev.json
|
||||
|
@ -185,7 +185,7 @@ export default JadefinIntegrity("Jadefin", import.meta.url, () => window["Jadefi
|
||||
];
|
||||
|
||||
await this._loadingMods;
|
||||
await this.initMods();
|
||||
await this._initLoadingMods();
|
||||
|
||||
await Promise.all(initing);
|
||||
|
||||
@ -389,7 +389,7 @@ export default JadefinIntegrity("Jadefin", import.meta.url, () => window["Jadefi
|
||||
|
||||
}
|
||||
|
||||
async initMods(list) {
|
||||
async _initLoadingMods() {
|
||||
await Promise.all(this._loadingMods_all.map(async (mod) => {
|
||||
this.log.i(`Initializing mod ${mod.name}`);
|
||||
|
||||
@ -400,7 +400,6 @@ export default JadefinIntegrity("Jadefin", import.meta.url, () => window["Jadefi
|
||||
this.log.dir(e);
|
||||
}
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
})());
|
||||
|
@ -20,7 +20,7 @@ class JadefinMod {
|
||||
this.modUrl = url;
|
||||
}
|
||||
|
||||
initStyle() {
|
||||
async initStyle() {
|
||||
document.head.appendChild(rd$()`<link rel="stylesheet" type="text/css" href=${this.getUrl(".css")}>`);
|
||||
}
|
||||
|
||||
|
4
init.js
4
init.js
@ -42,7 +42,7 @@ jadefinInitExtremelyEarly();
|
||||
console.log("[jadefin-init] loadJadefin");
|
||||
|
||||
const loader = document.createElement("script");
|
||||
this.document.head.appendChild(loader);
|
||||
document.head.appendChild(loader);
|
||||
|
||||
window["_JadefinLoaded"] = () => resolve(true);
|
||||
window["_JadefinErrored"] = (e) => reject(e);
|
||||
@ -95,7 +95,7 @@ jadefinInitExtremelyEarly();
|
||||
}
|
||||
|
||||
const loader = document.createElement("script");
|
||||
this.document.head.appendChild(loader);
|
||||
document.head.appendChild(loader);
|
||||
|
||||
loader.addEventListener("load", () => resolve(true));
|
||||
loader.addEventListener("error", (e) => reject(e));
|
||||
|
@ -15,6 +15,8 @@ export default JadefinIntegrity("ExtrasMenu", import.meta.url, () => new (class
|
||||
IN_DRAWER = 2;
|
||||
IN_LIBRARY = 4;
|
||||
IN_MOVIE = 8;
|
||||
IN_PLAYBACKSETTINGS = 16;
|
||||
IN_PLAYBACKSETTINGS_ADVANCED = 32;
|
||||
|
||||
_popupId = 0;
|
||||
_items = [];
|
||||
@ -83,23 +85,25 @@ export default JadefinIntegrity("ExtrasMenu", import.meta.url, () => new (class
|
||||
async init(name, url) {
|
||||
await super.init(name, url);
|
||||
|
||||
await JadefinUtils.waitUntil(() => document.querySelector(".headerRight"));
|
||||
|
||||
this.initStyle();
|
||||
this.initHeaderExtras();
|
||||
this.initDrawerExtras();
|
||||
await Promise.all([
|
||||
this.initStyle(),
|
||||
this.initHeaderExtras(),
|
||||
this.initDrawerExtras(),
|
||||
this.initHookActionSheetShow()
|
||||
]);
|
||||
|
||||
this.log.i("Ready");
|
||||
}
|
||||
|
||||
initHeaderExtras() {
|
||||
async initHeaderExtras() {
|
||||
await JadefinUtils.waitUntil(() => document.querySelector(".headerRight"));
|
||||
document.querySelector(".headerRight")?.appendChild(this.headerExtrasEl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} [silentWarn]
|
||||
*/
|
||||
initDrawerExtras(silentWarn) {
|
||||
async initDrawerExtras(silentWarn) {
|
||||
const drawer = document.querySelector(".mainDrawer > .mainDrawer-scrollContainer");
|
||||
const userMenuOptions = drawer?.querySelector("& > .userMenuOptions");
|
||||
|
||||
@ -129,51 +133,100 @@ export default JadefinIntegrity("ExtrasMenu", import.meta.url, () => new (class
|
||||
this.update();
|
||||
}
|
||||
|
||||
async initHookActionSheetShow() {
|
||||
await JadefinUtils.waitUntil(() => JadefinModules.actionSheet);
|
||||
|
||||
const orig = this._actionSheetShowOrig = JadefinModules.actionSheet.show.bind(JadefinModules.actionSheet);
|
||||
JadefinModules.actionSheet.show = (options) => {
|
||||
const optionsOrig = Object.assign({}, options, {
|
||||
items: options.items.slice()
|
||||
});
|
||||
|
||||
// Options menu during playback
|
||||
if (!options.dialogClass &&
|
||||
options.items.length >= 6 &&
|
||||
options.items[0].id == "aspectratio" &&
|
||||
options.items[1].id == "playbackrate" &&
|
||||
options.items[2].id == "quality" &&
|
||||
options.items[3].id == "repeatmode" &&
|
||||
options.items[4].id == "suboffset" &&
|
||||
options.items[5].id == "stats" &&
|
||||
true
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const currentVisibility = this.IN_PLAYBACKSETTINGS;
|
||||
const items = [
|
||||
{id: "extrasMenuPopup-all", name: "Advanced..."},
|
||||
{divider: true},
|
||||
...this._items.map((item, i) => Object.assign({
|
||||
id: i
|
||||
}, item)).filter(item => this.checkVisibility(currentVisibility, item)),
|
||||
...optionsOrig.items.slice(4)
|
||||
];
|
||||
|
||||
const p = this._actionSheetShow({
|
||||
positionTo: optionsOrig.positionTo,
|
||||
currentVisibility,
|
||||
items
|
||||
});
|
||||
|
||||
p.then(id => {
|
||||
if (id == "extrasMenuPopup-all") {
|
||||
const currentVisibility = this.IN_PLAYBACKSETTINGS_ADVANCED;
|
||||
const items = [
|
||||
...optionsOrig.items.slice(0, 4),
|
||||
...this._items.map((item, i) => Object.assign({
|
||||
id: i
|
||||
}, item)).filter(item => this.checkVisibility(currentVisibility, item)),
|
||||
{divider: true},
|
||||
{id: "extrasMenuPopup-back", name: "Back..."}
|
||||
];
|
||||
|
||||
const p = this._actionSheetShow(Object.assign({}, optionsOrig, {
|
||||
currentVisibility,
|
||||
items
|
||||
}));
|
||||
|
||||
p.then(id => {
|
||||
if (id == "extrasMenuPopup-back") {
|
||||
JadefinModules.actionSheet.show(optionsOrig).then(resolve).catch(reject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id && this._items[id]) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(id);
|
||||
}).catch(reject);
|
||||
return;
|
||||
}
|
||||
|
||||
if (id && this._items[id]) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(id);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
return orig(options);
|
||||
};
|
||||
}
|
||||
|
||||
openExtrasPopup() {
|
||||
const currentVisibility = JadefinUtils.isInMovie ? this.IN_MOVIE : this.IN_LIBRARY;
|
||||
|
||||
const dialogClass = `extrasMenuPopup-${this._popupId++}`;
|
||||
|
||||
const items = this._items.map((item, i) => Object.assign({
|
||||
id: i
|
||||
}, item)).filter(item => this.checkVisibility(currentVisibility, item));
|
||||
|
||||
const p = JadefinModules.actionSheet.show({
|
||||
dialogClass,
|
||||
this._actionSheetShow({
|
||||
title: "Extras",
|
||||
positionTo: this.headerExtrasEl,
|
||||
items
|
||||
});
|
||||
|
||||
p.then(id => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._items[id]?.cb?.();
|
||||
});
|
||||
|
||||
const dialogEl = document.querySelector(`.${dialogClass}`);
|
||||
if (!dialogEl) {
|
||||
this.log.e(`Couldn't find .${dialogClass}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.log.i(`Opened .${dialogClass}`);
|
||||
this.log.dir(dialogEl);
|
||||
|
||||
dialogEl.classList.add("extrasMenuPopup");
|
||||
|
||||
const dialogButtons = dialogEl.querySelectorAll("button");
|
||||
|
||||
for (let i in items) {
|
||||
items[i].cbEl?.(dialogButtons[i], currentVisibility, true);
|
||||
}
|
||||
|
||||
p.finally(() => {
|
||||
for (let i in items) {
|
||||
items[i].cbEl?.(dialogButtons[i], currentVisibility, false);
|
||||
}
|
||||
currentVisibility,
|
||||
items: this._items.map((item, i) => Object.assign({
|
||||
id: i
|
||||
}, item)).filter(item => this.checkVisibility(currentVisibility, item))
|
||||
});
|
||||
}
|
||||
|
||||
@ -219,4 +272,45 @@ export default JadefinIntegrity("ExtrasMenu", import.meta.url, () => new (class
|
||||
return (item.in & current) == current;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ positionTo: any; currentVisibility: any; items: any; title?: string; dialogClass?: any; }} options
|
||||
*/
|
||||
_actionSheetShow(options) {
|
||||
options.dialogClass = `extrasMenuPopup-${this._popupId++}`;
|
||||
|
||||
const p = JadefinModules.actionSheet.show(options);
|
||||
|
||||
p.then(id => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._items[id]?.cb?.(options.positionTo);
|
||||
});
|
||||
|
||||
const dialogEl = document.querySelector(`.${options.dialogClass}`);
|
||||
if (!dialogEl) {
|
||||
this.log.e(`Couldn't find .${options.dialogClass}`);
|
||||
return p;
|
||||
}
|
||||
|
||||
this.log.i(`Opened .${options.dialogClass}`);
|
||||
this.log.dir(dialogEl);
|
||||
|
||||
dialogEl.classList.add("extrasMenuPopup");
|
||||
|
||||
const dialogButtons = dialogEl.querySelectorAll("button");
|
||||
|
||||
for (let i in options.items) {
|
||||
options.items[i].cbEl?.(dialogButtons[i], options.currentVisibility, true);
|
||||
}
|
||||
|
||||
p.finally(() => {
|
||||
for (let i in options.items) {
|
||||
options.items[i].cbEl?.(dialogButtons[i], options.currentVisibility, false);
|
||||
}
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
})());
|
||||
|
@ -72,7 +72,7 @@ export default JadefinIntegrity("InputEater", import.meta.url, () => new (class
|
||||
|
||||
await JadefinUtils.waitUntil(() => JadefinModules.syncPlay);
|
||||
|
||||
this.initStyle();
|
||||
await this.initStyle();
|
||||
this.initHookSyncPlayEnabled();
|
||||
this.initHookSyncPlayDisabled();
|
||||
this.initHookMediaSessionHandlers();
|
||||
|
@ -121,8 +121,8 @@ export default JadefinIntegrity("Transcript", import.meta.url, () => new (class
|
||||
async init(name, url) {
|
||||
await super.init(name, url);
|
||||
|
||||
this.initStyle();
|
||||
const initing = [
|
||||
this.initStyle(),
|
||||
this.initHookSetTrackForDisplay(),
|
||||
this.initHookFetchSubtitles(),
|
||||
this.initHookSetOffset(),
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import JadefinIntegrity from '../JadefinIntegrity.js';
|
||||
|
||||
import Jadefin from "../Jadefin.js";
|
||||
import JadefinMod from "../JadefinMod.js";
|
||||
import JadefinModules from "../JadefinModules.js";
|
||||
import JadefinUtils from "../JadefinUtils.js";
|
||||
@ -62,9 +63,34 @@ export default JadefinIntegrity("VolumeBoost", import.meta.url, () => new (class
|
||||
async init(name, url) {
|
||||
await super.init(name, url);
|
||||
|
||||
await JadefinUtils.waitUntil(() => JadefinModules.actionSheet);
|
||||
const ExtrasMenu = /** @type {import("./ExtrasMenu.js").default} */ (Jadefin.getMod("ExtrasMenu"));
|
||||
|
||||
this.initHookActionSheetShow();
|
||||
ExtrasMenu.items.push({
|
||||
name: "Volume Boost",
|
||||
in: ExtrasMenu.IN_CUSTOM,
|
||||
inCustom: (current, item) => {
|
||||
item.asideText = `${this.currentGain}x`;
|
||||
|
||||
return (current & (ExtrasMenu.IN_PLAYBACKSETTINGS)) == current;
|
||||
},
|
||||
cb: async (positionTo) => {
|
||||
JadefinModules.actionSheet.show({
|
||||
positionTo,
|
||||
items: [
|
||||
{id: "1", name: "1x", selected: this.currentGain == 1},
|
||||
{id: "2", name: "2x", selected: this.currentGain == 2},
|
||||
{id: "3", name: "3x", selected: this.currentGain == 3},
|
||||
{id: "4", name: "4x", selected: this.currentGain == 4},
|
||||
]
|
||||
}).then(id => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentGain = parseInt(id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("viewshow", () => {
|
||||
if (JadefinUtils.routePathIsVideo) {
|
||||
@ -83,86 +109,6 @@ export default JadefinIntegrity("VolumeBoost", import.meta.url, () => new (class
|
||||
this.log.i("Ready");
|
||||
}
|
||||
|
||||
initHookActionSheetShow() {
|
||||
const orig = this._actionSheetShowOrig = JadefinModules.actionSheet.show.bind(JadefinModules.actionSheet);
|
||||
JadefinModules.actionSheet.show = (options) => {
|
||||
const optionsOrig = Object.assign({}, options, {
|
||||
items: options.items.slice()
|
||||
});
|
||||
|
||||
this.log.v("actionSheet.show(...)");
|
||||
this.log.dir(options);
|
||||
|
||||
// Options menu during playback
|
||||
if (options.items.length >= 6 &&
|
||||
options.items[0].id == "aspectratio" &&
|
||||
options.items[1].id == "playbackrate" &&
|
||||
options.items[2].id == "quality" &&
|
||||
options.items[3].id == "repeatmode" &&
|
||||
options.items[4].id == "suboffset" &&
|
||||
options.items[5].id == "stats" &&
|
||||
true
|
||||
) {
|
||||
options.items.splice(4, 0, {id: "custom-volumeboost", name: "Volume Boost", asideText: `${this.currentGain}x`});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
JadefinModules.actionSheet.show({
|
||||
positionTo: options.positionTo,
|
||||
items: [
|
||||
{id: "all", name: "Advanced..."},
|
||||
{divider: true},
|
||||
...options.items.slice(4),
|
||||
]
|
||||
}).then(id => {
|
||||
if (id == "all") {
|
||||
orig(Object.assign({}, options, {
|
||||
items: [
|
||||
...options.items.slice(0, 4),
|
||||
{divider: true},
|
||||
{id: "back", name: "Back..."},
|
||||
]
|
||||
})).then(id => {
|
||||
if (id == "back") {
|
||||
JadefinModules.actionSheet.show(optionsOrig).then(resolve).catch(reject);
|
||||
} else {
|
||||
resolve(id);
|
||||
}
|
||||
}).catch(reject);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (id == "custom-volumeboost") {
|
||||
reject();
|
||||
|
||||
JadefinModules.actionSheet.show({
|
||||
positionTo: options.positionTo,
|
||||
items: [
|
||||
{id: "1", name: "1x", selected: this.currentGain == 1},
|
||||
{id: "2", name: "2x", selected: this.currentGain == 2},
|
||||
{id: "3", name: "3x", selected: this.currentGain == 3},
|
||||
{id: "4", name: "4x", selected: this.currentGain == 4},
|
||||
]
|
||||
}).then(id => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentGain = parseInt(id);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(id);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
return orig(options);
|
||||
};
|
||||
}
|
||||
|
||||
connect() {
|
||||
const video = JadefinUtils.video;
|
||||
if (!video) {
|
||||
|
29
mods/jade/Filterworks.css
Normal file
29
mods/jade/Filterworks.css
Normal file
@ -0,0 +1,29 @@
|
||||
.htmlvideoplayer[data-filterworks-canvas="1"] {
|
||||
/* Still needs to be layouted for subs and our own canvas. */
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.filterworks-canvasParent {
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
order: -2;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.filterworks-canvas {
|
||||
position: absolute;
|
||||
display: block;
|
||||
padding: 0;
|
||||
margin: auto;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
228
mods/jade/Filterworks.js
Normal file
228
mods/jade/Filterworks.js
Normal file
@ -0,0 +1,228 @@
|
||||
//@ts-check
|
||||
|
||||
import JadefinIntegrity from '../../JadefinIntegrity.js';
|
||||
|
||||
import Jadefin from "../../Jadefin.js";
|
||||
import JadefinMod from "../../JadefinMod.js";
|
||||
import JadefinModules from "../../JadefinModules.js";
|
||||
import JadefinUtils from "../../JadefinUtils.js";
|
||||
|
||||
import { rd, rdom, rd$, RDOMListHelper } from "../../utils/rdom.js";
|
||||
|
||||
export class FilterworksFilter {
|
||||
name = "Hello, World!";
|
||||
|
||||
/**
|
||||
* @param {HTMLVideoElement} video
|
||||
*/
|
||||
start(video) {
|
||||
}
|
||||
|
||||
stop(video) {
|
||||
}
|
||||
}
|
||||
|
||||
export class FilterworksSrc {
|
||||
modName = "ExampleSource";
|
||||
|
||||
/** @type {{
|
||||
[id: string]: FilterworksFilter;
|
||||
}} */
|
||||
filters = {
|
||||
test: new FilterworksFilter()
|
||||
};
|
||||
}
|
||||
|
||||
export default JadefinIntegrity("Filterworks", import.meta.url, () => new (class Filterworks extends JadefinMod {
|
||||
PATH_OFF = "Filterworks/Off";
|
||||
|
||||
_sources = [];
|
||||
_pathsToFilters = {};
|
||||
_filtersToMeta = {};
|
||||
|
||||
/** @type {any} */
|
||||
appliedFilter = null;
|
||||
|
||||
canvasParentEl = rd$()`
|
||||
<div class="filterworks-canvasParent">
|
||||
</div>
|
||||
`;
|
||||
|
||||
/** @type {typeof this._sources} */
|
||||
sources = new Proxy(this._sources, {
|
||||
deleteProperty: (target, property) => {
|
||||
delete target[property];
|
||||
|
||||
this.updateSources();
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
set: (target, property, value, receiver) => {
|
||||
target[property] = value;
|
||||
|
||||
this.updateSources();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.sources.push({
|
||||
modName: "Filterworks",
|
||||
filters: {
|
||||
Off: {
|
||||
name: "Off",
|
||||
start: (video) => {},
|
||||
stop: () => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get currentFilterPathPath() {
|
||||
let id = "default";
|
||||
|
||||
const item = JadefinUtils.currentPlayer?.streamInfo?.item;
|
||||
if (item) {
|
||||
id = item.SeriesId || item.ParentId || item.Id || id;
|
||||
}
|
||||
|
||||
return `currentFilterPath-${id}`;
|
||||
}
|
||||
|
||||
get currentFilterPath() {
|
||||
return this.storage.get(this.currentFilterPathPath, this.PATH_OFF);
|
||||
}
|
||||
|
||||
set currentFilterPath(value) {
|
||||
this.storage.set(this.currentFilterPathPath, value);
|
||||
this.update();
|
||||
}
|
||||
|
||||
get currentFilter() {
|
||||
return this._pathsToFilters[this.currentFilterPath] || this._pathsToFilters[this.PATH_OFF];
|
||||
}
|
||||
|
||||
async init(name, url) {
|
||||
await super.init(name, url);
|
||||
|
||||
const ExtrasMenu = /** @type {import("../ExtrasMenu.js").default} */ (Jadefin.getMod("ExtrasMenu"));
|
||||
|
||||
await this.initStyle();
|
||||
|
||||
ExtrasMenu.items.push({
|
||||
name: "Filter",
|
||||
in: ExtrasMenu.IN_CUSTOM,
|
||||
inCustom: (current, item) => {
|
||||
item.asideText = this.currentFilter.name;
|
||||
|
||||
return (current & (ExtrasMenu.IN_PLAYBACKSETTINGS)) == current;
|
||||
},
|
||||
cb: async (positionTo) => {
|
||||
const items = [];
|
||||
|
||||
items.push({id: this.PATH_OFF, name: this._pathsToFilters[this.PATH_OFF].name, selected: this.currentFilter == this._pathsToFilters[this.PATH_OFF]});
|
||||
|
||||
for (const path in this._pathsToFilters) {
|
||||
if (path == this.PATH_OFF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
items.push({id: path, name: this._pathsToFilters[path].name, selected: this.currentFilterPath == path});
|
||||
}
|
||||
|
||||
JadefinModules.actionSheet.show({
|
||||
positionTo,
|
||||
items
|
||||
}).then(id => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentFilterPath = id;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("viewshow", () => {
|
||||
if (JadefinUtils.routePathIsVideo) {
|
||||
if (this._tryUpdateRepeat) {
|
||||
clearInterval(this._tryUpdateRepeat);
|
||||
}
|
||||
|
||||
clearInterval(this._tryUpdateRepeat);
|
||||
this._tryUpdateRepeat = setInterval(() => this.tryUpdate(), 100);
|
||||
}
|
||||
|
||||
this.update();
|
||||
});
|
||||
|
||||
this.log.i("Ready");
|
||||
}
|
||||
|
||||
updateSources() {
|
||||
this._pathsToFilters = {};
|
||||
|
||||
for (const src of this._sources) {
|
||||
for (const id in src.filters) {
|
||||
this._pathsToFilters[`${src.modName}/${id}`] = src.filters[id];
|
||||
this._filtersToMeta[src.filters[id]] = { src, id };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tryUpdate() {
|
||||
const video = JadefinUtils.video;
|
||||
if (!video) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.update();
|
||||
|
||||
if (this._tryUpdateRepeat) {
|
||||
clearInterval(this._tryUpdateRepeat);
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
const video = JadefinUtils.video;
|
||||
if (!video) {
|
||||
if (this.appliedFilter) {
|
||||
this.appliedFilter.stop();
|
||||
this.appliedFilter = null;
|
||||
}
|
||||
|
||||
this.video = null;
|
||||
this.canvas = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.video == video && this.appliedFilter == this.currentFilter) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.appliedFilter?.stop();
|
||||
if (this.canvas) {
|
||||
video.removeAttribute("data-filterworks-canvas");
|
||||
this.canvas.remove();
|
||||
}
|
||||
|
||||
this.video = video;
|
||||
|
||||
this.appliedFilter = this.currentFilter;
|
||||
this.canvas = this.appliedFilter.start(video);
|
||||
if (this.canvas) {
|
||||
this.canvas.classList.add("filterworks-canvas");
|
||||
this.canvasParentEl.append(this.canvas);
|
||||
|
||||
if (this.canvasParentEl.parentElement != video.parentElement) {
|
||||
video.parentElement?.prepend(this.canvasParentEl);
|
||||
}
|
||||
|
||||
video.setAttribute("data-filterworks-canvas", "1");
|
||||
}
|
||||
}
|
||||
})());
|
@ -16,7 +16,7 @@ export default JadefinIntegrity("Shortcuts", import.meta.url, () => new (class S
|
||||
async init(name, url) {
|
||||
await super.init(name, url);
|
||||
|
||||
this.initStyle();
|
||||
await this.initStyle();
|
||||
|
||||
const ExtrasMenu = /** @type {import("../ExtrasMenu.js").default} */ (Jadefin.getMod("ExtrasMenu"));
|
||||
|
||||
|
1
mods/jade/filters/Anime4K.dist.js
Normal file
1
mods/jade/filters/Anime4K.dist.js
Normal file
File diff suppressed because one or more lines are too long
95
mods/jade/filters/Anime4K.js
Normal file
95
mods/jade/filters/Anime4K.js
Normal file
@ -0,0 +1,95 @@
|
||||
//@ts-check
|
||||
|
||||
import JadefinIntegrity from '../../../JadefinIntegrity.js';
|
||||
|
||||
import Jadefin from "../../../Jadefin.js";
|
||||
import JadefinMod from "../../../JadefinMod.js";
|
||||
import JadefinModules from "../../../JadefinModules.js";
|
||||
import JadefinUtils from "../../../JadefinUtils.js";
|
||||
|
||||
class FilterworksAnime4KFilter {
|
||||
constructor(name, key) {
|
||||
this.name = name;
|
||||
this.key = key;
|
||||
|
||||
this.a4k = window["Anime4KJS"];
|
||||
if (!this.a4k) {
|
||||
throw new Error("Anime4KJS not loaded");
|
||||
}
|
||||
|
||||
this.profile = this.a4k[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLVideoElement} video
|
||||
*/
|
||||
start(video) {
|
||||
if (this.upscaler) {
|
||||
throw new Error("Filter already in use");
|
||||
}
|
||||
|
||||
const stream = JadefinUtils.currentPlayer.streamInfo.mediaSource.MediaStreams.find(x => x.Type == "Video");
|
||||
const fps = stream?.RealFrameRate || stream?.AverageFrameRate || 60;
|
||||
this.upscaler = new this.a4k.VideoUpscaler(fps, this.profile);
|
||||
|
||||
this.video = video;
|
||||
this.canvas = document.createElement("canvas");
|
||||
|
||||
this.upscaler.attachVideo(this.video, this.canvas);
|
||||
this.upscaler.start();
|
||||
|
||||
return this.canvas;
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.upscaler?.stop();
|
||||
this.upscaler?.detachVideo();
|
||||
this.upscaler = null;
|
||||
|
||||
this.canvas?.remove();
|
||||
this.video?.removeAttribute("data-filterworks-canvas");
|
||||
|
||||
this.video = null;
|
||||
}
|
||||
}
|
||||
|
||||
export default JadefinIntegrity("FilterworksAnime4KSrc", import.meta.url, () => new (class FilterworksAnime4KSrc extends JadefinMod {
|
||||
filters = {
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async init(name, url) {
|
||||
await super.init(name, url);
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const loader = document.createElement("script");
|
||||
document.head.appendChild(loader);
|
||||
|
||||
loader.addEventListener("load", () => resolve(true));
|
||||
loader.addEventListener("error", (e) => reject(e));
|
||||
|
||||
loader.defer = true;
|
||||
loader.src = this.getUrl(".dist.js");
|
||||
});
|
||||
|
||||
this.filters = {
|
||||
lqSIMPLE: new FilterworksAnime4KFilter("Anime4K LQ Simple", "ANIME4KJS_SIMPLE_M_2X"),
|
||||
lqA: new FilterworksAnime4KFilter("Anime4K LQ Mode A", "ANIME4K_LOWEREND_MODE_A_FAST"),
|
||||
lqB: new FilterworksAnime4KFilter("Anime4K LQ Mode B", "ANIME4K_LOWEREND_MODE_B_FAST"),
|
||||
lqC: new FilterworksAnime4KFilter("Anime4K LQ Mode C", "ANIME4K_LOWEREND_MODE_C_FAST"),
|
||||
hqSIMPLE: new FilterworksAnime4KFilter("Anime4K HQ Simple", "ANIME4KJS_SIMPLE_L_2X"),
|
||||
hqA: new FilterworksAnime4KFilter("Anime4K HQ Mode A", "ANIME4K_HIGHEREND_MODE_A_FAST"),
|
||||
hqB: new FilterworksAnime4KFilter("Anime4K HQ Mode B", "ANIME4K_HIGHEREND_MODE_B_FAST"),
|
||||
hqC: new FilterworksAnime4KFilter("Anime4K HQ Mode C", "ANIME4K_HIGHEREND_MODE_C_FAST")
|
||||
};
|
||||
|
||||
const Filterworks = /** @type {import("../Filterworks.js").default} */ (Jadefin.getMod("Filterworks"));
|
||||
|
||||
Filterworks.sources.push(this);
|
||||
|
||||
this.log.i("Ready");
|
||||
}
|
||||
})());
|
@ -8,5 +8,8 @@
|
||||
"Transcript.js",
|
||||
"PatchForceHLSJS.js",
|
||||
|
||||
"jade/Shortcuts.js"
|
||||
"jade/Shortcuts.js",
|
||||
|
||||
"jade/Filterworks.js",
|
||||
"jade/filters/Anime4K.js"
|
||||
]
|
Loading…
Reference in New Issue
Block a user