Greasy Fork is available in English.
为网易云音乐扁平风格样式表提供更佳的用户体验。
// ==UserScript== // @name:en Userscript Helper for Flat-Style Netease Music Userstyle 适用于网易云音乐扁平风格样式表的辅助用户脚本 // @description:en Provides a better experience for Flat-Style Netease Music Userstyle. 为网易云音乐扁平风格样式表提供更佳的用户体验。 // @name:zh 适用于网易云音乐扁平风格样式表的辅助用户脚本 // @description:zh 为网易云音乐扁平风格样式表提供更佳的用户体验。 // @name 适用于网易云音乐扁平风格样式表的辅助用户脚本 // @description 为网易云音乐扁平风格样式表提供更佳的用户体验。 // @namespace wTonyChen.flatnmusich // @version 0.2.18-0.9.20 // @author wTonyChen // @copyright 2022 wTonyChen (https://github.com/wTonyChen) // @compatible chrome 101+ // @compatible edge 101+ // @compatible opera 87+ // @compatible firefox 100+ 有限支持 // @license GPL-3.0-or-later // @homepage https://wtonychen.github.io/flatnmusic/ // @supportURL https://github.com/wTonyChen/flatnmusic/issues // @match http*://music.163.com/* // @run-at document-end // @grant none // ==/UserScript== !(function () { "use strict"; let e = "0.2.18-0.9.20", t = "wk-fnm-hi-cfg", l = document.querySelector("." + t); l || ((l = document.createElement("div")), (l.className = t), document.body.appendChild(l)); let s, a = getComputedStyle(l), i = { 86: "1f603", 85: "1f60a", 359: "263a", 95: "1f60d", 363: "1f618", 96: "1f631", 356: "1f62d", 362: "1f619", 352: "1f633", 87: "1f61e", 343: "1f601", 348: "1f61d", 353: "1f612", 361: "1f621", 341: "1f60f", 97: "1f613", 346: "1f616", 354: "1f630", 350: "1f628", 351: "1f637", 357: "1f602", 355: "1f635", 115: "1f47f", 360: "1f604", 94: "1f61c", 342: "1f614", 358: "1f622", 33: "2764", 34: "1f494", 303: "1f498", 309: "2b50", 314: "1f4a2", 89: "1f4a9", 13: "1f44d", 372: "1f44e", 14: "1f64f", 379: "1f46b", 380: "1f46f", 374: "1f645", 262: "1f481", 106: "1f48f", 376: "1f491", 367: "1f444", 81: "1f436", 78: "1f431", 100: "1f437", 459: "1f430", 450: "1f424", 461: "1f414", 116: "1f47b", 411: "1f385", 101: "1f47d", 52: "1f48e", 107: "1f381", 0: "1f466", 1: "1f467", 337: "1f382", 186: "1f51e", 312: "2b55", 313: "274c", }, n = "/style/web2/emt/emoji_", x = (e) => { let t = a.getPropertyValue("--" + e); if (t) try { t && t.indexOf("/") > -1 && (t = decodeURIComponent(t.replace(/\//g, "%"))); } catch (e) {} return ( ((0 === t.indexOf('"') && t.lastIndexOf('"') === t.length - 1) || (0 === t.indexOf("'") && t.lastIndexOf("'") === t.length - 1)) && (t = t.substr(1, t.length - 2)), t ); }, r = (e) => { let t; return window.localStorage && (t = localStorage.getItem(e)), t; }, c = (e, t) => { window.localStorage && localStorage.setItem(e, t); }, o = x("wkhi-a"), d = x("wkhi-b"); if (!d) return void l.parentElement.removeChild(l); document.documentElement.setAttribute("wk-style-assist", "true"); let p = r("wkoptin") || !1, f = function () { let e = arguments[0]; for (let t = 1; t < arguments.length; t++) { let l = RegExp("\\{" + t + "\\}", "g"); e = e.replace(l, arguments[t]); } return e; }; ((e) => { let t, l = 0, s = !1, a = document.querySelector("#g-topbar"), i = document.querySelector("#g_iframe"), n = 0, x = 0, c = !0; if (!a || !Object.is(window.self, window.top)) return; let o = 1.6 * a.getBoundingClientRect().height, d = (e) => { t && t.cancel(), (x = 0), (n = 0), (l = 0), (c = !1), (t = a.animate([{ transform: "translateY(0)" }], { duration: 200, fill: "backwards", easing: "cubic-bezier(.16,1,.29,.99)", })), (t.onfinish = (e) => { (c = !0), (a.style.transform = "translateY(0)"); }); }; i.addEventListener("load", (e) => { i.contentWindow.addEventListener("beforeunload", d), i.contentDocument.addEventListener("scroll", (e) => { c || t.cancel(), (l = i.contentWindow.scrollY), s || (window.requestAnimationFrame((e) => { ((e) => { if (r("wksdscrolling")) { let t = e - n; (x = Math.max(Math.min(x + t, o), 0)), (a.style.top = "0 !important"), (a.style.transform = `translateY(-${x}px)`); } else (a.style.top = ""), (a.style.transform = ""), (x = 0); n = e; })(l), (s = !1); }), (s = !0)); }); }); })(); let m = "", b = (e) => { let t = document.querySelector("a.u-btni-fav-dis,a.u-btni-fav-dis2"); if (t) { let e = t.parentElement.querySelector("[data-res-id]"); e && ((t.href = "/playlist?id=" + e.dataset.resId), (t.innerHTML = "<i title='跳转到歌单'>前往歌单</i>"), t.classList.remove("u-btni-fav-dis", "u-btni-fav-dis2")); } }; r("wkstoplistjump") && 0 === location.pathname.indexOf("/discover/toplist") && b(), r("wksmylistjump") && 0 === location.pathname.indexOf("/my") && setInterval((e) => b(), 1e3); let u = (e) => { let t = "" + e, l = 0; for (let e = 0; e < t.length; e++) l += t[e].charCodeAt(); return l; }, w = (e) => { if (!Object.is(window.self, window.top)) return; let t = document.querySelectorAll( ".m-playbar .listlyric>p:not(.wk-upgraded)" ); for (let e = 0; e < t.length; e++) (t[e].innerText = t[e].innerText.split("\n")[0]), (t[e].innerHTML = t[e].innerHTML.replace(/\ /g, " ")), t[e].classList.add("wk-upgraded"); }; r("wklrctrans") && document.body.classList.add("wk-playlist-applied"), (DocumentFragment.prototype.appendChildHost = DocumentFragment.prototype.appendChild), (DocumentFragment.prototype.appendChild = function () { if ( r("wksplayinguiani") && arguments[0].classList.contains("m-layer") && arguments[0].parentElement ) { let e = arguments[0].cloneNode(!0); arguments[0].dataset && arguments[0].dataset.wkAdvisedSize && ((e.style.minHeight = arguments[0].dataset.wkAdvisedSize + "px"), (arguments[0].dataset.wkAdvisedSize = "")), arguments[0].parentElement.insertBefore(e, arguments[0]), e.addEventListener("animationend", (t) => { e.remove(); }), e.classList.add("hidden"); } let e = "", t = r("wkspipfont"), l = r("wkspipfont2"), s = r("wkspipfsize"), a = r("wkspipfweight"), i = r("wkspipletterspacing"), n = r("wkspipwordspacing"), x = r("wkspiplinespacing"), c = r("wkspiplineheight"), o = r("wkspipcustomstyle"); if ("STYLE" == arguments[0].tagName) { r("wklrctrans") && (e += ".container>.line>.compare{display:none}"); let d = []; t && d.push(`"${t.replace(/"/g, '\\"')}"`), l && d.push(`"${l.replace(/"/g, '\\"')}"`), d.length > 0 && (e += `.container{font-family:${d.join(",")} !important}`), a && !isNaN(+a) && (e += `.container,.container *{font-weight:${+a} !important}`), s && !isNaN(+s) && (e += `.container>.line>.compare,.container>.line>.origin{font-size:${+s}px !important}`), i && !isNaN(+i) && (e += `.container,.container *{letter-spacing:${+i}px !important}`), n && !isNaN(+n) && (e += `.container,.container *{word-spacing:${+n}px !important}`), x && !isNaN(+x) && (e += `.container>.line{padding:${+x}px 0 !important}`), c && !isNaN(+c) && (e += `.container>.line{line-height:${+c}px !important}`), e && (this.appendChildHost.call( this, document.createElement("style") ).innerHTML = e), o && (this.appendChildHost.call( this, document.createElement("style") ).innerHTML = o); } if (!r("wksplayinguiani") || "g_playlist" != arguments[0].id) return this.appendChildHost.call(this, ...arguments); arguments[0].classList.add("hidden"), document.body.classList.remove("wk-playlist-showing"); }), (Element.prototype.appendChildHost = Element.prototype.appendChild), (Element.prototype.appendChild = function () { return ( r("wksplayinguiani") && "g_playlist" == arguments[0].id && (arguments[0].classList.remove("hidden"), document.body.classList.add("wk-playlist-showing")), r("wksplayinguiani") && arguments[0].classList && arguments[0].classList.contains("m-layer") && arguments[0].dataset && setTimeout((e) => { arguments[0].dataset.wkAdvisedSize = arguments[0].clientHeight; }, 50), r("wklrctrans") && "g_playlist" == arguments[0].id && setTimeout(w, 50), this.appendChildHost.call(this, ...arguments) ); }), ((e) => { if (r("wklistdisd") && !e) return; let t = x("wkhi-c"), l = x("wkhi-d"); if (!t || !l) return; (t = t.split("|")), (l = l.split("|")); let s = e ? 31536e5 : 1, a = (t, l) => { let a = `${t};path=${l};max-age=${s}` + (e ? "" : `;expires=${new Date(70).toGMTString()}`); document.cookie = a; }; for (let e = 0; e < t.length; e++) for (let s = 0; s < l.length; s++) a(t[e], l[s]); c("wklistdisd", e ? 0 : 1); })(!!r("wksfullpl")), r("wkslowcontrast") && Object.is(window.self, window.top) && (document.documentElement.style.filter = "contrast(.8)"), r("wkslowbrightness") && Object.is(window.self, window.top) && (document.documentElement.style.filter = document.documentElement.style.filter + " brightness(.5)"); let g = { kw7: (e) => { !isNaN(+e) && +e > 99999 && +e < 1e6 && alert( ((e) => { let t = "" + e, l = 0, s = t.length; for (let e = 0; e < s; e++) { let a = ( t[e].codePointAt() * (s - e) * (e + 1) + 1 + e ).toString(26); l += a .substr(a.length - 1, 1) .toUpperCase() .codePointAt(); } let a = ((9301 * l + 49297) % 233280) / 233280; return Math.round(1e5 + 899999 * a); })(e) ); }, }, y = (e) => { if ( (r("wklrctrans") && w(), r("wkshiresimages") && ((e) => { let t = document.querySelectorAll("img[data-src]"); for (let e = 0; e < t; e++) t[e].dataset.src && "" == t[e].src && (t[e].src = t[e].dataset.src); let l = document.querySelectorAll('img[src*="param="]'); for (let e = 0; e < l.length; e++) { let t = l[e].src.split("?")[0]; if (l[e].src != t) { let s = new Image(), a = (i) => { l[e] && (l[e].src.split("?")[0] == t && ((l[e].src = t), l[e].classList.add("wk-hires-loaded")), s.removeEventListener("load", a, !1)); }; s.addEventListener("load", a, !1), l[e].classList.remove("wk-hires-loaded"), (s.src = t); } } })(), r("wksemojisym") && ((e) => { let t = document.querySelectorAll(`img[src*="${n}"]`); for (let e = 0; e < t.length; e++) { let l = t[e].src.split(n)[1]; l && ((l = l.split(".")[0]), !isNaN(+l) && i[+l] && (t[e].src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent( [ "<svg", 'xmlns="http://www.w3.org/2000/svg"', 'width="21"', 'height="21"><text', 'x="10.5"', 'y="12.4"', "style=\"text-anchor:middle;dominant-baseline:middle;font-size:14px;font-family:'Apple", "Color", "Emoji','Noto", "Color", "Emoji','Segoe", "UI", `Emoji'">&#x${i[+l]};</text></svg>`, ].join(" ") ))); } })(), r("wksadptbg") && Object.is(window.self, window.top) && ((e) => { let t = document.querySelector(".m-playbar .head img"), l = document.querySelector(".m-playbar"); if (t && l && t.src && t.src != m) { l.classList.add("wksplybrbg"); let e = t.src; e.indexOf("?") < 0 && (e += "?param=34y34"), (l.style.cssText = `--a_plybarimgsrc:url(${e})`), (m = t.src); } })(), r("wksimprovedlook")) ) { if ("user" == location.pathname.substring(1).split("/")[0]) { let e = document.querySelector(".m-proifo dt img"), t = document.querySelector(".g-bd"); e && e.src && t && (document.documentElement.classList.add("has-upb"), (t.style.cssText = `--upb:url("${e.src}")`)); let l = document.querySelector(".m-proifo .name .tit"), s = document.querySelector(".m-proifo .name #j-name-wrap"); l && s && ((s.dataset.wkUsernameFull = s.title = l.innerText), s.classList.add("wk-full-username")); } let e = document.querySelector(".g-wrap>.m-info .cover img"), t = document.querySelector(".g-wrap>.m-info"); e && t && (document.documentElement.classList.add("has-mib"), (t.style.cssText = `--mib:url("${e.src}")`)); } let t = location.hash && ("video" == location.hash.substring(2).split("?")[0].split("/")[0] || "mv" == location.hash.substring(2).split("?")[0].split("/")[0]), l = "/" == location.pathname, a = "video" == location.pathname.substring(1).split("/")[0] || "mv" == location.pathname.substring(1).split("/")[0]; if ( r("wksmusicsessionmeta") && "mediaSession" in navigator && (a || (l && !t)) ) { let t = document.querySelector( a ? ".n-mv .title h2" : ".m-playbar .words .name" ), l = document.querySelector( a ? ".n-mv .title .name" : ".m-playbar .words .by" ), i = document.querySelector( a ? ".m-ctvideo .poster .pic" : ".m-playbar .head img" ), n = [], x = (document.querySelector(a ? null : ".m-playbar .btns .prv"), document.querySelector( a ? ".m-ctvideo.z-play .controls .wrap .play" : ".m-playbar .btns .ply" ), document.querySelector(a ? null : ".m-playbar .btns .nxt"), document.querySelector(a ? ".m-ctvideo" : ".m-playbar .btns .ply")); (x = x ? x.classList.contains(a ? "z-play" : "pas") ? "playing" : x.classList.contains(a ? "z-pause" : "ply") ? "paused" : "none" : "none"), i && i.src && (n = [ { src: i.src.split("?")[0] + "?param=96y96", sizes: "96x96", type: "image/jpeg", }, { src: i.src.split("?")[0] + "?param=128y128", sizes: "128x128", type: "image/jpeg", }, { src: i.src.split("?")[0] + "?param=192y192", sizes: "192x192", type: "image/jpeg", }, { src: i.src.split("?")[0] + "?param=256y256", sizes: "256x256", type: "image/jpeg", }, { src: i.src.split("?")[0] + "?param=384y384", sizes: "384x384", type: "image/jpeg", }, { src: i.src.split("?")[0] + "?param=512y512", sizes: "512x512", type: "image/jpeg", }, { src: i.src.split("?")[0], sizes: "any", type: "image/jpeg" }, ]); try { let e = { title: t ? t.innerText : document.title, artist: l ? l.innerText : "", album: l ? l.innerText : "", artwork: n, }; !((e, t) => { if ("object" == typeof e) try { e = JSON.stringify(e); } catch (e) {} if ("object" == typeof t) try { t = JSON.stringify(t); } catch (e) {} return e == t; })(e, s) && a && ((s = e), (navigator.mediaSession.metadata = new MediaMetadata(s))); } catch (e) {} } }; y(), window.setInterval(y, 500), d && (function () { if ("/user/update" == location.pathname) { let t = (t) => { let l = document.querySelector("#baseBox"); if (l) { ((e = 0, t = 0) => { let l = ("" + e).split("."), s = ("" + t).split("."); for (let e = 0; e < Math.max(l.length, s.length); e++) { let t = u(l[e] ? s[e] : 0), a = u(s[e] ? s[e] : 0); if (t > a) return !1; if (t < a) return !0; } })(e.split("-")[1], o); let t = `<div class="item"><h3><span class="f-fs1">辅助脚本设置</span><span class="sub s-fc3">辅助脚本版本:${e}</span><span class="sub s-fc3">样式表版本:${o}</span></h3><ul class="n-plist n-plist-1" data-prompt-prefix="请输入">{1}</ul></div>`, s = '<li><label><input type="checkbox" class="f-rdi" {2}>{1}</label></li>', a = '<li class="wk-settings-button-line"><a class="u-btn2 u-btn2-2 u-btn2-w2" href="javascript:;" {2}><i>{3}</i></a> <label>{1}</label></li>', i = [ { label: "样式表增强外观", lsm: "wksimprovedlook", }, { label: "显示歌单内全部音乐", lsm: "wksfullpl", }, { label: "显示高清图片", lsm: "wkshiresimages", }, { label: "视频页面媒体信息显示支持", lsm: "wksmusicsessionmeta", test: "'mediaSession' in navigator", }, { label: "顶栏动态固定 (忽略顶栏滚动状态设置)", lsm: "wksdscrolling", }, { label: "表情图片以系统 Emoji 表情显示", lsm: "wksemojisym", }, { label: "正在播放歌单界面和窗口的增强动画 (刷新页面应用更改)", lsm: "wksplayinguiani", }, { label: "排行榜页面的收藏按钮跳转到对应歌单", lsm: "wkstoplistjump", }, { label: "我的音乐中歌单的收藏按钮跳转到对应歌单", lsm: "wksmylistjump", }, { label: "隐藏正在播放界面和画中画歌词翻译", lsm: "wklrctrans", }, { label: "降低页面亮度 (刷新页面应用更改)", lsm: "wkslowbrightness", }, { label: "降低页面对比度 (刷新页面应用更改)", lsm: "wkslowcontrast", }, { label: "播放底栏和歌词动态背景 (Beta)", lsm: "wksadptbg", }, { label: "画中画显示首选字体名称 (换歌应用更改)", lsm: "wkspipfont", t: "t", }, { label: "画中画显示备选字体名称 (换歌应用更改)", lsm: "wkspipfont2", t: "t", }, { label: "画中画显示字体粗细 (范围 100-900, 换歌应用更改)", lsm: "wkspipfweight", t: "n", }, { label: "画中画歌词字体大小 (像素,换歌应用更改)", lsm: "wkspipfsize", t: "n", }, { label: "画中画歌词行间距 (像素,换歌应用更改)", lsm: "wkspiplinespacing", t: "n", }, { label: "画中画歌词行高 (像素,换歌应用更改)", lsm: "wkspiplineheight", t: "n", }, { label: "画中画显示字间距 (像素,换歌应用更改)", lsm: "wkspipletterspacing", t: "n", }, { label: "画中画显示词间距 (像素,换歌应用更改)", lsm: "wkspipwordspacing", t: "n", }, { label: "自定义画中画样式 (换歌应用更改)", lsm: "wkspipcustomstyle", t: "t", }, ], n = ""; for (let e = 0; e < i.length; e++) { if (i[e].roi && !p) continue; let t = !0; if (i[e].test) { t = !1; try { t = !!window.eval(i[e].test); } catch (e) {} } if (!t) continue; let l = r(i[e].lsm); "n" == i[e].t || "t" == i[e].t || "p" == i[e].t ? (n += f( a, i[e].label, `data-wk-lsm="${i[e].lsm}" data-wk-t="${i[e].t}" data-wk-l="${i[e].label}"`, "p" == i[e].t ? "开始" : "修改" )) : (n += f( s, i[e].label, `${l ? "checked " : ""}data-wk-lsm="${i[e].lsm}"` )); } n = f(t, n); let x = document.createElement("div"); (x.className = "n-priv f-cb flatnmusic-settings"), (x.style.display = "none"), (x.innerHTML = n), x.addEventListener("change", (e) => { let t = e.target.closest("[data-wk-lsm]"); if (!t || !t.dataset) return; let l = t.dataset.wkLsm; t && l && ("checkbox" == t.type ? c(l, t.checked ? "1" : "") : c(l, t.value)); }), l.appendChild(x), x.addEventListener("click", (e) => { let t = e.target.closest("[data-wk-t]"); if (!t || !t.dataset) return; let l = t.dataset.wkLsm, s = t.dataset.wkT, a = t.dataset.wkL, i = r(l), n = t.closest("[data-prompt-prefix]"); if (((n = n ? n.dataset.promptPrefix : ""), t && l)) { let e = n + a; "p" == s && (e = n); let t = window.prompt(e, i || ""), x = ((e) => { let t = 0, l = "" + e, s = l.length; for (let e = 0; e < s; e++) t += l[e].codePointAt(); return t.toString(36) + s; })(l); if ("n" == s && isNaN(+t) && "" != t) return void alert( ((e) => { let t = "无效的值", l = t.match(/\&#x[a-fA-F0-9]+;/g); if (l) for (let e = 0; e < l.length; e++) { let s = l[e].substring(3, l[e].length - 1); try { s = JSON.parse(`"\\u${s.padStart(4, 0)}"`); } catch (e) {} t = t.replace(l[e], s); } return t; })() ); null != t && "p" != s ? c(l, t || "") : "p" == s && g[x] && "function" == typeof g[x] && g[x](t); } }); } }; window.addEventListener("load", t); } })(); })();