// ==UserScript==
// @name 【移动端】bilibili优化
// @namespace https://github.com/WhiteSevs/TamperMonkeyScript
// @version 2024.6.5
// @author WhiteSevs
// @description bilibili(哔哩哔哩)优化,免登录等
// @license GPL-3.0-only
// @icon https://i0.hdslb.com/bfs/static/jinkela/long/images/512.png
// @supportURL https://github.com/WhiteSevs/TamperMonkeyScript/issues
// @match *://m.bilibili.com/*
// @match *://live.bilibili.com/*
// @require https://update.greasyfork.icu/scripts/494167/1376186/CoverUMD.js
// @require https://update.greasyfork.icu/scripts/456485/1384984/pops.js
// @require https://cdn.jsdelivr.net/npm/qmsg@1.1.0/dist/index.umd.js
// @require https://cdn.jsdelivr.net/npm/@whitesev/utils@1.3.6/dist/index.umd.js
// @require https://cdn.jsdelivr.net/npm/@whitesev/domutils@1.1.1/dist/index.umd.js
// @connect *
// @connect m.bilibili.com
// @connect www.bilibili.com
// @connect api.bilibili.com
// @grant GM_addStyle
// @grant GM_deleteValue
// @grant GM_getValue
// @grant GM_info
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_unregisterMenuCommand
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// @run-at document-start
// @downloadURL none
// ==/UserScript==
(a=>{function e(n){if(typeof n!="string")throw new TypeError("cssText must be a string");let p=document.createElement("style");return p.setAttribute("type","text/css"),p.innerHTML=n,document.head?document.head.appendChild(p):document.body?document.body.appendChild(p):document.documentElement.childNodes.length===0?document.documentElement.appendChild(p):document.documentElement.insertBefore(p,document.documentElement.childNodes[0]),p}if(typeof GM_addStyle=="function"){GM_addStyle(a);return}e(a)})(" .m-video2-awaken-btn,.m-head .launch-app-btn.m-nav-openapp,.m-head .launch-app-btn.home-float-openapp,.m-home .launch-app-btn.home-float-openapp,.m-space .launch-app-btn.m-space-float-openapp,.m-space .launch-app-btn.m-nav-openapp{display:none!important}#app .video .openapp-dialog,#app .video .launch-app-btn.m-video-main-launchapp:has([class^=m-video2-awaken]),#app .video .launch-app-btn.m-nav-openapp,#app .video .mplayer-widescreen-callapp,#app .video .launch-app-btn.m-float-openapp{display:none!important}#app.LIVE .open-app-btn.bili-btn-warp,#app .m-dynamic .launch-app-btn.m-nav-openapp,#app .m-dynamic .dynamic-float-openapp.dynamic-float-btn,#app .m-opus .float-openapp.opus-float-btn,#app .m-opus .v-switcher .launch-app-btn.list-more,#app .m-opus .opus-nav .launch-app-btn.m-nav-openapp,#app .topic-detail .launch-app-btn.m-nav-openapp,#app .topic-detail .launch-app-btn.m-topic-float-openapp{display:none!important}#app.main-container bili-open-app.btn-download{display:none!important} ");
(function (Qmsg, Utils, DOMUtils) {
'use strict';
var _a;
var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
var _GM_info = /* @__PURE__ */ (() => typeof GM_info != "undefined" ? GM_info : void 0)();
var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
var _GM_unregisterMenuCommand = /* @__PURE__ */ (() => typeof GM_unregisterMenuCommand != "undefined" ? GM_unregisterMenuCommand : void 0)();
var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
var _monkeyWindow = /* @__PURE__ */ (() => window)();
const _SCRIPT_NAME_ = "【移动端】bilibili优化";
const utils = Utils.noConflict();
const domutils = DOMUtils.noConflict();
const pops = _monkeyWindow.pops || _unsafeWindow.pops;
const log = new utils.Log(
_GM_info,
_unsafeWindow.console || _monkeyWindow.console
);
const SCRIPT_NAME = ((_a = _GM_info == null ? void 0 : _GM_info.script) == null ? void 0 : _a.name) || _SCRIPT_NAME_;
const DEBUG = false;
log.config({
debug: DEBUG,
logMaxCount: 2e4,
autoClearConsole: true,
tag: true
});
Qmsg.config({
position: "bottom",
html: true,
maxNums: 5,
autoClose: true,
showClose: false,
showReverse: true
});
const GM_Menu = new utils.GM_Menu({
GM_getValue: _GM_getValue,
GM_setValue: _GM_setValue,
GM_registerMenuCommand: _GM_registerMenuCommand,
GM_unregisterMenuCommand: _GM_unregisterMenuCommand
});
const httpx = new utils.Httpx(_GM_xmlhttpRequest);
httpx.config({
logDetails: DEBUG,
onabort() {
Qmsg.warning("请求取消");
},
ontimeout() {
Qmsg.error("请求超时");
},
onerror(response) {
Qmsg.error("请求异常");
log.error(["httpx-onerror 请求异常", response]);
}
});
const OriginPrototype = {
Object: {
defineProperty: _unsafeWindow.Object.defineProperty
},
Function: {
apply: _unsafeWindow.Function.prototype.apply,
call: _unsafeWindow.Function.prototype.call
},
Element: {
appendChild: _unsafeWindow.Element.prototype.appendChild
},
setTimeout: _unsafeWindow.setTimeout
};
const addStyle = utils.addStyle;
const KEY = "GM_Panel";
const ATTRIBUTE_KEY = "data-key";
const ATTRIBUTE_DEFAULT_VALUE = "data-default-value";
const UISwitch = function(text, key, defaultValue, clickCallBack, description) {
let result = {
text,
type: "switch",
description,
attributes: {},
getValue() {
return Boolean(PopsPanel.getValue(key, defaultValue));
},
callback(event, value) {
log.success(`${value ? "开启" : "关闭"} ${text}`);
PopsPanel.setValue(key, Boolean(value));
},
afterAddToUListCallBack: void 0
};
if (result.attributes) {
result.attributes[ATTRIBUTE_KEY] = key;
result.attributes[ATTRIBUTE_DEFAULT_VALUE] = Boolean(defaultValue);
}
return result;
};
const SettingUICommon = {
id: "panel-common",
title: "通用",
forms: [
{
text: "功能",
type: "forms",
forms: [
UISwitch(
"监听路由改变",
"bili-listenRouterChange",
true,
void 0,
"用于处理页面跳转时功能不生效问题"
),
UISwitch(
"新标签页打开",
"bili-go-to-url-blank",
false,
void 0,
"通过开启【覆盖点击事件】相关的设置,通过新标签页打开链接"
)
]
},
{
text: "变量设置",
type: "forms",
forms: [
UISwitch(
"isLogin",
"bili-setLogin",
true,
void 0,
"$store.state.common.noCallApp=true
$store.state.common.userInfo.isLogin=true
$store.state.loginInfo.isLogin=true"
),
UISwitch(
"isClient",
"bili-setIsClient",
true,
void 0,
"$store.state.video.isClient=true
$store.state.opus.isClient=true
$store.state.playlist.isClient=true
$store.state.ver.bili=true
$store.state.ver.biliVer=2333"
),
UISwitch(
"tinyApp",
"bili-setTinyApp",
true,
void 0,
"$store.state.common.tinyApp=true"
)
]
},
{
text: "劫持/拦截",
type: "forms",
forms: [
UISwitch(
"覆盖.launch-app-btn openApp",
"bili-overrideLaunchAppBtn_Vue_openApp",
true,
void 0,
"覆盖.launch-app-btn元素上的openApp函数,可阻止点击唤醒/下载App"
),
UISwitch(
"劫持setTimeout-autoOpenApp",
"bili-hookSetTimeout_autoOpenApp",
true,
void 0,
"阻止自动调用App"
)
]
}
]
};
const BilibiliRouter = {
/**
* 判断当前路径
* + /video/
*/
isVideo() {
return window.location.pathname.startsWith("/video/");
},
/**
* 判断当前路径
* + /banggumi/
*/
isBangumi() {
return window.location.pathname.startsWith("/bangumi/");
},
/**
* 判断当前路径
* + /search
*/
isSearch() {
return window.location.pathname.startsWith("/search");
},
/**
* 判断当前路径
* + live.bilibili.com
*/
isLive() {
return window.location.hostname === "live.bilibili.com";
},
/**
* 判断当前路径
* + /opus
*/
isOpus() {
return window.location.pathname.startsWith("/opus");
},
/**
* 判断当前路径
* + /topic-detail
*/
isTopicDetail() {
return window.location.pathname.startsWith("/topic-detail");
},
/**
* 判断当前路径
* + /dynamic
*/
isDynamic() {
return window.location.pathname.startsWith("/dynamic");
},
/**
* 判断当前路径
* + /
* + /channel
*/
isHead() {
return window.location.pathname === "/" || window.location.pathname.startsWith("/channel");
}
};
const SettingUIVideo = {
id: "panel-video",
title: "视频",
isDefault() {
return BilibiliRouter.isVideo();
},
forms: [
{
text: "功能",
type: "forms",
forms: [
UISwitch(
"修复视频底部区域高度",
"bili-video-repairVideoBottomAreaHeight",
true,
void 0,
"添加margin-top"
),
UISwitch(
"自动点击【继续在网页观看】",
"bili-video-autoClickContinueToWatchOnTheWebpage",
true,
void 0,
"可避免弹窗出现且自动点击后播放视频"
),
UISwitch(
"美化显示",
"bili-video-beautify",
true,
void 0,
"调整底部推荐视频卡片样式类似哔哩哔哩App"
),
UISwitch(
"手势返回关闭评论区",
"bili-video-gestureReturnToCloseCommentArea",
true,
void 0,
"当浏览器手势触发浏览器回退页面时,关闭评论区"
),
UISwitch(
"initPlayer",
"bili-video-initPlayer",
true,
void 0,
"自动执行初始化播放器"
)
]
},
{
text: "变量设置",
type: "forms",
forms: [
UISwitch(
"playBtnNoOpenApp",
"bili-video-setVideoPlayer",
true,
void 0,
"playBtnNoOpenApp=true
playBtnOpenApp=false
coverOpenApp=false"
),
UISwitch(
"解锁充电限制",
"bili-video-unlockUpower",
false,
void 0,
"is_upower_exclusive=true
is_upower_play=false
is_upower_preview=false"
)
]
},
{
text: "覆盖点击事件",
type: "forms",
forms: [
UISwitch(
"相关视频",
"bili-video-cover-bottomRecommendVideo",
true,
void 0,
"点击下面的相关视频可正确跳转至该视频"
)
]
},
{
text: "劫持/拦截",
type: "forms",
forms: [
UISwitch(
"阻止调用App",
"bili-video-hook-callApp",
true,
void 0,
"处理函数: PlayerAgent"
)
]
}
]
};
const SettingUIBangumi = {
id: "panel-bangumi",
title: "番剧",
isDefault() {
return BilibiliRouter.isBangumi();
},
forms: [
{
text: "变量设置",
type: "forms",
forms: [
UISwitch(
"pay",
"bili-bangumi-setPay",
true,
void 0,
"$store.state.userStat.pay=1
$store.state.mediaInfo.user_status.pay=1"
)
]
},
{
text: "覆盖点击事件",
type: "forms",
forms: [
UISwitch(
"【选集】",
"bili-bangumi-cover-clicl-event-chooseEp",
true,
void 0,
"让【选集】的视频列表可点击跳转"
),
UISwitch(
"【其它】",
"bili-bangumi-cover-clicl-event-other",
true,
void 0,
"让【PV&其他】、【预告】、【主题曲】、【香境剧场】等的视频列表可点击跳转"
),
UISwitch(
"【更多推荐】",
"bili-bangumi-cover-clicl-event-recommend",
true,
void 0,
"让【更多推荐】的视频列表可点击跳转"
)
]
},
{
text: "劫持/拦截",
type: "forms",
forms: [
UISwitch("阻止调用App", "bili-bangumi-hook-callApp", true, void 0, "")
]
}
]
};
const SettingUISearch = {
id: "panel-search",
title: "搜索",
isDefault() {
return BilibiliRouter.isSearch();
},
forms: [
{
text: "功能",
type: "forms",
forms: [
UISwitch(
"修复点击UP主正确进入空间",
"bili-search-repair-enter-user-home",
true,
void 0,
"可以修复点击UP主进入个人空间但是是404问题"
)
]
}
]
};
const SettingUILive = {
id: "panel-live",
title: "直播",
isDefault() {
return BilibiliRouter.isLive();
},
forms: [
{
text: "屏蔽",
type: "forms",
forms: [
UISwitch(
"【屏蔽】聊天室",
"bili-live-block-chatRoom",
false,
void 0,
"直接不显示底部的聊天室"
),
UISwitch(
"【屏蔽】xxx进入直播间",
"bili-live-block-brush-prompt",
false,
void 0,
"直接不显示底部的xxx进入直播间"
),
UISwitch(
"【屏蔽】控制面板",
"bili-live-block-control-panel",
false,
void 0,
"屏蔽底部的发个弹幕、送礼"
)
]
},
{
text: "劫持/拦截",
type: "forms",
forms: [
UISwitch(
"阻止open-app-btn元素点击事件触发",
"bili-live-prevent-openAppBtn",
true,
void 0,
"开启后可不跳转至唤醒App页面"
)
]
}
]
};
const SettingUIOpus = {
id: "panel-opus",
title: "专栏",
isDefault() {
return BilibiliRouter.isOpus();
},
forms: [
{
text: "覆盖点击事件",
type: "forms",
forms: [
UISwitch(
"话题",
"bili-opus-cover-topicJump",
true,
void 0,
"点击话题正确跳转"
)
]
}
]
};
const SettingUIDynamic = {
id: "panel-dynamic",
title: "动态",
isDefault() {
return BilibiliRouter.isDynamic();
},
forms: [
{
text: "覆盖点击事件",
type: "forms",
forms: [
UISwitch(
"话题",
"bili-dynamic-cover-topicJump",
true,
void 0,
"点击话题正确跳转"
),
UISwitch(
"header用户",
"bili-dynamic-cover-header",
true,
void 0,
"点击内容上的发布本动态的用户正确跳转个人空间"
),
UISwitch(
"@用户",
"bili-dynamic-cover-atJump",
true,
void 0,
"点击@用户正确跳转个人空间"
),
UISwitch(
"引用",
"bili-dynamic-cover-referenceJump",
true,
void 0,
"点击引用的视频|用户正确跳转"
)
]
}
]
};
const SettingUITopicDetail = {
id: "panel-topic-detail",
title: "话题",
isDefault() {
return BilibiliRouter.isTopicDetail();
},
forms: []
};
const SettingUIHead = {
id: "panel-head",
title: "首页",
forms: [
{
text: "功能",
type: "forms",
forms: [
UISwitch(
"美化显示",
"bili-head-beautify",
true,
void 0,
"调整瀑布流视频卡片样式类似哔哩哔哩App"
),
UISwitch(
"补充推荐视频信息",
"bili-head-supplementaryVideoStreamingInformation",
true,
void 0,
"给视频添加UP主名,当前视频总时长信息"
)
]
}
]
};
const PopsPanel = {
/** 数据 */
$data: {
/**
* 菜单项的默认值
*/
data: new utils.Dictionary(),
/**
* 成功只执行了一次的项
*/
oneSuccessExecMenu: new utils.Dictionary(),
/**
* 成功只执行了一次的项
*/
onceExec: new utils.Dictionary(),
/** 脚本名,一般用在设置的标题上 */
scriptName: SCRIPT_NAME,
/** 菜单项的总值在本地数据配置的键名 */
key: KEY,
/** 菜单项在attributes上配置的菜单键 */
attributeKeyName: ATTRIBUTE_KEY,
/** 菜单项在attributes上配置的菜单默认值 */
attributeDefaultValueName: ATTRIBUTE_DEFAULT_VALUE
},
/** 监听器 */
$listener: {
/**
* 值改变的监听器
*/
listenData: new utils.Dictionary()
},
init() {
this.initPanelDefaultValue();
this.initExtensionsMenu();
},
initExtensionsMenu() {
if (_unsafeWindow.top !== _unsafeWindow.self) {
return;
}
GM_Menu.add([
{
key: "show_pops_panel_setting",
text: "⚙ 设置",
autoReload: false,
isStoreValue: false,
showText(text) {
return text;
},
callback: () => {
this.showPanel();
}
}
]);
},
/** 初始化本地设置默认的值 */
initPanelDefaultValue() {
let that = this;
function initDefaultValue(config) {
if (!config["attributes"]) {
return;
}
let key = config.attributes[ATTRIBUTE_KEY];
let defaultValue = config["attributes"][ATTRIBUTE_DEFAULT_VALUE];
if (key == null) {
log.warn(["请先配置键", config]);
return;
}
if (that.$data.data.has(key)) {
log.warn("请检查该key(已存在): " + key);
}
that.$data.data.set(key, defaultValue);
}
let contentConfigList = this.getPanelContentConfig();
for (let index = 0; index < contentConfigList.length; index++) {
let leftContentConfigItem = contentConfigList[index];
if (!leftContentConfigItem.forms) {
continue;
}
let rightContentConfigList = leftContentConfigItem.forms;
for (let formItemIndex = 0; formItemIndex < rightContentConfigList.length; formItemIndex++) {
let rightContentConfigItem = rightContentConfigList[formItemIndex];
if (rightContentConfigItem.forms) {
let childFormConfigList = rightContentConfigItem.forms;
for (let formChildConfigIndex = 0; formChildConfigIndex < childFormConfigList.length; formChildConfigIndex++) {
initDefaultValue(childFormConfigList[formChildConfigIndex]);
}
} else {
initDefaultValue(rightContentConfigItem);
}
}
}
},
/**
* 设置值
* @param key 键
* @param value 值
*/
setValue(key, value) {
let locaData = _GM_getValue(KEY, {});
let oldValue = locaData[key];
locaData[key] = value;
_GM_setValue(KEY, locaData);
if (this.$listener.listenData.has(key)) {
this.$listener.listenData.get(key).callback(key, oldValue, value);
}
},
/**
* 获取值
* @param key 键
* @param defaultValue 默认值
*/
getValue(key, defaultValue) {
let locaData = _GM_getValue(KEY, {});
let localValue = locaData[key];
if (localValue == null) {
if (this.$data.data.has(key)) {
return this.$data.data.get(key);
}
return defaultValue;
}
return localValue;
},
/**
* 删除值
* @param key 键
*/
deleteValue(key) {
let locaData = _GM_getValue(KEY, {});
let oldValue = locaData[key];
Reflect.deleteProperty(locaData, key);
_GM_setValue(KEY, locaData);
if (this.$listener.listenData.has(key)) {
this.$listener.listenData.get(key).callback(key, oldValue, void 0);
}
},
/**
* 监听调用setValue、deleteValue
* @param key 需要监听的键
* @param callback
*/
addValueChangeListener(key, callback) {
let listenerId = Math.random();
this.$listener.listenData.set(key, {
id: listenerId,
key,
callback
});
return listenerId;
},
/**
* 移除监听
* @param listenerId 监听的id
*/
removeValueChangeListener(listenerId) {
let deleteKey = null;
for (const [key, value] of this.$listener.listenData.entries()) {
if (value.id === listenerId) {
deleteKey = key;
break;
}
}
this.$listener.listenData.delete(deleteKey);
},
/**
* 判断该键是否存在
* @param key 键
*/
hasKey(key) {
let locaData = _GM_getValue(KEY, {});
return key in locaData;
},
/**
* 自动判断菜单是否启用,然后执行回调
* @param key
* @param callback 回调
*/
execMenu(key, callback) {
if (typeof key !== "string") {
throw new TypeError("key 必须是字符串");
}
if (!this.$data.data.has(key)) {
log.warn(`${key} 键不存在`);
return;
}
let value = PopsPanel.getValue(key);
if (value) {
callback(value);
}
},
/**
* 自动判断菜单是否启用,然后执行回调,只会执行一次
* @param key
* @param callback 回调
*/
execMenuOnce(key, callback) {
if (typeof key !== "string") {
throw new TypeError("key 必须是字符串");
}
if (!this.$data.data.has(key)) {
log.warn(`${key} 键不存在`);
return;
}
let value = PopsPanel.getValue(key);
if (value) {
if (this.$data.oneSuccessExecMenu.has(key)) {
return;
}
callback(value);
this.$data.oneSuccessExecMenu.set(key, 1);
}
},
/**
* 根据key执行一次
* @param key
*/
onceExec(key, callback) {
if (typeof key !== "string") {
throw new TypeError("key 必须是字符串");
}
if (this.$data.onceExec.has(key)) {
return;
}
callback();
this.$data.onceExec.set(key, 1);
},
/**
* 显示设置面板
*/
showPanel() {
pops.panel({
title: {
text: `${SCRIPT_NAME}-设置`,
position: "center",
html: false,
style: ""
},
content: this.getPanelContentConfig(),
mask: {
enable: true,
clickEvent: {
toClose: true,
toHide: false
}
},
isMobile: this.isMobile(),
width: this.getWidth(),
height: this.getHeight(),
drag: true,
only: true
});
},
isMobile() {
return window.outerWidth < 550;
},
/**
* 获取设置面板的宽度
*/
getWidth() {
if (window.outerWidth < 550) {
return "92dvw";
} else {
return "550px";
}
},
/**
* 获取设置面板的高度
*/
getHeight() {
if (window.outerHeight > 450) {
return "80dvh";
} else {
return "450px";
}
},
/**
* 获取配置内容
*/
getPanelContentConfig() {
let configList = [
SettingUICommon,
SettingUIHead,
SettingUIVideo,
SettingUIOpus,
SettingUIDynamic,
SettingUIBangumi,
SettingUITopicDetail,
SettingUISearch,
SettingUILive
];
return configList;
}
};
const BilibiliBeautifyCSS = "/* 主页 */\r\n#app .m-head {\r\n --bg-color: #f0f1f3;\r\n --bg-rever-color: #ffffff;\r\n --pd-width: 1.3333vmin;\r\n --bd-circle: 1.3333vmin;\r\n --card-height: 30vmin;\r\n --icon-font-size: 3.2vmin;\r\n --icon-text-font-size: 2.6vmin;\r\n --icon-font-margin-right: 3vmin;\r\n --title-font-size: 2.8vmin;\r\n\r\n background-color: var(--bg-color);\r\n .m-home {\r\n background-color: var(--bg-color);\r\n }\r\n /* 美化视频卡片 */\r\n .video-list .card-box {\r\n .v-card {\r\n background-color: var(--bg-rever-color);\r\n padding: 0px;\r\n margin: 0px;\r\n width: calc(50% - var(--pd-width) / 2);\r\n border-radius: var(--bd-circle);\r\n margin-top: var(--pd-width);\r\n display: grid;\r\n\r\n /* 视频封面区域 */\r\n .card {\r\n background: var(--bg-rever-color);\r\n border-radius: unset;\r\n border-top-left-radius: var(--bd-circle);\r\n border-top-right-radius: var(--bd-circle);\r\n height: var(--card-height);\r\n\r\n .count {\r\n display: flex;\r\n justify-content: safe flex-start;\r\n padding-right: 0;\r\n\r\n .iconfont {\r\n font-size: var(--icon-text-font-size);\r\n }\r\n\r\n > span {\r\n font-size: var(--icon-text-font-size);\r\n margin-right: var(--icon-font-margin-right);\r\n }\r\n }\r\n }\r\n /* 视频标题区域 */\r\n .title {\r\n padding: 0;\r\n margin: var(--pd-width);\r\n font-size: var(--title-font-size);\r\n }\r\n }\r\n /* 两列 => 左边的 */\r\n .v-card:nth-child(2n-1) {\r\n /*background-color: red;*/\r\n margin-right: calc(var(--pd-width) / 2);\r\n }\r\n /* 两列 => 右边的 */\r\n .v-card:nth-child(2n) {\r\n /*background-color: rebeccapurple;*/\r\n margin-left: calc(var(--pd-width) / 2);\r\n }\r\n }\r\n}\r\n";
const BilibiliUtils = {
/**
* 获取元素上的__vue__属性
* @param element
* @returns
*/
getVue(element) {
return element == null ? void 0 : element.__vue__;
},
/**
* 等待vue属性并进行设置
*/
waitVuePropToSet($target, needSetList) {
function getTarget() {
let __target__ = null;
if (typeof $target === "string") {
__target__ = document.querySelector($target);
} else if (typeof $target === "function") {
__target__ = $target();
} else if ($target instanceof HTMLElement) {
__target__ = $target;
}
return __target__;
}
needSetList.forEach((needSetOption) => {
if (typeof needSetOption.msg === "string") {
log.info(needSetOption.msg);
}
function checkVue() {
let target = getTarget();
if (target == null) {
return false;
}
let vueObj = BilibiliUtils.getVue(target);
if (vueObj == null) {
return false;
}
let needOwnCheck = needSetOption.check(vueObj);
return Boolean(needOwnCheck);
}
utils.waitVueByInterval(
() => {
return getTarget();
},
checkVue,
250,
1e4
).then((result) => {
if (!result) {
return;
}
let target = getTarget();
let vueObj = BilibiliUtils.getVue(target);
if (vueObj == null) {
return;
}
needSetOption.set(vueObj);
});
});
},
/**
* 前往网址
* @param path
*/
goToUrl(path) {
let $app = document.querySelector("#app");
if ($app == null) {
Qmsg.error("跳转Url: 获取根元素#app失败");
log.error("跳转Url: 获取根元素#app失败:" + path);
return;
}
let vueObj = BilibiliUtils.getVue($app);
if (vueObj == null) {
log.error("获取#app的vue属性失败");
Qmsg.error("获取#app的vue属性失败");
return;
}
let $router = vueObj.$router;
let isGoToUrlBlank = PopsPanel.getValue("bili-go-to-url-blank");
log.info("即将跳转URL:" + path);
if (isGoToUrlBlank) {
window.open(path, "_blank");
} else {
if (path.startsWith("http") || path.startsWith("//")) {
window.location.href = path;
} else {
$router.push(path);
}
}
},
/**
* 转换时长为显示的时长
*
* + 30 => 0:30
* + 120 => 2:00
* + 14400 => 4:00:00
* @param duration 秒
*/
parseDuration(duration) {
if (typeof duration !== "number") {
duration = parseInt(duration);
}
if (isNaN(duration)) {
return duration.toString();
}
function zeroPadding(num) {
if (num < 10) {
return `0${num}`;
} else {
return num;
}
}
if (duration < 60) {
return `0:${zeroPadding(duration)}`;
} else if (duration >= 60 && duration < 3600) {
return `${Math.floor(duration / 60)}:${zeroPadding(duration % 60)}`;
} else {
return `${Math.floor(duration / 3600)}:${zeroPadding(
Math.floor(duration / 60) % 60
)}:${zeroPadding(duration % 60)}`;
}
},
/**
* 手势返回
*/
hookGestureReturnByVueRouter(option) {
function popstateEvent() {
log.success("触发popstate事件");
resumeBack(true);
}
function banBack() {
log.success("监听地址改变");
option.vueObj.$router.history.push(option.hash);
domutils.on(window, "popstate", popstateEvent);
}
async function resumeBack(isFromPopState = false) {
domutils.off(window, "popstate", popstateEvent);
let callbackResult = option.callback(isFromPopState);
if (callbackResult) {
return;
}
while (1) {
if (option.vueObj.$router.history.current.hash === option.hash) {
log.info("后退!");
option.vueObj.$router.back();
await utils.sleep(250);
} else {
return;
}
}
}
banBack();
return {
resumeBack
};
},
/**
* 加载