@oplayer/plugins
Version:
oplayer's plugin
139 lines (137 loc) • 9.75 kB
JavaScript
/**
* name: @oplayer/playlist
* version: v1.0.15-beta.3
* description: oplayer's plugin
* author: shiyiya
* homepage: https://github.com/shiyiya/oplayer
*/
(function(){"use strict";try{if(typeof document<"u"){var t=document.createElement("style");t.appendChild(document.createTextNode('.playlist{position:absolute;top:0;left:100%;height:100%;z-index:9;width:18em;transition:transform .3s;background-color:#1c1c1ce6}@media (max-width: 991px){.playlist{max-width:70%}}.playlist.playlist__active{transform:translate(-100%)}.playlist.playlist__wait .playlist-list{cursor:wait}.playlist.playlist__wait .playlist-list .playlist-list-item{pointer-events:none}.playlist.playlist__active:before{content:"";position:absolute;width:100vw;height:100%;right:0;z-index:-1}.playlist-head{display:flex;justify-content:space-between;background:#000;border-bottom:1px solid #484848;padding:.2em .2em .2em .4em;align-items:center;color:#fff;box-sizing:border-box;height:2.2em}.playlist-head>span{font-size:.8em}.playlist-head .playlist-back{display:flex;align-items:center;cursor:pointer}.playlist-head .playlist-back>svg{width:1.75em;height:1.75em;fill:#fff;pointer-events:none}.playlist-head .playlist-back:hover{background-color:#ffffff4d;border-radius:2px}.playlist-list{overflow:auto;height:100%;padding-bottom:2.2em;box-sizing:border-box;color:#ccc}.playlist-list::-webkit-scrollbar{width:.3em}.playlist-list::-webkit-scrollbar-thumb{background:#ccc}.playlist-list-item{position:relative;border-bottom:1px solid #444;padding:8px;display:flex;height:5em;cursor:pointer;box-sizing:border-box;overflow:hidden}.playlist-list-item>*{pointer-events:none}.playlist-list-item:hover,.playlist-list-item.playlist-source__active{color:#fff;background-color:#ffffff1a}.playlist-list-item.playlist-source__progress:before{content:"";top:0;left:-100%;position:absolute;width:100%;height:100%;animation:progress 1s infinite;background:linear-gradient(to right,transparent,rgba(255,255,255,.4),transparent)}@keyframes progress{0%{left:-100%}to{left:100%}}.playlist-list-item-thumb{background-color:#000;border:1px solid #444;float:left;margin-right:10px;height:100%;aspect-ratio:16/9;color:#555;display:flex;justify-content:center;align-items:center;position:relative}.playlist-list-item-img{height:100%;width:100%;object-fit:cover}.playlist-list-item-img__error:after{content:"ERROR";position:absolute;left:0;top:0;width:100%;height:100%;background-color:#000;display:flex;justify-content:center;align-items:center}.playlist-list-item-desc{width:100%;font-size:14px;display:flex;flex-direction:column;justify-content:space-evenly}.playlist-list-item-desc>p{margin:0 0 6px;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;overflow:hidden;-webkit-box-orient:vertical;line-height:1.2}')),document.head.appendChild(t)}}catch(i){console.error("vite-plugin-css-injected-by-js",i)}})();
const r = class r {
constructor(s) {
this.key = "playlist", this.name = "oplayer-plugin-playlist", this.version = "1.0.15-beta.3", this.options = Object.assign({ autoNext: !0, autoHide: !0, sources: [] }, s);
}
apply(s) {
if (!s.isNativeUI)
return this.player = s, this._init(), this;
}
async _init() {
var o;
const s = () => {
var a;
this.renderContainer(), this.changeSourceList(this.options.sources), typeof i == "number" && this.changeSource(i), this.options.autoNext && this.player.on(["ended", "error"], () => {
this.next();
}), (a = this.player.context.ui.keyboard) == null || a.register({
l: () => {
this.$root.classList.toggle("playlist__active");
}
});
}, { initialIndex: i, m3uList: t, sources: e } = this.options;
t && ((o = e[0]) != null && o.src) ? (r.m3u8Parser || (r.m3u8Parser = globalThis.m3u8Parser || await import("m3u8-parser")), fetch(e[0].src).then((a) => a.text()).then((a) => {
const l = new r.m3u8Parser.Parser();
l.push(a), l.end(), this.options.sources = l.manifest.segments.map((c) => t != null && t.sourceFormat ? t.sourceFormat(c) : { src: c.uri, title: c.title }), s();
}).catch((a) => {
this.player.emit("notice", { pluginName: this.name, text: "Playlist: " + a.message });
})) : s();
}
get isWaiting() {
return this.$root.classList.contains("playlist__wait");
}
changeSource(s) {
if (!this.options.sources[s] || this.isWaiting) return;
const i = this.$root.querySelector(`.playlist-list-item[data-index='${s}']`);
this.$root.classList.add("playlist__wait"), i == null || i.classList.add("playlist-source__progress");
const t = this.options.sources[s];
return new Promise((e) => {
var o, a;
if (!t.src && this.options.customFetcher) {
e((a = (o = this.options).customFetcher) == null ? void 0 : a.call(o, this.player, t, s));
return;
}
e(t);
}).then((e) => {
if (!e.src)
throw this.player.context.ui.notice("Empty Source"), new Error("Empty Source");
const { src: o, poster: a, format: l, title: c, subtitles: n, thumbnails: h, highlights: p, danmaku: u } = e;
return this.player.changeSource({ src: o, poster: a, format: l, title: c }).then(() => {
var y;
n && this.player.context.ui.subtitle.changeSource(n), h && this.player.context.ui.changThumbnails(h), p && this.player.context.ui.changHighlightSource(p), u && ((y = this.player.context.danmaku) == null || y.changeSource(u));
});
}).then(() => {
this.player.emit("playlistsourcechange", { source: t, id: s }), this.options.autoHide && setTimeout(() => {
this.hideUI();
}, 300);
}).catch((e) => {
this.player.emit("playlistsourceerror", { error: (e == null ? void 0 : e.payload) || e, idx: s });
}).finally(() => {
var e;
this.currentIndex = s, this._updateHeader(), (e = this.$root.querySelector(".playlist-source__active")) == null || e.classList.remove("playlist-source__active"), i == null || i.classList.add("playlist-source__active"), setTimeout(() => {
this.$root.classList.remove("playlist__wait"), i == null || i.classList.remove("playlist-source__progress");
}, 300);
});
}
changeSourceList(s) {
this.options.sources = s, this.renderList(s), this.player.emit("playlistchange", s);
}
next() {
this.changeSource((this.currentIndex || 0) + 1);
}
previous() {
this.changeSource((this.currentIndex || 0) - 1);
}
showUI() {
this.$root.classList.add("playlist__active");
}
hideUI() {
this.$root.classList.remove("playlist__active");
}
renderContainer() {
const s = `
<div class="playlist-head">
<span class="playlist-head-title">${this.player.locales.get("Playlist")}</span>
<div class="playlist-back">${this.player.context.ui.icons.playlist || '<svg viewBox="0 0 32 32"><path d="m 12.59,20.34 4.58,-4.59 -4.58,-4.59 1.41,-1.41 6,6 -6,6 z"></path></svg>'}</div>
</div>
<div class="playlist-list">
</div>`;
this.$root = document.createElement("div"), this.$root.innerHTML = s, this.$root.className = "playlist", this.$root.onclick = (i) => {
const t = i.target;
t.classList.contains("playlist-list-item") ? this.changeSource(+t.getAttribute("data-index")) : (t.classList.contains("playlist-back") || t == this.$root && t.classList.contains("playlist__active")) && this.hideUI();
}, this.player.context.ui.$root.appendChild(this.$root), this.player.context.ui.menu.register({
name: this.player.locales.get("Playlist"),
icon: '<svg style="transform: scale(1.2);" viewBox="0 0 1024 1024"><path d="M213.333333 426.666667h426.666667c23.466667 0 42.666667 19.2 42.666667 42.666666s-19.2 42.666667-42.666667 42.666667H213.333333c-23.466667 0-42.666667-19.2-42.666666-42.666667s19.2-42.666667 42.666666-42.666666z m0-170.666667h426.666667c23.466667 0 42.666667 19.2 42.666667 42.666667s-19.2 42.666667-42.666667 42.666666H213.333333c-23.466667 0-42.666667-19.2-42.666666-42.666666s19.2-42.666667 42.666666-42.666667z m0 341.333333h256c23.466667 0 42.666667 19.2 42.666667 42.666667s-19.2 42.666667-42.666667 42.666667H213.333333c-23.466667 0-42.666667-19.2-42.666666-42.666667s19.2-42.666667 42.666666-42.666667z m384 37.546667v180.48c0 16.64 17.92 26.88 32.426667 18.346667l150.613333-90.453334c13.653333-8.106667 13.653333-28.16 0-36.693333l-150.613333-90.453333a21.674667 21.674667 0 0 0-32.426667 18.773333z"></path></svg>',
position: "top",
onClick: () => {
this.showUI();
const i = this.$root.querySelector(".playlist-list"), t = this.$root.querySelector(".playlist-source__active");
t && i.scrollHeight > 0 && this.currentIndex && i.scrollTo(0, t.offsetTop - t.offsetHeight);
}
});
}
renderList(s) {
const i = s.map(
(t, e) => `
<div class="playlist-list-item" data-index="${e}">
<div class="playlist-list-item-thumb">
${t.poster ? `<img class="playlist-list-item-img" src="${t.poster}" alt="${t.title || ""}" loading="lazy" onerror="this.classList.add('playlist-list-item-img__error');"/>` : "<span>EMPTY</span>"}
</div>
<div class="playlist-list-item-desc">
<p>${t.title}</p>
${t.duration ? `<span>${t.duration}</span>` : ""}
</div>
</div>`
).join("");
this._updateHeader(), this.$root.querySelector(".playlist-list").innerHTML = i;
}
_updateHeader() {
this.$root.querySelector(".playlist-head-title").textContent = `${this.player.locales.get(
"Playlist"
)} (${this.currentIndex !== void 0 ? `${this.currentIndex + 1}/` : ""}${this.options.sources.length})`;
}
destroy() {
this.currentIndex = void 0, this.options.sources = [], this.renderList([]);
}
};
r.m3u8Parser = globalThis.m3u8Parser;
let d = r;
export {
d as default
};