UNPKG

@oplayer/plugins

Version:
139 lines (137 loc) 9.75 kB
/** * 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 };