56
README.md
@ -1,29 +1,23 @@
|
||||
# Bilibili-Evolved
|
||||
增强哔哩哔哩Web端体验的油猴脚本.
|
||||
增强哔哩哔哩Web端体验的油猴脚本: 修复界面瑕疵, 删除广告, 使用夜间模式浏览, 下载视频或视频封面, 以及增加对触屏设备的支持等.
|
||||
|
||||
- [安装](#安装)
|
||||
- [了解所有功能](#功能概览)
|
||||
- [浏览设置项](#设置)
|
||||
- [浏览器兼容性](#兼容性)
|
||||
- [版本历史与更新日志](https://github.com/the1812/Bilibili-Evolved/releases)
|
||||
|
||||
# 安装
|
||||
需要浏览器拥有[Tampermonkey](https://tampermonkey.net/)或同类插件.
|
||||
|
||||
[](https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.user.js)
|
||||
|
||||
正式发布的版本, 最稳定, 更新频率较低.
|
||||
|
||||
[](https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js)
|
||||
|
||||
新增内容测试的地方, 更新频率高, 但功能不稳定.
|
||||
|
||||
[](https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.offline.user.js)
|
||||
|
||||
内置所有依赖项, 体积较大, 可以减少GitHub服务器不稳定的影响. 由于任何依赖项更新后此脚本也需更新, 所以更新频率会高于正式版.
|
||||
|
||||
[](https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview-offline.user.js)
|
||||
|
||||
兼备预览版和离线版的特点.
|
||||
[正式版](https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.user.js) | [预览版](https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js) | [离线版](https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js) | [预览离线版](https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.offline.user.js)
|
||||
----- | ----- | ----- | -----
|
||||
正式发布的版本, 最稳定, 更新频率较低. | 新增内容测试的地方, 更新频率高, 但功能不稳定. | 内置所有依赖项, 体积较大, 更新频率高于正式版. | 兼备预览版和离线版的特点.
|
||||
|
||||
> 某些破坏性的大更新会使旧版脚本**完全**无法工作, 请及时检查更新.
|
||||
# 设置
|
||||
脚本启用后, 在网页左侧中央会有一个齿轮图标, 点击即可打开设置.
|
||||
设置项的说明见功能概览一节.
|
||||
设置项的说明见[功能概览](#功能概览)一节.
|
||||
|
||||
**设置保存后, 需要刷新网页才能生效.**
|
||||

|
||||
@ -102,7 +96,7 @@
|
||||
#### 启用后
|
||||

|
||||
#### 移除横幅
|
||||
在搜索框位置调整启用的时候, 还可以使用此功能移除顶部横幅.
|
||||
在搜索栏置顶启用的时候, 还可以使用此功能移除顶部横幅.
|
||||
##### 启用前
|
||||

|
||||
##### 启用后
|
||||
@ -110,7 +104,10 @@
|
||||
### 强制宽屏
|
||||
对主站强制使用宽屏样式, 默认将在宽度达到`1368px`时启用. 这个触发宽度可以在设置中更改为任何有效的CSS宽度值.
|
||||
> 原有的宽屏样式会在宽度超过`1400px`时使用, 如果将触发宽度设为大于`1400px`的值实际上没有意义.
|
||||
|
||||
#### 启用前
|
||||

|
||||
#### 启用后
|
||||

|
||||
|
||||
## 工具
|
||||
### 删除广告
|
||||
@ -132,13 +129,24 @@
|
||||
|
||||
|
||||
## 视频与直播
|
||||
### 下载视频(实验性)
|
||||
在视频播放页面中, `设置`→`视频与直播`下会出现下载视频按钮, 点击可以选择清晰度并下载.
|
||||
|
||||
由于JavaScript的单线程限制, 下载速度可能不是很快, 如果你更喜欢使用其他的多线程下载软件, 可以在选择清晰度后选择`复制链接`. **下载时的请求Header必须包含`Origin=https://www.bilibili.com`和`Referer=当前视频网址`**
|
||||
> 目前此功能只支持普通视频, 对番剧和电影无效. 下载后的格式通常为`.flv`, 若需要`.mp4`格式则要手动用其他软件转换.
|
||||
|
||||
> **分段**的视频会把所有视频打包成`.zip`格式.
|
||||
|
||||
> 能够下载的清晰度取决于当前登录的账号, 例如`高清 1080P60`需要已登录大会员账号.
|
||||
|
||||

|
||||
### 查看封面
|
||||
在视频播放页面/直播间中, `设置`→`视频与直播`下会出现查看封面按钮, 点击可以查看或保存封面.
|
||||
在视频播放页面/直播间中, `设置`→`视频与直播`下会出现查看封面按钮, 点击可以查看或保存封面. (其实还可以看专栏的封面, 不过专栏的封面本来就显示在标题上方了)
|
||||

|
||||
### 自动展开弹幕列表
|
||||
新版播放页面中, 弹幕列表默认收起以显示推荐的其他视频. 启用此功能可在每次加载视频时自动展开弹幕列表.
|
||||
### 缩放看板娘
|
||||
根据屏幕DPI缩放看板娘的大小以提高像素的清晰度.
|
||||
根据屏幕DPI缩放看板娘的大小以提高像素的清晰度, DPI缩放为100%的用户可以忽略此选项.
|
||||
### 删除直播水印
|
||||
删除观看直播时角落的水印.
|
||||
### 删除视频标题层
|
||||
@ -183,6 +191,8 @@
|
||||

|
||||
### 模糊设置面板背景
|
||||
使设置面板的内容区半透明并模糊后方图像.
|
||||
#### 效果对比
|
||||

|
||||
### 启用缓存
|
||||
使用缓存以提高脚本的加载速度, 此选项只对非离线版有效.
|
||||
|
||||
@ -199,4 +209,6 @@
|
||||
- 顶栏触摸体验不佳.
|
||||
- 触摸功能需要手动在`about:flags`中开启.
|
||||
## 
|
||||
尚未在Safari中测试.
|
||||
- 尚未在Safari中测试.
|
||||
|
||||
[返回顶部](#Bilibili-Evolved)
|
||||
@ -1,8 +1,10 @@
|
||||
// ==UserScript==
|
||||
// @name Bilibili Evolved (Preview)
|
||||
// @version 1.5.10
|
||||
// @description 增强哔哩哔哩Web端体验. (预览版分支)
|
||||
// @version 1.5.22
|
||||
// @description 增强哔哩哔哩Web端体验(预览版分支): 修复界面瑕疵, 删除广告, 使用夜间模式浏览, 下载视频或视频封面, 以及增加对触屏设备的支持等.
|
||||
// @author Grant Howard, Coulomb-G
|
||||
// @copyright 2018, Grant Howrad (https://github.com/the1812)
|
||||
// @license MIT
|
||||
// @match *://*.bilibili.com/*
|
||||
// @match *://*.bilibili.com
|
||||
// @run-at document-end
|
||||
@ -14,7 +16,10 @@
|
||||
// @grant GM_getValue
|
||||
// @grant GM_setValue
|
||||
// @grant GM_addValueChangeListener
|
||||
// @grant GM_setClipboard
|
||||
// @grant GM_info
|
||||
// @require https://code.jquery.com/jquery-3.2.1.min.js
|
||||
// @require https://cdn.bootcss.com/jszip/3.1.5/jszip.min.js
|
||||
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/logo.png
|
||||
// ==/UserScript==
|
||||
(self$ =>
|
||||
@ -56,8 +61,10 @@
|
||||
notifyNewVersion: true,
|
||||
clearCache: true,
|
||||
fixFullscreen: false,
|
||||
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js",
|
||||
currentVersion: "1.5.10"
|
||||
downloadVideo: true,
|
||||
about: false,
|
||||
latestVersionLink: GM_info.script.updateURL,
|
||||
currentVersion: GM_info.script.version
|
||||
};
|
||||
function loadSettings()
|
||||
{
|
||||
@ -86,129 +93,348 @@
|
||||
}
|
||||
function loadResources()
|
||||
{
|
||||
Resource.root = "https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/";
|
||||
Resource.all = {
|
||||
style: new Resource("min/style.min.scss", 1),
|
||||
oldStyle: new Resource("min/old.min.scss", 1),
|
||||
scrollbarStyle: new Resource("min/scrollbar.min.css", 1),
|
||||
darkStyle: new Resource("min/dark.min.scss", 2),
|
||||
darkStyleImportant: new Resource("min/dark-important.min.scss"),
|
||||
darkStyleNavBar: new Resource("min/dark-navbar.min.scss"),
|
||||
touchPlayerStyle: new Resource("min/touch-player.min.scss", 3),
|
||||
navbarOverrideStyle: new Resource("min/override-navbar.min.css", 4),
|
||||
noBannerStyle: new Resource("min/no-banner.min.css", 5),
|
||||
removeAdsStyle: new Resource("min/remove-promotions.min.css", 6),
|
||||
guiSettingsStyle: new Resource("min/gui-settings.min.scss", 0),
|
||||
fullTweetsTitleStyle: new Resource("min/full-tweets-title.min.css", 7),
|
||||
imageViewerStyle: new Resource("min/image-viewer.min.scss", 8),
|
||||
toastStyle: new Resource("min/toast.min.scss", 9),
|
||||
blurVideoControlStyle: new Resource("min/blur-video-control.min.css", 10),
|
||||
forceWideStyle: new Resource("min/force-wide.min.scss"),
|
||||
|
||||
guiSettingsDom: new Resource("min/gui-settings.min.html"),
|
||||
imageViewerDom: new Resource("min/image-viewer.min.html"),
|
||||
latestVersion: new Resource("version.txt"),
|
||||
|
||||
guiSettings: new Resource("min/gui-settings.min.js"),
|
||||
useDarkStyle: new Resource("min/dark-styles.min.js"),
|
||||
useNewStyle: new Resource("min/new-styles.min.js"),
|
||||
overrideNavBar: new Resource("min/override-navbar.min.js"),
|
||||
touchNavBar: new Resource("min/touch-navbar.min.js"),
|
||||
touchVideoPlayer: new Resource("min/touch-player.min.js"),
|
||||
expandDanmakuList: new Resource("min/expand-danmaku.min.js"),
|
||||
removeAds: new Resource("min/remove-promotions.min.js"),
|
||||
watchLaterRedirect: new Resource("min/watchlater.min.js"),
|
||||
hideTopSearch: new Resource("min/hide-top-search.min.js"),
|
||||
harunaScale: new Resource("min/haruna-scale.min.js"),
|
||||
removeLiveWatermark: new Resource("min/remove-watermark.min.js"),
|
||||
fullTweetsTitle: new Resource("min/full-tweets-title.min.js"),
|
||||
viewCover: new Resource("min/view-cover.min.js"),
|
||||
notifyNewVersion: new Resource("min/notify-new-version.min.js"),
|
||||
toast: new Resource("min/toast.min.js"),
|
||||
removeVideoTopMask: new Resource("min/remove-top-mask.min.js"),
|
||||
blurVideoControl: new Resource("min/blur-video-control.min.js"),
|
||||
darkSchedule: new Resource("min/dark-schedule.min.js"),
|
||||
forceWide: new Resource("min/force-wide.min.js"),
|
||||
clearCache: new Resource("min/clear-cache.min.js")
|
||||
const resouceManifest = {
|
||||
style: {
|
||||
path: "min/style.min.scss",
|
||||
order: 1
|
||||
},
|
||||
oldStyle: {
|
||||
path: "min/old.min.scss",
|
||||
order: 1
|
||||
},
|
||||
scrollbarStyle: {
|
||||
path: "min/scrollbar.min.css",
|
||||
order: 1
|
||||
},
|
||||
darkStyle: {
|
||||
path: "min/dark.min.scss",
|
||||
order: 2
|
||||
},
|
||||
darkStyleImportant: {
|
||||
path: "min/dark-important.min.scss"
|
||||
},
|
||||
darkStyleNavBar: {
|
||||
path: "min/dark-navbar.min.scss"
|
||||
},
|
||||
touchPlayerStyle: {
|
||||
path: "min/touch-player.min.scss",
|
||||
order: 3
|
||||
},
|
||||
navbarOverrideStyle: {
|
||||
path: "min/override-navbar.min.css",
|
||||
order: 4
|
||||
},
|
||||
noBannerStyle: {
|
||||
path: "min/no-banner.min.css",
|
||||
order: 5
|
||||
},
|
||||
removeAdsStyle: {
|
||||
path: "min/remove-promotions.min.css",
|
||||
order: 6
|
||||
},
|
||||
guiSettingsStyle: {
|
||||
path: "min/gui-settings.min.scss",
|
||||
order: 0
|
||||
},
|
||||
fullTweetsTitleStyle: {
|
||||
path: "min/full-tweets-title.min.css",
|
||||
order: 7
|
||||
},
|
||||
imageViewerStyle: {
|
||||
path: "min/image-viewer.min.scss",
|
||||
order: 8
|
||||
},
|
||||
toastStyle: {
|
||||
path: "min/toast.min.scss",
|
||||
order: 9
|
||||
},
|
||||
blurVideoControlStyle: {
|
||||
path: "min/blur-video-control.min.css",
|
||||
order: 10
|
||||
},
|
||||
forceWideStyle: {
|
||||
path: "min/force-wide.min.scss"
|
||||
},
|
||||
downloadVideoStyle: {
|
||||
path: "min/download-video.min.scss"
|
||||
},
|
||||
guiSettingsDom: {
|
||||
path: "min/gui-settings.min.html"
|
||||
},
|
||||
imageViewerDom: {
|
||||
path: "min/image-viewer.min.html"
|
||||
},
|
||||
downloadVideoDom: {
|
||||
path: "min/download-video.min.html"
|
||||
},
|
||||
latestVersion: {
|
||||
path: "version.txt"
|
||||
},
|
||||
guiSettings: {
|
||||
path: "min/gui-settings.min.js",
|
||||
dependencies: [
|
||||
"guiSettingsDom",
|
||||
"guiSettingsStyle"
|
||||
],
|
||||
displayNames: {
|
||||
guiSettings: "设置",
|
||||
blurSettingsPanel: "模糊设置面板背景"
|
||||
}
|
||||
},
|
||||
useDarkStyle: {
|
||||
path: "min/dark-styles.min.js",
|
||||
dependencies: [
|
||||
"darkStyle",
|
||||
"darkStyleImportant",
|
||||
"darkStyleNavBar",
|
||||
"scrollbarStyle"
|
||||
],
|
||||
displayNames: {
|
||||
useDarkStyle: "夜间模式"
|
||||
}
|
||||
},
|
||||
useNewStyle: {
|
||||
path: "min/new-styles.min.js",
|
||||
dependencies: [
|
||||
"style",
|
||||
"oldStyle",
|
||||
"scrollbarStyle"
|
||||
],
|
||||
displayNames: {
|
||||
useNewStyle: "样式调整",
|
||||
blurBackgroundOpacity: "顶栏(对横幅)不透明度"
|
||||
}
|
||||
},
|
||||
overrideNavBar: {
|
||||
path: "min/override-navbar.min.js",
|
||||
dependencies: [
|
||||
"navbarOverrideStyle",
|
||||
"noBannerStyle"
|
||||
],
|
||||
displayNames: {
|
||||
overrideNavBar: "搜索栏置顶",
|
||||
showBanner: "显示顶部横幅"
|
||||
}
|
||||
},
|
||||
touchNavBar: {
|
||||
path: "min/touch-navbar.min.js",
|
||||
displayNames: {
|
||||
touchNavBar: "顶栏触摸优化"
|
||||
}
|
||||
},
|
||||
touchVideoPlayer: {
|
||||
path: "min/touch-player.min.js",
|
||||
dependencies: [
|
||||
"touchPlayerStyle"
|
||||
],
|
||||
displayNames: {
|
||||
touchVideoPlayer: "播放器触摸支持",
|
||||
touchVideoPlayerAnimation: "启用实验性动画效果",
|
||||
touchVideoPlayerDoubleTapControl: "启用双击控制"
|
||||
}
|
||||
},
|
||||
expandDanmakuList: {
|
||||
path: "min/expand-danmaku.min.js",
|
||||
displayNames: {
|
||||
expandDanmakuList: "自动展开弹幕列表"
|
||||
}
|
||||
},
|
||||
removeAds: {
|
||||
path: "min/remove-promotions.min.js",
|
||||
dependencies: [
|
||||
"removeAdsStyle"
|
||||
],
|
||||
displayNames: {
|
||||
removeAds: "删除广告"
|
||||
}
|
||||
},
|
||||
watchLaterRedirect: {
|
||||
path: "min/watchlater.min.js",
|
||||
displayNames: {
|
||||
watchLaterRedirect: "稍后再看重定向"
|
||||
}
|
||||
},
|
||||
hideTopSearch: {
|
||||
path: "min/hide-top-search.min.js",
|
||||
displayNames: {
|
||||
hideTopSearch: "隐藏搜索推荐"
|
||||
}
|
||||
},
|
||||
harunaScale: {
|
||||
path: "min/haruna-scale.min.js",
|
||||
displayNames: {
|
||||
harunaScale: "缩放看板娘"
|
||||
}
|
||||
},
|
||||
removeLiveWatermark: {
|
||||
path: "min/remove-watermark.min.js",
|
||||
displayNames: {
|
||||
removeLiveWatermark: "删除直播水印"
|
||||
}
|
||||
},
|
||||
fullTweetsTitle: {
|
||||
path: "min/full-tweets-title.min.js",
|
||||
dependencies: [
|
||||
"fullTweetsTitleStyle"
|
||||
],
|
||||
displayNames: {
|
||||
fullTweetsTitle: "展开动态标题"
|
||||
}
|
||||
},
|
||||
viewCover: {
|
||||
path: "min/view-cover.min.js",
|
||||
dependencies: [
|
||||
"imageViewerDom",
|
||||
"imageViewerStyle"
|
||||
],
|
||||
displayNames: {
|
||||
viewCover: "查看封面"
|
||||
}
|
||||
},
|
||||
notifyNewVersion: {
|
||||
path: "min/notify-new-version.min.js",
|
||||
dependencies: [
|
||||
"latestVersion"
|
||||
],
|
||||
displayNames: {
|
||||
notifyNewVersion: "检查更新"
|
||||
}
|
||||
},
|
||||
toast: {
|
||||
path: "min/toast.min.js",
|
||||
dependencies: [
|
||||
"toastStyle"
|
||||
],
|
||||
displayNames: {
|
||||
toast: "显示消息"
|
||||
}
|
||||
},
|
||||
removeVideoTopMask: {
|
||||
path: "min/remove-top-mask.min.js",
|
||||
displayNames: {
|
||||
removeVideoTopMask: "删除视频标题层"
|
||||
}
|
||||
},
|
||||
blurVideoControl: {
|
||||
path: "min/blur-video-control.min.js",
|
||||
dependencies: [
|
||||
"blurVideoControlStyle"
|
||||
],
|
||||
displayNames: {
|
||||
blurVideoControl: "模糊视频控制栏背景"
|
||||
}
|
||||
},
|
||||
darkSchedule: {
|
||||
path: "min/dark-schedule.min.js",
|
||||
displayNames: {
|
||||
darkSchedule: "夜间模式计划时段",
|
||||
darkScheduleStart: "起始时间",
|
||||
darkScheduleEnd: "结束时间"
|
||||
}
|
||||
},
|
||||
forceWide: {
|
||||
path: "min/force-wide.min.js",
|
||||
dependencies: [
|
||||
"forceWideStyle"
|
||||
],
|
||||
displayNames: {
|
||||
forceWide: "强制宽屏",
|
||||
forceWideMinWidth: "触发宽度"
|
||||
}
|
||||
},
|
||||
clearCache: {
|
||||
path: "min/clear-cache.min.js",
|
||||
displayNames: {
|
||||
useCache: "启用缓存"
|
||||
}
|
||||
},
|
||||
downloadVideo: {
|
||||
path: "min/download-video.min.js",
|
||||
dependencies: [
|
||||
"downloadVideoDom",
|
||||
"downloadVideoStyle",
|
||||
"videoInfo"
|
||||
]
|
||||
},
|
||||
videoInfo: {
|
||||
path: "min/video-info.min.js"
|
||||
},
|
||||
aboutDom: {
|
||||
path: "min/about.min.html"
|
||||
},
|
||||
aboutStyle: {
|
||||
path: "min/about.min.scss"
|
||||
},
|
||||
about: {
|
||||
path: "min/about.min.js",
|
||||
dependencies: [
|
||||
"aboutDom",
|
||||
"aboutStyle"
|
||||
]
|
||||
}
|
||||
};
|
||||
(function ()
|
||||
Resource.root = "https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/";
|
||||
Resource.all = {};
|
||||
Resource.displayNames = {};
|
||||
for (const [key, data] of Object.entries(resouceManifest))
|
||||
{
|
||||
this.guiSettings.dependencies = [
|
||||
this.guiSettingsDom,
|
||||
this.guiSettingsStyle
|
||||
];
|
||||
this.useDarkStyle.dependencies = [
|
||||
this.darkStyle,
|
||||
this.darkStyleImportant,
|
||||
this.darkStyleNavBar,
|
||||
this.scrollbarStyle
|
||||
];
|
||||
this.useNewStyle.dependencies = [
|
||||
this.style,
|
||||
this.oldStyle,
|
||||
this.scrollbarStyle
|
||||
];
|
||||
this.overrideNavBar.dependencies = [
|
||||
this.navbarOverrideStyle,
|
||||
this.noBannerStyle
|
||||
];
|
||||
this.touchVideoPlayer.dependencies = [
|
||||
this.touchPlayerStyle
|
||||
];
|
||||
this.removeAds.dependencies = [
|
||||
this.removeAdsStyle
|
||||
];
|
||||
this.fullTweetsTitle.dependencies = [
|
||||
this.fullTweetsTitleStyle
|
||||
];
|
||||
this.viewCover.dependencies = [
|
||||
this.imageViewerDom,
|
||||
this.imageViewerStyle
|
||||
];
|
||||
this.notifyNewVersion.dependencies = [
|
||||
this.latestVersion
|
||||
];
|
||||
this.toast.dependencies = [
|
||||
this.toastStyle
|
||||
];
|
||||
this.blurVideoControl.dependencies = [
|
||||
this.blurVideoControlStyle
|
||||
];
|
||||
this.forceWide.dependencies = [
|
||||
this.forceWideStyle
|
||||
];
|
||||
}).apply(Resource.all);
|
||||
(function ()
|
||||
const resource = new Resource(data.path, data.order);
|
||||
resource.key = key;
|
||||
if (data.displayNames)
|
||||
{
|
||||
resource.displayName = data.displayNames[key];
|
||||
Object.assign(Resource.displayNames, data.displayNames);
|
||||
}
|
||||
Resource.all[key] = resource;
|
||||
}
|
||||
for (const [key, data] of Object.entries(resouceManifest))
|
||||
{
|
||||
this.guiSettings.displayName = "设置";
|
||||
this.useDarkStyle.displayName = "夜间模式";
|
||||
this.useNewStyle.displayName = "样式调整";
|
||||
this.overrideNavBar.displayName = "搜索栏置顶";
|
||||
this.touchNavBar.displayName = "顶栏触摸优化";
|
||||
this.touchVideoPlayer.displayName = "播放器触摸支持";
|
||||
this.expandDanmakuList.displayName = "自动展开弹幕列表";
|
||||
this.removeAds.displayName = "删除广告";
|
||||
this.watchLaterRedirect.displayName = "稍后再看重定向";
|
||||
this.hideTopSearch.displayName = "隐藏搜索推荐";
|
||||
this.harunaScale.displayName = "缩放看板娘";
|
||||
this.removeLiveWatermark.displayName = "删除直播水印";
|
||||
this.fullTweetsTitle.displayName = "展开动态标题";
|
||||
this.viewCover.displayName = "查看封面";
|
||||
this.notifyNewVersion.displayName = "新版本提醒";
|
||||
this.toast.displayName = "显示消息";
|
||||
this.removeVideoTopMask.displayName = "删除视频标题层";
|
||||
this.blurVideoControl.displayName = "模糊视频控制栏背景";
|
||||
this.darkSchedule.displayName = "夜间模式计划时段";
|
||||
this.forceWide.displayName = "强制宽屏";
|
||||
}).apply(Resource.all);
|
||||
if (data.dependencies)
|
||||
{
|
||||
Resource.all[key].dependencies = data.dependencies.map(name => Resource.all[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
function downloadText(url, load, error)
|
||||
{
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("load", () => load && load(xhr.responseText));
|
||||
xhr.addEventListener("error", () => error && error(xhr.responseText));
|
||||
xhr.open("GET", url);
|
||||
xhr.send();
|
||||
|
||||
if (load) // callback
|
||||
{
|
||||
xhr.addEventListener("load", () => load && load(xhr.responseText));
|
||||
xhr.addEventListener("error", () => error && error(xhr.responseText));
|
||||
xhr.send();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
xhr.addEventListener("load", () => resolve(xhr.responseText));
|
||||
xhr.addEventListener("error", () => reject(xhr.responseText));
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
}
|
||||
function fixed(number, precision = 1)
|
||||
{
|
||||
const str = number.toString();
|
||||
const index = str.indexOf(".");
|
||||
if (index !== -1)
|
||||
{
|
||||
if (str.length - index > precision + 1)
|
||||
{
|
||||
return str.substring(0, index + precision + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return str + ".0";
|
||||
}
|
||||
}
|
||||
// Placeholder class for Toast
|
||||
class Toast
|
||||
@ -561,17 +787,19 @@
|
||||
{
|
||||
return new ResourceType("html", html =>
|
||||
{
|
||||
const keys = Object.keys(Resource.all).filter(key => Resource.all[key].displayName);
|
||||
for (const key of keys)
|
||||
for (const [key, name] of Object.entries(Resource.displayNames))
|
||||
{
|
||||
html = html
|
||||
.replace(new RegExp(`(<checkbox\\s*?indent=".+?"\\s*?key="${key}"\\s*?dependencies=".*?">)[^\\0]*?(</checkbox>)`, "g"),
|
||||
`$1${Resource.all[key].displayName}$2`);
|
||||
html = html.replace(new RegExp(`(<(.+)\\s*?indent="[\\d]+?"\\s*?key="${key}"\\s*?dependencies=".*?">)[^\\0]*?(</\\2>)`, "g"),
|
||||
`$1${name}$3`);
|
||||
}
|
||||
return html
|
||||
.replace(/<category>([^\0]*?)<\/category>/g, `
|
||||
return html.replace(/<category>([^\0]*?)<\/category>/g, `
|
||||
<li class="indent-center category">
|
||||
<span class="settings-category">$1</span>
|
||||
<span class="settings-category">
|
||||
$1
|
||||
<i class="settings-category-arrow"></i>
|
||||
</span>
|
||||
</li>
|
||||
<li class="indent-center widgets-container" category-name="$1">
|
||||
</li>
|
||||
`).replace(/<checkbox\s*?indent="(.+?)"\s*?key="(.+?)"\s*?dependencies="(.*?)">([^\0]*?)<\/checkbox>/g, `
|
||||
<li class="indent-$1">
|
||||
@ -612,16 +840,13 @@
|
||||
{
|
||||
return this.text !== null;
|
||||
}
|
||||
get key()
|
||||
{
|
||||
return Object.keys(Resource.all).find(k => Resource.all[k] === this);
|
||||
}
|
||||
constructor(url, priority)
|
||||
{
|
||||
this.url = Resource.root + url;
|
||||
this.dependencies = [];
|
||||
this.priority = priority;
|
||||
this.text = null;
|
||||
this.key = null;
|
||||
this.type = ResourceType.fromUrl(url);
|
||||
this.displayName = "";
|
||||
}
|
||||
@ -779,6 +1004,9 @@
|
||||
return null;
|
||||
}
|
||||
const promise = resource.download();
|
||||
resource.dependencies
|
||||
.filter(it => it.type.name === "script")
|
||||
.forEach(it => this.fetchByKey(it.key));
|
||||
return new Promise(resolve =>
|
||||
{
|
||||
promise.then(text =>
|
||||
@ -854,6 +1082,10 @@
|
||||
{
|
||||
panel.find(info.before()).before(info.content);
|
||||
}
|
||||
else if (info.category)
|
||||
{
|
||||
panel.find(`.widgets-container[category-name=${info.category}]`).append(info.content);
|
||||
}
|
||||
|
||||
if (info.success)
|
||||
{
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
// ==UserScript==
|
||||
// @name Bilibili Evolved
|
||||
// @version 1.5.10
|
||||
// @description 增强哔哩哔哩Web端体验.
|
||||
// @version 1.5.22
|
||||
// @description 增强哔哩哔哩Web端体验: 修复界面瑕疵, 删除广告, 使用夜间模式浏览, 下载视频或视频封面, 以及增加对触屏设备的支持等.
|
||||
// @author Grant Howard, Coulomb-G
|
||||
// @copyright 2018, Grant Howrad (https://github.com/the1812)
|
||||
// @license MIT
|
||||
// @match *://*.bilibili.com/*
|
||||
// @match *://*.bilibili.com
|
||||
// @run-at document-end
|
||||
@ -14,7 +16,10 @@
|
||||
// @grant GM_getValue
|
||||
// @grant GM_setValue
|
||||
// @grant GM_addValueChangeListener
|
||||
// @grant GM_setClipboard
|
||||
// @grant GM_info
|
||||
// @require https://code.jquery.com/jquery-3.2.1.min.js
|
||||
// @require https://cdn.bootcss.com/jszip/3.1.5/jszip.min.js
|
||||
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/images/logo.png
|
||||
// ==/UserScript==
|
||||
(self$ =>
|
||||
@ -56,8 +61,10 @@
|
||||
notifyNewVersion: true,
|
||||
clearCache: true,
|
||||
fixFullscreen: false,
|
||||
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.user.js",
|
||||
currentVersion: "1.5.10"
|
||||
downloadVideo: true,
|
||||
about: false,
|
||||
latestVersionLink: GM_info.script.updateURL,
|
||||
currentVersion: GM_info.script.version
|
||||
};
|
||||
function loadSettings()
|
||||
{
|
||||
@ -86,129 +93,348 @@
|
||||
}
|
||||
function loadResources()
|
||||
{
|
||||
Resource.root = "https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/";
|
||||
Resource.all = {
|
||||
style: new Resource("min/style.min.scss", 1),
|
||||
oldStyle: new Resource("min/old.min.scss", 1),
|
||||
scrollbarStyle: new Resource("min/scrollbar.min.css", 1),
|
||||
darkStyle: new Resource("min/dark.min.scss", 2),
|
||||
darkStyleImportant: new Resource("min/dark-important.min.scss"),
|
||||
darkStyleNavBar: new Resource("min/dark-navbar.min.scss"),
|
||||
touchPlayerStyle: new Resource("min/touch-player.min.scss", 3),
|
||||
navbarOverrideStyle: new Resource("min/override-navbar.min.css", 4),
|
||||
noBannerStyle: new Resource("min/no-banner.min.css", 5),
|
||||
removeAdsStyle: new Resource("min/remove-promotions.min.css", 6),
|
||||
guiSettingsStyle: new Resource("min/gui-settings.min.scss", 0),
|
||||
fullTweetsTitleStyle: new Resource("min/full-tweets-title.min.css", 7),
|
||||
imageViewerStyle: new Resource("min/image-viewer.min.scss", 8),
|
||||
toastStyle: new Resource("min/toast.min.scss", 9),
|
||||
blurVideoControlStyle: new Resource("min/blur-video-control.min.css", 10),
|
||||
forceWideStyle: new Resource("min/force-wide.min.scss"),
|
||||
|
||||
guiSettingsDom: new Resource("min/gui-settings.min.html"),
|
||||
imageViewerDom: new Resource("min/image-viewer.min.html"),
|
||||
latestVersion: new Resource("version.txt"),
|
||||
|
||||
guiSettings: new Resource("min/gui-settings.min.js"),
|
||||
useDarkStyle: new Resource("min/dark-styles.min.js"),
|
||||
useNewStyle: new Resource("min/new-styles.min.js"),
|
||||
overrideNavBar: new Resource("min/override-navbar.min.js"),
|
||||
touchNavBar: new Resource("min/touch-navbar.min.js"),
|
||||
touchVideoPlayer: new Resource("min/touch-player.min.js"),
|
||||
expandDanmakuList: new Resource("min/expand-danmaku.min.js"),
|
||||
removeAds: new Resource("min/remove-promotions.min.js"),
|
||||
watchLaterRedirect: new Resource("min/watchlater.min.js"),
|
||||
hideTopSearch: new Resource("min/hide-top-search.min.js"),
|
||||
harunaScale: new Resource("min/haruna-scale.min.js"),
|
||||
removeLiveWatermark: new Resource("min/remove-watermark.min.js"),
|
||||
fullTweetsTitle: new Resource("min/full-tweets-title.min.js"),
|
||||
viewCover: new Resource("min/view-cover.min.js"),
|
||||
notifyNewVersion: new Resource("min/notify-new-version.min.js"),
|
||||
toast: new Resource("min/toast.min.js"),
|
||||
removeVideoTopMask: new Resource("min/remove-top-mask.min.js"),
|
||||
blurVideoControl: new Resource("min/blur-video-control.min.js"),
|
||||
darkSchedule: new Resource("min/dark-schedule.min.js"),
|
||||
forceWide: new Resource("min/force-wide.min.js"),
|
||||
clearCache: new Resource("min/clear-cache.min.js")
|
||||
const resouceManifest = {
|
||||
style: {
|
||||
path: "min/style.min.scss",
|
||||
order: 1
|
||||
},
|
||||
oldStyle: {
|
||||
path: "min/old.min.scss",
|
||||
order: 1
|
||||
},
|
||||
scrollbarStyle: {
|
||||
path: "min/scrollbar.min.css",
|
||||
order: 1
|
||||
},
|
||||
darkStyle: {
|
||||
path: "min/dark.min.scss",
|
||||
order: 2
|
||||
},
|
||||
darkStyleImportant: {
|
||||
path: "min/dark-important.min.scss"
|
||||
},
|
||||
darkStyleNavBar: {
|
||||
path: "min/dark-navbar.min.scss"
|
||||
},
|
||||
touchPlayerStyle: {
|
||||
path: "min/touch-player.min.scss",
|
||||
order: 3
|
||||
},
|
||||
navbarOverrideStyle: {
|
||||
path: "min/override-navbar.min.css",
|
||||
order: 4
|
||||
},
|
||||
noBannerStyle: {
|
||||
path: "min/no-banner.min.css",
|
||||
order: 5
|
||||
},
|
||||
removeAdsStyle: {
|
||||
path: "min/remove-promotions.min.css",
|
||||
order: 6
|
||||
},
|
||||
guiSettingsStyle: {
|
||||
path: "min/gui-settings.min.scss",
|
||||
order: 0
|
||||
},
|
||||
fullTweetsTitleStyle: {
|
||||
path: "min/full-tweets-title.min.css",
|
||||
order: 7
|
||||
},
|
||||
imageViewerStyle: {
|
||||
path: "min/image-viewer.min.scss",
|
||||
order: 8
|
||||
},
|
||||
toastStyle: {
|
||||
path: "min/toast.min.scss",
|
||||
order: 9
|
||||
},
|
||||
blurVideoControlStyle: {
|
||||
path: "min/blur-video-control.min.css",
|
||||
order: 10
|
||||
},
|
||||
forceWideStyle: {
|
||||
path: "min/force-wide.min.scss"
|
||||
},
|
||||
downloadVideoStyle: {
|
||||
path: "min/download-video.min.scss"
|
||||
},
|
||||
guiSettingsDom: {
|
||||
path: "min/gui-settings.min.html"
|
||||
},
|
||||
imageViewerDom: {
|
||||
path: "min/image-viewer.min.html"
|
||||
},
|
||||
downloadVideoDom: {
|
||||
path: "min/download-video.min.html"
|
||||
},
|
||||
latestVersion: {
|
||||
path: "version.txt"
|
||||
},
|
||||
guiSettings: {
|
||||
path: "min/gui-settings.min.js",
|
||||
dependencies: [
|
||||
"guiSettingsDom",
|
||||
"guiSettingsStyle"
|
||||
],
|
||||
displayNames: {
|
||||
guiSettings: "设置",
|
||||
blurSettingsPanel: "模糊设置面板背景"
|
||||
}
|
||||
},
|
||||
useDarkStyle: {
|
||||
path: "min/dark-styles.min.js",
|
||||
dependencies: [
|
||||
"darkStyle",
|
||||
"darkStyleImportant",
|
||||
"darkStyleNavBar",
|
||||
"scrollbarStyle"
|
||||
],
|
||||
displayNames: {
|
||||
useDarkStyle: "夜间模式"
|
||||
}
|
||||
},
|
||||
useNewStyle: {
|
||||
path: "min/new-styles.min.js",
|
||||
dependencies: [
|
||||
"style",
|
||||
"oldStyle",
|
||||
"scrollbarStyle"
|
||||
],
|
||||
displayNames: {
|
||||
useNewStyle: "样式调整",
|
||||
blurBackgroundOpacity: "顶栏(对横幅)不透明度"
|
||||
}
|
||||
},
|
||||
overrideNavBar: {
|
||||
path: "min/override-navbar.min.js",
|
||||
dependencies: [
|
||||
"navbarOverrideStyle",
|
||||
"noBannerStyle"
|
||||
],
|
||||
displayNames: {
|
||||
overrideNavBar: "搜索栏置顶",
|
||||
showBanner: "显示顶部横幅"
|
||||
}
|
||||
},
|
||||
touchNavBar: {
|
||||
path: "min/touch-navbar.min.js",
|
||||
displayNames: {
|
||||
touchNavBar: "顶栏触摸优化"
|
||||
}
|
||||
},
|
||||
touchVideoPlayer: {
|
||||
path: "min/touch-player.min.js",
|
||||
dependencies: [
|
||||
"touchPlayerStyle"
|
||||
],
|
||||
displayNames: {
|
||||
touchVideoPlayer: "播放器触摸支持",
|
||||
touchVideoPlayerAnimation: "启用实验性动画效果",
|
||||
touchVideoPlayerDoubleTapControl: "启用双击控制"
|
||||
}
|
||||
},
|
||||
expandDanmakuList: {
|
||||
path: "min/expand-danmaku.min.js",
|
||||
displayNames: {
|
||||
expandDanmakuList: "自动展开弹幕列表"
|
||||
}
|
||||
},
|
||||
removeAds: {
|
||||
path: "min/remove-promotions.min.js",
|
||||
dependencies: [
|
||||
"removeAdsStyle"
|
||||
],
|
||||
displayNames: {
|
||||
removeAds: "删除广告"
|
||||
}
|
||||
},
|
||||
watchLaterRedirect: {
|
||||
path: "min/watchlater.min.js",
|
||||
displayNames: {
|
||||
watchLaterRedirect: "稍后再看重定向"
|
||||
}
|
||||
},
|
||||
hideTopSearch: {
|
||||
path: "min/hide-top-search.min.js",
|
||||
displayNames: {
|
||||
hideTopSearch: "隐藏搜索推荐"
|
||||
}
|
||||
},
|
||||
harunaScale: {
|
||||
path: "min/haruna-scale.min.js",
|
||||
displayNames: {
|
||||
harunaScale: "缩放看板娘"
|
||||
}
|
||||
},
|
||||
removeLiveWatermark: {
|
||||
path: "min/remove-watermark.min.js",
|
||||
displayNames: {
|
||||
removeLiveWatermark: "删除直播水印"
|
||||
}
|
||||
},
|
||||
fullTweetsTitle: {
|
||||
path: "min/full-tweets-title.min.js",
|
||||
dependencies: [
|
||||
"fullTweetsTitleStyle"
|
||||
],
|
||||
displayNames: {
|
||||
fullTweetsTitle: "展开动态标题"
|
||||
}
|
||||
},
|
||||
viewCover: {
|
||||
path: "min/view-cover.min.js",
|
||||
dependencies: [
|
||||
"imageViewerDom",
|
||||
"imageViewerStyle"
|
||||
],
|
||||
displayNames: {
|
||||
viewCover: "查看封面"
|
||||
}
|
||||
},
|
||||
notifyNewVersion: {
|
||||
path: "min/notify-new-version.min.js",
|
||||
dependencies: [
|
||||
"latestVersion"
|
||||
],
|
||||
displayNames: {
|
||||
notifyNewVersion: "检查更新"
|
||||
}
|
||||
},
|
||||
toast: {
|
||||
path: "min/toast.min.js",
|
||||
dependencies: [
|
||||
"toastStyle"
|
||||
],
|
||||
displayNames: {
|
||||
toast: "显示消息"
|
||||
}
|
||||
},
|
||||
removeVideoTopMask: {
|
||||
path: "min/remove-top-mask.min.js",
|
||||
displayNames: {
|
||||
removeVideoTopMask: "删除视频标题层"
|
||||
}
|
||||
},
|
||||
blurVideoControl: {
|
||||
path: "min/blur-video-control.min.js",
|
||||
dependencies: [
|
||||
"blurVideoControlStyle"
|
||||
],
|
||||
displayNames: {
|
||||
blurVideoControl: "模糊视频控制栏背景"
|
||||
}
|
||||
},
|
||||
darkSchedule: {
|
||||
path: "min/dark-schedule.min.js",
|
||||
displayNames: {
|
||||
darkSchedule: "夜间模式计划时段",
|
||||
darkScheduleStart: "起始时间",
|
||||
darkScheduleEnd: "结束时间"
|
||||
}
|
||||
},
|
||||
forceWide: {
|
||||
path: "min/force-wide.min.js",
|
||||
dependencies: [
|
||||
"forceWideStyle"
|
||||
],
|
||||
displayNames: {
|
||||
forceWide: "强制宽屏",
|
||||
forceWideMinWidth: "触发宽度"
|
||||
}
|
||||
},
|
||||
clearCache: {
|
||||
path: "min/clear-cache.min.js",
|
||||
displayNames: {
|
||||
useCache: "启用缓存"
|
||||
}
|
||||
},
|
||||
downloadVideo: {
|
||||
path: "min/download-video.min.js",
|
||||
dependencies: [
|
||||
"downloadVideoDom",
|
||||
"downloadVideoStyle",
|
||||
"videoInfo"
|
||||
]
|
||||
},
|
||||
videoInfo: {
|
||||
path: "min/video-info.min.js"
|
||||
},
|
||||
aboutDom: {
|
||||
path: "min/about.min.html"
|
||||
},
|
||||
aboutStyle: {
|
||||
path: "min/about.min.scss"
|
||||
},
|
||||
about: {
|
||||
path: "min/about.min.js",
|
||||
dependencies: [
|
||||
"aboutDom",
|
||||
"aboutStyle"
|
||||
]
|
||||
}
|
||||
};
|
||||
(function ()
|
||||
Resource.root = "https://raw.githubusercontent.com/the1812/Bilibili-Evolved/master/";
|
||||
Resource.all = {};
|
||||
Resource.displayNames = {};
|
||||
for (const [key, data] of Object.entries(resouceManifest))
|
||||
{
|
||||
this.guiSettings.dependencies = [
|
||||
this.guiSettingsDom,
|
||||
this.guiSettingsStyle
|
||||
];
|
||||
this.useDarkStyle.dependencies = [
|
||||
this.darkStyle,
|
||||
this.darkStyleImportant,
|
||||
this.darkStyleNavBar,
|
||||
this.scrollbarStyle
|
||||
];
|
||||
this.useNewStyle.dependencies = [
|
||||
this.style,
|
||||
this.oldStyle,
|
||||
this.scrollbarStyle
|
||||
];
|
||||
this.overrideNavBar.dependencies = [
|
||||
this.navbarOverrideStyle,
|
||||
this.noBannerStyle
|
||||
];
|
||||
this.touchVideoPlayer.dependencies = [
|
||||
this.touchPlayerStyle
|
||||
];
|
||||
this.removeAds.dependencies = [
|
||||
this.removeAdsStyle
|
||||
];
|
||||
this.fullTweetsTitle.dependencies = [
|
||||
this.fullTweetsTitleStyle
|
||||
];
|
||||
this.viewCover.dependencies = [
|
||||
this.imageViewerDom,
|
||||
this.imageViewerStyle
|
||||
];
|
||||
this.notifyNewVersion.dependencies = [
|
||||
this.latestVersion
|
||||
];
|
||||
this.toast.dependencies = [
|
||||
this.toastStyle
|
||||
];
|
||||
this.blurVideoControl.dependencies = [
|
||||
this.blurVideoControlStyle
|
||||
];
|
||||
this.forceWide.dependencies = [
|
||||
this.forceWideStyle
|
||||
];
|
||||
}).apply(Resource.all);
|
||||
(function ()
|
||||
const resource = new Resource(data.path, data.order);
|
||||
resource.key = key;
|
||||
if (data.displayNames)
|
||||
{
|
||||
resource.displayName = data.displayNames[key];
|
||||
Object.assign(Resource.displayNames, data.displayNames);
|
||||
}
|
||||
Resource.all[key] = resource;
|
||||
}
|
||||
for (const [key, data] of Object.entries(resouceManifest))
|
||||
{
|
||||
this.guiSettings.displayName = "设置";
|
||||
this.useDarkStyle.displayName = "夜间模式";
|
||||
this.useNewStyle.displayName = "样式调整";
|
||||
this.overrideNavBar.displayName = "搜索栏置顶";
|
||||
this.touchNavBar.displayName = "顶栏触摸优化";
|
||||
this.touchVideoPlayer.displayName = "播放器触摸支持";
|
||||
this.expandDanmakuList.displayName = "自动展开弹幕列表";
|
||||
this.removeAds.displayName = "删除广告";
|
||||
this.watchLaterRedirect.displayName = "稍后再看重定向";
|
||||
this.hideTopSearch.displayName = "隐藏搜索推荐";
|
||||
this.harunaScale.displayName = "缩放看板娘";
|
||||
this.removeLiveWatermark.displayName = "删除直播水印";
|
||||
this.fullTweetsTitle.displayName = "展开动态标题";
|
||||
this.viewCover.displayName = "查看封面";
|
||||
this.notifyNewVersion.displayName = "新版本提醒";
|
||||
this.toast.displayName = "显示消息";
|
||||
this.removeVideoTopMask.displayName = "删除视频标题层";
|
||||
this.blurVideoControl.displayName = "模糊视频控制栏背景";
|
||||
this.darkSchedule.displayName = "夜间模式计划时段";
|
||||
this.forceWide.displayName = "强制宽屏";
|
||||
}).apply(Resource.all);
|
||||
if (data.dependencies)
|
||||
{
|
||||
Resource.all[key].dependencies = data.dependencies.map(name => Resource.all[name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
function downloadText(url, load, error)
|
||||
{
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("load", () => load && load(xhr.responseText));
|
||||
xhr.addEventListener("error", () => error && error(xhr.responseText));
|
||||
xhr.open("GET", url);
|
||||
xhr.send();
|
||||
|
||||
if (load) // callback
|
||||
{
|
||||
xhr.addEventListener("load", () => load && load(xhr.responseText));
|
||||
xhr.addEventListener("error", () => error && error(xhr.responseText));
|
||||
xhr.send();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
xhr.addEventListener("load", () => resolve(xhr.responseText));
|
||||
xhr.addEventListener("error", () => reject(xhr.responseText));
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
}
|
||||
function fixed(number, precision = 1)
|
||||
{
|
||||
const str = number.toString();
|
||||
const index = str.indexOf(".");
|
||||
if (index !== -1)
|
||||
{
|
||||
if (str.length - index > precision + 1)
|
||||
{
|
||||
return str.substring(0, index + precision + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return str + ".0";
|
||||
}
|
||||
}
|
||||
// Placeholder class for Toast
|
||||
class Toast
|
||||
@ -561,17 +787,19 @@
|
||||
{
|
||||
return new ResourceType("html", html =>
|
||||
{
|
||||
const keys = Object.keys(Resource.all).filter(key => Resource.all[key].displayName);
|
||||
for (const key of keys)
|
||||
for (const [key, name] of Object.entries(Resource.displayNames))
|
||||
{
|
||||
html = html
|
||||
.replace(new RegExp(`(<checkbox\\s*?indent=".+?"\\s*?key="${key}"\\s*?dependencies=".*?">)[^\\0]*?(</checkbox>)`, "g"),
|
||||
`$1${Resource.all[key].displayName}$2`);
|
||||
html = html.replace(new RegExp(`(<(.+)\\s*?indent="[\\d]+?"\\s*?key="${key}"\\s*?dependencies=".*?">)[^\\0]*?(</\\2>)`, "g"),
|
||||
`$1${name}$3`);
|
||||
}
|
||||
return html
|
||||
.replace(/<category>([^\0]*?)<\/category>/g, `
|
||||
return html.replace(/<category>([^\0]*?)<\/category>/g, `
|
||||
<li class="indent-center category">
|
||||
<span class="settings-category">$1</span>
|
||||
<span class="settings-category">
|
||||
$1
|
||||
<i class="settings-category-arrow"></i>
|
||||
</span>
|
||||
</li>
|
||||
<li class="indent-center widgets-container" category-name="$1">
|
||||
</li>
|
||||
`).replace(/<checkbox\s*?indent="(.+?)"\s*?key="(.+?)"\s*?dependencies="(.*?)">([^\0]*?)<\/checkbox>/g, `
|
||||
<li class="indent-$1">
|
||||
@ -612,16 +840,13 @@
|
||||
{
|
||||
return this.text !== null;
|
||||
}
|
||||
get key()
|
||||
{
|
||||
return Object.keys(Resource.all).find(k => Resource.all[k] === this);
|
||||
}
|
||||
constructor(url, priority)
|
||||
{
|
||||
this.url = Resource.root + url;
|
||||
this.dependencies = [];
|
||||
this.priority = priority;
|
||||
this.text = null;
|
||||
this.key = null;
|
||||
this.type = ResourceType.fromUrl(url);
|
||||
this.displayName = "";
|
||||
}
|
||||
@ -779,6 +1004,9 @@
|
||||
return null;
|
||||
}
|
||||
const promise = resource.download();
|
||||
resource.dependencies
|
||||
.filter(it => it.type.name === "script")
|
||||
.forEach(it => this.fetchByKey(it.key));
|
||||
return new Promise(resolve =>
|
||||
{
|
||||
promise.then(text =>
|
||||
@ -854,6 +1082,10 @@
|
||||
{
|
||||
panel.find(info.before()).before(info.content);
|
||||
}
|
||||
else if (info.category)
|
||||
{
|
||||
panel.find(`.widgets-container[category-name=${info.category}]`).append(info.content);
|
||||
}
|
||||
|
||||
if (info.success)
|
||||
{
|
||||
|
||||
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.4 MiB |
BIN
images/download-video.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
images/force-wide-after.png
Normal file
|
After Width: | Height: | Size: 2.9 MiB |
BIN
images/force-wide-before.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
images/gui-settings-blur.png
Normal file
|
After Width: | Height: | Size: 521 KiB |
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 1.7 MiB |
|
Before Width: | Height: | Size: 1.8 MiB After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 368 KiB After Width: | Height: | Size: 1.3 MiB |
1
min/about.min.html
Normal file
@ -0,0 +1 @@
|
||||
<div class="bilibili-evolved-about"></div>
|
||||
1
min/about.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
(()=>{return(t,n)=>{$("body").append(n.data.aboutDom.text);function e(){n.applyStyle("aboutStyle");$("#about-link").on("click",()=>{$(".bilibili-evolved-about").toggleClass("opened")})}return{settingsWidget:{after:()=>$(".gui-settings-content"),content:`\n <div class="about gui-settings-footer">\n <span id="about-version">${GM_info.script.name}, version ${t.currentVersion}</span>\n <span id="about-link">About</span>\n </div>`,success:e}}}})();
|
||||
1
min/about.min.scss
Normal file
@ -0,0 +1 @@
|
||||
.about.gui-settings-footer{height:24px;font-size:14px;justify-content:space-between;padding:6px 24px;border-top:1px dashed #8884;}.about.gui-settings-footer>span{opacity:0.2;}.bilibili-evolved-about{display:none;width:60vw;height:40vh;background-color:white;position:absolute;top:20%;left:20%;z-index:100000;box-shadow:0px 3px 20px 2px #0004;}.bilibili-evolved-about.opened{display:flex;}#about-link{cursor:pointer;transition:all .2s;}#about-link:hover{opacity:1;color:$customStyleColor;}
|
||||
2
min/clear-cache.min.js
vendored
@ -1 +1 @@
|
||||
(()=>{return(e,n)=>{return{settingsWidget:{after:()=>$("input[key=useCache]").parent().parent(),content:`<li class="indent-center">\n <button\n class="gui-settings-button"\n title="清除缓存"\n id="clear-cache">\n 清除缓存\n </button>\n </li>`,success:()=>{$("#clear-cache").on("click",()=>{e.cache={};Toast.show("已删除全部缓存.","清除缓存",5e3)});if(typeof offlineData!=="undefined"){$("button#clear-cache").parent().addClass("hidden")}}}}}})();
|
||||
(()=>{return(t,e)=>{return{settingsWidget:{category:"其他",content:`<div>\n <button\n class="gui-settings-button"\n title="清除缓存"\n id="clear-cache">\n 清除缓存\n </button>\n </div>`,success:()=>{$("#clear-cache").on("click",()=>{t.cache={};Toast.show("已删除全部缓存.","清除缓存",5e3)});if(typeof offlineData!=="undefined"){$("button#clear-cache").parent().addClass("hidden")}}}}}})();
|
||||
1
min/download-video.min.html
Normal file
@ -0,0 +1 @@
|
||||
<div style="position: relative;" class="hidden"><button class="gui-settings-button" title="下载当前视频" id="download-video">下载视频</button><div class="download-video-panel quality"><ol class="video-quality"></ol><div class="video-action"><div id="video-action-download">直接下载</div><div id="video-action-copy">复制链接</div></div><div class="video-progress"><div class="download-progress-text"><span class="download-progress-title">正在下载</span><span class="download-progress-value">0</span><span class="download-progress-percent">%</span></div><div class="download-progress-background"><div class="download-progress-foreground"></div></div><div class="download-progress-cancel"><span>取消</span></div></div><div class="video-error"></div><a href="" id="video-complete"></a></div></div>
|
||||
1
min/download-video.min.js
vendored
Normal file
1
min/download-video.min.scss
Normal file
@ -0,0 +1 @@
|
||||
.download-video-panel.opened{transform:scaleY(1);}.download-video-panel{position:absolute;top:calc(100% + 8px);transition:all .16s ease-out;transform-origin:top;transform:scaleY(0);background:white;border-radius:4px;box-shadow:0px 3px 20px 2px #0004;z-index:100;}.gui-settings-content ol.video-quality li,.video-action>div{cursor:pointer;align-items:center;margin:0;padding:8px 16px;border-radius:4px;transition:all .2s ease-out;}.video-action>div{padding:12px 24px;}.gui-settings-content ol.video-quality li:hover,.video-action>div:hover{background:rgba(0,0,0,0.16);}.video-quality,.video-progress,.video-action,.video-error{display:none;}.download-video-panel.quality:not(.error) .video-quality,.download-video-panel.progress:not(.error) .video-progress,.download-video-panel.action:not(.error) .video-action,.download-video-panel.error .video-error{display:block;}.download-progress-text{display:flex;}.download-progress-title{flex:1 0 0;}.download-progress-background{background-color:#8884;height:4px;width:100%;margin-top:4px;}.download-progress-foreground{background-color:$customStyleColor;transform-origin:left;transition:all .2s ease-out;transform:scaleX(0);height:100%;width:100%;}.download-progress-cancel{margin-top:8px;display:flex;justify-content:center;}.download-progress-cancel>span{border-radius:4px;background-color:#8884;padding:4px 8px;cursor:pointer;}.download-progress-cancel>span:hover{opacity:.9;}.download-progress-cancel>span:active{opacity:.8;}.video-error,.video-progress{padding:12px;}.video-progress{min-width:160px;}#video-complete{display:none;}
|
||||
@ -1 +1 @@
|
||||
<div class="gui-settings-panel"><div class="gui-settings-box"><div class="gui-settings-header"><span class="gui-settings-title">设置</span><svg class="gui-settings-close" viewBox="0 0 24 24"><path/></svg></div><div class="gui-settings-content"><ul><category>样式</category><li class="indent-0"><label class="gui-settings-textbox-container"><span>主题颜色</span><div class="custom-color-preview"><div class="predefined-colors"><div class="predefined-colors-grid"></div></div></div><input key="customStyleColor" dependencies="" spellcheck="false" type="text"/></label></li><checkbox indent="0" key="useNewStyle" dependencies=""></checkbox><textbox indent="1" key="blurBackgroundOpacity" dependencies="useNewStyle">顶栏(对横幅)不透明度</textbox><checkbox indent="0" key="useDarkStyle" dependencies=""></checkbox><checkbox indent="0" key="darkSchedule" dependencies=""></checkbox><textbox indent="1" key="darkScheduleStart" dependencies="darkSchedule">起始时间</textbox><textbox indent="1" key="darkScheduleEnd" dependencies="darkSchedule">结束时间</textbox><checkbox indent="0" key="overrideNavBar" dependencies=""></checkbox><checkbox indent="1" key="showBanner" dependencies="overrideNavBar">显示顶部横幅</checkbox><checkbox indent="0" key="forceWide" dependencies=""></checkbox><textbox indent="1" key="forceWideMinWidth" dependencies="forceWide">触发宽度</textbox><category>工具</category><checkbox indent="0" key="removeAds" dependencies=""></checkbox><checkbox indent="0" key="watchLaterRedirect" dependencies=""></checkbox><checkbox indent="0" key="hideTopSearch" dependencies=""></checkbox><checkbox indent="0" key="fullTweetsTitle" dependencies=""></checkbox><category>视频与直播</category><checkbox indent="0" key="expandDanmakuList" dependencies=""></checkbox><checkbox indent="0" key="harunaScale" dependencies=""></checkbox><checkbox indent="0" key="removeLiveWatermark" dependencies=""></checkbox><checkbox indent="0" key="removeVideoTopMask" dependencies=""></checkbox><checkbox indent="0" key="blurVideoControl" dependencies=""></checkbox><category>触摸优化</category><checkbox indent="0" key="touchNavBar" dependencies=""></checkbox><checkbox indent="0" key="touchVideoPlayer" dependencies=""></checkbox><checkbox indent="1" key="touchVideoPlayerAnimation" dependencies="touchVideoPlayer">启用实验性动画效果</checkbox><checkbox indent="1" key="touchVideoPlayerDoubleTapControl" dependencies="touchVideoPlayer">启用双击控制</checkbox><category>其他</category><checkbox indent="0" key="toast" dependencies=""></checkbox><checkbox indent="0" key="blurSettingsPanel" dependencies="">模糊设置面板背景</checkbox><checkbox indent="0" key="useCache" dependencies="">启用缓存</checkbox></ul></div></div></div>
|
||||
<div class="gui-settings-panel"><div class="gui-settings-box"><div class="gui-settings-header"><span class="gui-settings-title">设置</span><svg class="gui-settings-close" viewBox="0 0 24 24"><path/></svg></div><div class="gui-settings-content"><ul><category>样式</category><li class="indent-0"><label class="gui-settings-textbox-container"><span>主题颜色</span><div class="custom-color-preview"><div class="predefined-colors"><div class="predefined-colors-grid"></div></div></div><input key="customStyleColor" dependencies="" spellcheck="false" type="text"/></label></li><checkbox indent="0" key="useNewStyle" dependencies=""></checkbox><textbox indent="1" key="blurBackgroundOpacity" dependencies="useNewStyle"></textbox><checkbox indent="0" key="useDarkStyle" dependencies=""></checkbox><checkbox indent="0" key="darkSchedule" dependencies=""></checkbox><textbox indent="1" key="darkScheduleStart" dependencies="darkSchedule"></textbox><textbox indent="1" key="darkScheduleEnd" dependencies="darkSchedule"></textbox><checkbox indent="0" key="overrideNavBar" dependencies=""></checkbox><checkbox indent="1" key="showBanner" dependencies="overrideNavBar"></checkbox><checkbox indent="0" key="forceWide" dependencies=""></checkbox><textbox indent="1" key="forceWideMinWidth" dependencies="forceWide"></textbox><category>工具</category><checkbox indent="0" key="removeAds" dependencies=""></checkbox><checkbox indent="0" key="watchLaterRedirect" dependencies=""></checkbox><checkbox indent="0" key="hideTopSearch" dependencies=""></checkbox><checkbox indent="0" key="fullTweetsTitle" dependencies=""></checkbox><category>视频与直播</category><checkbox indent="0" key="expandDanmakuList" dependencies=""></checkbox><checkbox indent="0" key="harunaScale" dependencies=""></checkbox><checkbox indent="0" key="removeLiveWatermark" dependencies=""></checkbox><checkbox indent="0" key="removeVideoTopMask" dependencies=""></checkbox><checkbox indent="0" key="blurVideoControl" dependencies=""></checkbox><category>触摸优化</category><checkbox indent="0" key="touchNavBar" dependencies=""></checkbox><checkbox indent="0" key="touchVideoPlayer" dependencies=""></checkbox><checkbox indent="1" key="touchVideoPlayerAnimation" dependencies="touchVideoPlayer"></checkbox><checkbox indent="1" key="touchVideoPlayerDoubleTapControl" dependencies="touchVideoPlayer"></checkbox><category>其他</category><checkbox indent="0" key="toast" dependencies=""></checkbox><checkbox indent="0" key="blurSettingsPanel" dependencies=""></checkbox><checkbox indent="0" key="useCache" dependencies=""></checkbox></ul></div></div></div>
|
||||
2
min/gui-settings.min.js
vendored
2
min/touch-player.min.js
vendored
1
min/video-info.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
(()=>{return()=>{class i{constructor(i){this.aid=i}async fetchInfo(){const i=JSON.parse(await downloadText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));if(i.code!==0){throw new Error(i.message)}const t=i.data;this.cid=t.cid;this.pageCount=t.videos;this.coverUrl=t.pic;this.tagId=t.tid;this.tagName=t.tname;this.title=t.title;this.description=t.desc;this.up={uid:t.owner.mid,name:t.owner.name,faceUrl:t.owner.face};this.pages=t.pages.map(i=>{return{cid:i.cid,title:i.part,pageNumber:i.page}});return this}}class t{constructor(i){this.ep=i;this.videos=[]}async fetchInfo(){const t=await downloadText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);const e=JSON.parse(t.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);this.title=e.mediaInfo.title;this.cover=e.mediaInfo.cover;this.squareCover=e.mediaInfo.square_cover;this.aid=e.epInfo.aid;this.cid=e.epInfo.cid;this.videos=e.epList.map(async t=>{return{title:t.index_title,aid:t.aid,cid:t.cid,info:await new i(t.aid).fetchInfo()}});return this}}return{export:{VideoInfo:i,BangumiInfo:t}}}})();
|
||||
2
min/view-cover.min.js
vendored
@ -1 +1 @@
|
||||
(()=>{return(e,t)=>{class n{constructor(e){this.url=e;if($(".image-viewer").length===0){this.createDom()}this.viewer=$(".image-viewer-container");this.downloadImage()}createDom(){$("body").append(t.data.imageViewerDom.text);t.applyStyle("imageViewerStyle");$(".image-viewer-container .close").on("click",()=>this.hide())}downloadImage(){const e=new XMLHttpRequest;e.open("GET",this.url.replace("http:","https:"),true);e.responseType="blob";e.onload=(()=>{const t=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");const n=URL.createObjectURL(e.response);this.imageData=n;this.viewer.find(".download").attr("href",n).attr("download",t);this.viewer.find(".image").prop("src",n)});e.send()}show(){this.viewer.addClass("opened");$("html,body").addClass("image-viewer-opened")}hide(){this.viewer.removeClass("opened");$("html,body").removeClass("image-viewer-opened")}}if($("meta[itemprop='image']").length>0){return{settingsWidget:{after:()=>$("span.settings-category").filter((e,t)=>t.innerHTML==="视频与直播").parent(),content:`<li class="indent-center hidden">\n <button\n class="gui-settings-button"\n title="查看当前视频的封面"\n id="view-video-cover">\n 查看封面\n </button>\n </li>`,success:()=>{new SpinQuery(()=>$("meta[itemprop='image']"),e=>e.length>0&&e.prop("content"),e=>{const t=new n(e.prop("content"));$("#view-video-cover").on("click",()=>{t.show()}).parent().removeClass("hidden")}).start()}}}}else{return{settingsWidget:{after:()=>$("span.settings-category").filter((e,t)=>t.innerHTML==="视频与直播").parent(),content:`<li class="indent-center hidden">\n <button\n class="gui-settings-button"\n title="查看当前直播的封面"\n id="view-live-cover">\n 查看封面\n </button>\n </li>`,success:()=>{SpinQuery.any(()=>$(".header-info-ctnr .room-cover"),e=>{const t=e.attr("href").match(/space\.bilibili\.com\/([\d]+)/);if(t&&t[1]){const e=t[1];const i=`https://api.live.bilibili.com/bili/getRoomInfo/${e}`;downloadText(i,e=>{const t=e.slice(1,-2);const i=JSON.parse(t).data.cover;const o=new n(i);$("#view-live-cover").on("click",()=>{o.show()}).parent().removeClass("hidden")})}})}}}}}})();
|
||||
(()=>{return(e,t)=>{class i{constructor(e){this.url=e;if($(".image-viewer").length===0){this.createDom()}this.viewer=$(".image-viewer-container");this.downloadImage()}createDom(){$("body").append(t.data.imageViewerDom.text);t.applyStyle("imageViewerStyle");$(".image-viewer-container .close").on("click",()=>this.hide())}downloadImage(){const e=new XMLHttpRequest;e.open("GET",this.url.replace("http:","https:"),true);e.responseType="blob";e.onload=(()=>{const t=document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili","");const i=URL.createObjectURL(e.response);this.imageData=i;this.viewer.find(".download").attr("href",i).attr("download",t);this.viewer.find(".image").prop("src",i)});e.send()}show(){this.viewer.addClass("opened")}hide(){this.viewer.removeClass("opened")}}if($("meta[itemprop='image'],meta[property='og:image']").length>0){return{settingsWidget:{category:"视频与直播",content:`<div class="hidden">\n <button\n class="gui-settings-button"\n title="查看当前视频的封面"\n id="view-video-cover">\n 查看封面\n </button>\n </div>`,success:()=>{new SpinQuery(()=>$("meta[itemprop='image'],meta[property='og:image']"),e=>e.length>0&&e.prop("content"),e=>{const t=new i(e.prop("content"));$("#view-video-cover").on("click",()=>{t.show()}).parent().removeClass("hidden")}).start()}}}}else{return{settingsWidget:{category:"视频与直播",content:`<div class="hidden">\n <button\n class="gui-settings-button"\n title="查看当前直播的封面"\n id="view-live-cover">\n 查看封面\n </button>\n </div>`,success:()=>{SpinQuery.any(()=>$(".header-info-ctnr .room-cover"),e=>{const t=e.attr("href").match(/space\.bilibili\.com\/([\d]+)/);if(t&&t[1]){const e=t[1];const n=`https://api.live.bilibili.com/bili/getRoomInfo/${e}`;downloadText(n,e=>{const t=e.slice(1,-2);const n=JSON.parse(t).data.cover;const o=new i(n);$("#view-live-cover").on("click",()=>{o.show()}).parent().removeClass("hidden")})}})}}}}}})();
|
||||
@ -476,7 +476,6 @@ a.bp_box_bot_click,
|
||||
.medal .medal-form .page-tip,
|
||||
.empty-wrp .text,
|
||||
.ui-serch .run-serch,
|
||||
.container .iconfont,
|
||||
.container .song-list .song-li .content .num,
|
||||
.container .host-list-layout .hot-list-wrap .show-more-song,
|
||||
.container .host-list-layout .hot-list-wrap .hot-song-list .song-info .song-num,
|
||||
|
||||
@ -50,7 +50,11 @@ div#square.container,
|
||||
.live-status.offline,
|
||||
.banner-wrapper .swiper-pagination-bullet,
|
||||
.nav-header-wrapper .nav-header .nav-header-search-bar-wrapper .suggestion-list,
|
||||
.project-list .project-list-item .project-list-item-img
|
||||
.project-list .project-list-item .project-list-item-img,
|
||||
.download-video-panel,
|
||||
.article-action .ops .share-container .weixin-holder,
|
||||
.coin-wrap,
|
||||
.bilibili-evolved-about
|
||||
{
|
||||
background-color: #222 !important;
|
||||
}
|
||||
@ -164,14 +168,17 @@ body>div.to-top.on,
|
||||
.area-section .card-ctnr .more:hover,
|
||||
.link-panigation-ctnr .pagination,
|
||||
.link-progress-tv,
|
||||
.jumping-ctnr .jumping-input
|
||||
.jumping-ctnr .jumping-input,
|
||||
#song_detail_click_upper~div .pager .pages .page-item.active button,
|
||||
#song_detail_click_upper~div .pager .pages .page-item button,
|
||||
.filter-wrap .sub-filter
|
||||
{
|
||||
background-color: transparent !important;
|
||||
}
|
||||
// a
|
||||
// {
|
||||
// background: #fff1 !important;
|
||||
// }
|
||||
.coin-wrap .coin-nav .coin-checkbox
|
||||
{
|
||||
background: #fff !important;
|
||||
}
|
||||
// a
|
||||
// {
|
||||
// background: transparent !important;
|
||||
@ -224,7 +231,12 @@ body>div.to-top.on,
|
||||
.leaveMsg .leaveMsgBody .infoArea .infoAreaTitle,
|
||||
.leaveMsgUpload .btnarea span.btareatxt,
|
||||
.evaluate .h2,
|
||||
.hot-list .card-ctnr .room-count .icon-font
|
||||
.hot-list .card-ctnr .room-count .icon-font,
|
||||
.article-action .ops i,
|
||||
.page-container .article-action,
|
||||
.article-action .ops .share-container .weixin-holder p,
|
||||
.coin-wrap .coin-tips,
|
||||
.up-feedback .up-fb-btn
|
||||
{
|
||||
color: #aaa !important;
|
||||
}
|
||||
@ -301,7 +313,11 @@ body>div.to-top.on,
|
||||
.jumping-ctnr .jumping-input,
|
||||
.banner-wrapper .swiper-pagination-bullet,
|
||||
.nav-header-wrapper .nav-header .user-panel,
|
||||
.nav-header-wrapper .nav-header .user-panel a
|
||||
.nav-header-wrapper .nav-header .user-panel a,
|
||||
.similar-song-menu .similar-right .title,
|
||||
.gridview-sidebar .album-title,
|
||||
.article-holder .bangumi-card a .container .title,
|
||||
.coin-wrap .coin-title
|
||||
{
|
||||
color: #eee !important;
|
||||
}
|
||||
@ -346,7 +362,13 @@ body>div.to-top.on,
|
||||
.evaluateWether .noactive,
|
||||
.evaluate .situation span,
|
||||
.bilibili-live-player .bilibili-live-player-enter-tips,
|
||||
.nav-header-wrapper .nav-header .nav-header-search-bar-wrapper .suggestion-list
|
||||
.nav-header-wrapper .nav-header .nav-header-search-bar-wrapper .suggestion-list,
|
||||
.publish-panel .hash-popup,
|
||||
.hash-popup .topic-container .item.is-selected,
|
||||
.article-holder .bangumi-card a .container,
|
||||
.article-action .ops .share-container .weixin-holder,
|
||||
.coin-wrap .coin-sure,
|
||||
.filter-wrap .sub-filter
|
||||
{
|
||||
border-color: transparent !important;
|
||||
}
|
||||
@ -467,6 +489,10 @@ body>div.to-top.on,
|
||||
{
|
||||
filter: brightness(0.2) !important;
|
||||
}
|
||||
.up-feedback .icon-beta
|
||||
{
|
||||
filter: brightness(0.5) !important;
|
||||
}
|
||||
// a
|
||||
// {
|
||||
// filter: none !important;
|
||||
@ -510,7 +536,9 @@ body>div.to-top.on,
|
||||
.mainBox .leaveMsg,
|
||||
.js-evaluateArea .evaluateDialog,
|
||||
.project-list .project-list-item:hover,
|
||||
#app .toolbar-wrapper
|
||||
.publish-panel .hash-popup,
|
||||
#app .toolbar-wrapper,
|
||||
.article-action .ops .share-container .weixin-holder
|
||||
{
|
||||
box-shadow: 0px 1px 10px 0px $customStyleColor30 !important;
|
||||
}
|
||||
@ -521,7 +549,8 @@ body>div.to-top.on,
|
||||
.nav-bar .sub-nav::after,
|
||||
.bui-sns-info a .bd::after,
|
||||
.more .help .icon,
|
||||
.more .link .icon
|
||||
.more .link .icon,
|
||||
.filter-wrap .icon-tid2-arr
|
||||
{
|
||||
display: none !important;
|
||||
}
|
||||
@ -562,6 +591,10 @@ body>div.to-top.on
|
||||
{
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
.article-action .ops .share-container .weixin-holder p
|
||||
{
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
.list-filter-bar .sort-box .item.active,
|
||||
.list-filter-bar .sort-box .item:hover,
|
||||
@ -635,7 +668,9 @@ body>div.to-top.on
|
||||
.bilibili-live-player .blpui-btn.default-btn.btn-blue,
|
||||
.bilibili-live-player .bilibili-live-player-enter-tips,
|
||||
.banner-wrapper .swiper-pagination-bullet-active,
|
||||
.nav-header-wrapper .nav-header .profile-img.active::before
|
||||
.nav-header-wrapper .nav-header .profile-img.active::before,
|
||||
.coin-wrap .coin-sure,
|
||||
.up-feedback .up-fb-btn:hover
|
||||
{
|
||||
background-color: $customStyleColor !important;
|
||||
}
|
||||
@ -708,7 +743,25 @@ body>div.to-top.on
|
||||
.hot-list .card-ctnr .room-count:hover .amount,
|
||||
.hot-list .card-ctnr .room-count:hover .icon-font,
|
||||
.hot-list .card-ctnr .room-count:hover,
|
||||
.panel-list .order-center-item:hover a
|
||||
.panel-list .order-center-item:hover a,
|
||||
.similar-song-menu .similar-right .title:hover,
|
||||
#song_detail_click_upper~div .pager .pages .page-item.active button,
|
||||
#song_detail_click_upper~div .pager .pages .page-item button:hover,
|
||||
.article-action .coin-btn.on,
|
||||
.article-action .coin-btn.on i,
|
||||
.article-action .coin-btn:hover,
|
||||
.article-action .coin-btn:hover i,
|
||||
.article-action .fav-btn.on,
|
||||
.article-action .fav-btn.on i,
|
||||
.article-action .fav-btn:hover,
|
||||
.article-action .fav-btn:hover i,
|
||||
.article-action .like-btn.on,
|
||||
.article-action .like-btn.on i,
|
||||
.article-action .like-btn:hover,
|
||||
.article-action .like-btn:hover i,
|
||||
.article-action .ops i:hover,
|
||||
.coin-wrap .coin-title i,
|
||||
.coin-wrap .coin-nav .coin-checkbox.on .lable
|
||||
{
|
||||
color: $customStyleColor !important;
|
||||
}
|
||||
@ -739,7 +792,9 @@ body>div.to-top.on
|
||||
.evaluateSubmitArea .submit,
|
||||
.bilibili-live-player .blpui-btn.default-btn.btn-blue,
|
||||
.bilibili-live-player .bilibili-live-player-enter-tips,
|
||||
.banner-wrapper .swiper-pagination-bullet-active
|
||||
.banner-wrapper .swiper-pagination-bullet-active,
|
||||
.coin-wrap .coin-sure,
|
||||
.up-feedback .up-fb-btn:hover
|
||||
{
|
||||
color: $foreground !important;
|
||||
}
|
||||
|
||||
@ -2,7 +2,18 @@
|
||||
.title-factory-card,
|
||||
.p-relative.gold-seed-store.over-hidden .content,
|
||||
.live-btn.default,
|
||||
.collapse-subitem--active
|
||||
.collapse-subitem--active,
|
||||
.invtable tr:nth-child(odd) td,
|
||||
.el-input-group__append,
|
||||
.el-input-group__prepend,
|
||||
.cc-article-wrp .article-card .meta-view .appeal,
|
||||
.cc-article-wrp .article-card .meta-view .data,
|
||||
.cc-article-wrp .article-card .meta-view .delete,
|
||||
.cc-article-wrp .article-card .meta-view .option,
|
||||
.comment-list-item .ci-action a:hover,
|
||||
.comment-manage-wrap .content .action-bar .dropdown .action-menu li:hover,
|
||||
.comment-manage-wrap .content .action-bar .dropdown .sort-menu li:hover,
|
||||
.hash-popup .topic-container .item.is-selected
|
||||
{
|
||||
background-color: #222 !important;
|
||||
}
|
||||
@ -10,7 +21,20 @@
|
||||
.title-item,
|
||||
.help-list,
|
||||
.help-box,
|
||||
.right-action-ctnr.pointer.dp-i-block.primary.btn.p-relative .btn.primary
|
||||
.right-action-ctnr.pointer.dp-i-block.primary.btn.p-relative .btn.primary,
|
||||
.code-content,
|
||||
.invtable .codedone,
|
||||
.cc-article-wrp .article-card,
|
||||
.videoCharts .stat .stat-wrp,
|
||||
.article-data-wrp .video-box,
|
||||
.article-net-charts .content-box,
|
||||
.article-net-charts .area,
|
||||
.comment-manage-wrap .content,
|
||||
.head .dropdown-btn,
|
||||
.head .dropdown.open .dropdown-btn,
|
||||
.dc-button.dc-button-text,
|
||||
.dc-progress-bar,
|
||||
.h-none-btn
|
||||
{
|
||||
background-color: #444 !important;
|
||||
}
|
||||
@ -26,7 +50,8 @@
|
||||
// {
|
||||
// background-color: #fff1 !important;
|
||||
// }
|
||||
.live-haruna .section-stage .stage-wrap
|
||||
.live-haruna .section-stage .stage-wrap,
|
||||
.tabs-nav .active
|
||||
{
|
||||
background-image: none !important;
|
||||
}
|
||||
@ -59,7 +84,16 @@
|
||||
.record-ctnr .summary .s-item .title,
|
||||
.main_body .future .future_list .future_block .info .loca,
|
||||
.edit-button > span,
|
||||
.room-introduction-content.empty
|
||||
.room-introduction-content.empty,
|
||||
.invitation-subtitle,
|
||||
.cc-article-wrp .article-card .meta-title .typename,
|
||||
.cc-article-wrp .article-card .meta-view .appeal,
|
||||
.cc-article-wrp .article-card .meta-view .data,
|
||||
.cc-article-wrp .article-card .meta-view .delete,
|
||||
.cc-article-wrp .article-card .meta-view .option,
|
||||
.article-data-wrp .menu-wrp .menu-tips,
|
||||
.type-rank-item-label,
|
||||
.h-none-msg
|
||||
{
|
||||
color: #aaa !important;
|
||||
}
|
||||
@ -78,7 +112,23 @@
|
||||
.collapse-item a,
|
||||
.help-subtitle,
|
||||
.collapse-subitem--active a,
|
||||
.drop-menu-item
|
||||
.drop-menu-item,
|
||||
.invitation-title,
|
||||
.code-btn,
|
||||
table.invtable td,
|
||||
.invtable .codedone,
|
||||
.el-input-group__append,
|
||||
.el-input-group__prepend,
|
||||
.cc-article-wrp .article-header .search-wrp input,
|
||||
.head .dropdown-menu .search .bili-input,
|
||||
#dc-section_summary .source-rank-list-item .video-info-title a,
|
||||
.dc-button.dc-button-text,
|
||||
.dc-button.dc-button-text a,
|
||||
.dc-button.dc-button-text:hover,
|
||||
.home-top-msg-name,
|
||||
.h-none-btn,
|
||||
.h-none-btn:hover,
|
||||
.big-user-name
|
||||
{
|
||||
color: #eee !important;
|
||||
}
|
||||
@ -103,12 +153,23 @@
|
||||
.areas .area,
|
||||
.record-ctnr .summary,
|
||||
.help-list,
|
||||
.help-box
|
||||
.help-box,
|
||||
.code-result,
|
||||
.el-input-group__append,
|
||||
.el-input-group__prepend,
|
||||
.page-wrp.is-article.cc-article-wrp .article-card,
|
||||
.videoCharts .stat .stat-wrp .stat-card,
|
||||
.article-chart-wrp,
|
||||
.comment-list-item,
|
||||
.head .dropdown-btn,
|
||||
.dropdown .dropdown-menu,
|
||||
#dc-section_summary .source-rank-list-item
|
||||
{
|
||||
border-color: transparent !important;
|
||||
}
|
||||
.link-input,
|
||||
.add-cover
|
||||
.add-cover,
|
||||
.cc-article-wrp .article-card .meta-title .typename
|
||||
{
|
||||
border-color: #aaa !important;
|
||||
}
|
||||
@ -162,10 +223,13 @@
|
||||
// {
|
||||
// border-radius: 4px !important;
|
||||
// }
|
||||
// a
|
||||
// {
|
||||
// box-shadow: none !important;
|
||||
// }
|
||||
.videoCharts .stat .stat-wrp,
|
||||
.article-data-wrp .video-box,
|
||||
.article-net-charts .content-box,
|
||||
.el-radio-button__orig-radio:checked + .el-radio-button__inner
|
||||
{
|
||||
box-shadow: none !important;
|
||||
}
|
||||
// a
|
||||
// {
|
||||
// box-shadow: 0px 1px 10px 0px $customStyleColor30 !important;
|
||||
@ -187,9 +251,12 @@
|
||||
// opacity: 1 !important;
|
||||
// }
|
||||
.add-cover:hover,
|
||||
.category:hover,
|
||||
.category:not(.gui-settings-content .category):hover,
|
||||
.data-card .data-box .tab .fan-tab.current:after,
|
||||
.data-card .fans-box .tab .fan-tab.current:after
|
||||
.data-card .fans-box .tab .fan-tab.current:after,
|
||||
.data-card .data-box .tab .fan-tab.current:after,
|
||||
.data-card .fans-box .tab .fan-tab.current:after,
|
||||
.section-item .diff-wrp .diff-text:before
|
||||
{
|
||||
border-color: $customStyleColor !important;
|
||||
}
|
||||
@ -199,7 +266,16 @@
|
||||
.live-btn.default:active,
|
||||
.live-btn.default:hover,
|
||||
.popup-close-btn,
|
||||
.helper-icon-dots
|
||||
.helper-icon-dots,
|
||||
.code-btn,
|
||||
.code-btn:hover,
|
||||
.cc-article-wrp .article-card .meta-view .appeal:hover,
|
||||
.cc-article-wrp .article-card .meta-view .data:hover,
|
||||
.cc-article-wrp .article-card .meta-view .delete:hover,
|
||||
.cc-article-wrp .article-card .meta-view .option:hover,
|
||||
.head .dropdown-btn:hover,
|
||||
.dc-button.dc-button-text:hover,
|
||||
.h-none-btn:hover
|
||||
{
|
||||
background-color: $customStyleColor !important;
|
||||
}
|
||||
@ -209,12 +285,15 @@
|
||||
.bili-blue,
|
||||
.text-blue,
|
||||
.save-btn.active,
|
||||
.category:hover,
|
||||
.category:not(.gui-settings-content .category):hover,
|
||||
.help-title,
|
||||
.collapse-item--active .collapse-title,
|
||||
.help-subindex,
|
||||
.drop-menu-item:hover,
|
||||
icon-label.hover-text-blue:hover .label
|
||||
icon-label.hover-text-blue:hover .label,
|
||||
.stat-card .num .text,
|
||||
.comment-card .comment-item .comment-info .reply-block .comment-vedio a,
|
||||
.section-item .diff-wrp .diff-text
|
||||
{
|
||||
color: $customStyleColor !important;
|
||||
}
|
||||
@ -238,7 +317,10 @@ icon-label.hover-text-blue:hover .label
|
||||
// border-right-color: transparent !important;
|
||||
// }
|
||||
.data-card .data-box .tab .fan-tab.current:after,
|
||||
.data-card .fans-box .tab .fan-tab.current:after
|
||||
.data-card .fans-box .tab .fan-tab.current:after,
|
||||
.data-card .data-box .tab .fan-tab.current:after,
|
||||
.data-card .fans-box .tab .fan-tab.current:after,
|
||||
.section-item .diff-wrp .diff-text:before
|
||||
{
|
||||
border-left-color: transparent !important;
|
||||
border-right-color: transparent !important;
|
||||
|
||||
@ -14,26 +14,6 @@
|
||||
}
|
||||
return { x: x, y: y };
|
||||
};
|
||||
const fixed = (number, precision = 1) =>
|
||||
{
|
||||
const str = number.toString();
|
||||
const index = str.indexOf(".");
|
||||
if (index !== -1)
|
||||
{
|
||||
if (str.length - index > precision + 1)
|
||||
{
|
||||
return str.substring(0, index + precision + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return str;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return str + ".0";
|
||||
}
|
||||
};
|
||||
const secondsToTime = sec =>
|
||||
{
|
||||
sec = Math.abs(sec);
|
||||
@ -303,45 +283,24 @@
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
const url = window.location.href;
|
||||
const aidMatch = url.match(/av([\d]+)/);
|
||||
this.aid = aidMatch[1];
|
||||
const pageMatch = url.match(/p=([\d]+)/);
|
||||
this.page = pageMatch ? pageMatch[1] : 1;
|
||||
|
||||
this.pagesData = null;
|
||||
this.cidMap = {};
|
||||
this.cidData = {};
|
||||
this.aid = unsafeWindow.aid;
|
||||
this.cid = unsafeWindow.cid;
|
||||
this.cidData = null;
|
||||
this.supportWebp = VideoShot.supportWebp;
|
||||
|
||||
downloadText(url, html => this.findCid(html));
|
||||
}
|
||||
findCid(html)
|
||||
{
|
||||
const match = html.match(/"pages":(\[[^\0]*\]),"embedPlayer"/);
|
||||
if (match)
|
||||
{
|
||||
this.pagesData = JSON.parse(match[1]);
|
||||
this.pagesData.forEach(pageData =>
|
||||
{
|
||||
this.cidMap[pageData.page] = pageData.cid;
|
||||
});
|
||||
}
|
||||
}
|
||||
getVideoshot(currentTime, done)
|
||||
{
|
||||
if (!this.cidData[this.page])
|
||||
if (!this.cidData)
|
||||
{
|
||||
downloadText(`https://api.bilibili.com/x/player/videoshot?aid=${this.aid}&cid=${this.cidMap[this.page]}&index=1`, response =>
|
||||
downloadText(`https://api.bilibili.com/x/player/videoshot?aid=${this.aid}&cid=${this.cid}&index=1`, response =>
|
||||
{
|
||||
this.cidData[this.page] = JSON.parse(response).data;
|
||||
this.cidData = JSON.parse(response).data;
|
||||
this.getVideoshot(currentTime, done);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
const data = this.cidData[this.page];
|
||||
|
||||
const data = this.cidData;
|
||||
const indexData = data.index;
|
||||
let shotIndex = 0;
|
||||
for (let index = 0; index < indexData.length - 2; index++)
|
||||
|
||||
3
utils/about/about.html
Normal file
@ -0,0 +1,3 @@
|
||||
<div class="bilibili-evolved-about">
|
||||
|
||||
</div>
|
||||
26
utils/about/about.js
Normal file
@ -0,0 +1,26 @@
|
||||
(() =>
|
||||
{
|
||||
return (settings, resources) =>
|
||||
{
|
||||
$("body").append(resources.data.aboutDom.text);
|
||||
function init()
|
||||
{
|
||||
resources.applyStyle("aboutStyle");
|
||||
$("#about-link").on("click", () =>
|
||||
{
|
||||
$(".bilibili-evolved-about").toggleClass("opened");
|
||||
});
|
||||
}
|
||||
return {
|
||||
settingsWidget: {
|
||||
after: () => $(".gui-settings-content"),
|
||||
content: `
|
||||
<div class="about gui-settings-footer">
|
||||
<span id="about-version">${GM_info.script.name}, version ${settings.currentVersion}</span>
|
||||
<span id="about-link">About</span>
|
||||
</div>`,
|
||||
success: init
|
||||
}
|
||||
};
|
||||
};
|
||||
})();
|
||||
38
utils/about/about.scss
Normal file
@ -0,0 +1,38 @@
|
||||
.about.gui-settings-footer
|
||||
{
|
||||
height: 24px;
|
||||
font-size: 14px;
|
||||
justify-content: space-between;
|
||||
padding: 6px 24px;
|
||||
border-top: 1px dashed #8884;
|
||||
}
|
||||
.about.gui-settings-footer>span
|
||||
{
|
||||
opacity: 0.2;
|
||||
}
|
||||
.bilibili-evolved-about
|
||||
{
|
||||
display: none;
|
||||
width: 60vw;
|
||||
height: 40vh;
|
||||
background-color: white;
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
left: 20%;
|
||||
z-index: 100000;
|
||||
box-shadow: 0px 3px 20px 2px #0004;
|
||||
}
|
||||
.bilibili-evolved-about.opened
|
||||
{
|
||||
display: flex;
|
||||
}
|
||||
#about-link
|
||||
{
|
||||
cursor: pointer;
|
||||
transition: all .2s;
|
||||
}
|
||||
#about-link:hover
|
||||
{
|
||||
opacity: 1;
|
||||
color: $customStyleColor;
|
||||
}
|
||||
@ -4,15 +4,15 @@
|
||||
{
|
||||
return {
|
||||
settingsWidget: {
|
||||
after: () => $("input[key=useCache]").parent().parent(),
|
||||
content: `<li class="indent-center">
|
||||
category: "其他",
|
||||
content: `<div>
|
||||
<button
|
||||
class="gui-settings-button"
|
||||
title="清除缓存"
|
||||
id="clear-cache">
|
||||
清除缓存
|
||||
</button>
|
||||
</li>`,
|
||||
</div>`,
|
||||
success: () =>
|
||||
{
|
||||
$("#clear-cache").on("click", () =>
|
||||
|
||||
@ -21,25 +21,15 @@
|
||||
</label>
|
||||
</li>
|
||||
<checkbox indent="0" key="useNewStyle" dependencies=""></checkbox>
|
||||
<textbox indent="1" key="blurBackgroundOpacity" dependencies="useNewStyle">
|
||||
顶栏(对横幅)不透明度
|
||||
</textbox>
|
||||
<textbox indent="1" key="blurBackgroundOpacity" dependencies="useNewStyle"></textbox>
|
||||
<checkbox indent="0" key="useDarkStyle" dependencies=""></checkbox>
|
||||
<checkbox indent="0" key="darkSchedule" dependencies=""></checkbox>
|
||||
<textbox indent="1" key="darkScheduleStart" dependencies="darkSchedule">
|
||||
起始时间
|
||||
</textbox>
|
||||
<textbox indent="1" key="darkScheduleEnd" dependencies="darkSchedule">
|
||||
结束时间
|
||||
</textbox>
|
||||
<textbox indent="1" key="darkScheduleStart" dependencies="darkSchedule"></textbox>
|
||||
<textbox indent="1" key="darkScheduleEnd" dependencies="darkSchedule"></textbox>
|
||||
<checkbox indent="0" key="overrideNavBar" dependencies=""></checkbox>
|
||||
<checkbox indent="1" key="showBanner" dependencies="overrideNavBar">
|
||||
显示顶部横幅
|
||||
</checkbox>
|
||||
<checkbox indent="1" key="showBanner" dependencies="overrideNavBar"></checkbox>
|
||||
<checkbox indent="0" key="forceWide" dependencies=""></checkbox>
|
||||
<textbox indent="1" key="forceWideMinWidth" dependencies="forceWide">
|
||||
触发宽度
|
||||
</textbox>
|
||||
<textbox indent="1" key="forceWideMinWidth" dependencies="forceWide"></textbox>
|
||||
<category>工具</category>
|
||||
<checkbox indent="0" key="removeAds" dependencies=""></checkbox>
|
||||
<checkbox indent="0" key="watchLaterRedirect" dependencies=""></checkbox>
|
||||
@ -54,20 +44,12 @@
|
||||
<category>触摸优化</category>
|
||||
<checkbox indent="0" key="touchNavBar" dependencies=""></checkbox>
|
||||
<checkbox indent="0" key="touchVideoPlayer" dependencies=""></checkbox>
|
||||
<checkbox indent="1" key="touchVideoPlayerAnimation" dependencies="touchVideoPlayer">
|
||||
启用实验性动画效果
|
||||
</checkbox>
|
||||
<checkbox indent="1" key="touchVideoPlayerDoubleTapControl" dependencies="touchVideoPlayer">
|
||||
启用双击控制
|
||||
</checkbox>
|
||||
<checkbox indent="1" key="touchVideoPlayerAnimation" dependencies="touchVideoPlayer"></checkbox>
|
||||
<checkbox indent="1" key="touchVideoPlayerDoubleTapControl" dependencies="touchVideoPlayer"></checkbox>
|
||||
<category>其他</category>
|
||||
<checkbox indent="0" key="toast" dependencies=""></checkbox>
|
||||
<checkbox indent="0" key="blurSettingsPanel" dependencies="">
|
||||
模糊设置面板背景
|
||||
</checkbox>
|
||||
<checkbox indent="0" key="useCache" dependencies="">
|
||||
启用缓存
|
||||
</checkbox>
|
||||
<checkbox indent="0" key="blurSettingsPanel" dependencies=""></checkbox>
|
||||
<checkbox indent="0" key="useCache" dependencies=""></checkbox>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- <div class="gui-settings-footer">
|
||||
|
||||
@ -60,6 +60,17 @@
|
||||
return settings.blurBackgroundOpacity;
|
||||
}
|
||||
};
|
||||
function getCategoriyItems(category)
|
||||
{
|
||||
let element = category.nextElementSibling;
|
||||
const elements = [];
|
||||
while (element !== null && !element.classList.contains("category"))
|
||||
{
|
||||
elements.push(element);
|
||||
element = element.nextElementSibling;
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
function darkScheduleValidate(text, defaultValue)
|
||||
{
|
||||
const match = text.match(/^([\d]{1,2}):([\d]{1,2})$/);
|
||||
@ -109,6 +120,16 @@
|
||||
{
|
||||
settingsChange(key, undefined, settings[key]);
|
||||
}
|
||||
$(".gui-settings-content ul li.category").each((_, e) =>
|
||||
{
|
||||
const items = getCategoriyItems(e);
|
||||
if (items
|
||||
.filter(it => !it.classList.contains("disabled"))
|
||||
.every(it => $(it).has("input:checked").length === 0))
|
||||
{
|
||||
$(e).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
function setupEvents()
|
||||
{
|
||||
@ -130,6 +151,11 @@
|
||||
const box = $(".predefined-colors");
|
||||
box.toggleClass("opened");
|
||||
});
|
||||
$(".gui-settings-content ul li.category").on("click", e =>
|
||||
{
|
||||
e.currentTarget.classList.toggle("folded");
|
||||
getCategoriyItems(e.currentTarget).forEach(it => it.classList.toggle("folded"));
|
||||
});
|
||||
onSettingsChange(settingsChange);
|
||||
}
|
||||
function listenSettingsChange()
|
||||
@ -185,22 +211,13 @@
|
||||
{
|
||||
disable = false;
|
||||
}
|
||||
$(`input[key='${key}']`).prop("disabled", disable);
|
||||
if (disable)
|
||||
{
|
||||
$(`input[key='${key}'][type='text']`).parent().addClass("disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
$(`input[key='${key}'][type='text']`).parent().removeClass("disabled");
|
||||
}
|
||||
const li = $(`li:has(input[key='${key}'])`);
|
||||
const action = disable ? "addClass" : "removeClass";
|
||||
li[action]("disabled");
|
||||
$(`input[key='${key}'][type='text']`).parent()[action]("disabled");
|
||||
}
|
||||
}
|
||||
const box = $(".predefined-colors");
|
||||
if (box.hasClass("opened"))
|
||||
{
|
||||
box.removeClass("opened");
|
||||
}
|
||||
$(".download-video-panel,.predefined-colors").removeClass("opened");
|
||||
};
|
||||
$(`input[type='checkbox'][key]`)
|
||||
.on("change", e => checkBoxChange($(e.target)))
|
||||
@ -240,18 +257,8 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addSettingsIcon($("body"));
|
||||
const settingsBox = resources.data.guiSettingsDom.text;
|
||||
if (settingsBox)
|
||||
function applyBlurEffect()
|
||||
{
|
||||
$("body").append(settingsBox);
|
||||
setupEvents();
|
||||
fillSvgData();
|
||||
syncGui();
|
||||
listenDependencies();
|
||||
addPredefinedColors();
|
||||
listenSettingsChange();
|
||||
if (settings.blurSettingsPanel)
|
||||
{
|
||||
$(".gui-settings-box").addClass("blur");
|
||||
@ -260,16 +267,35 @@
|
||||
{
|
||||
$(".gui-settings-panel").addClass("animation");
|
||||
}
|
||||
}
|
||||
function checkOfflineData()
|
||||
{
|
||||
if (typeof offlineData !== "undefined")
|
||||
{
|
||||
$("li:has(input[key=useCache])").addClass("disabled");
|
||||
$("input[key=useCache]").prop("disabled", true);
|
||||
}
|
||||
}
|
||||
|
||||
addSettingsIcon($("body"));
|
||||
const settingsBox = resources.data.guiSettingsDom.text;
|
||||
if (settingsBox)
|
||||
{
|
||||
$("body").append(settingsBox);
|
||||
setupEvents();
|
||||
fillSvgData();
|
||||
checkOfflineData();
|
||||
syncGui();
|
||||
listenDependencies();
|
||||
addPredefinedColors();
|
||||
listenSettingsChange();
|
||||
applyBlurEffect();
|
||||
}
|
||||
|
||||
new SpinQuery(
|
||||
() => $("body"),
|
||||
it => it.length > 0 && !(unsafeWindow.parent.window === unsafeWindow),
|
||||
_ => $(".gui-settings-icon-panel").css("display", "none")
|
||||
).start();
|
||||
};
|
||||
})();
|
||||
})();
|
||||
@ -102,7 +102,6 @@
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
overscroll-behavior: contain;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
.gui-settings-content-top-mask,
|
||||
.gui-settings-content-bottom-mask
|
||||
@ -131,9 +130,17 @@
|
||||
.gui-settings-content ul li
|
||||
{
|
||||
font-size: 16px;
|
||||
margin: 12px 0;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
transition: all .2s;
|
||||
overflow: hidden;
|
||||
}
|
||||
.gui-settings-content ul li.disabled,
|
||||
.gui-settings-content ul li:not(.category).folded
|
||||
{
|
||||
height: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.gui-settings-content ul li.indent-0
|
||||
{
|
||||
@ -152,20 +159,44 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.gui-settings-content ul li.widgets-container
|
||||
{
|
||||
margin: 0;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: visible;
|
||||
}
|
||||
.gui-settings-content ul li.widgets-container>div
|
||||
{
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 50%;
|
||||
display: inline-flex;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.gui-settings-content ul li.category
|
||||
{
|
||||
padding: 8px 0;
|
||||
margin: 0;
|
||||
margin-bottom: 12px;
|
||||
border-top: 1px dashed #8884;
|
||||
border-bottom: 1px dashed #8884;
|
||||
background: white;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
transition: all .2s ease-out;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.gui-settings-content ul li.category.folded
|
||||
{
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
span.settings-category
|
||||
{
|
||||
opacity: 0.6;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.gui-settings-title
|
||||
{
|
||||
@ -454,3 +485,29 @@ input[type='text'][key]
|
||||
{
|
||||
transition: all .2s ease-out;
|
||||
}
|
||||
i.settings-category-arrow
|
||||
{
|
||||
transform-origin: center;
|
||||
transition: all .2s ease-out;
|
||||
transform: translateY(2.828427px) rotate(-135deg);
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
margin-left: 12px;
|
||||
}
|
||||
li.category.folded i.settings-category-arrow
|
||||
{
|
||||
transform: translateY(-2.828427px) rotate(45deg);
|
||||
}
|
||||
i.settings-category-arrow::after
|
||||
{
|
||||
content: "";
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: transparent;
|
||||
border: 2px solid white;
|
||||
opacity: .8;
|
||||
display: block;
|
||||
border-left-color: transparent;
|
||||
border-top-color: transparent;
|
||||
border-radius: 2.4px;
|
||||
}
|
||||
@ -1 +1 @@
|
||||
1.5.10
|
||||
1.5.22
|
||||
27
video/download-video/download-video.html
Normal file
@ -0,0 +1,27 @@
|
||||
<div style="position: relative;" class="hidden">
|
||||
<button class="gui-settings-button" title="下载当前视频" id="download-video">
|
||||
下载视频
|
||||
</button>
|
||||
<div class="download-video-panel quality">
|
||||
<ol class="video-quality">
|
||||
|
||||
</ol>
|
||||
<div class="video-action">
|
||||
<div id="video-action-download">直接下载</div>
|
||||
<div id="video-action-copy">复制链接</div>
|
||||
</div>
|
||||
<div class="video-progress">
|
||||
<div class="download-progress-text">
|
||||
<span class="download-progress-title">正在下载</span>
|
||||
<span class="download-progress-value">0</span>
|
||||
<span class="download-progress-percent">%</span>
|
||||
</div>
|
||||
<div class="download-progress-background">
|
||||
<div class="download-progress-foreground"></div>
|
||||
</div>
|
||||
<div class="download-progress-cancel"><span>取消</span></div>
|
||||
</div>
|
||||
<div class="video-error"></div>
|
||||
<a href="" id="video-complete"></a>
|
||||
</div>
|
||||
</div>
|
||||
334
video/download-video/download-video.js
Normal file
@ -0,0 +1,334 @@
|
||||
(() =>
|
||||
{
|
||||
return (_, resources) =>
|
||||
{
|
||||
const VideoInfo = resources.attributes.videoInfo.export.VideoInfo;
|
||||
const BangumiInfo = resources.attributes.videoInfo.export.BangumiInfo;
|
||||
const pageData = {
|
||||
aid: undefined,
|
||||
cid: undefined,
|
||||
isBangumi: false,
|
||||
isMovie: false
|
||||
};
|
||||
class VideoFormat
|
||||
{
|
||||
constructor(quality, internalName, displayName)
|
||||
{
|
||||
this.quality = quality;
|
||||
this.internalName = internalName;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
async downloadInfo()
|
||||
{
|
||||
const videoInfo = new VideoDownloadInfo(this);
|
||||
await videoInfo.fetchVideoInfo();
|
||||
return videoInfo;
|
||||
}
|
||||
static get availableFormats()
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
const url = `https://api.bilibili.com/x/player/playurl?avid=${pageData.aid}&cid=${pageData.cid}&otype=json`;
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("load", () =>
|
||||
{
|
||||
const json = JSON.parse(xhr.responseText);
|
||||
if (json.code !== 0)
|
||||
{
|
||||
reject("获取清晰度信息失败.");
|
||||
}
|
||||
const data = json.data;
|
||||
const qualities = data.accept_quality;
|
||||
const internalNames = data.accept_format.split(",");
|
||||
const displayNames = data.accept_description;
|
||||
const formats = [];
|
||||
while (qualities.length > 0)
|
||||
{
|
||||
const format = new VideoFormat(
|
||||
qualities.pop(),
|
||||
internalNames.pop(),
|
||||
displayNames.pop()
|
||||
);
|
||||
formats.push(format);
|
||||
}
|
||||
resolve(formats);
|
||||
});
|
||||
xhr.addEventListener("error", () => reject(`获取清晰度信息失败.`));
|
||||
xhr.withCredentials = true;
|
||||
xhr.open("GET", url);
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
}
|
||||
class VideoDownloadInfoFragment
|
||||
{
|
||||
constructor(length, size, url, backupUrls)
|
||||
{
|
||||
this.length = length;
|
||||
this.size = size;
|
||||
this.url = url;
|
||||
this.backupUrls = backupUrls;
|
||||
}
|
||||
}
|
||||
class VideoDownloadInfo
|
||||
{
|
||||
constructor(format, fragments)
|
||||
{
|
||||
this.format = format;
|
||||
this.fragments = fragments || [];
|
||||
this.progress = null;
|
||||
this.loaded = 0;
|
||||
this.totalSize = null;
|
||||
this.workingXhr = null;
|
||||
}
|
||||
fetchVideoInfo()
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
const url = `https://api.bilibili.com/x/player/playurl?avid=${pageData.aid}&cid=${pageData.cid}&qn=${this.format.quality}&otype=json`;
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.addEventListener("load", () =>
|
||||
{
|
||||
const data = JSON.parse(xhr.responseText.replace(/http:/g, "https:")).data;
|
||||
if (data.quality !== this.format.quality)
|
||||
{
|
||||
reject("获取下载链接失败, 请确认当前账号有下载权限后重试.");
|
||||
}
|
||||
const urls = data.durl;
|
||||
this.fragments = urls.map(it => new VideoDownloadInfoFragment(
|
||||
it.length, it.size,
|
||||
it.url,
|
||||
it.backup_url
|
||||
));
|
||||
// if (this.fragments.length > 1)
|
||||
// {
|
||||
// reject("暂不支持分段视频的下载.");
|
||||
// }
|
||||
resolve(this.fragments);
|
||||
});
|
||||
xhr.withCredentials = true;
|
||||
xhr.open("GET", url);
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
cancelDownload()
|
||||
{
|
||||
if (this.workingXhr)
|
||||
{
|
||||
this.workingXhr.abort();
|
||||
}
|
||||
}
|
||||
downloadUrl(url)
|
||||
{
|
||||
return new Promise((resolve, reject) =>
|
||||
{
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", url);
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.withCredentials = false;
|
||||
xhr.addEventListener("progress", (e) =>
|
||||
{
|
||||
this.progress && this.progress((this.loaded + e.loaded) / this.totalSize);
|
||||
});
|
||||
xhr.addEventListener("load", () =>
|
||||
{
|
||||
if (xhr.status === 200)
|
||||
{
|
||||
resolve(xhr.response);
|
||||
}
|
||||
else
|
||||
{
|
||||
reject(`请求失败.`);
|
||||
}
|
||||
});
|
||||
xhr.addEventListener("abort", () => reject("下载已取消."));
|
||||
xhr.addEventListener("error", () => reject(`下载失败.`));
|
||||
xhr.send();
|
||||
this.workingXhr = xhr;
|
||||
});
|
||||
}
|
||||
copyUrl()
|
||||
{
|
||||
const urls = this.fragments.map(it => it.url).reduce((acc, it) => acc + "\r\n" + it);
|
||||
GM_setClipboard(urls, "text");
|
||||
}
|
||||
async download()
|
||||
{
|
||||
const downloadedData = [];
|
||||
this.loaded = 0;
|
||||
this.totalSize = this.fragments.map(it => it.size).reduce((acc, it) => acc + it);
|
||||
for (const fragment of this.fragments)
|
||||
{
|
||||
const data = await this.downloadUrl(fragment.url);
|
||||
this.loaded += fragment.size;
|
||||
downloadedData.push(data);
|
||||
}
|
||||
if (downloadedData.length < 1)
|
||||
{
|
||||
throw new Error("下载失败.");
|
||||
}
|
||||
|
||||
let blob = null;
|
||||
let filename = null;
|
||||
const extension = fragment => (fragment || this.fragments[0]).url.indexOf(".flv") !== -1 ? ".flv" : ".mp4";
|
||||
if (downloadedData.length === 1)
|
||||
{
|
||||
const [data] = downloadedData;
|
||||
blob = new Blob([data], {
|
||||
type: extension() === ".flv" ? "video/x-flv" : "video/mp4"
|
||||
});
|
||||
filename = document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili", "") + extension();
|
||||
}
|
||||
else
|
||||
{
|
||||
const zip = new JSZip();
|
||||
const title = document.title.replace("_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili", "");
|
||||
downloadedData.forEach((data, index) =>
|
||||
{
|
||||
zip.file(`${title} - ${index + 1}${extension(this.fragments[index])}`, data);
|
||||
});
|
||||
blob = await zip.generateAsync({ type: "blob" });
|
||||
filename = title + ".zip";
|
||||
}
|
||||
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
const oldBlobUrl = $("a#video-complete").attr("href");
|
||||
if (oldBlobUrl)
|
||||
{
|
||||
URL.revokeObjectURL(oldBlobUrl);
|
||||
}
|
||||
this.progress && this.progress(0);
|
||||
return {
|
||||
url: blobUrl,
|
||||
filename: filename
|
||||
};
|
||||
}
|
||||
}
|
||||
function loadWidget()
|
||||
{
|
||||
(async () =>
|
||||
{
|
||||
let aid = (unsafeWindow || window).aid;
|
||||
let cid = (unsafeWindow || window).cid;
|
||||
if (aid === undefined || cid === undefined)
|
||||
{
|
||||
const aidMatch = document.URL.match(/\/av(\d+)/);
|
||||
const epMatch = document.URL.match(/\/ep(\d+)/);
|
||||
if (aidMatch && aidMatch[1])
|
||||
{
|
||||
const info = await new VideoInfo(aidMatch[1]).fetchInfo();
|
||||
aid = info.aid;
|
||||
cid = info.cid;
|
||||
}
|
||||
// TODO: Download bangumi, the legacy method not work...
|
||||
// else if (epMatch && epMatch[1])
|
||||
// {
|
||||
// const info = await new BangumiInfo(epMatch[1]).fetchInfo();
|
||||
// aid = info.aid;
|
||||
// cid = info.cid;
|
||||
// }
|
||||
}
|
||||
return [aid, cid];
|
||||
})().then(result =>
|
||||
{
|
||||
const [aid, cid] = result;
|
||||
if (aid === undefined || cid === undefined)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pageData.aid = aid;
|
||||
pageData.cid = cid;
|
||||
VideoFormat.availableFormats.then((formats) =>
|
||||
{
|
||||
let [selectedFormat] = formats;
|
||||
const getVideoInfo = () => selectedFormat.downloadInfo().catch(error =>
|
||||
{
|
||||
$(".download-video-panel").addClass("error");
|
||||
$(".video-error").text(error);
|
||||
});
|
||||
async function download()
|
||||
{
|
||||
if (!selectedFormat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
$(".download-video-panel")
|
||||
.removeClass("action")
|
||||
.addClass("progress");
|
||||
const info = await getVideoInfo();
|
||||
info.progress = percent =>
|
||||
{
|
||||
$(".download-progress-value").text(`${fixed(percent * 100)}`);
|
||||
$(".download-progress-foreground").css("transform", `scaleX(${percent})`);
|
||||
};
|
||||
document.querySelector(".download-progress-cancel>span").onclick = () => info.cancelDownload();
|
||||
const result = await info.download()
|
||||
.catch(error =>
|
||||
{
|
||||
$(".download-video-panel").addClass("error");
|
||||
$(".video-error").text(error);
|
||||
});
|
||||
if (!result) // canceled or other errors
|
||||
{
|
||||
return;
|
||||
}
|
||||
const completeLink = document.getElementById("video-complete");
|
||||
completeLink.setAttribute("href", result.url);
|
||||
completeLink.setAttribute("download", result.filename);
|
||||
completeLink.click();
|
||||
$(".download-video-panel")
|
||||
.removeClass("progress")
|
||||
.addClass("quality");
|
||||
}
|
||||
async function copyLink()
|
||||
{
|
||||
if (!selectedFormat)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const info = await getVideoInfo();
|
||||
info.copyUrl();
|
||||
Toast.success("已复制链接到剪贴板.", "复制链接", 3000);
|
||||
$(".download-video-panel")
|
||||
.removeClass("action")
|
||||
.addClass("quality");
|
||||
}
|
||||
$(".video-action>#video-action-download").on("click", download);
|
||||
$(".video-action>#video-action-copy").on("click", copyLink);
|
||||
formats.forEach(format =>
|
||||
{
|
||||
$(`<li>${format.displayName}</li>`)
|
||||
.on("click", () =>
|
||||
{
|
||||
selectedFormat = format;
|
||||
$(".download-video-panel")
|
||||
.removeClass("quality")
|
||||
.addClass("action");
|
||||
})
|
||||
.prependTo("ol.video-quality");
|
||||
});
|
||||
resources.applyStyle("downloadVideoStyle");
|
||||
$("#download-video").on("click", () =>
|
||||
{
|
||||
$(".download-video-panel").toggleClass("opened");
|
||||
}).parent().removeClass("hidden");
|
||||
});
|
||||
$(".video-error").on("click", () =>
|
||||
{
|
||||
$(".video-error").text("");
|
||||
$(".download-video-panel")
|
||||
.removeClass("error")
|
||||
.removeClass("progress")
|
||||
.addClass("quality");
|
||||
});
|
||||
});
|
||||
}
|
||||
return {
|
||||
settingsWidget: {
|
||||
category: "视频与直播",
|
||||
content: resources.data.downloadVideoDom.text,
|
||||
success: loadWidget
|
||||
}
|
||||
};
|
||||
};
|
||||
})();
|
||||
107
video/download-video/download-video.scss
Normal file
@ -0,0 +1,107 @@
|
||||
.download-video-panel.opened
|
||||
{
|
||||
transform: scaleY(1);
|
||||
}
|
||||
.download-video-panel
|
||||
{
|
||||
position: absolute;
|
||||
top: calc(100% + 8px);
|
||||
transition: all .16s ease-out;
|
||||
transform-origin: top;
|
||||
transform: scaleY(0);
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 3px 20px 2px #0004;
|
||||
z-index: 100;
|
||||
}
|
||||
.gui-settings-content ol.video-quality li,
|
||||
.video-action>div
|
||||
{
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
transition: all .2s ease-out;
|
||||
}
|
||||
.video-action>div
|
||||
{
|
||||
padding: 12px 24px;
|
||||
}
|
||||
.gui-settings-content ol.video-quality li:hover,
|
||||
.video-action>div:hover
|
||||
{
|
||||
background: rgba(0,0,0,0.16);
|
||||
}
|
||||
.video-quality,
|
||||
.video-progress,
|
||||
.video-action,
|
||||
.video-error
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
.download-video-panel.quality:not(.error) .video-quality,
|
||||
.download-video-panel.progress:not(.error) .video-progress,
|
||||
.download-video-panel.action:not(.error) .video-action,
|
||||
.download-video-panel.error .video-error
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
.download-progress-text
|
||||
{
|
||||
display: flex;
|
||||
}
|
||||
.download-progress-title
|
||||
{
|
||||
flex: 1 0 0;
|
||||
}
|
||||
.download-progress-background
|
||||
{
|
||||
background-color: #8884;
|
||||
height: 4px;
|
||||
width: 100%;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.download-progress-foreground
|
||||
{
|
||||
background-color: $customStyleColor;
|
||||
transform-origin: left;
|
||||
transition: all .2s ease-out;
|
||||
transform: scaleX(0);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.download-progress-cancel
|
||||
{
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.download-progress-cancel>span
|
||||
{
|
||||
border-radius: 4px;
|
||||
background-color: #8884;
|
||||
padding: 4px 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.download-progress-cancel>span:hover
|
||||
{
|
||||
opacity: .9;
|
||||
}
|
||||
.download-progress-cancel>span:active
|
||||
{
|
||||
opacity: .8;
|
||||
}
|
||||
.video-error,
|
||||
.video-progress
|
||||
{
|
||||
padding: 12px;
|
||||
}
|
||||
.video-progress
|
||||
{
|
||||
min-width: 160px;
|
||||
}
|
||||
#video-complete
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
77
video/video-info.js
Normal file
@ -0,0 +1,77 @@
|
||||
(() =>
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
class VideoInfo
|
||||
{
|
||||
constructor(aid)
|
||||
{
|
||||
this.aid = aid;
|
||||
}
|
||||
async fetchInfo()
|
||||
{
|
||||
const json = JSON.parse(await downloadText(`https://api.bilibili.com/x/web-interface/view?aid=${this.aid}`));
|
||||
if (json.code !== 0)
|
||||
{
|
||||
throw new Error(json.message);
|
||||
}
|
||||
const data = json.data;
|
||||
this.cid = data.cid;
|
||||
this.pageCount = data.videos;
|
||||
this.coverUrl = data.pic;
|
||||
this.tagId = data.tid;
|
||||
this.tagName = data.tname;
|
||||
this.title = data.title;
|
||||
this.description = data.desc;
|
||||
this.up = {
|
||||
uid: data.owner.mid,
|
||||
name: data.owner.name,
|
||||
faceUrl: data.owner.face
|
||||
};
|
||||
this.pages = data.pages.map(it =>
|
||||
{
|
||||
return {
|
||||
cid: it.cid,
|
||||
title: it.part,
|
||||
pageNumber: it.page
|
||||
};
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class BangumiInfo
|
||||
{
|
||||
constructor(ep)
|
||||
{
|
||||
this.ep = ep;
|
||||
this.videos = [];
|
||||
}
|
||||
async fetchInfo()
|
||||
{
|
||||
const data = await downloadText(`https://www.bilibili.com/bangumi/play/ep${this.ep}/`);
|
||||
const json = JSON.parse(data.match(/window\.__INITIAL_STATE__=(.*);\(function\(\){/)[1]);
|
||||
this.title = json.mediaInfo.title;
|
||||
this.cover = json.mediaInfo.cover;
|
||||
this.squareCover = json.mediaInfo.square_cover;
|
||||
this.aid = json.epInfo.aid;
|
||||
this.cid = json.epInfo.cid;
|
||||
this.videos = json.epList.map(async (it) =>
|
||||
{
|
||||
return {
|
||||
title: it.index_title,
|
||||
aid: it.aid,
|
||||
cid: it.cid,
|
||||
info: await new VideoInfo(it.aid).fetchInfo()
|
||||
};
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return {
|
||||
export: {
|
||||
VideoInfo: VideoInfo,
|
||||
BangumiInfo: BangumiInfo
|
||||
}
|
||||
};
|
||||
};
|
||||
})();
|
||||
@ -41,31 +41,31 @@
|
||||
show()
|
||||
{
|
||||
this.viewer.addClass("opened");
|
||||
$("html,body").addClass("image-viewer-opened");
|
||||
// $("html,body").addClass("image-viewer-opened");
|
||||
}
|
||||
hide()
|
||||
{
|
||||
this.viewer.removeClass("opened");
|
||||
$("html,body").removeClass("image-viewer-opened");
|
||||
// $("html,body").removeClass("image-viewer-opened");
|
||||
}
|
||||
}
|
||||
|
||||
if ($("meta[itemprop='image']").length > 0)
|
||||
if ($("meta[itemprop='image'],meta[property='og:image']").length > 0)
|
||||
{
|
||||
return {
|
||||
settingsWidget: {
|
||||
after: () => $("span.settings-category").filter((_, e) => e.innerHTML === "视频与直播").parent(),
|
||||
content: `<li class="indent-center hidden">
|
||||
category: "视频与直播",
|
||||
content: `<div class="hidden">
|
||||
<button
|
||||
class="gui-settings-button"
|
||||
title="查看当前视频的封面"
|
||||
id="view-video-cover">
|
||||
查看封面
|
||||
</button>
|
||||
</li>`,
|
||||
</div>`,
|
||||
success: () =>
|
||||
{
|
||||
new SpinQuery(() => $("meta[itemprop='image']"),
|
||||
new SpinQuery(() => $("meta[itemprop='image'],meta[property='og:image']"),
|
||||
metaData => metaData.length > 0 && metaData.prop("content"),
|
||||
metaData =>
|
||||
{
|
||||
@ -83,15 +83,15 @@
|
||||
{
|
||||
return {
|
||||
settingsWidget: {
|
||||
after: () => $("span.settings-category").filter((_, e) => e.innerHTML === "视频与直播").parent(),
|
||||
content: `<li class="indent-center hidden">
|
||||
category: "视频与直播",
|
||||
content: `<div class="hidden">
|
||||
<button
|
||||
class="gui-settings-button"
|
||||
title="查看当前直播的封面"
|
||||
id="view-live-cover">
|
||||
查看封面
|
||||
</button>
|
||||
</li>`,
|
||||
</div>`,
|
||||
success: () =>
|
||||
{
|
||||
SpinQuery.any(() => $(".header-info-ctnr .room-cover"), coverLink =>
|
||||
|
||||