Merge pull request #192 from the1812/preview

Update to v1.9.5
This commit is contained in:
Grant Howard 2019-09-09 22:22:02 +08:00 committed by GitHub
commit 1f80e85c4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1570 additions and 909 deletions

View File

@ -348,6 +348,10 @@ declare global {
doubleClickFullscreenPreventSingleClick: boolean
simplifyHome: boolean,
simplifyHomeStyle: '清爽' | '极简',
ajaxHook: boolean,
scriptLoadingMode: '同时' | '延后' | '同时(自动)' | '延后(自动)' | '自动',
scriptDownloadMode: 'bundle' | 'legacy'
guiSettingsDockSide: '左侧' | '右侧'
latestVersionLink: string,
currentVersion: string,
}
@ -380,5 +384,7 @@ declare global {
const getDpiSourceSet: (src: string, baseSize: number | string | { width?: number | string, height?: number | string }, extension?: string) => string
const isOffline: () => boolean
const getUID: () => string
type ScriptVersion = 'Stable' | 'Preview' | 'Offline' | 'Preview Offline' | 'Local' | 'Local preview' | 'Local stable' | 'Local offline' | 'Local preview offline'
const scriptVersion: ScriptVersion
}
export { };

View File

@ -610,6 +610,21 @@
设定侧栏的垂直偏移量, 单位为百分比, 允许的范围为 -40% ~ 40%.
</details>
<details>
<summary><strong>Ajax Hook API</strong></summary>
是否启用 Ajax Hook API, 其他插件或附加功能能够通过此 API 获取 Ajax 请求的信息.
</details>
<details>
<summary><strong>加载模式</strong></summary>
脚本功能的加载模式:
- 同时: 与b站页面同时加载
- 延后: 优先加载b站页面, 在b站页面加载完成后再开始加载脚本功能
- 自动: 根据页面自动选择加载模式
</details>
# 兼容性

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -39,7 +39,7 @@ namespace BilibiliEvolved.Build
{
var filename = Path.GetFileName(url);
var hash = string.Join("", sha256.ComputeHash(File.OpenRead(url)).Select(b => b.ToString("X2")).ToArray());
zip.CreateEntryFromFile(url, filename);
zip.CreateEntryFromFile(url, filename, CompressionLevel.NoCompression);
hashDict.Add(filename, hash);
}
}

Binary file not shown.

2
min/about.min.js vendored
View File

@ -1 +1 @@
(()=>{return(t,e)=>{(async()=>{const i=await e.importAsync("aboutHtml");document.body.insertAdjacentHTML("beforeend",i);const o=(t,e)=>t.charCodeAt(0)-e.charCodeAt(0);const n=(t,e)=>o(t.name,e.name);const s=GM_info.script.name.match(/Bilibili Evolved \((.*)\)/);const a=s?s[1]:"Stable";new Vue({el:".bilibili-evolved-about",data:{version:t.currentVersion,clientType:a,logoImage:null,logoImageDark:null,branch:null,authors:[{name:"Grant Howard",link:"https://github.com/the1812"},{name:"Coulomb-G",link:"https://github.com/Coulomb-G"}],contributors:[{name:"PleiadeSubaru",link:"https://github.com/Etherrrr"}].sort(n),fetching:true,participants:[],websites:[{name:"GitHub",link:"https://github.com/the1812/Bilibili-Evolved/"},{name:"Greasy Fork",link:"https://greasyfork.org/zh-CN/scripts/373563-bilibili-evolved"}],components:[{name:"Vue.js",link:"https://cn.vuejs.org/index.html"},{name:"JSZip",link:"https://stuk.github.io/jszip/"},{name:"jQuery",link:"http://jquery.com/"},{name:"debounce",link:"https://github.com/component/debounce/"},{name:"Slip.js",link:"https://github.com/kornelski/slip"},{name:"MDI",link:"https://materialdesignicons.com"}]},mounted(){document.querySelector(".bilibili-evolved-about").addEventListener("be:about-load",()=>{this.init()},{once:true})},methods:{async getLogos(){this.logoImage=await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide.svg`);this.logoImageDark=await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide-dark.svg`)},async init(){this.branch=/Preview|Local/.test(a)?"preview":"master";this.getLogos();const t=new Set;let e=[];let i=1;do{e=await Ajax.getJson(`https://api.github.com/repos/the1812/Bilibili-Evolved/issues?state=all&direction=asc&per_page=100&page=${i}`).catch(()=>{e=[{name:"电波无法到达(´・_・`)",link:null}]});i++;for(const i of e){t.add(i.user.login)}}while(e.length>0);this.participants=[...t].map(t=>{return{name:t,link:`https://github.com/${t}`}}).filter(({link:t})=>{return!this.authors.some(e=>e.link===t)&&!this.contributors.some(e=>e.link===t)}).sort(n);this.fetching=false}}})})()}})();
(()=>{return(t,e)=>{(async()=>{const i=await e.importAsync("aboutHtml");document.body.insertAdjacentHTML("beforeend",i);dq(".bilibili-evolved-about").addEventListener("be:about-load",()=>{const e=(t,e)=>t.charCodeAt(0)-e.charCodeAt(0);const i=(t,i)=>e(t.name,i.name);const o=GM_info.script.name.match(/Bilibili Evolved \((.*)\)/);const n=o?o[1]:"Stable";new Vue({el:".bilibili-evolved-about",data:{version:t.currentVersion,clientType:n,logoImage:null,logoImageDark:null,branch:null,authors:[{name:"Grant Howard",link:"https://github.com/the1812"},{name:"Coulomb-G",link:"https://github.com/Coulomb-G"}],contributors:[{name:"PleiadeSubaru",link:"https://github.com/Etherrrr"}].sort(i),fetching:true,participants:[],websites:[{name:"GitHub",link:"https://github.com/the1812/Bilibili-Evolved/"},{name:"Greasy Fork",link:"https://greasyfork.org/zh-CN/scripts/373563-bilibili-evolved"}],components:[{name:"Vue.js",link:"https://cn.vuejs.org/index.html"},{name:"JSZip",link:"https://stuk.github.io/jszip/"},{name:"jQuery",link:"http://jquery.com/"},{name:"debounce",link:"https://github.com/component/debounce/"},{name:"Slip.js",link:"https://github.com/kornelski/slip"},{name:"MDI",link:"https://materialdesignicons.com"},{name:"Lodash",link:"https://lodash.com/"}]},mounted(){dq(".bilibili-evolved-about").addEventListener("be:about-load-community",()=>{this.init()},{once:true})},methods:{async getLogos(){this.logoImage=await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide.svg`);this.logoImageDark=await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide-dark.svg`)},async init(){this.branch=/Preview|Local/.test(n)?"preview":"master";this.getLogos();const t=new Set;let e=[];let o=1;do{e=await Ajax.getJson(`https://api.github.com/repos/the1812/Bilibili-Evolved/issues?state=all&direction=asc&per_page=100&page=${o}`).catch(()=>{e=[{name:"电波无法到达(´・_・`)",link:null}]});o++;for(const i of e){t.add(i.user.login)}}while(e.length>0);this.participants=[...t].map(t=>{return{name:t,link:`https://github.com/${t}`}}).filter(({link:t})=>{return!this.authors.some(e=>e.link===t)&&!this.contributors.some(e=>e.link===t)}).sort(i);this.fetching=false}}})},{once:true})})()}})();

View File

@ -1,7 +1,7 @@
{
"about.min.css": "839FB8FA5429AFB22AAE52B0B1114EB5474333D12082554BAD790E75936CF48C",
"about.min.html": "AE18D23499F4B636B32267440FAE92D67700FCA2F2AA2FBB4E2692018D66DD5F",
"about.min.js": "0E79611FC34B3EFB4B9428A18C391DF59674D5C41D34023F6F9DEFB656882A9E",
"about.min.js": "112689A1206CFA88EFA9AB144D6F0806E8D66C198B39EBC939F9721F9DB99391",
"aria2-rpc.min.js": "B13E731DDD503A645A19BB243FF0148BEAC313F0A54454752A07387176F04046",
"auto-continue.min.js": "96CD47C367D7397CE1467A69764409BAEFF16E8F535BC8E15523CD0B8A86687E",
"auto-draw.min.js": "AE72CF2623DF2D15AD4AF82D125FFAF7EF5B1E6B36D9E9AC646AC98AA6AA8698",
@ -19,15 +19,15 @@
"compact-layout.min.js": "B20609A7CBBDB1845FA0156FB5BE6B1E1A1B8B069EA85F65D16241DD2C12D738",
"custom-control-background.min.css": "1981FD2BF3B17ECF33F98D5DEDAF0D32ACBE9532A51FDB70822286991AB98EF3",
"custom-control-background.min.js": "6B6B7E99E88E9242AB4AB3A0B108AADBF48BD43D6A8F11F0E281F476A7D84C47",
"custom-navbar.min.css": "0C4E62C1C1C5B219F3EDCBDB14FB20BFC8BAEBAB5111E944B0345BC0C15561D4",
"custom-navbar.min.css": "4D1AEE4E9E6B97E698F2C995622C9019BAAFFA5675680B47743CE2EE4B1BF620",
"custom-navbar.min.html": "72A66BCE1D82163555AFBEAC651A0BB42A661338878C55B9BE8CE3655767A3CC",
"custom-navbar.min.js": "40946AF34FE0A2572DC554FF2617333C258B68D6987067E8D949E67CEDF63EA9",
"custom-navbar.min.js": "D19B794C325D8C78113DCC8B890BBEFC2CC37D6F49DA224BC2623A6DFB8853C9",
"danmaku-converter.min.js": "E056FD0E80469D3EC4C11BDD78435A1EBFA319DA8DAD9063286E1CA50037EA94",
"dark-important.min.css": "FED04F62558B979ACADEBC3850DF1155CEF55F99AAF6130CB9CFF741DCA16F92",
"dark-important.min.css": "7FC057E91B5BE14BF91A549EB33D9828D044546DBC5F47EF8E7829CD64BD5774",
"dark-navbar.min.css": "C02A4001942DE8E26C61520C2499D80512D8CBA0BBA81E7065BA219C4DF9C11D",
"dark-schedule.min.js": "853C446547603F4F0425F19F09F73335C9EC451A790C1C07E5E5B88A09E9B453",
"dark-styles.min.js": "A6CFEC32B3F78FD2BD5DBB2347A517F9A633802098DF458F70CBE094F9CAD854",
"dark.min.css": "72BFC81337E62915EB1C7409C00D64B78D813AA82D3ADCC9E654B1EFAAD15634",
"dark.min.css": "DC7E2869634F8135CB71ADBDCA06F25FE8C78599A72972FA3E3136BAF96D9E16",
"debounce.min.js": "54D33E1273C1F3FE19550BF1844339C3D54D6B01DF8A39C3162D95B93B079CFA",
"default-danmaku-settings.min.css": "D9942B184FEDA7B08CFA0C34920E97D7A83B81762DCBF757642EBB60F95FF25D",
"default-danmaku-settings.min.js": "30A8D36137B5A4D560BD47F7A264F77C7DD4428291DF3E7EBD8D632B2AE9973E",
@ -40,7 +40,7 @@
"download-danmaku.min.js": "8A39F93E266A7BE09091D06EF3CC40803CD2F813AEDD1EC3C822D64151770D6E",
"download-video.min.css": "544D7CA625C22BA021D3F3629E129253E7A9BF97C51C590987C3A18DB0597CC2",
"download-video.min.html": "DA50CED55A3DF543AFC3048EBD73C9C27664BDAA637614E6C7F318E9B201ABFC",
"download-video.min.js": "BCC3A0C78C819A51A0EEE15139EFC7D950A2F193D54DE6DDCE20263F74842003",
"download-video.min.js": "BC38D7BBDAAF888A52D4E275CC4433CC9E29DF0D5817BED8AE5B3A66EC082A8C",
"dpi-img.vue.min.js": "D4833A242EBDD84834B11DB4CEB68B8807BDFC9693C3E1AAE73071986FE26F78",
"expand-danmaku.min.js": "B21658C40085AEA8DC49652AE62EB8610BB2EBEAF7A9C9AF69EF3B11E08EEC8D",
"expand-description.min.css": "58C7710A50521B80F7D872BDC4C652610D84C4FABC6874BA66DA37B4F8759224",
@ -56,9 +56,9 @@
"full-page-title.min.js": "D761A0C4A8B0A25CC0A23A10C495C2A5E6028BC19C6460C8ABB8D4B0B855E748",
"full-tweets-title.min.css": "13A0CF1C96F374CED3FA59A532E28B4B620D7A4C374385A363F32AD1A7656764",
"full-tweets-title.min.js": "DD57BB732ABEF7739CA84AEFF97E86F8984FCC4A8A75B957213622350B2A7C37",
"gui-settings.min.css": "9C7CABF974C76DCFAD6DBECAD8CCA7C1EFA1EAEA9977DF5F0013B3F4FA664FCD",
"gui-settings.min.html": "AA990C3CE45A68755AA9BED58AC4B13CAFC88C81FEF7C080DFB40A248D269F46",
"gui-settings.min.js": "33DF9A8702A721E660106D225A3BCA000863568FF289E7DBAF90584378E1D273",
"gui-settings.min.css": "DB583E6B4DFDE26678BC00DEC23714FBEFEC13D1BC21CA0DA6292EA9A679A14F",
"gui-settings.min.html": "3CA6BC8AE8E1481A84B931E9CA126682B7C85C382679442A5133B9954A0AA503",
"gui-settings.min.js": "BE5C8F6D75F1AAF9DEBC1FA4D3F4CC3834F0EF647BDBECFC3C8A44E72CE177BF",
"haruna-scale.min.js": "7B0F89A664B6A3D0BE21F7501660058DE3DC0881A81FCDA44B9F3C31BBD73D30",
"hide-bangumi-reviews.min.js": "CC3CE6B3F1606F8AB0A4ADAD3B16E6DA9245D0676ACF74B97FB143FBFF0C7223",
"hide-banner.min.css": "FF157AF84741AF0564FE2930CC49F524F99A41739DB4C44DC944EC6F4F620A0F",
@ -68,8 +68,8 @@
"hide-top-search.min.js": "19641CCB6A883DB5DD143A768606DEF0C571572D91CCD3FD5A9302A2A916E19B",
"home-video.vue.min.js": "D1A4CFB69C8224247D1C085D0AC61011B18F349F551A835C1449E12B9693C963",
"i18n.de-DE.min.js": "5BDAC5F0493F447A98B4D308817B21AB2787BEF9E3929EA37F0D2ACD3D879337",
"i18n.en-US.min.js": "C9D7D5E586FC4E08B6B6D78806076EC10D2C2362BEA8A7E4AA02A63BE74AC065",
"i18n.ja-JP.min.js": "02A0C1FDDBACFABE3D4E62342BD637C93421489F5BD3A1E251539F0AA3279456",
"i18n.en-US.min.js": "9DF9263CB0D4CA8FDB17A75F6ECA0D48F8B34540947C70C4FEA0403613DD1C43",
"i18n.ja-JP.min.js": "9D924D58A6CD265EB95DA29B7E64885CD74089EC14A07C36CF3EAF42C8BEE33B",
"i18n.min.css": "6B6A1C2F3E222CF1B686BF94F939B494471C979CC6A5F53CFBAC2F4E32048DD4",
"i18n.min.js": "7FCB933FD43C05A152B672D4BD721F3ECEBA6AD29648379947DAAFC403907B38",
"i18n.zh-TW.min.js": "803F67270809E3258E2B302ADE542B12EF222C83EDC67FB8C68301C5F4E3A1CC",
@ -105,25 +105,25 @@
"remove-top-mask.min.js": "A15C1EC10D2E1A61845B1ADAE51860553F96427059E10443B1E53FAF48F45304",
"remove-watermark.min.js": "EF8A48E379DE9400E7FCEA7A455EC966B56ADCE31D722FF02C8111FB92A148AF",
"screenshot.min.css": "C8BFD4B0A76A758477B767338ABA1D0A49408EDBA861351EA5CB57070515CE76",
"screenshot.min.js": "DF1F34103A1DB88A7A4F6DDAA3C8F55710FC6C11802CED917A026D66A9F7FE3B",
"screenshot.min.js": "655DE531468A00BCE2F78B406B9A79C6D00F22A299D37BFC8F5C775E15D26DDC",
"scrollbar.min.css": "9792340121B6EE6E618A3F62AABD9C992D9C325803DF4879C8A74F02DA0E2213",
"search.vue.min.js": "1A4E23DFE187B1A3792F3D8E7847B9F2E8593043A8527C7B1D644CA171FC8376",
"seeds-to-coins.min.js": "3F1D383501A6E989255808A82850903EB10931CBE0ADE652AADED69FB9502C57",
"settings-search.min.js": "C3B605AF2581F562415B6AA30F7B1D825A74EB0B2B83A5F17A303B7B5646E261",
"settings-side-bar.min.js": "CC0E3477BF8574606720D3261C4A0202713E42B30CFE737403E629CBA97B2A98",
"settings-tooltip.en-US.min.js": "0D70BE86EABBC87E8E8249AD72B298EA249BD721C46B34764FAF10EE39CE1789",
"settings-side-bar.min.js": "B299CF87359B416711F4DED3BCF0A32A4CA4C9B1B96D045B383A20C641C6C1C7",
"settings-tooltip.en-US.min.js": "44E33B86E82D55BF0575D9AF28EADF12B6CDB05A822C0344CFC2B56076E85F61",
"settings-tooltip.ja-JP.min.js": "E02B7D9AD4AD241AF6EBA5F15B11AC6DC2214A1BBDB868A1F0AB7FF0B373BB74",
"settings-tooltip.loader.min.js": "F9DFB09E32B8C814A61EE7E7D354C15A6FEF39BBBC22F476A930526DC26DA558",
"settings-tooltip.loader.min.js": "B3941A6B9A5AC693832EA49015397114DC95137E12E6D1ABC311EFF3A3D6F319",
"settings-tooltip.min.css": "0C138D5CF16B9068E73D173D229B2B458C15F50272DA73D6A580921C5A848845",
"settings-tooltip.min.js": "E9ABA72B3C29CA850342109E57B055B193F3356DD59876B202E8E908AE6247C9",
"settings-tooltip.zh-CN.min.js": "38D45D4908ECEA26CA3A9457E81B12ABF6DEBE690051ECA77CBA46D20E3399ED",
"settings-tooltip.zh-CN.min.js": "8C32C96C69AC6BFD43725CF243EEE37043351E2FD96B84347AC087D39AA221B3",
"show-dead-video-title.min.js": "945C4F0E5FB2C62DB21C42FCE01829BAE7B13F4FBD90731CB85C38B82801B1A8",
"simple-home.vue.min.js": "F64C88FB33612D715A4ED98A398E6D0E003DCDBF7A2CEDBA9FEC56A63E761A3C",
"simplify-home.min.css": "37DC1F7ABDA7BD514F1DF5B3D470C620CEDC4AD1D9EFDFD8D9E43F6A45B3CEB3",
"simplify-home.min.js": "A81F7063A6EBA963E80673B0E285173D142C354388894AB4A872BFC73DEA4789",
"simplify-home.vue.min.js": "D67FE9B51098D65B863854879CA3EF8026F342912CA9B56F5DBB10A8C4BC948B",
"simplify-liveroom.min.css": "0F24C08B156121AF7B321448572996B29519881CC08D2EAA340BE2510E90B458",
"simplify-liveroom.min.js": "68750BB42318229348198961E88AC92E4F8D4F2AF9A8CAEFF4C6F228FC037AE6",
"simplify-liveroom.min.js": "5830D4C0A222EFDEAFE5D49989F3C0F8D1E8900D9ECC461961E4B51D499C2C92",
"skip-charge-list.min.css": "D3C988CE131CEBFAC8A60360529C83EC4AE1B9EA122F9A6924F19963E25A4FE9",
"skip-charge-list.min.js": "D057258F8EE77D949147174585B1A8C640DDB74E0C0B711A50AEAC8D6792F49F",
"slip.min.js": "0905C7F3B0BFA6535D48CA9A4D2DDCE0EDD83E66AA3D19AA3C1A6A53ECDD15FE",
@ -132,7 +132,7 @@
"theme-colors.min.js": "3001D5DAD0EFBAEC7F96C51FD3BE2C4677E358AD70D8DD019D2280EA450A34E7",
"title.min.js": "0F738220A30AB7707BD1F7EA0380279E55295DDE500D313E8AC39EF713385B2C",
"toast.min.css": "6F4343B67FF70C0A1217051F92BC854EE7A510A5AD5F115D98203C61C5A57D27",
"toast.min.js": "F363B62C0C53F6CE5C13A186055EA40C0BC3E73A5FFD11586DDB4A17335CC930",
"toast.min.js": "9B71F0AC57C75F8BDD267839101881ACAC61ED52EC67DEE30B97965D4CB21713",
"touch-navbar.min.js": "21EF203296CF795E2471D04E7C44F5FA734FC7EB3EF6187B5AC6D562572D2649",
"touch-player.min.css": "70F9BB443A8D1D629EF30BEDD48BC766C2F6640CBA7C6C35B6B002FCD8BF2A66",
"touch-player.min.js": "28F2AF5C066CC4C3A2490D844861188907D1BB7B254F4B8A403F0AB3C7F4FB31",

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
min/dark.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{return(e,t)=>{const{ThemeColors:n}=t.import("theme-colors");const{SettingsSearch:i}=t.import("settings-search");const{Validator:s}=t.import("text-validate");let o=[];let c=[];let r=[];function l(e){let t=e.nextElementSibling;const n=[];while(t!==null&&!t.classList.contains("category")){n.push(t);t=t.nextElementSibling}return n}function a(){r.forEach(t=>t.value=e[t.getAttribute("key")]);c.forEach(t=>t.checked=e[t.getAttribute("key")])}function d(){document.querySelector(".gui-settings-mask").addEventListener("click",()=>{document.querySelectorAll(".gui-settings-widgets-box,.gui-settings-box,.gui-settings-mask,.bilibili-evolved-about").forEach(e=>e.classList.remove("opened"))});r.forEach(t=>{t.setAttribute("placeholder",e[t.getAttribute("key")])});document.querySelectorAll(".gui-settings-content ul li.category").forEach(e=>{e.addEventListener("click",e=>{const t=document.querySelector(".gui-settings-search");if(t.value!==""){t.value="";raiseEvent(t,"input")}e.currentTarget.classList.toggle("folded");l(e.currentTarget).forEach(e=>e.classList.toggle("folded"))})});document.querySelectorAll(".gui-settings-dropdown>input").forEach(e=>{e.addEventListener("click",e=>{e.currentTarget.parentElement.classList.toggle("opened")})})}function u(){c.forEach(t=>{t.addEventListener("change",()=>{const n=t.getAttribute("key");const i=t.checked;e[n]=i})});r.forEach(t=>{t.addEventListener("change",()=>{const n=t.getAttribute("key");const i=s.getValidator(n).validate(t.value);e[n]=i;t.value=i})})}function g(){const e=o.map(e=>[e.getAttribute("dependencies").split(" ").map(e=>o.find(t=>t.getAttribute("key")===e)),e]);const t=e=>e.nodeName.toUpperCase()==="LI"?e:t(e.parentElement);e.forEach(([e,n])=>{if(e[0]===undefined){return}const i=()=>{if(e.every(e=>e.checked)){t(n).classList.remove("disabled")}else{t(n).classList.add("disabled")}};e.forEach(e=>e.addEventListener("change",i));i()})}function f(){if(typeof offlineData!=="undefined"){}}function p(){if(!CSS.supports("backdrop-filter","blur(24px)")&&!CSS.supports("-webkit-backdrop-filter","blur(24px)")){o.find(e=>e.getAttribute("key")==="blurVideoControl").disabled=true;e.blurVideoControl=false}if(window.devicePixelRatio===1){o.find(e=>e.getAttribute("key")==="harunaScale").disabled=true;o.find(e=>e.getAttribute("key")==="imageResolution").disabled=true;e.harunaScale=false;e.imageResolution=false}}function b(){for(const[e,t]of Object.entries(Resource.displayNames)){const n=o.find(t=>t.getAttribute("key")===e);if(!n){continue}switch(n.type){case"checkbox":n.nextElementSibling.nextElementSibling.innerHTML=t;break;case"text":const e=n.parentElement;if(e.classList.contains("gui-settings-textbox-container")){n.previousElementSibling.innerHTML=t}else if(e.classList.contains("gui-settings-dropdown")){e.previousElementSibling.innerHTML=t}break;default:break}}}(async()=>{t.applyStyle("guiSettingsStyle");t.applyImportantStyle("iconsStyle");document.body.classList.add("round-corner");const e=document.body&&unsafeWindow.parent.window!==unsafeWindow;if(e){document.querySelector(".gui-settings-icon-panel").style.display="none"}const s=t.data.guiSettingsHtml.text;document.body.insertAdjacentHTML("beforeend",s);const{style:l}=await t.importAsync("mdi");if(!l){document.body.insertAdjacentHTML("afterbegin",`<link rel="stylesheet" href="//cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css">`)}t.applyDropdownOptions();const m=document.querySelector(".widgets-container");const y=m.querySelector(".empty-tip");Observer.childList(m,()=>{if(m.childElementCount<=1){y.classList.add("show")}else{y.classList.remove("show")}});(new n).setupDom();const h=document.querySelectorAll(".gui-settings-widgets-box,.gui-settings-box");const E=document.querySelector(".gui-settings-icon-panel");E.addEventListener("mouseover",()=>{raiseEvent(E,"be:load");h.forEach(e=>e.classList.add("loaded"));o=[...document.querySelectorAll("input[key]")];c=o.filter(e=>e.type==="checkbox");r=o.filter(e=>e.type==="text"&&!e.parentElement.classList.contains("gui-settings-dropdown"));d();f();a();g();u();p();b();new i},{once:true})})()}})();
(()=>{return(e,t)=>{const{ThemeColors:n}=t.import("theme-colors");const{SettingsSearch:i}=t.import("settings-search");const{Validator:s}=t.import("text-validate");let o=[];let c=[];let r=[];function a(e){let t=e.nextElementSibling;const n=[];while(t!==null&&!t.classList.contains("category")){n.push(t);t=t.nextElementSibling}return n}function l(){r.forEach(t=>t.value=e[t.getAttribute("key")]);c.forEach(t=>t.checked=e[t.getAttribute("key")])}function d(){document.querySelector(".gui-settings-mask").addEventListener("click",()=>{document.querySelectorAll(".gui-settings-widgets-box,.gui-settings-box,.gui-settings-mask,.bilibili-evolved-about").forEach(e=>e.classList.remove("opened"))});r.forEach(t=>{t.setAttribute("placeholder",e[t.getAttribute("key")])});document.querySelectorAll(".gui-settings-content ul li.category").forEach(e=>{e.addEventListener("click",e=>{const t=document.querySelector(".gui-settings-search");if(t.value!==""){t.value="";raiseEvent(t,"input")}e.currentTarget.classList.toggle("folded");a(e.currentTarget).forEach(e=>e.classList.toggle("folded"))})});document.querySelectorAll(".gui-settings-dropdown>input").forEach(e=>{e.addEventListener("click",e=>{e.currentTarget.parentElement.classList.toggle("opened")})})}function u(){c.forEach(t=>{t.addEventListener("change",()=>{const n=t.getAttribute("key");const i=t.checked;e[n]=i})});r.forEach(t=>{t.addEventListener("change",()=>{const n=t.getAttribute("key");const i=s.getValidator(n).validate(t.value);e[n]=i;t.value=i})})}function g(){const e=o.map(e=>[e.getAttribute("dependencies").split(" ").map(e=>o.find(t=>t.getAttribute("key")===e)),e]);const t=e=>e.nodeName.toUpperCase()==="LI"?e:t(e.parentElement);e.forEach(([e,n])=>{if(e[0]===undefined){return}const i=()=>{if(e.every(e=>e.checked)){t(n).classList.remove("disabled")}else{t(n).classList.add("disabled")}};e.forEach(e=>e.addEventListener("change",i));i()})}function p(){if(typeof offlineData!=="undefined"){}}function f(){if(!CSS.supports("backdrop-filter","blur(24px)")&&!CSS.supports("-webkit-backdrop-filter","blur(24px)")){o.find(e=>e.getAttribute("key")==="blurVideoControl").disabled=true;e.blurVideoControl=false}if(window.devicePixelRatio===1){o.find(e=>e.getAttribute("key")==="harunaScale").disabled=true;o.find(e=>e.getAttribute("key")==="imageResolution").disabled=true;e.harunaScale=false;e.imageResolution=false}}function b(){for(const[e,t]of Object.entries(Resource.displayNames)){const n=o.find(t=>t.getAttribute("key")===e);if(!n){continue}switch(n.type){case"checkbox":n.nextElementSibling.nextElementSibling.innerHTML=t;break;case"text":const e=n.parentElement;if(e.classList.contains("gui-settings-textbox-container")){n.previousElementSibling.innerHTML=t}else if(e.classList.contains("gui-settings-dropdown")){e.previousElementSibling.innerHTML=t}break;default:break}}}(async()=>{t.applyStyle("guiSettingsStyle");t.applyImportantStyle("iconsStyle");document.body.classList.add("round-corner");const e=document.body&&unsafeWindow.parent.window!==unsafeWindow;if(e){document.querySelector(".gui-settings-icon-panel").style.display="none"}const s=t.data.guiSettingsHtml.text;document.body.insertAdjacentHTML("beforeend",s);const{style:a}=await t.importAsync("mdi");if(!a){document.body.insertAdjacentHTML("afterbegin",`<link rel="stylesheet" href="//cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css">`)}const m=document.querySelector(".widgets-container");const y=m.querySelector(".empty-tip");Observer.childList(m,()=>{if(m.childElementCount<=1){y.classList.add("show")}else{y.classList.remove("show")}});const h=document.querySelectorAll(".gui-settings-widgets-box,.gui-settings-box");const E=document.querySelector(".gui-settings-icon-panel");E.addEventListener("mouseover",async()=>{const{loadTooltip:e}=await t.importAsync("settings-tooltip.loader");await e();await t.applyDropdownOptions();t.applyWidgets();raiseEvent(E,"be:load");raiseEvent(dq(".bilibili-evolved-about"),"be:about-load");(new n).setupDom();h.forEach(e=>e.classList.add("loaded"));o=[...document.querySelectorAll("input[key]")];c=o.filter(e=>e.type==="checkbox");r=o.filter(e=>e.type==="text"&&!e.parentElement.classList.contains("gui-settings-dropdown"));d();p();l();g();u();f();b();new i},{once:true})})()}})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{return(e,t)=>{if(document.querySelector(".gui-settings-icon-panel")===null){document.body.insertAdjacentHTML("beforeend",`\n <div class='gui-settings-icon-panel icons-enabled'>\n <div class='gui-settings-widgets' title='附加功能'>\n <i class="icon-widgets"></i>\n </div>\n <div class='gui-settings' title='设置'>\n <i class="icon-settings"></i>\n </div>\n </div>`);dq(".gui-settings").addEventListener("click",e=>{if(e.shiftKey===false){dqa(".gui-settings-box,.gui-settings-mask").forEach(e=>e.classList.add("opened"))}else{dqa(".bilibili-evolved-about,.gui-settings-mask").forEach(e=>e.classList.add("opened"));raiseEvent(document.querySelector(".bilibili-evolved-about"),"be:about-load")}});dq(".gui-settings-widgets").addEventListener("click",e=>{if(e.shiftKey===false){dqa(".gui-settings-widgets-box,.gui-settings-mask").forEach(e=>e.classList.add("opened"))}else{debugger}});const e=dq(".gui-settings-icon-panel .gui-settings-widgets>i");const t=dq(".gui-settings-icon-panel .gui-settings>i");let i=false;let s=false;const n=()=>{t.classList.remove("icon-info");t.classList.add("icon-settings");t.parentElement.title="设置";e.classList.remove("icon-time");e.classList.add("icon-widgets");e.parentElement.title="附加功能";i=false;s=false};const d=()=>{t.classList.remove("icon-settings");t.classList.add("icon-info");t.parentElement.title="关于";e.classList.remove("icon-widgets");e.classList.add("icon-time");e.parentElement.title="「ザ・ワールド」";if(!i){document.body.addEventListener("keyup",n,{once:true});i=true}if(!s){window.addEventListener("blur",n,{once:true});s=true}};document.body.addEventListener("keydown",e=>{if(document.activeElement&&["input","textarea"].includes(document.activeElement.nodeName.toLowerCase())){return}if(e.shiftKey===true){d()}})}const i=(t=e.sideBarOffset)=>{document.body.style.setProperty("--side-bar-offset",t+"%")};addSettingsListener("sideBarOffset",i);i()}})();
(()=>{return(e,t)=>{if(document.querySelector(".gui-settings-icon-panel")===null){document.body.insertAdjacentHTML("beforeend",`\n <div class='gui-settings-icon-panel icons-enabled'>\n <div class='gui-settings-widgets' title='附加功能'>\n <i class="icon-widgets"></i>\n </div>\n <div class='gui-settings' title='设置'>\n <i class="icon-settings"></i>\n </div>\n </div>`);dq(".gui-settings").addEventListener("click",e=>{if(e.shiftKey===false){dqa(".gui-settings-box,.gui-settings-mask").forEach(e=>e.classList.add("opened"))}else{dqa(".bilibili-evolved-about,.gui-settings-mask").forEach(e=>e.classList.add("opened"));raiseEvent(dq(".bilibili-evolved-about"),"be:about-load-community")}});dq(".gui-settings-widgets").addEventListener("click",e=>{if(e.shiftKey===false){dqa(".gui-settings-widgets-box,.gui-settings-mask").forEach(e=>e.classList.add("opened"))}else{debugger}});const e=dq(".gui-settings-icon-panel .gui-settings-widgets>i");const t=dq(".gui-settings-icon-panel .gui-settings>i");let i=false;let s=false;const n=()=>{t.classList.remove("icon-info");t.classList.add("icon-settings");t.parentElement.title="设置";e.classList.remove("icon-time");e.classList.add("icon-widgets");e.parentElement.title="附加功能";i=false;s=false};const d=()=>{t.classList.remove("icon-settings");t.classList.add("icon-info");t.parentElement.title="关于";e.classList.remove("icon-widgets");e.classList.add("icon-time");e.parentElement.title="「ザ・ワールド」";if(!i){document.body.addEventListener("keyup",n,{once:true});i=true}if(!s){window.addEventListener("blur",n,{once:true});s=true}};document.body.addEventListener("keydown",e=>{if(document.activeElement&&["input","textarea"].includes(document.activeElement.nodeName.toLowerCase())){return}if(e.shiftKey===true){d()}})}const i=(t=e.sideBarOffset)=>{document.body.style.setProperty("--side-bar-offset",t+"%")};addSettingsListener("sideBarOffset",i);i()}})();

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{return(t,e)=>{function n(t){const e=t.querySelector("input");if(e){return e.getAttribute("key")}return null}(async()=>{e.applyStyle("settingsTooltipStyle");const{toolTips:t}=await e.importAsync(`settings-tooltip.${getI18nKey()}`);const s=await SpinQuery.select(".gui-settings-tooltip");if(!s){return}document.querySelectorAll(".gui-settings-content>ul>li").forEach(e=>{e.addEventListener("mouseover",()=>{const i=n(e);if(i===null||t===null){return}const o=t.get(i);if(o!==undefined){s.innerHTML=o;s.classList.add("show")}});e.addEventListener("mouseout",()=>{s.classList.remove("show")})})})()}})();
(()=>{return(t,e)=>{function n(t){const e=t.querySelector("input");if(e){return e.getAttribute("key")}return null}const o=async()=>{e.applyStyle("settingsTooltipStyle");const{toolTips:t}=await e.importAsync(`settings-tooltip.${getI18nKey()}`);const o=await SpinQuery.select(".gui-settings-tooltip");if(!o){return}document.querySelectorAll(".gui-settings-content>ul>li").forEach(e=>{e.addEventListener("mouseover",()=>{const s=n(e);if(s===null||t===null){return}const i=t.get(s);if(i!==undefined){o.innerHTML=i;o.classList.add("show")}});e.addEventListener("mouseout",()=>{o.classList.remove("show")})})};return{export:{loadTooltip:o}}}})();

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{return(e,i)=>{const s={vip:"老爷图标",fansMedal:"粉丝勋章",title:"活动头衔",userLevel:"用户等级",guard:"舰长图标",systemMessage:"全区广播",welcomeMessage:"欢迎信息",giftMessage:"礼物弹幕",guardPurchase:"上舰提示",popup:"抽奖提示",skin:"房间皮肤"};return{widget:{condition:()=>document.URL.startsWith(`https://live.bilibili.com/`),content:`\n <div class="gui-settings-flat-button" style="position: relative" id="simplify-liveroom">\n <i class="mdi mdi-24px mdi-settings"></i>\n <span>简化直播间</span>\n <div class="simplify-liveroom-settings popup">\n <ul>\n <li v-for="item in items" v-on:click="itemClick(item)">\n <i class="mdi mdi-18px" v-bind:class="{'mdi-eye': !item.checked, 'mdi-eye-off': item.checked}"></i>\n {{item.name}}\n </li>\n </ul>\n </div>\n </div>\n `,success:()=>{const i=document.querySelector("#simplify-liveroom");const t=document.querySelector(".gui-settings-mask");i.addEventListener("click",e=>{const i=document.querySelector(".simplify-liveroom-settings");if(i.contains(e.target)||e.target===i){return}i.classList.toggle("opened")});i.addEventListener("mouseenter",()=>t.classList.add("transparent"));i.addEventListener("mouseleave",()=>t.classList.remove("transparent"));let n=e.simplifyLiveroomSettings.skin;const a=["#head-info-vm","#gift-control-vm","#rank-list-vm","#rank-list-ctnr-box",".gift-panel.base-panel",".gift-panel.extend-panel",".seeds-wrap>div:first-child",".gift-section>div:last-child",".z-gift-package>div>div",".right-action"];const c="live-skin-coloration-area";a.forEach(e=>{SpinQuery.select(e,i=>{Observer.attributes(e,e=>{e.forEach(e=>{if(e.attributeName==="class"){if(n&&i.classList.contains(c)){i.classList.remove(c)}else if(!n&&!i.classList.contains(c)){i.classList.add(c)}}})})})});const o=(e,i)=>{document.body.classList[e?"add":"remove"](`simplify-${i}`);if(i==="skin"){n=e;a.forEach(i=>{SpinQuery.select(i,i=>i.classList[e?"remove":"add"]("live-skin-coloration-area"))})}};new Vue({el:".simplify-liveroom-settings",data:{items:Object.entries(s).map(([i,s])=>{const t=e.simplifyLiveroomSettings[i];o(t,i);return{key:i,name:s,checked:t}})},methods:{itemClick(i){i.checked=!i.checked;o(i.checked,i.key);e.simplifyLiveroomSettings=Object.assign(e.simplifyLiveroomSettings,{[i.key]:i.checked})}}})}}}}})();
(()=>{return(e,i)=>{const s={vip:"老爷图标",fansMedal:"粉丝勋章",title:"活动头衔",userLevel:"用户等级",guard:"舰长图标",systemMessage:"全区广播",welcomeMessage:"欢迎信息",giftMessage:"礼物弹幕",guardPurchase:"上舰提示",popup:"抽奖提示",skin:"房间皮肤"};let t=e.simplifyLiveroomSettings.skin;const n=["#head-info-vm","#gift-control-vm","#rank-list-vm","#rank-list-ctnr-box",".gift-panel.base-panel",".gift-panel.extend-panel",".seeds-wrap>div:first-child",".gift-section>div:last-child",".z-gift-package>div>div",".right-action"];const c="live-skin-coloration-area";n.forEach(e=>{SpinQuery.select(e,i=>{Observer.attributes(e,e=>{e.forEach(e=>{if(e.attributeName==="class"){if(t&&i.classList.contains(c)){i.classList.remove(c)}else if(!t&&!i.classList.contains(c)){i.classList.add(c)}}})})})});const o=(e,i)=>{document.body.classList[e?"add":"remove"](`simplify-${i}`);if(i==="skin"){t=e;n.forEach(i=>{SpinQuery.select(i,i=>i.classList[e?"remove":"add"]("live-skin-coloration-area"))})}};const a=()=>document.URL.startsWith(`https://live.bilibili.com/`);if(a()){Object.keys(s).forEach(i=>{const s=e.simplifyLiveroomSettings[i];o(s,i)})}return{widget:{condition:a,content:`\n <div class="gui-settings-flat-button" style="position: relative" id="simplify-liveroom">\n <i class="mdi mdi-24px mdi-settings"></i>\n <span>简化直播间</span>\n <div class="simplify-liveroom-settings popup">\n <ul>\n <li v-for="item in items" v-on:click="itemClick(item)">\n <i class="mdi mdi-18px" v-bind:class="{'mdi-eye': !item.checked, 'mdi-eye-off': item.checked}"></i>\n {{item.name}}\n </li>\n </ul>\n </div>\n </div>\n `,success:()=>{const i=document.querySelector("#simplify-liveroom");const t=document.querySelector(".gui-settings-mask");i.addEventListener("click",e=>{const i=document.querySelector(".simplify-liveroom-settings");if(i.contains(e.target)||e.target===i){return}i.classList.toggle("opened")});i.addEventListener("mouseenter",()=>t.classList.add("transparent"));i.addEventListener("mouseleave",()=>t.classList.remove("transparent"));new Vue({el:".simplify-liveroom-settings",data:{items:Object.entries(s).map(([i,s])=>{const t=e.simplifyLiveroomSettings[i];o(t,i);return{key:i,name:s,checked:t}})},methods:{itemClick(i){i.checked=!i.checked;o(i.checked,i.key);e.simplifyLiveroomSettings=Object.assign(e.simplifyLiveroomSettings,{[i.key]:i.checked})}}})}}}}})();

2
min/toast.min.js vendored
View File

@ -1 +1 @@
(()=>{return(t,s)=>{var e;(function(t){t["Default"]="default";t["Info"]="info";t["Success"]="success";t["Error"]="error"})(e||(e={}));class a{constructor(t="",s="",a=e.Default){this.creationTime=new Date;this.type=a;this.message=t;this.title=s;this.duration=3e3}show(){r.cards.splice(0,0,this);if(this.duration!==undefined){setTimeout(()=>this.dismiss(),this.duration)}}dismiss(){if(r.cards.includes(this)){r.cards.splice(r.cards.indexOf(this),1)}}get element(){return dq(`.toast-card[key='${this.key}']`)}get key(){return this.creationTime.toISOString()}static get container(){return document.querySelector(".toast-card-container")}static createToastContainer(){if(!document.querySelector(".toast-card-container")){document.body.insertAdjacentHTML("beforeend",`\n <transition-group class="toast-card-container" name="toast-card-container" tag="div">\n <toast-card v-for="card of cards" v-bind:key="card.key" v-bind:card="card"></toast-card>\n </transition-group>`)}}static internalShow(t,s,e,r){const n=new a(t,s,r);n.duration=e;n.show();return n}static show(t,s,a){return this.internalShow(t,s,a,e.Default)}static info(t,s,a){return this.internalShow(t,s,a,e.Info)}static success(t,s,a){return this.internalShow(t,s,a,e.Success)}static error(t,s,a){return this.internalShow(t,s,a,e.Error)}}s.applyStyle("toastStyle");Vue.component("toast-card",{props:["card"],template:`\n <div class="toast-card icons-enabled visible" v-bind:class="'toast-' + card.type">\n <div class="toast-card-border"></div>\n <div class="toast-card-header">\n <h1 class="toast-card-title">{{card.title}}</h1>\n <div class="toast-card-dismiss" v-on:click="card.dismiss()">\n <svg style="width:22px;height:22px" viewBox="0 0 24 24">\n <path\n d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />\n </svg>\n </div>\n </div>\n <div class="toast-card-message" v-html="card.message"></div>\n </div>\n `});a.createToastContainer();const r=new Vue({el:".toast-card-container",data:{cards:[]}});return{export:a}}})();
(()=>{return(t,s)=>{var a;(function(t){t["Default"]="default";t["Info"]="info";t["Success"]="success";t["Error"]="error"})(a||(a={}));let e;class r{constructor(t="",s="",e=a.Default){this.creationTime=new Date;this.type=e;this.message=t;this.title=s;this.duration=3e3}show(){r.containerVM.cards.splice(0,0,this);if(this.duration!==undefined){setTimeout(()=>this.dismiss(),this.duration)}}dismiss(){if(r.containerVM.cards.includes(this)){r.containerVM.cards.splice(r.containerVM.cards.indexOf(this),1)}}get element(){return dq(`.toast-card[key='${this.key}']`)}get key(){return this.creationTime.toISOString()}static get containerVM(){if(!e){r.createToastContainer()}return e}static createToastContainer(){if(!document.querySelector(".toast-card-container")){document.body.insertAdjacentHTML("beforeend",`\n <transition-group class="toast-card-container" name="toast-card-container" tag="div">\n <toast-card v-for="card of cards" v-bind:key="card.key" v-bind:card="card"></toast-card>\n </transition-group>`);e=new Vue({el:".toast-card-container",components:{"toast-card":{props:["card"],template:`\n <div class="toast-card icons-enabled visible" v-bind:class="'toast-' + card.type">\n <div class="toast-card-border"></div>\n <div class="toast-card-header">\n <h1 class="toast-card-title">{{card.title}}</h1>\n <div class="toast-card-dismiss" v-on:click="card.dismiss()">\n <svg style="width:22px;height:22px" viewBox="0 0 24 24">\n <path\n d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />\n </svg>\n </div>\n </div>\n <div class="toast-card-message" v-html="card.message"></div>\n </div>\n `}},data:{cards:[]}})}}static internalShow(t,s,a,e){const n=new r(t,s,e);n.duration=a;n.show();return n}static show(t,s,e){return this.internalShow(t,s,e,a.Default)}static info(t,s,e){return this.internalShow(t,s,e,a.Info)}static success(t,s,e){return this.internalShow(t,s,e,a.Success)}static error(t,s,e){return this.internalShow(t,s,e,a.Error)}}s.applyStyle("toastStyle");return{export:r}}})();

View File

@ -1,6 +1,6 @@
// ==UserScript==
// @name Bilibili Evolved (Preview)
// @version 1.9.1
// @version 1.9.5
// @description Bilibili Evolved 的预览版, 可以抢先体验新功能.
// @author Grant Howard, Coulomb-G
// @copyright 2019, Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G)
@ -27,6 +27,12 @@
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/logo-small.png
// @icon64 https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/logo.png
// ==/UserScript==
Vue.config.productionTip = false
Vue.config.devtools = false
if (GM_getValue('customNavbar') === true
&& document.URL === 'https://message.bilibili.com/pages/nav/index_new_sync') {
return
}
import { logError, raiseEvent, loadLazyPanel, contentLoaded, fixed } from './utils'
import { settings, loadSettings, saveSettings, onSettingsChange, settingsChangeHandlers } from './settings'
import { Ajax, setupAjaxHook } from './ajax'
@ -44,9 +50,6 @@ import { StyleManager } from './style-manager'
import { ResourceManager } from './resource-manager'
try {
Vue.config.productionTip = false
Vue.config.devtools = false
setupAjaxHook()
const events = {}
for (const name of ['init', 'styleLoaded', 'scriptLoaded']) {
events[name] = {
@ -80,9 +83,20 @@ try {
})
loadResources()
loadSettings()
if (settings.ajaxHook) {
setupAjaxHook()
}
const resources = new ResourceManager()
events.init.complete()
resources.styleManager.prefetchStyles()
// if (settings.customNavbar) {
// contentLoaded(() => {
// document.body.classList.add('custom-navbar-loading')
// if (settings.useDarkStyle) {
// document.body.classList.add('dark')
// }
// })
// }
events.styleLoaded.complete()
Object.assign(unsafeWindow.bilibiliEvolved, {
@ -160,7 +174,43 @@ try {
Object.assign(unsafeWindow.bilibiliEvolved, { addons })
})
.catch(error => logError(error))
contentLoaded(applyScripts)
const loadingMode = settings.scriptLoadingMode
switch (loadingMode) {
case '延后':
fullyLoaded(applyScripts)
break
case '同时':
contentLoaded(applyScripts)
break
case '自动':
case '延后(自动)':
{
const quickLoads = [
'//live.bilibili.com',
]
if (quickLoads.some(it => document.URL.includes(it))) {
contentLoaded(applyScripts)
} else {
fullyLoaded(applyScripts)
}
break
}
case '同时(自动)':
{
const delayLoads = [
'//www.bilibili.com/video/av',
'//www.bilibili.com/bangumi/play',
]
if (delayLoads.some(it => document.URL.includes(it))) {
fullyLoaded(applyScripts)
} else {
contentLoaded(applyScripts)
}
break
}
default:
break
}
} catch (error) {
logError(error)
}

View File

@ -61,6 +61,9 @@ export class ResourceManager {
key += 'Component'
}
resource.key = key
if (resource.text === undefined) {
resource.text = null
}
Resource.all[key] = resource
}
return resource
@ -149,8 +152,19 @@ export class ResourceManager {
// }
this.applyReloadables() // reloadables run sync
// await this.applyDropdownOptions();
this.applyWidgets() // No need to wait the widgets
this.checkUpdates(!isCacheValid)
// this.applyWidgets() // No need to wait the widgets
if (!isOffline() && settings.scriptDownloadMode === 'bundle') {
console.log('scheduled bundle update')
const checkUpdates = () => {
console.log('downloading bundle')
this.checkUpdates(!isCacheValid)
}
if ('requestIdleCallback' in window) {
window.requestIdleCallback(checkUpdates)
} else {
fullyLoaded(checkUpdates)
}
}
}
applyReloadables () {
const checkAttribute = (key, attributes) => {
@ -199,7 +213,7 @@ export class ResourceManager {
}
}
applyComponent (key, text) {
const func = eval(text)
const func = typeof text === 'string' ? eval(text) : text
if (func) {
try {
const attribute = func(settings, this) || {}
@ -215,66 +229,70 @@ export class ResourceManager {
}
}
}
async checkUpdates (fullDownload) {
async checkUpdates () {
if (isOffline()) {
return
}
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
const getHash = async (message) => {
const msgUint8 = new TextEncoder().encode(message)
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8)
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
return hashHex
}
if (fullDownload) {
const url = Resource.root + 'min/bundle.zip'
const zip = new JSZip()
await zip.loadAsync(await Ajax.monkey({
url,
responseType: 'blob',
}))
zip.forEach((filename, file) => {
const url = Resource.root + 'min/' + filename
const resource = Object.values(Resource.all).find(it => it.rawUrl === url)
if (resource) {
file.async('text').then(text => {
settings.cache = Object.assign(settings.cache, {
[resource.key]: text
})
getHash(text).then(hash => console.log(`full download: saved ${resource.key} (${hash})`))
})
}
})
} else {
const hashJson = await Ajax.monkey({
url: Resource.root + 'min/bundle.json',
responseType: 'json',
})
const scriptHashWrap = h => `(()=>{return${h}})();`
await Promise.all(Object.entries(hashJson).map(async ([name, hash]) => {
const url = Resource.root + 'min/' + name
const resource = Object.values(Resource.all).find(it => it.rawUrl === url)
if (!resource) {
return
}
const cache = settings.cache[resource.key]
if (cache) {
const cacheHash = await getHash(cache)
if (cacheHash.toLowerCase() !== hash.toLowerCase() &&
scriptHashWrap(cacheHash).toLowerCase() !== hash.toLowerCase()) {
console.log(`hash not match: ${resource.key} (${cacheHash.toLowerCase()}) !== (${hash.toLowerCase()})`)
await resource.download()
settings.cache = Object.assign(settings.cache, {
[resource.key]: resource.text
})
console.log(`downloaded ${resource.key}`)
} else {
console.log(`checked hash: ${resource.key}`)
}
}
}))
// const getHash = async (message) => {
// const msgUint8 = new TextEncoder().encode(message)
// const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8)
// const hashArray = Array.from(new Uint8Array(hashBuffer))
// const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
// return hashHex
// }
// if (fullDownload) {
const url = Resource.root + 'min/bundle.zip'
const zip = new JSZip()
await zip.loadAsync(await Ajax.monkey({
url,
responseType: 'blob',
}))
let cache = {}
const files = zip.file(/.+/)
for (const file of files) {
const url = Resource.root + 'min/' + file.name
const resource = Object.values(Resource.all).find(it => it.rawUrl === url)
if (resource) {
if (scriptVersion === 'Stable' && resource.alwaysPreview) {
continue
}
const text = await file.async('text')
cache[resource.key] = text
// console.log(`bundle update: saved ${resource.key}`)
}
}
settings.cache = Object.assign(settings.cache, cache)
console.log('bundle updated')
// } else {
// const hashJson = await Ajax.monkey({
// url: Resource.root + 'min/bundle.json',
// responseType: 'json',
// })
// const scriptHashWrap = h => `(()=>{return${h}})();`
// await Promise.all(Object.entries(hashJson).map(async ([name, hash]) => {
// const url = Resource.root + 'min/' + name
// const resource = Object.values(Resource.all).find(it => it.rawUrl === url)
// if (!resource) {
// return
// }
// const cache = settings.cache[resource.key]
// if (cache) {
// const cacheHash = await getHash(cache)
// if (cacheHash.toLowerCase() !== hash.toLowerCase() &&
// scriptHashWrap(cacheHash).toLowerCase() !== hash.toLowerCase()) {
// console.log(`hash not match: ${resource.key} (${cacheHash.toLowerCase()}) !== (${hash.toLowerCase()})`)
// await resource.download()
// settings.cache = Object.assign(settings.cache, {
// [resource.key]: resource.text
// })
// console.log(`downloaded ${resource.key}`)
// } else {
// console.log(`checked hash: ${resource.key}`)
// }
// }
// }))
// }
}
async applyWidget (info) {
@ -306,6 +324,9 @@ export class ResourceManager {
await Promise.all(info.map(applyDropdownOption))
} else {
const dropdownInput = dq(`.gui-settings-dropdown input[key=${info.key}]`)
if (!dropdownInput) {
return
}
dropdownInput.value = settings[info.key]
dropdownInput.setAttribute('data-name', settings[info.key])
const dropdown = dropdownInput.parentElement
@ -331,6 +352,10 @@ export class ResourceManager {
manifests.push(it)
}
})
manifests.push({
key: 'scriptLoadingMode',
items: ['同时', '延后', '同时(自动)', '延后(自动)']
})
await Promise.all(manifests.map(it => applyDropdownOption(it)))
}
toggleStyle (content, id) {

View File

@ -91,7 +91,9 @@ Resource.manifest = {
clearCache: '清除缓存',
settingsTooltip: '设置项帮助',
settingsSearch: '搜索设置',
sideBarOffset: '侧栏垂直偏移量'
sideBarOffset: '侧栏垂直偏移量',
ajaxHook: '启用 Ajax Hook API',
scriptLoadingMode: '加载模式',
}
},
useDarkStyle: {

View File

@ -56,15 +56,46 @@ export class Resource {
const cache = this.loadCache(key)
if (cache !== null) {
this.text = cache
console.log(`hit cache: ${key}`)
// console.log(`hit cache: ${key}`)
resolve(cache)
} else {
this.text = onlineData[this.rawUrl]
console.log(`load online data: ${key}`)
settings.cache = Object.assign(settings.cache, {
[key]: this.text
})
resolve(this.text)
} else if (settings.scriptDownloadMode === 'bundle') {
const text = onlineData[this.url]
// settings.cache = Object.assign(settings.cache, {
// [key]: this.text
// })
if (text) {
console.log(`load online data: ${key}`)
this.text = text
resolve(this.text)
} else {
Ajax.monkey({ url: this.url })
.then(text => {
console.log(`load preview data: ${key}`)
this.text = text
settings.cache = Object.assign(settings.cache, {
[key]: text
})
resolve(this.text)
})
.catch(error => reject(error))
}
}
if (settings.scriptDownloadMode !== 'bundle') {
Ajax.monkey({ url: this.url })
.then(text => {
this.text = text
if (cache !== this.text) {
if (cache === null) {
resolve(this.text)
}
console.log(`individual cache: ${key}`)
settings.cache = Object.assign(settings.cache, {
[key]: this.text
})
}
resolve(this.text)
})
.catch(error => reject(error))
}
} else {
Ajax.monkey({ url: this.url })

View File

@ -42,7 +42,7 @@ export const settings = {
touchNavBar: false,
touchVideoPlayer: false,
customControlBackgroundOpacity: 0.64,
customControlBackground: true,
customControlBackground: false,
darkScheduleStart: '18:00',
darkScheduleEnd: '6:00',
darkSchedule: false,
@ -147,6 +147,10 @@ export const settings = {
doubleClickFullscreenPreventSingleClick: false,
simplifyHome: false,
simplifyHomeStyle: '清爽',
ajaxHook: false,
scriptLoadingMode: '延后(自动)',
scriptDownloadMode: 'bundle',
guiSettingsDockSide: '左侧',
cache: {},
}
const fixedSettings = {

View File

@ -123,3 +123,7 @@ export const getDpiSourceSet = (src, baseSize, extension = 'jpg') => {
}
export const isOffline = () => typeof offlineData !== 'undefined'
export const getUID = () => document.cookie.replace(new RegExp(`(?:(?:^|.*;\\s*)DedeUserID\\s*\\=\\s*([^;]*).*$)|^.*$`), '$1')
export const scriptVersion = (() => {
const match = GM_info.script.name.match(/Bilibili Evolved \((.*)\)/)
return match ? match[1] : 'Stable'
})()

View File

@ -1,6 +1,7 @@
if (isIframe()) {
return;
}
document.body.classList.add('custom-navbar-loading')
document.body.style.setProperty("--navbar-bounds-padding", `0 ${settings.customNavbarBoundsPadding}%`);
document.body.style.setProperty("--navbar-blur-opacity", settings.customNavbarBlurOpacity || 0.7);
addSettingsListener("customNavbarBlurOpacity", value => {
@ -229,6 +230,7 @@ const unsupportedUrls = [
if (!supportedUrls.some(it => document.URL.includes(it))
|| unsupportedUrls.some(it => document.URL.includes(it))) {
showWidget = false;
document.body.classList.remove('custom-navbar-loading')
return attributes;
}
@ -388,135 +390,154 @@ class Category extends NavbarComponent {
constructor () {
super();
this.html = `主站`;
this.requestedPopup = true;
// this.requestedPopup = true;
this.popupHtml = /*html*/`
<ul id="custom-navbar-home-popup">
<li class="category-item" v-for="item of info" v-bind:class="{ main: item[1].count }">
<a v-bind:href="item[1].link">
<li class="category-item" v-if="loading">
<i class="mdi mdi-18px mdi-loading mdi-spin" style="margin-right: 8px"></i>...
</li>
<li class="category-item" style="display: none" :style="{display: loading ? 'none' : 'list-item'}" v-for="item of info" :class="{ main: item[1].count }">
<a :href="item[1].link">
<svg aria-hidden="true">
<use v-bind:href="'#header-icon-' + item[1].icon" v-bind:xlink:href="'#header-icon-' + item[1].icon"></use>
<use :href="'#header-icon-' + item[1].icon" :xlink:href="'#header-icon-' + item[1].icon"></use>
</svg>
<div>{{item[0]}}</div>
<span>{{item[1].count}}</span>
</a>
<div class="popup" v-if="item[1].subRegions">
<a v-for="region of Object.entries(item[1].subRegions)" v-bind:href="region[1]">
<a v-for="region of Object.entries(item[1].subRegions)" :href="region[1]">
{{region[0]}}
</a>
</div>
</li>
</ul>
`;
this.getOnlineInfo().then(info => {
new Vue({
el: "#custom-navbar-home-popup",
data: {
info: Object.entries(info),
// this.getOnlineInfo().then(info => {
// new Vue({
// el: "#custom-navbar-home-popup",
// data: {
// info: Object.entries(info),
// },
// });
// });
const getOnlineInfo = async () => {
const json = await Ajax.getJson("https://api.bilibili.com/x/web-interface/online");
if (parseInt(json.code) !== 0) {
throw new Error(`[自定义顶栏] 分区投稿信息获取失败: ${json.message}`);
}
const regionCount = json.data.region_count;
await SpinQuery.select("#custom-navbar-home-popup");
return {
动画: {
icon: "douga",
count: regionCount[1], link: `https://www.bilibili.com/v/douga/`,
subRegions: {
"MAD·AMV": `https://www.bilibili.com/v/douga/mad/`,
"MMD·3D": `https://www.bilibili.com/v/douga/mmd/`,
"短片·手书·配音": `https://www.bilibili.com/v/douga/voice/`,
"综合": `https://www.bilibili.com/v/douga/other/`,
},
},
});
});
番剧: {
icon: "anime",
count: regionCount[13], link: `https://www.bilibili.com/anime/`,
subRegions: {
"连载动画": `https://www.bilibili.com/v/anime/serial/`,
"完结动画": `https://www.bilibili.com/v/anime/finish/`,
"资讯": `https://www.bilibili.com/v/anime/information/`,
"官方延伸": `https://www.bilibili.com/v/anime/offical/`,
"新番时间表": `https://www.bilibili.com/anime/timeline/`,
},
},
国创: {
icon: "guochuang",
count: regionCount[167], link: `https://www.bilibili.com/guochuang/`,
subRegions: {
"国产动画": `https://www.bilibili.com/v/guochuang/chinese/`,
"国产原创相关": `https://www.bilibili.com/v/guochuang/original/`,
"布袋戏": `https://www.bilibili.com/v/guochuang/puppetry/`,
"资讯": `https://www.bilibili.com/v/guochuang/information/`,
"新番时间表": `https://www.bilibili.com/guochuang/timeline/`,
"国产动画索引": `https://www.bilibili.com/guochuang/index/`,
},
},
音乐: {
icon: "music",
count: regionCount[3], link: `https://www.bilibili.com/v/music/`,
subRegions: {
"原创音乐": "https://www.bilibili.com/v/music/original/",
"翻唱": "https://www.bilibili.com/v/music/cover/",
"VOCALOID·UTAU": "https://www.bilibili.com/v/music/vocaloid/",
"电音": "https://www.bilibili.com/v/music/electronic/",
"演奏": "https://www.bilibili.com/v/music/perform/",
"MV": "https://www.bilibili.com/v/music/mv/",
"音乐现场": "https://www.bilibili.com/v/music/live/",
"音乐综合": "https://www.bilibili.com/v/music/other/",
"音频": "https://www.bilibili.com/audio/home?musicType=music",
},
},
舞蹈: {
icon: "dance",
count: regionCount[129], link: `https://www.bilibili.com/v/dance/`, subRegions: { "宅舞": "https://www.bilibili.com/v/dance/otaku/", "三次元舞蹈": "https://www.bilibili.com/v/dance/three_d/", "舞蹈教程": "https://www.bilibili.com/v/dance/demo/" },
},
游戏: {
icon: "game",
count: regionCount[4], link: `https://www.bilibili.com/v/game/`, subRegions: { "单机游戏": "https://www.bilibili.com/v/game/stand_alone/", "电子竞技": "https://www.bilibili.com/v/game/esports/", "手机游戏": "https://www.bilibili.com/v/game/mobile/", "网络游戏": "https://www.bilibili.com/v/game/online/", "桌游棋牌": "https://www.bilibili.com/v/game/board/", "GMV": "https://www.bilibili.com/v/game/gmv/", "音游": "https://www.bilibili.com/v/game/music/", "Mugen": "https://www.bilibili.com/v/game/mugen/", "游戏赛事": "https://www.bilibili.com/v/game/match/" },
},
科技: {
icon: "technology",
count: regionCount[36], link: `https://www.bilibili.com/v/technology/`, subRegions: { "趣味科普人文": "https://www.bilibili.com/v/technology/fun/", "野生技术协会": "https://www.bilibili.com/v/technology/wild/", "演讲·公开课": "https://www.bilibili.com/v/technology/speech_course/", "星海": "https://www.bilibili.com/v/technology/military/", "机械": "https://www.bilibili.com/v/technology/mechanical/", "汽车": "https://www.bilibili.com/v/technology/automobile/" },
},
数码: { icon: "digital", count: regionCount[188], link: `https://www.bilibili.com/v/digital/`, subRegions: { "手机平板": "https://www.bilibili.com/v/digital/mobile/", "电脑装机": "https://www.bilibili.com/v/digital/pc/", "摄影摄像": "https://www.bilibili.com/v/digital/photography/", "影音智能": "https://www.bilibili.com/v/digital/intelligence_av/" }, },
生活: {
icon: "life",
count: regionCount[160], link: `https://www.bilibili.com/v/life/`, subRegions: { "搞笑": "https://www.bilibili.com/v/life/funny/", "日常": "https://www.bilibili.com/v/life/daily/", "美食圈": "https://www.bilibili.com/v/life/food/", "动物圈": "https://www.bilibili.com/v/life/animal/", "手工": "https://www.bilibili.com/v/life/handmake/", "绘画": "https://www.bilibili.com/v/life/painting/", "运动": "https://www.bilibili.com/v/life/sports/", "其他": "https://www.bilibili.com/v/life/other/" },
},
鬼畜: {
icon: "kichiku",
count: regionCount[119], link: `https://www.bilibili.com/v/kichiku/`, subRegions: { "鬼畜调教": "https://www.bilibili.com/v/kichiku/guide/", "音MAD": "https://www.bilibili.com/v/kichiku/mad/", "人力VOCALOID": "https://www.bilibili.com/v/kichiku/manual_vocaloid/", "教程演示": "https://www.bilibili.com/v/kichiku/course/" },
},
时尚: { icon: "fashion", count: regionCount[155], link: `https://www.bilibili.com/v/fashion/`, subRegions: { "美妆": "https://www.bilibili.com/v/fashion/makeup/", "服饰": "https://www.bilibili.com/v/fashion/clothing/", "健身": "https://www.bilibili.com/v/fashion/aerobics/", "T台": "https://www.bilibili.com/v/fashion/catwalk/", "风尚标": "https://www.bilibili.com/v/fashion/trends/" }, },
广告: { icon: "ad", count: regionCount[165], link: `https://www.bilibili.com/v/ad/ad/`, },
娱乐: {
icon: "ent",
count: regionCount[5], link: `https://www.bilibili.com/v/ent/`, subRegions: { "综艺": "https://www.bilibili.com/v/ent/variety/", "明星": "https://www.bilibili.com/v/ent/star/", "Korea相关": "https://www.bilibili.com/v/ent/korea/" },
},
影视: {
icon: "cinephile",
count: regionCount[181], link: `https://www.bilibili.com/v/cinephile/`, subRegions: { "影视杂谈": "https://www.bilibili.com/v/cinephile/cinecism/", "影视剪辑": "https://www.bilibili.com/v/cinephile/montage/", "短片": "https://www.bilibili.com/v/cinephile/shortfilm/", "预告·资讯": "https://www.bilibili.com/v/cinephile/trailer_info/", "特摄": "https://www.bilibili.com/v/cinephile/tokusatsu/" },
},
放映厅: { icon: "cinema", count: regionCount[177] + regionCount[23] + regionCount[11], link: `https://www.bilibili.com/cinema/`, subRegions: { "纪录片": "https://www.bilibili.com/documentary/", "电影": "https://www.bilibili.com/movie/", "电视剧": "https://www.bilibili.com/tv/" }, },
专栏: { icon: "read", count: ``, link: `https://www.bilibili.com/read/home`, },
直播: {
icon: "zhibo",
count: ``, link: `https://live.bilibili.com`, subRegions: { "全部直播": "https://live.bilibili.com/all?visit_id=5icxsa0kmts0", "游戏直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=2&areaId=0&visit_id=5icxsa0kmts0#/2/0", "手游直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=3&areaId=0&visit_id=5icxsa0kmts0#/3/0", "娱乐直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=1&areaId=0&visit_id=5icxsa0kmts0#/1/0", "电台直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=5&areaId=0&visit_id=5icxsa0kmts0#/5/0", "绘画直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=4&areaId=0&visit_id=5icxsa0kmts0#/4/0" },
},
小黑屋: { icon: "blackroom", count: ``, link: `https://www.bilibili.com/blackroom/`, },
话题: { icon: "topic", count: ``, link: `https://www.bilibili.com/blackboard/topic_list.html`, },
活动: { icon: "activit", count: ``, link: `https://www.bilibili.com/blackboard/x/act_list`, },
};
}
this.initialPopup = async () => {
new Vue({
el: await SpinQuery.select('#custom-navbar-home-popup'),
data: {
info: [],
loading: true,
},
async mounted() {
try {
this.info = Object.entries(await getOnlineInfo())
} finally {
this.loading = false
}
},
})
}
}
get name () {
return "category";
}
async getOnlineInfo () {
const json = await Ajax.getJson("https://api.bilibili.com/x/web-interface/online");
if (parseInt(json.code) !== 0) {
throw new Error(`[自定义顶栏] 分区投稿信息获取失败: ${json.message}`);
}
const regionCount = json.data.region_count;
await SpinQuery.select("#custom-navbar-home-popup");
return {
动画: {
icon: "douga",
count: regionCount[1], link: `https://www.bilibili.com/v/douga/`,
subRegions: {
"MAD·AMV": `https://www.bilibili.com/v/douga/mad/`,
"MMD·3D": `https://www.bilibili.com/v/douga/mmd/`,
"短片·手书·配音": `https://www.bilibili.com/v/douga/voice/`,
"综合": `https://www.bilibili.com/v/douga/other/`,
},
},
番剧: {
icon: "anime",
count: regionCount[13], link: `https://www.bilibili.com/anime/`,
subRegions: {
"连载动画": `https://www.bilibili.com/v/anime/serial/`,
"完结动画": `https://www.bilibili.com/v/anime/finish/`,
"资讯": `https://www.bilibili.com/v/anime/information/`,
"官方延伸": `https://www.bilibili.com/v/anime/offical/`,
"新番时间表": `https://www.bilibili.com/anime/timeline/`,
},
},
国创: {
icon: "guochuang",
count: regionCount[167], link: `https://www.bilibili.com/guochuang/`,
subRegions: {
"国产动画": `https://www.bilibili.com/v/guochuang/chinese/`,
"国产原创相关": `https://www.bilibili.com/v/guochuang/original/`,
"布袋戏": `https://www.bilibili.com/v/guochuang/puppetry/`,
"资讯": `https://www.bilibili.com/v/guochuang/information/`,
"新番时间表": `https://www.bilibili.com/guochuang/timeline/`,
"国产动画索引": `https://www.bilibili.com/guochuang/index/`,
},
},
音乐: {
icon: "music",
count: regionCount[3], link: `https://www.bilibili.com/v/music/`,
subRegions: {
"原创音乐": "https://www.bilibili.com/v/music/original/",
"翻唱": "https://www.bilibili.com/v/music/cover/",
"VOCALOID·UTAU": "https://www.bilibili.com/v/music/vocaloid/",
"电音": "https://www.bilibili.com/v/music/electronic/",
"演奏": "https://www.bilibili.com/v/music/perform/",
"MV": "https://www.bilibili.com/v/music/mv/",
"音乐现场": "https://www.bilibili.com/v/music/live/",
"音乐综合": "https://www.bilibili.com/v/music/other/",
"音频": "https://www.bilibili.com/audio/home?musicType=music",
},
},
舞蹈: {
icon: "dance",
count: regionCount[129], link: `https://www.bilibili.com/v/dance/`, subRegions: { "宅舞": "https://www.bilibili.com/v/dance/otaku/", "三次元舞蹈": "https://www.bilibili.com/v/dance/three_d/", "舞蹈教程": "https://www.bilibili.com/v/dance/demo/" },
},
游戏: {
icon: "game",
count: regionCount[4], link: `https://www.bilibili.com/v/game/`, subRegions: { "单机游戏": "https://www.bilibili.com/v/game/stand_alone/", "电子竞技": "https://www.bilibili.com/v/game/esports/", "手机游戏": "https://www.bilibili.com/v/game/mobile/", "网络游戏": "https://www.bilibili.com/v/game/online/", "桌游棋牌": "https://www.bilibili.com/v/game/board/", "GMV": "https://www.bilibili.com/v/game/gmv/", "音游": "https://www.bilibili.com/v/game/music/", "Mugen": "https://www.bilibili.com/v/game/mugen/", "游戏赛事": "https://www.bilibili.com/v/game/match/" },
},
科技: {
icon: "technology",
count: regionCount[36], link: `https://www.bilibili.com/v/technology/`, subRegions: { "趣味科普人文": "https://www.bilibili.com/v/technology/fun/", "野生技术协会": "https://www.bilibili.com/v/technology/wild/", "演讲·公开课": "https://www.bilibili.com/v/technology/speech_course/", "星海": "https://www.bilibili.com/v/technology/military/", "机械": "https://www.bilibili.com/v/technology/mechanical/", "汽车": "https://www.bilibili.com/v/technology/automobile/" },
},
数码: { icon: "digital", count: regionCount[188], link: `https://www.bilibili.com/v/digital/`, subRegions: { "手机平板": "https://www.bilibili.com/v/digital/mobile/", "电脑装机": "https://www.bilibili.com/v/digital/pc/", "摄影摄像": "https://www.bilibili.com/v/digital/photography/", "影音智能": "https://www.bilibili.com/v/digital/intelligence_av/" }, },
生活: {
icon: "life",
count: regionCount[160], link: `https://www.bilibili.com/v/life/`, subRegions: { "搞笑": "https://www.bilibili.com/v/life/funny/", "日常": "https://www.bilibili.com/v/life/daily/", "美食圈": "https://www.bilibili.com/v/life/food/", "动物圈": "https://www.bilibili.com/v/life/animal/", "手工": "https://www.bilibili.com/v/life/handmake/", "绘画": "https://www.bilibili.com/v/life/painting/", "运动": "https://www.bilibili.com/v/life/sports/", "其他": "https://www.bilibili.com/v/life/other/" },
},
鬼畜: {
icon: "kichiku",
count: regionCount[119], link: `https://www.bilibili.com/v/kichiku/`, subRegions: { "鬼畜调教": "https://www.bilibili.com/v/kichiku/guide/", "音MAD": "https://www.bilibili.com/v/kichiku/mad/", "人力VOCALOID": "https://www.bilibili.com/v/kichiku/manual_vocaloid/", "教程演示": "https://www.bilibili.com/v/kichiku/course/" },
},
时尚: { icon: "fashion", count: regionCount[155], link: `https://www.bilibili.com/v/fashion/`, subRegions: { "美妆": "https://www.bilibili.com/v/fashion/makeup/", "服饰": "https://www.bilibili.com/v/fashion/clothing/", "健身": "https://www.bilibili.com/v/fashion/aerobics/", "T台": "https://www.bilibili.com/v/fashion/catwalk/", "风尚标": "https://www.bilibili.com/v/fashion/trends/" }, },
广告: { icon: "ad", count: regionCount[165], link: `https://www.bilibili.com/v/ad/ad/`, },
娱乐: {
icon: "ent",
count: regionCount[5], link: `https://www.bilibili.com/v/ent/`, subRegions: { "综艺": "https://www.bilibili.com/v/ent/variety/", "明星": "https://www.bilibili.com/v/ent/star/", "Korea相关": "https://www.bilibili.com/v/ent/korea/" },
},
影视: {
icon: "cinephile",
count: regionCount[181], link: `https://www.bilibili.com/v/cinephile/`, subRegions: { "影视杂谈": "https://www.bilibili.com/v/cinephile/cinecism/", "影视剪辑": "https://www.bilibili.com/v/cinephile/montage/", "短片": "https://www.bilibili.com/v/cinephile/shortfilm/", "预告·资讯": "https://www.bilibili.com/v/cinephile/trailer_info/", "特摄": "https://www.bilibili.com/v/cinephile/tokusatsu/" },
},
放映厅: { icon: "cinema", count: regionCount[177] + regionCount[23] + regionCount[11], link: `https://www.bilibili.com/cinema/`, subRegions: { "纪录片": "https://www.bilibili.com/documentary/", "电影": "https://www.bilibili.com/movie/", "电视剧": "https://www.bilibili.com/tv/" }, },
专栏: { icon: "read", count: ``, link: `https://www.bilibili.com/read/home`, },
直播: {
icon: "zhibo",
count: ``, link: `https://live.bilibili.com`, subRegions: { "全部直播": "https://live.bilibili.com/all?visit_id=5icxsa0kmts0", "游戏直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=2&areaId=0&visit_id=5icxsa0kmts0#/2/0", "手游直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=3&areaId=0&visit_id=5icxsa0kmts0#/3/0", "娱乐直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=1&areaId=0&visit_id=5icxsa0kmts0#/1/0", "电台直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=5&areaId=0&visit_id=5icxsa0kmts0#/5/0", "绘画直播": "https://live.bilibili.com/p/eden/area-tags?parentAreaId=4&areaId=0&visit_id=5icxsa0kmts0#/4/0" },
},
小黑屋: { icon: "blackroom", count: ``, link: `https://www.bilibili.com/blackroom/`, },
话题: { icon: "topic", count: ``, link: `https://www.bilibili.com/blackboard/topic_list.html`, },
活动: { icon: "activit", count: ``, link: `https://www.bilibili.com/blackboard/x/act_list`, },
};
}
}
class UserInfo extends NavbarComponent {
constructor () {
@ -1619,6 +1640,9 @@ class Subscriptions extends NavbarComponent {
component.onPopup && component.onPopup()
}
},
mounted() {
document.body.classList.remove('custom-navbar-loading')
},
});
})();
return attributes;

View File

@ -124,6 +124,19 @@ body {
--navbar-blur-opacity: 0.7;
--navbar-icon-size: 24px;
}
body.custom-navbar-loading::after {
content: "";
height: var(--navbar-height);
width: 100%;
position: absolute;
top: 0;
left: 0;
background-color: white;
z-index: 10001;
}
body.dark.custom-navbar-loading::after {
background-color: #333;
}
body.no-banner #banner_link,
body.no-banner .z-top-container.has-banner > .header,
.bili-header-m > #banner_link .search,

View File

@ -105,7 +105,6 @@ blockquote .color-yellow-04,
#app .sticky-bar .bar-content .message,
.coupon-content-con .coupon-btn-disable,
.common .bb-comment .no-login .comment-submit,
.popup-content-ctnr .bl-button--ghost:hover,
.customize-wrp .select,
.manga-detail .episode-list-component .episode-list .list-data .list-item.last-read,
.live-room-app .tabs.isHundred .item.active,
@ -114,7 +113,8 @@ blockquote .color-yellow-04,
.live-room-app .guard-rank-cntr.hundred .page-box .live-skin-main-text,
.live-room-app .guard-rank-cntr.thousand .page-box .live-skin-main-text,
.live-room-app .guard-rank-cntr.hundred .live-skin-highlight-text,
.live-room-app .guard-rank-cntr.thousand .live-skin-highlight-text
.live-room-app .guard-rank-cntr.thousand .live-skin-highlight-text,
.popup-content-ctnr .bl-button--ghost
{
color: #eee !important;
}
@ -215,8 +215,8 @@ blockquote .color-yellow-04,
.el-date-table td.current:not(.disabled),
.el-date-table td.end-date,
.el-date-table td.start-date,
.popup-content-ctnr .bl-button--ghost,
.style-section .tag-block .tag-containers .style-tag:active
.style-section .tag-block .tag-containers .style-tag:active,
.popup-content-ctnr .bl-button--ghost:hover
{
color: var(--foreground-color) !important;
}

View File

@ -964,7 +964,6 @@ div.con header,
.select-wrap .select-option,
.select-wrap .select-option p:hover,
.card .more-panel,
.card .more-panel .child-button:hover,
.report-popup .content-text,
.im-popup .bp-popup-panel .title-ctnr .popup-title,
.selector-box,
@ -2286,11 +2285,9 @@ a.s-btn:hover,
.history-wrap .time-label.active,
.dynamic-btn.pink,
.sticky-bar .bar-content .send-button,
.up-info .up-focus-btn,
.textarea-container .comm-tool .comm-submit,
.new-notice-bar .message,
.card .focus-btn .unfocus .unfocus-text:hover,
.article-container:hover .text-area .title,
.tab-list .tb-item.active,
.btn-submit,
.multi-page .more-box li.on,

View File

@ -572,7 +572,6 @@ button.button.more,
.tab-box .item .title,
.tab-box .item .desc,
.buy-info-box .left-part,
.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-electric.little,
.pk-rank.side-bar-icon + .size-bar-text,
.gui-settings-button:not(.save),
.live-module .tab-item .r-item .r-i-t .u-name,

View File

@ -1060,7 +1060,6 @@ body>div.to-top.on
.guide .feedback-btn a,
.gift>.expires,
.uploader-info .info .follow .btn,
.upload-v2-step1-container .upload-btn,
.error-container .big-btn,
.infoBarName .inputIng,
.infoBarName .titleName,

View File

@ -47,7 +47,10 @@
.container .logout a:hover,
.container .video-card:hover,
.container .tab-item--normal:hover,
.guest-home .button-box button
.guest-home .button-box button,
.video-editor-ol-wrp,
.qa-area-ol-wrp,
.bui-swiper-wrap .bui-swiper-item .bui-swiper-text
{
background-color: #333 !important;
}
@ -127,7 +130,10 @@ li.danmaku-info-row.bpui-selecting,
.main-panel .hot-topic-panel,
.guest-home .login-panel,
.international-home .bilibili-search-history .history-item.focus,
.international-home .bilibili-search-history .history-item:hover
.international-home .bilibili-search-history .history-item:hover,
.live-charge-box .tip-popup,
.bui-swiper-wrap .bui-swiper-next,
.bui-swiper-wrap .bui-swiper-pre
{
background-color: #444 !important;
}
@ -180,7 +186,9 @@ li.danmaku-info-row.bpui-selecting,
.mini-header__content .i-frame,
.round-corner .out-container,
.round-corner .out-container .tab-bar,
.container .info .date
.container .info .date,
.iframe-comp-container>div,
.edit-article-wrap #edit-article-box
{
background-color: transparent !important;
}
@ -258,7 +266,9 @@ li.danmaku-info-row.bpui-selecting,
.video-list .card-view .collect-num,
.video-list .card-view .danmu-num,
.video-list .card-view .play-num,
.guest-home .title h2
.guest-home .title h2,
.video-editor-ol-wrp .video-editor-ol-content a,
.qa-area-ol-wrp .qa-area-ol-content a
{
color: #aaa !important;
}
@ -450,7 +460,13 @@ li.danmaku-info-row.bpui-selecting,
.main-panel .title,
.main-panel .more,
.guest-home .title h1,
.guest-home .button-box .regist
.guest-home .button-box .regist,
.video-editor-ol-wrp .video-editor-ol-content p,
.qa-area-ol-wrp .qa-area-ol-content p,
.up-info .btn-panel .following,
.live-charge-cntr .popup-cntr .tip-content,
.live-charge-box .popup-cntr .retry,
.bui-swiper-wrap .bui-swiper-item .bui-swiper-text
{
color: #eee !important;
}
@ -612,7 +628,9 @@ li.danmaku-info-row.bpui-selecting,
.ops canvas.ring-progress,
.home-slide .trigger span.on,
.bili-search #live-list .headline-room .icon-live-face,
.bili-search #live-list .headline-room .icon-live-frame
.bili-search #live-list .headline-room .icon-live-frame,
.bui-swiper-wrap .bui-swiper-next svg,
.bui-swiper-wrap .bui-swiper-pre svg
{
filter: var(--blue-image-filter) !important;
}
@ -761,7 +779,11 @@ li.danmaku-info-row.bpui-selecting,
.bili-search .user-item .attention-btn:hover,
.follow-right-module .follow-head .follow-more:hover,
.carousel-wrap .page .next.current,
.guest-home .button-box button:hover
.guest-home .button-box button:hover,
.video-editor-ol-wrp .video-editor-ol-btn,
.qa-area-ol-wrp .qa-area-ol-btn,
.bui-swiper-wrap .bui-swiper-next:hover,
.bui-swiper-wrap .bui-swiper-pre:hover
{
background-color: var(--theme-color) !important;
}
@ -868,7 +890,13 @@ li.danmaku-info-row.bpui-selecting,
.video-item-biref:hover .biref-info .biref-title,
.video-list .card-txt:hover,
.main-panel .more:hover,
.international-home .bilibili-search-history .cancel-icon:hover
.international-home .bilibili-search-history .cancel-icon:hover,
.up-info .up-focus-btn,
.video-editor-ol-wrp .video-editor-ol-content a:hover,
.qa-area-ol-wrp .qa-area-ol-content a:hover,
.article-container:hover .text-area .title,
.card .more-panel .child-button:hover,
.bui-swiper-wrap .bui-swiper-item .bui-swiper-text:hover
{
color: var(--theme-color) !important;
}
@ -906,10 +934,21 @@ li.danmaku-info-row.bpui-selecting,
.timeline-box .timeline-item.new p.num a,
.new-stat-module .zone-title .headline .new-stat-more:hover,
.block-area .timeline-title .headline .timeline-more:hover,
.guest-home .button-box button:hover
.guest-home .button-box button:hover,
.upload-v2-step1-container #homeDrop .upload-btn .upload-btn-title,
.video-editor-ol-wrp .video-editor-ol-btn,
.qa-area-ol-wrp .qa-area-ol-btn,
.upload-v2-step1-container #homeDrop .upload-btn .upload-btn-title,
.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-electric.little,
.follow-dialog-wrap .follow-dialog-window .bottom .btn,
.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-electric
{
color: var(--foreground-color) !important;
}
.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-follow .bp-svgicon
{
fill: var(--foreground-color) !important;
}
/* a
{
fill: var(--theme-color) !important;

View File

@ -40,7 +40,8 @@
.container .level-intro,
.van-popover .upload-item:hover,
.container .play-all:hover,
.van-popover .btn-box .btn.reg-btn:hover
.van-popover .btn-box .btn.reg-btn:hover,
.international-header .bili-banner
{
background-color: #333 !important;
}

View File

@ -11,9 +11,61 @@ const displayNames = {
popup: "抽奖提示",
skin: "房间皮肤",
}
let skinDisabled = settings.simplifyLiveroomSettings.skin;
const skinSelectors = [
"#head-info-vm",
"#gift-control-vm",
"#rank-list-vm",
"#rank-list-ctnr-box",
".gift-panel.base-panel",
".gift-panel.extend-panel",
".seeds-wrap>div:first-child",
".gift-section>div:last-child",
".z-gift-package>div>div",
".right-action"
];
const skinClass = "live-skin-coloration-area";
skinSelectors.forEach(selector => {
SpinQuery.select(
selector,
skin => {
Observer.attributes(selector, records => {
records.forEach(record => {
if (record.attributeName === "class") {
// console.log("Observed class change: ", record);
if (skinDisabled && skin.classList.contains(skinClass)) {
skin.classList.remove(skinClass);
}
else if (!skinDisabled && !skin.classList.contains(skinClass)) {
skin.classList.add(skinClass);
}
}
});
});
});
});
const setBodyClass = (checked, key) => {
document.body.classList[checked ? "add" : "remove"](`simplify-${key}`);
if (key === "skin") {
skinDisabled = checked;
skinSelectors.forEach(selector => {
SpinQuery.select(
selector,
skin => skin.classList[checked ? "remove" : "add"]("live-skin-coloration-area")
);
});
}
};
const isLiveroom = () => document.URL.startsWith(`https://live.bilibili.com/`)
if (isLiveroom()) {
Object.keys(displayNames).forEach(key => {
const checked = settings.simplifyLiveroomSettings[key];
setBodyClass(checked, key);
})
}
export default {
widget: {
condition: () => document.URL.startsWith(`https://live.bilibili.com/`),
condition: isLiveroom,
content: /*html*/`
<div class="gui-settings-flat-button" style="position: relative" id="simplify-liveroom">
<i class="mdi mdi-24px mdi-settings"></i>
@ -40,51 +92,6 @@ export default {
});
button.addEventListener("mouseenter", () => mask.classList.add("transparent"));
button.addEventListener("mouseleave", () => mask.classList.remove("transparent"));
let skinDisabled = settings.simplifyLiveroomSettings.skin;
const skinSelectors = [
"#head-info-vm",
"#gift-control-vm",
"#rank-list-vm",
"#rank-list-ctnr-box",
".gift-panel.base-panel",
".gift-panel.extend-panel",
".seeds-wrap>div:first-child",
".gift-section>div:last-child",
".z-gift-package>div>div",
".right-action"
];
const skinClass = "live-skin-coloration-area";
skinSelectors.forEach(selector => {
SpinQuery.select(
selector,
skin => {
Observer.attributes(selector, records => {
records.forEach(record => {
if (record.attributeName === "class") {
// console.log("Observed class change: ", record);
if (skinDisabled && skin.classList.contains(skinClass)) {
skin.classList.remove(skinClass);
}
else if (!skinDisabled && !skin.classList.contains(skinClass)) {
skin.classList.add(skinClass);
}
}
});
});
});
});
const setBodyClass = (checked, key) => {
document.body.classList[checked ? "add" : "remove"](`simplify-${key}`);
if (key === "skin") {
skinDisabled = checked;
skinSelectors.forEach(selector => {
SpinQuery.select(
selector,
skin => skin.classList[checked ? "remove" : "add"]("live-skin-coloration-area")
);
});
}
};
new Vue({
el: ".simplify-liveroom-settings",
data: {

View File

@ -1,114 +1,121 @@
(async () => {
const html = await import("aboutHtml")
document.body.insertAdjacentHTML('beforeend', html)
const nameSorter = (a, b) => a.charCodeAt(0) - b.charCodeAt(0)
const userSorter = (a, b) => nameSorter(a.name, b.name)
const clientTypeMatch = GM_info.script.name.match(/Bilibili Evolved \((.*)\)/)
const clientType = clientTypeMatch ? clientTypeMatch[1] : 'Stable'
new Vue({
el: '.bilibili-evolved-about',
data: {
version: settings.currentVersion,
clientType,
logoImage: null,
logoImageDark: null,
branch: null,
authors: [
{
name: 'Grant Howard',
link: 'https://github.com/the1812'
},
{
name: 'Coulomb-G',
link: 'https://github.com/Coulomb-G'
}
],
contributors: [
{
name: 'PleiadeSubaru',
link: 'https://github.com/Etherrrr'
}
].sort(userSorter),
fetching: true,
participants: [],
websites: [
{
name: 'GitHub',
link: 'https://github.com/the1812/Bilibili-Evolved/'
},
{
name: 'Greasy Fork',
link: 'https://greasyfork.org/zh-CN/scripts/373563-bilibili-evolved'
}
],
components: [
{
name: 'Vue.js',
link: 'https://cn.vuejs.org/index.html'
},
{
name: 'JSZip',
link: 'https://stuk.github.io/jszip/'
},
{
name: 'jQuery',
link: 'http://jquery.com/'
},
{
name: 'debounce',
link: 'https://github.com/component/debounce/'
},
{
name: 'Slip.js',
link: 'https://github.com/kornelski/slip'
},
{
name: 'MDI',
link: 'https://materialdesignicons.com'
}
]
},
mounted () {
document.querySelector('.bilibili-evolved-about').addEventListener('be:about-load', () => {
this.init()
}, { once: true })
},
methods: {
async getLogos() {
this.logoImage = await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide.svg`)
this.logoImageDark = await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide-dark.svg`)
dq('.bilibili-evolved-about').addEventListener('be:about-load', () => {
const nameSorter = (a, b) => a.charCodeAt(0) - b.charCodeAt(0)
const userSorter = (a, b) => nameSorter(a.name, b.name)
const clientTypeMatch = GM_info.script.name.match(/Bilibili Evolved \((.*)\)/)
const clientType = clientTypeMatch ? clientTypeMatch[1] : 'Stable'
new Vue({
el: '.bilibili-evolved-about',
data: {
version: settings.currentVersion,
clientType,
logoImage: null,
logoImageDark: null,
branch: null,
authors: [
{
name: 'Grant Howard',
link: 'https://github.com/the1812'
},
{
name: 'Coulomb-G',
link: 'https://github.com/Coulomb-G'
}
],
contributors: [
{
name: 'PleiadeSubaru',
link: 'https://github.com/Etherrrr'
}
].sort(userSorter),
fetching: true,
participants: [],
websites: [
{
name: 'GitHub',
link: 'https://github.com/the1812/Bilibili-Evolved/'
},
{
name: 'Greasy Fork',
link: 'https://greasyfork.org/zh-CN/scripts/373563-bilibili-evolved'
}
],
components: [
{
name: 'Vue.js',
link: 'https://cn.vuejs.org/index.html'
},
{
name: 'JSZip',
link: 'https://stuk.github.io/jszip/'
},
{
name: 'jQuery',
link: 'http://jquery.com/'
},
{
name: 'debounce',
link: 'https://github.com/component/debounce/'
},
{
name: 'Slip.js',
link: 'https://github.com/kornelski/slip'
},
{
name: 'MDI',
link: 'https://materialdesignicons.com'
},
{
name: 'Lodash',
link: 'https://lodash.com/',
},
]
},
async init () {
this.branch = /Preview|Local/.test(clientType) ? 'preview' : 'master'
this.getLogos()
const allParticipants = new Set()
let issues = []
let page = 1
do {
issues = await Ajax.getJson(`https://api.github.com/repos/the1812/Bilibili-Evolved/issues?state=all&direction=asc&per_page=100&page=${page}`)
.catch(() => {
issues = [{
name: '电波无法到达(´・_・`)',
link: null
}]
})
page++
for (const issue of issues) {
allParticipants.add(issue.user.login)
mounted () {
// this.init()
dq('.bilibili-evolved-about').addEventListener('be:about-load-community', () => {
this.init()
}, { once: true })
},
methods: {
async getLogos () {
this.logoImage = await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide.svg`)
this.logoImageDark = await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide-dark.svg`)
},
async init () {
this.branch = /Preview|Local/.test(clientType) ? 'preview' : 'master'
this.getLogos()
const allParticipants = new Set()
let issues = []
let page = 1
do {
issues = await Ajax.getJson(`https://api.github.com/repos/the1812/Bilibili-Evolved/issues?state=all&direction=asc&per_page=100&page=${page}`)
.catch(() => {
issues = [{
name: '电波无法到达(´・_・`)',
link: null
}]
})
page++
for (const issue of issues) {
allParticipants.add(issue.user.login)
}
}
while (issues.length > 0)
this.participants = [...allParticipants].map(name => {
return {
name,
link: `https://github.com/${name}`
}
}).filter(({ link }) => {
return !this.authors.some(it => it.link === link) &&
!this.contributors.some(it => it.link === link)
}).sort(userSorter)
this.fetching = false
}
while (issues.length > 0)
this.participants = [...allParticipants].map(name => {
return {
name,
link: `https://github.com/${name}`
}
}).filter(({ link }) => {
return !this.authors.some(it => it.link === link) &&
!this.contributors.some(it => it.link === link)
}).sort(userSorter)
this.fetching = false
}
}
})
})
}, { once: true })
})()

View File

@ -455,6 +455,10 @@ li.category.folded i.icon-arrow
{
max-width: 120px;
}
.gui-settings-dropdown input[key='scriptLoadingMode']
{
max-width: 170px;
}
.gui-settings-dropdown input[key='defaultPlayerLayout'],
.gui-settings-dropdown input[key='defaultBangumiLayout'],
.gui-settings-dropdown input[key='defaultVideoSpeed']

View File

@ -122,6 +122,8 @@
<!-- <checkbox indent="0" key="useCache" dependencies=""></checkbox> -->
<textbox indent="0" key="filenameFormat" dependencies=""></textbox>
<textbox indent="0" key="sideBarOffset" dependencies=""></textbox>
<checkbox indent="0" key="ajaxHook" dependencies=""></checkbox>
<dropdown indent="0" key="scriptLoadingMode" dependencies=""></dropdown>
</ul>
</div>
<div class="gui-settings-tooltip"></div>

View File

@ -139,7 +139,6 @@ function setDisplayNames () {
if (!style) {
document.body.insertAdjacentHTML('afterbegin', `<link rel="stylesheet" href="//cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css">`)
}
resources.applyDropdownOptions()
const widgetsContainer = document.querySelector('.widgets-container')
const emptyTip = widgetsContainer.querySelector('.empty-tip')
@ -150,13 +149,16 @@ function setDisplayNames () {
emptyTip.classList.remove('show')
}
})
new ThemeColors().setupDom()
const boxes = document.querySelectorAll('.gui-settings-widgets-box,.gui-settings-box')
const iconPanel = document.querySelector('.gui-settings-icon-panel')
iconPanel.addEventListener('mouseover', () => {
iconPanel.addEventListener('mouseover', async () => {
const { loadTooltip } = await import('./tooltip/settings-tooltip.loader')
await loadTooltip()
await resources.applyDropdownOptions()
resources.applyWidgets()
raiseEvent(iconPanel, 'be:load')
raiseEvent(dq('.bilibili-evolved-about'), 'be:about-load')
new ThemeColors().setupDom()
boxes.forEach(it => it.classList.add('loaded'))
inputs = [...document.querySelectorAll('input[key]')]
checkBoxes = inputs.filter(it => it.type === 'checkbox')

View File

@ -13,7 +13,7 @@ if (document.querySelector('.gui-settings-icon-panel') === null) {
dqa('.gui-settings-box,.gui-settings-mask').forEach(it => it.classList.add('opened'))
} else {
dqa('.bilibili-evolved-about,.gui-settings-mask').forEach(it => it.classList.add('opened'))
raiseEvent(document.querySelector('.bilibili-evolved-about'), 'be:about-load')
raiseEvent(dq('.bilibili-evolved-about'), 'be:about-load-community')
}
})
dq('.gui-settings-widgets').addEventListener('click', e => {

View File

@ -122,6 +122,12 @@ A more specific example: To use a "video title + AV ID + time" format, we can us
- <kbd>s</kbd> Favorite
- <kbd>Shift</kbd> + <kbd></kbd>/<kbd></kbd> Playback Speed Adjust`],
['doubleClickFullscreen', `Allow double click the player to toggle fullscreen, please note that this feature will not work if <span>播放器触摸支持</span> - <span>启用双击控制</span> is also enabled.`],
['ajaxHook', `The Ajax Hook API may help other extensions or add-ons access ajax requests in bilibili.`],
['scriptLoadingMode', `Feature loading mode:
- Simultaneous: Load features as soon as possible
- Delay: Load features after the original page has loaded
- Simultaneous (Auto): Auto determine loading mode and prefer Simultaneous mode
- Delay (Auto): Auto determine loading mode and prefer Delay mode`],
]);
export default {
export: { toolTips },

View File

@ -1,40 +1,36 @@
function extractKey(listItem: Element)
{
const input = listItem.querySelector("input");
if (input)
{
return input.getAttribute("key");
}
return null;
function extractKey(listItem: Element) {
const input = listItem.querySelector("input");
if (input) {
return input.getAttribute("key");
}
return null;
}
(async () =>
{
resources.applyStyle("settingsTooltipStyle");
const { toolTips } = await import(`settings-tooltip.${getI18nKey()}`);
const tooltip = await SpinQuery.select(".gui-settings-tooltip");
if (!tooltip)
{
export const loadTooltip = async () => {
resources.applyStyle("settingsTooltipStyle");
const { toolTips } = await import(`settings-tooltip.${getI18nKey()}`);
const tooltip = await SpinQuery.select(".gui-settings-tooltip");
if (!tooltip) {
return;
}
document.querySelectorAll(".gui-settings-content>ul>li").forEach(element => {
element.addEventListener("mouseover", () => {
const key = extractKey(element);
if (key === null || toolTips === null) {
return;
}
document.querySelectorAll(".gui-settings-content>ul>li").forEach(element =>
{
element.addEventListener("mouseover", () =>
{
const key = extractKey(element);
if (key === null || toolTips === null)
{
return;
}
const tipText = toolTips.get(key);
if (tipText !== undefined)
{
tooltip.innerHTML = tipText;
tooltip.classList.add("show");
}
});
element.addEventListener("mouseout", () =>
{
tooltip.classList.remove("show");
});
}
const tipText = toolTips.get(key);
if (tipText !== undefined) {
tooltip.innerHTML = tipText;
tooltip.classList.add("show");
}
});
})();
element.addEventListener("mouseout", () => {
tooltip.classList.remove("show");
});
});
}
export default {
export: {
loadTooltip
}
}

View File

@ -145,6 +145,12 @@ export const toolTips = new Map<keyof BilibiliEvolvedSettings, string>([
- <kbd>s</kbd>
- <kbd>Shift</kbd> + <kbd></kbd>/<kbd></kbd> `],
['doubleClickFullscreen', /*html*/`允许双击播放器切换全屏, 请注意不能与<span>播放器触摸支持-启用双击控制</span>一同使用.`],
['ajaxHook', /*html*/`是否启用 Ajax Hook API, 其他插件或附加功能能够通过此 API 获取 Ajax 请求的信息.`],
['scriptLoadingMode', /*html*/`脚本功能的加载模式:
- 同时: 与b站页面同时加载
- 延后: 优先加载b站页面, b站页面加载完成后再开始加载脚本功能
- (): ,
- (): , `],
]);
export default {
export: { toolTips },

View File

@ -676,6 +676,12 @@ export const map = new Map([
[`快捷键扩展`, `Extended Keymap`],
[`限速`, `Speed Limit`],
[`双击全屏`, `Quick fullscreen`],
[`启用 Ajax Hook API`, `Enable Ajax Hook API`],
[`加载模式`, `Loading Mode`],
[`同时`, `Simultaneous`],
[`延后`, `Delay`],
[`同时(自动)`, `Simultaneous (Auto)`],
[`延后(自动)`, `Delay (Auto)`],
[`*`, [
{
selector: `.gui-settings-widgets-box .widgets-container .empty-tip`,

View File

@ -687,7 +687,7 @@ export const map = new Map([
[`违反直播言论规范, 请立即调整`, `ライブスピーチ規範の違反、すぐに調整`],
[`系统通知`, `システム通知`],
[`当前直播间被直播管理员切断直播。`, `今、配信ルームはスーパー管理者によって中断されています.`],
[`悲痛欲绝 >△<`, `悲しすぎる >△<`],
[`系统升级维护中`, `システム更新中`],
[`*`, [
{
selector: `.gui-settings-widgets-box .widgets-container .empty-tip`,
@ -744,6 +744,7 @@ export const regex = new Map([
[/^流畅 ([\d]+)P$/, `$1P`],
[/^兑换成功\n剩余银瓜子:([\d]+)$/, `引き換え成功\n残り銀ヒマワリの種:$1`],
[/^预计大小: ([0-9\.A-Z]+)$/, `推定サイズ: $1`],
[/^悲痛欲绝/, `悲しすぎる`],
]);
export default {
export: { map, regex },

View File

@ -4,6 +4,7 @@ export enum ToastType {
Success = 'success',
Error = 'error',
}
let container: { cards: Toast[] }
export class Toast {
type: ToastType
message: string
@ -17,14 +18,14 @@ export class Toast {
this.duration = 3000
}
show() {
container.cards.splice(0, 0, this)
Toast.containerVM.cards.splice(0, 0, this)
if (this.duration !== undefined) {
setTimeout(() => this.dismiss(), this.duration)
}
}
dismiss() {
if (container.cards.includes(this)) {
container.cards.splice(container.cards.indexOf(this), 1)
if (Toast.containerVM.cards.includes(this)) {
Toast.containerVM.cards.splice(Toast.containerVM.cards.indexOf(this), 1)
}
}
get element() {
@ -33,8 +34,11 @@ export class Toast {
get key() {
return this.creationTime.toISOString()
}
static get container() {
return document.querySelector('.toast-card-container')
static get containerVM() {
if (!container) {
Toast.createToastContainer()
}
return container
}
static createToastContainer() {
if (!document.querySelector('.toast-card-container')) {
@ -42,6 +46,32 @@ export class Toast {
<transition-group class="toast-card-container" name="toast-card-container" tag="div">
<toast-card v-for="card of cards" v-bind:key="card.key" v-bind:card="card"></toast-card>
</transition-group>`)
container = new Vue({
el: '.toast-card-container',
components: {
'toast-card': {
props: ['card'],
template: /*html*/`
<div class="toast-card icons-enabled visible" v-bind:class="'toast-' + card.type">
<div class="toast-card-border"></div>
<div class="toast-card-header">
<h1 class="toast-card-title">{{card.title}}</h1>
<div class="toast-card-dismiss" v-on:click="card.dismiss()">
<svg style="width:22px;height:22px" viewBox="0 0 24 24">
<path
d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
</svg>
</div>
</div>
<div class="toast-card-message" v-html="card.message"></div>
</div>
`,
}
},
data: {
cards: [] as Toast[]
},
})
}
}
private static internalShow(message: string, title: string, duration: number | undefined, type: ToastType) {
@ -65,32 +95,6 @@ export class Toast {
}
resources.applyStyle('toastStyle')
Vue.component('toast-card', {
props: ['card'],
template: /*html*/`
<div class="toast-card icons-enabled visible" v-bind:class="'toast-' + card.type">
<div class="toast-card-border"></div>
<div class="toast-card-header">
<h1 class="toast-card-title">{{card.title}}</h1>
<div class="toast-card-dismiss" v-on:click="card.dismiss()">
<svg style="width:22px;height:22px" viewBox="0 0 24 24">
<path
d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
</svg>
</div>
</div>
<div class="toast-card-message" v-html="card.message"></div>
</div>
`,
})
Toast.createToastContainer()
const container = new Vue({
el: '.toast-card-container',
data: {
cards: [] as Toast[]
},
})
export default {
export: Toast
}

View File

@ -132,7 +132,7 @@ class VideoDownloaderFragment {
class VideoDownloader {
format: VideoFormat
fragments: VideoDownloaderFragment[]
fragmentSplitFactor = 6 * 5
fragmentSplitFactor = 6 * 2
workingXhr: XMLHttpRequest[] | null = null
progress: (progress: number) => void
progressMap: Map<XMLHttpRequest, number> = new Map()
@ -192,9 +192,14 @@ class VideoDownloader {
this.workingXhr = []
this.progressMap = new Map()
this.updateProgress()
// 按一定大小分段或许对大视频更好
// const partialLength = Math.round(fragment.size / this.fragmentSplitFactor)
const partialLength = 16 * 1024 * 1024 // 16MB
// 按一定大小分段或许对大视频更好
let partialLength: number
if (fragment.size <= 96 * 1024 * 1024) { // 小于等于96MB时, 均分为12段 (this.fragmentSplitFactor)
partialLength = fragment.size / this.fragmentSplitFactor
} else { // 大于96MB时, 每16MB为一段
partialLength = 16 * 1024 * 1024 // 16MB
}
let startByte = 0
const getPartNumber = (xhr: XMLHttpRequest) => [...this.progressMap.keys()].indexOf(xhr) + 1
while (startByte < fragment.size) {

View File

@ -1,5 +1,4 @@
import { getFriendlyTitle } from '../title';
import { getFriendlyTitle } from '../title'
const canvas = document.createElement("canvas");
class Screenshot {
video: HTMLVideoElement;
@ -62,96 +61,96 @@ export const takeScreenshot = (video: HTMLVideoElement, withDanmaku = false) =>
const time = video.currentTime
return new Screenshot(video, time, withDanmaku)
}
resources.applyStyle("videoScreenshotStyle");
document.body.insertAdjacentHTML("beforeend", /*html*/`
<div class="video-screenshot-container">
<transition-group class="video-screenshot-list" name="video-screenshot-list" tag="div">
<video-screenshot v-for="screenshot of screenshots" v-bind:filename="screenshot.filename"
v-bind:object-url="screenshot.url" v-bind:time="screenshot.time" v-on:discard="discard(screenshot)"
v-bind:key="screenshot.id"></video-screenshot>
</transition-group>
<div v-show="showBatch" class="video-screenshot-batch">
<a class="batch-link" style="display:none" v-bind:download="batchFilename"></a>
<button v-on:click="saveAll">
<i class="mdi mdi-content-save"></i>
</button>
<button v-on:click="discardAll">
<i class="mdi mdi-delete-forever"></i>
</button>
</div>
</div>
`);
Vue.component("video-screenshot", {
props: {
objectUrl: String,
filename: String,
time: String,
},
template: /*html*/`
<div class="video-screenshot-thumbnail">
<img v-if="objectUrl" v-bind:src="objectUrl">
<div class="mask" v-if="objectUrl">
<a class="link" style="display:none" v-bind:href="objectUrl" v-bind:download="filename"></a>
<button v-on:click="save" class="save" title="保存"><i class="mdi mdi-content-save-outline"></i></button>
<button v-on:click="discard" title="丢弃" class="discard"><i class="mdi mdi-delete-forever-outline"></i></button>
<span class="time">{{time}}</span>
</div>
<div class="loading" v-else>
</div>
</div>
`,
methods: {
discard() {
this.$emit("discard");
},
save() {
this.$el.querySelector(".link").click();
this.discard();
},
},
});
const screenShotsList = new Vue({
el: ".video-screenshot-container",
data: {
screenshots: [] as Screenshot[],
batchFilename: getFriendlyTitle() + ".zip",
},
methods: {
discard(screenshot: Screenshot) {
this.screenshots.splice(this.screenshots.indexOf(screenshot), 1);
screenshot.revoke();
},
async saveAll() {
const zip = new JSZip();
this.screenshots.forEach((it: Screenshot) => {
zip.file(it.filename, it.blob, {
date: new Date(it.timeStamp),
});
});
const blob = await zip.generateAsync({ type: "blob" });
const link = this.$el.querySelector(".batch-link");
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);
link.href = "";
this.discardAll();
},
discardAll() {
this.screenshots.forEach((it: Screenshot) => it.revoke());
this.screenshots = [];
},
},
computed: {
showBatch() {
return this.screenshots.length >= 2;
},
},
});
const buttonHtml = /*html*/`
<div class="video-take-screenshot" title="截图">
<span><i class="mdi mdi-camera"></i></span>
</div>`;
let screenShotsList: { screenshots: Screenshot[] } = { screenshots: [] }
Observer.videoChange(async () => {
if (!dq('.video-screenshot-container')) {
resources.applyStyle("videoScreenshotStyle");
document.body.insertAdjacentHTML("beforeend", /*html*/`
<div class="video-screenshot-container">
<transition-group class="video-screenshot-list" name="video-screenshot-list" tag="div">
<video-screenshot v-for="screenshot of screenshots" v-bind:filename="screenshot.filename"
v-bind:object-url="screenshot.url" v-bind:time="screenshot.time" v-on:discard="discard(screenshot)"
v-bind:key="screenshot.id"></video-screenshot>
</transition-group>
<div v-show="showBatch" class="video-screenshot-batch">
<a class="batch-link" style="display:none" v-bind:download="batchFilename"></a>
<button v-on:click="saveAll">
<i class="mdi mdi-content-save"></i>
</button>
<button v-on:click="discardAll">
<i class="mdi mdi-delete-forever"></i>
</button>
</div>
</div>
`);
Vue.component("video-screenshot", {
props: {
objectUrl: String,
filename: String,
time: String,
},
template: /*html*/`
<div class="video-screenshot-thumbnail">
<img v-if="objectUrl" v-bind:src="objectUrl">
<div class="mask" v-if="objectUrl">
<a class="link" style="display:none" v-bind:href="objectUrl" v-bind:download="filename"></a>
<button v-on:click="save" class="save" title="保存"><i class="mdi mdi-content-save-outline"></i></button>
<button v-on:click="discard" title="丢弃" class="discard"><i class="mdi mdi-delete-forever-outline"></i></button>
<span class="time">{{time}}</span>
</div>
<div class="loading" v-else>
</div>
</div>
`,
methods: {
discard() {
this.$emit("discard");
},
save() {
this.$el.querySelector(".link").click();
this.discard();
},
},
});
screenShotsList = new Vue({
el: ".video-screenshot-container",
data: {
screenshots: [] as Screenshot[],
batchFilename: getFriendlyTitle() + ".zip",
},
methods: {
discard(screenshot: Screenshot) {
this.screenshots.splice(this.screenshots.indexOf(screenshot), 1);
screenshot.revoke();
},
async saveAll() {
const zip = new JSZip();
this.screenshots.forEach((it: Screenshot) => {
zip.file(it.filename, it.blob, {
date: new Date(it.timeStamp),
});
});
const blob = await zip.generateAsync({ type: "blob" });
const link = this.$el.querySelector(".batch-link");
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);
link.href = "";
this.discardAll();
},
discardAll() {
this.screenshots.forEach((it: Screenshot) => it.revoke());
this.screenshots = [];
},
},
computed: {
showBatch() {
return this.screenshots.length >= 2;
},
},
});
}
const video = await SpinQuery.select("#bofqi video") as HTMLVideoElement;
if (video === null) {
return;
@ -160,6 +159,11 @@ Observer.videoChange(async () => {
if (time === null || document.querySelector(".video-take-screenshot")) {
return;
}
const buttonHtml = /*html*/`
<div class="video-take-screenshot" title="截图">
<span><i class="mdi mdi-camera"></i></span>
</div>`;
time.insertAdjacentHTML("afterend", buttonHtml);
const screenshotButton = document.querySelector(".video-take-screenshot") as HTMLElement;
screenshotButton.addEventListener("click", async e => {

View File

@ -1 +1 @@
1.9.1
1.9.5