2024-03-01 21:01:22 +01:00
|
|
|
//@ts-check
|
|
|
|
|
|
|
|
import JadefinIntegrity from '../JadefinIntegrity.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 default JadefinIntegrity("ExtrasMenu", import.meta.url, () => new (class ExtrasMenu extends JadefinMod {
|
|
|
|
IN_ALL = 0;
|
|
|
|
IN_CUSTOM = 1;
|
|
|
|
IN_DRAWER = 2;
|
|
|
|
IN_LIBRARY = 4;
|
|
|
|
IN_MOVIE = 8;
|
|
|
|
|
|
|
|
_popupId = 0;
|
|
|
|
_items = [];
|
|
|
|
|
|
|
|
/** @type {typeof this._items} */
|
|
|
|
items = new Proxy(this._items, {
|
|
|
|
deleteProperty: (target, property) => {
|
|
|
|
delete target[property];
|
|
|
|
|
|
|
|
this.update();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
set: (target, property, value, receiver) => {
|
|
|
|
target[property] = value;
|
|
|
|
|
|
|
|
this.update();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
headerExtrasEl = rd$()`
|
|
|
|
<button is="paper-icon-button-light" class="headerExtrasMenu headerButton headerButtonRight" title="Extras" style="display: inline-flex;">
|
|
|
|
<span class="material-icons tune"></span>
|
|
|
|
</button>
|
|
|
|
`;
|
|
|
|
|
|
|
|
drawerExtrasEl = rd$()`
|
|
|
|
<div class="extrasMenuOptions">
|
|
|
|
</div>
|
|
|
|
`;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
|
|
|
|
this.items.push({
|
|
|
|
name: "Reload",
|
|
|
|
secondaryText: "Fully reload and update Jellyfin",
|
|
|
|
icon: "update",
|
|
|
|
in: this.IN_LIBRARY,
|
|
|
|
cb: async () => {
|
|
|
|
try {
|
|
|
|
await window.caches.delete("embydata");
|
|
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
await window.caches.delete(`workbox-precache-v2-${JadefinModules.Emby.Page.baseRoute}/`);
|
|
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.headerExtrasEl.addEventListener("click", e => this.openExtrasPopup());
|
|
|
|
}
|
|
|
|
|
|
|
|
async init(name, url) {
|
|
|
|
await super.init(name, url);
|
|
|
|
|
2024-05-13 21:24:03 +02:00
|
|
|
await JadefinUtils.waitUntil(() => document.querySelector(".headerRight"));
|
|
|
|
|
2024-03-01 21:01:22 +01:00
|
|
|
this.initStyle();
|
|
|
|
this.initHeaderExtras();
|
|
|
|
this.initDrawerExtras();
|
|
|
|
|
|
|
|
this.log.i("Ready");
|
|
|
|
}
|
|
|
|
|
|
|
|
initHeaderExtras() {
|
|
|
|
document.querySelector(".headerRight")?.appendChild(this.headerExtrasEl);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {boolean} [silentWarn]
|
|
|
|
*/
|
|
|
|
initDrawerExtras(silentWarn) {
|
|
|
|
const drawer = document.querySelector(".mainDrawer > .mainDrawer-scrollContainer");
|
|
|
|
const userMenuOptions = drawer?.querySelector("& > .userMenuOptions");
|
|
|
|
|
|
|
|
if (!userMenuOptions) {
|
|
|
|
if (!silentWarn) {
|
|
|
|
this.log.w("Couldn't find mainDrawer / home userMenuOptions, retrying");
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(() => this.initDrawerExtras(true), 1500);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drawer?.insertBefore(this.drawerExtrasEl, userMenuOptions);
|
|
|
|
|
|
|
|
this.update();
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
update() {
|
|
|
|
if (this.drawerExtrasEl) {
|
|
|
|
this.drawerExtrasEl.innerHTML = `<h3 class="sidebarHeader">Extras</h3>`;
|
|
|
|
|
|
|
|
for (let item of this._items) {
|
|
|
|
if (!this.checkVisibility(this.IN_DRAWER, item)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let itemEl = rd$()`
|
|
|
|
<a is="emby-linkbutton" class="navMenuOption emby-button" href="#">
|
|
|
|
<span class=${`material-icons navMenuOptionIcon ${item.icon}`} aria-hidden="true"></span>
|
|
|
|
<div class="navMenuOptionTextBlock">
|
|
|
|
<span class="navMenuOptionText">${item.name}</span><br>
|
|
|
|
<span class="navMenuOptionTextSubtext">${item.secondaryText}</span>
|
|
|
|
</div>
|
|
|
|
</a>
|
|
|
|
`;
|
|
|
|
|
|
|
|
itemEl.addEventListener("click", e => item.cb?.());
|
|
|
|
|
|
|
|
item.cbEl?.(itemEl, this.IN_DRAWER);
|
|
|
|
|
|
|
|
this.drawerExtrasEl.appendChild(itemEl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {number} current
|
|
|
|
* @param {any} item
|
|
|
|
*/
|
|
|
|
checkVisibility(current, item) {
|
|
|
|
if ((item.in || this.IN_ALL) == this.IN_ALL) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((item.in & this.IN_CUSTOM) == this.IN_CUSTOM) {
|
|
|
|
return item.inCustom(current, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (item.in & current) == current;
|
|
|
|
}
|
|
|
|
|
|
|
|
})());
|