Redesign user info panel (not logged in)

This commit is contained in:
the1812 2019-06-15 10:47:16 +08:00
parent c2e0d1573f
commit 670eb6b75a
9 changed files with 1058 additions and 1233 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -139,8 +139,8 @@ const customNavbarDefaultOrders = {
favoritesList: 16,
historyList: 17,
upload: 18,
blank3: 19
};
blank3: 19,
}
const settings = {
useDarkStyle: false,
compactLayout: false,
@ -153,8 +153,8 @@ const settings = {
touchVideoPlayer: false,
customControlBackgroundOpacity: 0.64,
customControlBackground: true,
darkScheduleStart: "18:00",
darkScheduleEnd: "6:00",
darkScheduleStart: '18:00',
darkScheduleEnd: '6:00',
darkSchedule: false,
blurVideoControl: false,
toast: true,
@ -167,14 +167,14 @@ const settings = {
hideTopSearch: false,
touchVideoPlayerDoubleTapControl: false,
touchVideoPlayerAnimation: false,
customStyleColor: "#00A0D8",
customStyleColor: '#00A0D8',
preserveRank: true,
blurBackgroundOpacity: 0.382,
useDefaultPlayerMode: false,
applyPlayerModeOnPlay: true,
defaultPlayerMode: "常规",
defaultPlayerMode: '常规',
useDefaultVideoQuality: false,
defaultVideoQuality: "自动",
defaultVideoQuality: '自动',
useDefaultDanmakuSettings: false,
enableDanmaku: true,
rememberDanmakuSettings: false,
@ -182,8 +182,8 @@ const settings = {
subtitlesPreserve: false,
smartMask: false,
},
defaultPlayerLayout: "新版",
defaultBangumiLayout: "旧版",
defaultPlayerLayout: '新版',
defaultBangumiLayout: '旧版',
useDefaultPlayerLayout: false,
skipChargeList: false,
comboLike: false,
@ -198,10 +198,10 @@ const settings = {
framePlayback: true,
useCommentStyle: true,
imageResolution: false,
imageResolutionScale: "auto",
imageResolutionScale: 'auto',
toastInternalError: false,
i18n: false,
i18nLanguage: "日本語",
i18nLanguage: '日本語',
playerFocus: false,
playerFocusOffset: -10,
oldTweets: false,
@ -234,13 +234,15 @@ const settings = {
hideOldEntry: true,
videoScreenshot: false,
hideBangumiReviews: false,
filenameFormat: "[title][ - ep]",
filenameFormat: '[title][ - ep]',
sideBarOffset: 0,
noLiveAutoplay: false,
hideHomeLive: false,
noMiniVideoAutoplay: false,
useDefaultVideoSpeed: false,
defaultVideoSpeed: 1,
cache: {},
};
}
const fixedSettings = {
guiSettings: true,
viewCover: true,
@ -255,16 +257,15 @@ const fixedSettings = {
forceWide: false,
useNewStyle: false,
overrideNavBar: false,
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js",
latestVersionLink: 'https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js',
currentVersion: GM_info.script.version,
};
const settingsChangeHandlers = {};
}
const settingsChangeHandlers = {}
function addSettingsListener (key, handler, initCall) {
if (!settingsChangeHandlers[key]) {
settingsChangeHandlers[key] = [handler];
}
else {
settingsChangeHandlers[key].push(handler);
settingsChangeHandlers[key] = [handler]
} else {
settingsChangeHandlers[key].push(handler)
}
if (initCall) {
const value = settings[key]
@ -272,81 +273,63 @@ function addSettingsListener (key, handler, initCall) {
}
}
function removeSettingsListener (key, handler) {
const handlers = settingsChangeHandlers[key];
const handlers = settingsChangeHandlers[key]
if (!handlers) {
return;
return
}
handlers.splice(handlers.indexOf(handler), 1);
handlers.splice(handlers.indexOf(handler), 1)
}
function loadSettings () {
for (const key in fixedSettings) {
settings[key] = fixedSettings[key];
GM_setValue(key, fixedSettings[key]);
settings[key] = fixedSettings[key]
GM_setValue(key, fixedSettings[key])
}
if (Object.keys(languageCodeToName).includes(navigator.language)) {
settings.i18n = true;
settings.i18nLanguage = languageCodeToName[navigator.language];
settings.i18n = true
settings.i18nLanguage = languageCodeToName[navigator.language]
}
for (const key in settings) {
let value = GM_getValue(key);
let value = GM_getValue(key)
if (value === undefined) {
value = settings[key];
GM_setValue(key, settings[key]);
}
else if (settings[key] !== undefined && value.constructor === Object) {
value = Object.assign(settings[key], value);
value = settings[key]
GM_setValue(key, settings[key])
} else if (settings[key] !== undefined && value.constructor === Object) {
value = Object.assign(settings[key], value)
}
Object.defineProperty(settings, key, {
get () {
return value;
return value
},
set (newValue) {
value = newValue;
GM_setValue(key, newValue);
value = newValue
GM_setValue(key, newValue)
const handlers = settingsChangeHandlers[key];
const handlers = settingsChangeHandlers[key]
if (handlers) {
if (key === "useDarkStyle") {
setTimeout(() => handlers.forEach(h => h(newValue, value)), 200);
}
else {
handlers.forEach(h => h(newValue, value));
if (key === 'useDarkStyle') {
setTimeout(() => handlers.forEach(h => h(newValue, value)), 200)
} else {
handlers.forEach(h => h(newValue, value))
}
}
const input = document.querySelector(`input[key=${key}]`);
const input = document.querySelector(`input[key=${key}]`)
if (input !== null) {
if (input.type === "checkbox") {
input.checked = newValue;
}
else if (input.type === "text" && !input.parentElement.classList.contains("gui-settings-dropdown")) {
input.value = newValue;
if (input.type === 'checkbox') {
input.checked = newValue
} else if (input.type === 'text' && !input.parentElement.classList.contains('gui-settings-dropdown')) {
input.value = newValue
}
}
},
});
// if (settings[key] !== undefined && value.constructor === Object)
// {
// settings[key] = Object.assign(settings[key], value);
// }
// else
// {
// settings[key] = value;
// }
}
})
}
}
function saveSettings (newSettings) {
// for (const key in settings)
// {
// GM_setValue(key, newSettings[key]);
// }
}
function onSettingsChange () {
// for (const key in settings)
// {
// GM_addValueChangeListener(key, change);
// }
console.warn("此功能已弃用.");
};
console.warn('此功能已弃用.')
}
;
class Ajax
{
static send(xhr, body, text = true)

View File

@ -139,8 +139,8 @@ const customNavbarDefaultOrders = {
favoritesList: 16,
historyList: 17,
upload: 18,
blank3: 19
};
blank3: 19,
}
const settings = {
useDarkStyle: false,
compactLayout: false,
@ -153,8 +153,8 @@ const settings = {
touchVideoPlayer: false,
customControlBackgroundOpacity: 0.64,
customControlBackground: true,
darkScheduleStart: "18:00",
darkScheduleEnd: "6:00",
darkScheduleStart: '18:00',
darkScheduleEnd: '6:00',
darkSchedule: false,
blurVideoControl: false,
toast: true,
@ -167,14 +167,14 @@ const settings = {
hideTopSearch: false,
touchVideoPlayerDoubleTapControl: false,
touchVideoPlayerAnimation: false,
customStyleColor: "#00A0D8",
customStyleColor: '#00A0D8',
preserveRank: true,
blurBackgroundOpacity: 0.382,
useDefaultPlayerMode: false,
applyPlayerModeOnPlay: true,
defaultPlayerMode: "常规",
defaultPlayerMode: '常规',
useDefaultVideoQuality: false,
defaultVideoQuality: "自动",
defaultVideoQuality: '自动',
useDefaultDanmakuSettings: false,
enableDanmaku: true,
rememberDanmakuSettings: false,
@ -182,8 +182,8 @@ const settings = {
subtitlesPreserve: false,
smartMask: false,
},
defaultPlayerLayout: "新版",
defaultBangumiLayout: "旧版",
defaultPlayerLayout: '新版',
defaultBangumiLayout: '旧版',
useDefaultPlayerLayout: false,
skipChargeList: false,
comboLike: false,
@ -198,10 +198,10 @@ const settings = {
framePlayback: true,
useCommentStyle: true,
imageResolution: false,
imageResolutionScale: "auto",
imageResolutionScale: 'auto',
toastInternalError: false,
i18n: false,
i18nLanguage: "日本語",
i18nLanguage: '日本語',
playerFocus: false,
playerFocusOffset: -10,
oldTweets: false,
@ -234,13 +234,15 @@ const settings = {
hideOldEntry: true,
videoScreenshot: false,
hideBangumiReviews: false,
filenameFormat: "[title][ - ep]",
filenameFormat: '[title][ - ep]',
sideBarOffset: 0,
noLiveAutoplay: false,
hideHomeLive: false,
noMiniVideoAutoplay: false,
useDefaultVideoSpeed: false,
defaultVideoSpeed: 1,
cache: {},
};
}
const fixedSettings = {
guiSettings: true,
viewCover: true,
@ -255,16 +257,15 @@ const fixedSettings = {
forceWide: false,
useNewStyle: false,
overrideNavBar: false,
latestVersionLink: "https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.user.js",
latestVersionLink: 'https://github.com/the1812/Bilibili-Evolved/raw/master/bilibili-evolved.user.js',
currentVersion: GM_info.script.version,
};
const settingsChangeHandlers = {};
}
const settingsChangeHandlers = {}
function addSettingsListener (key, handler, initCall) {
if (!settingsChangeHandlers[key]) {
settingsChangeHandlers[key] = [handler];
}
else {
settingsChangeHandlers[key].push(handler);
settingsChangeHandlers[key] = [handler]
} else {
settingsChangeHandlers[key].push(handler)
}
if (initCall) {
const value = settings[key]
@ -272,81 +273,63 @@ function addSettingsListener (key, handler, initCall) {
}
}
function removeSettingsListener (key, handler) {
const handlers = settingsChangeHandlers[key];
const handlers = settingsChangeHandlers[key]
if (!handlers) {
return;
return
}
handlers.splice(handlers.indexOf(handler), 1);
handlers.splice(handlers.indexOf(handler), 1)
}
function loadSettings () {
for (const key in fixedSettings) {
settings[key] = fixedSettings[key];
GM_setValue(key, fixedSettings[key]);
settings[key] = fixedSettings[key]
GM_setValue(key, fixedSettings[key])
}
if (Object.keys(languageCodeToName).includes(navigator.language)) {
settings.i18n = true;
settings.i18nLanguage = languageCodeToName[navigator.language];
settings.i18n = true
settings.i18nLanguage = languageCodeToName[navigator.language]
}
for (const key in settings) {
let value = GM_getValue(key);
let value = GM_getValue(key)
if (value === undefined) {
value = settings[key];
GM_setValue(key, settings[key]);
}
else if (settings[key] !== undefined && value.constructor === Object) {
value = Object.assign(settings[key], value);
value = settings[key]
GM_setValue(key, settings[key])
} else if (settings[key] !== undefined && value.constructor === Object) {
value = Object.assign(settings[key], value)
}
Object.defineProperty(settings, key, {
get () {
return value;
return value
},
set (newValue) {
value = newValue;
GM_setValue(key, newValue);
value = newValue
GM_setValue(key, newValue)
const handlers = settingsChangeHandlers[key];
const handlers = settingsChangeHandlers[key]
if (handlers) {
if (key === "useDarkStyle") {
setTimeout(() => handlers.forEach(h => h(newValue, value)), 200);
}
else {
handlers.forEach(h => h(newValue, value));
if (key === 'useDarkStyle') {
setTimeout(() => handlers.forEach(h => h(newValue, value)), 200)
} else {
handlers.forEach(h => h(newValue, value))
}
}
const input = document.querySelector(`input[key=${key}]`);
const input = document.querySelector(`input[key=${key}]`)
if (input !== null) {
if (input.type === "checkbox") {
input.checked = newValue;
}
else if (input.type === "text" && !input.parentElement.classList.contains("gui-settings-dropdown")) {
input.value = newValue;
if (input.type === 'checkbox') {
input.checked = newValue
} else if (input.type === 'text' && !input.parentElement.classList.contains('gui-settings-dropdown')) {
input.value = newValue
}
}
},
});
// if (settings[key] !== undefined && value.constructor === Object)
// {
// settings[key] = Object.assign(settings[key], value);
// }
// else
// {
// settings[key] = value;
// }
}
})
}
}
function saveSettings (newSettings) {
// for (const key in settings)
// {
// GM_setValue(key, newSettings[key]);
// }
}
function onSettingsChange () {
// for (const key in settings)
// {
// GM_addValueChangeListener(key, change);
// }
console.warn("此功能已弃用.");
};
console.warn('此功能已弃用.')
}
;
class Ajax
{
static send(xhr, body, text = true)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
min/index.min.html Normal file
View File

@ -0,0 +1 @@
<!doctypehtml><html lang=en><meta charset=UTF-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=X-UA-Compatible content="ie=edge"><title>Document</title><script src=index.js defer=defer type=module></script>

View File

@ -444,7 +444,36 @@ li.nav-item[report-id='playpage_dynamic'] .i-frame,
width: 240px;
font-size: 12px;
}
.user-info-panel>*
.user-info-panel .welcome
{
font-size: 16px;
font-weight: bold;
margin: 46px 0 16px 0;
text-align: center;
}
.user-info-panel .grey-button,
.user-info-panel .theme-button
{
align-self: stretch;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
}
.user-info-panel .grey-button
{
background: #EDEDED;
}
.custom-navbar.dark .user-info-panel .grey-button
{
background: #444;
}
.custom-navbar .user-info-panel .theme-button
{
background: var(--theme-color);
color: var(--foreground-color);
}
/* .user-info-panel>*
{
display: flex;
flex-direction: column;
@ -608,7 +637,7 @@ li.nav-item[report-id='playpage_dynamic'] .i-frame,
.custom-navbar .not-logged-in .sign-up:hover
{
background-color: #8884;
}
} */
.custom-navbar li:hover .user-face,
.custom-navbar li:hover .user-pendant

View File

@ -1,11 +1,9 @@
if (isIframe())
{
if (isIframe()) {
return;
}
document.body.style.setProperty("--navbar-bounds-padding", `0 ${settings.customNavbarBoundsPadding}%`);
document.body.style.setProperty("--navbar-blur-opacity", settings.customNavbarBlurOpacity || 0.7);
addSettingsListener("customNavbarBlurOpacity", value =>
{
addSettingsListener("customNavbarBlurOpacity", value => {
document.body.style.setProperty("--navbar-blur-opacity", value);
});
let showWidget = true;
@ -17,24 +15,20 @@ const attributes = {
<span>顶栏布局</span>
</div>`,
condition: () => showWidget,
success: async () =>
{
success: async () => {
await SpinQuery.select(".custom-navbar-settings");
await import("slip");
const { debounce } = await import("debounce");
// const customNavbar = document.querySelector(".custom-navbar");
const button = document.querySelector("#custom-navbar-settings");
button.addEventListener("click", async () =>
{
button.addEventListener("click", async () => {
const settingsPanel = await SpinQuery.select(".custom-navbar-settings");
if (settingsPanel)
{
if (settingsPanel) {
settingsPanel.classList.toggle("show");
document.querySelector(".gui-settings-mask").click();
}
});
button.addEventListener("mouseover", () =>
{
button.addEventListener("mouseover", () => {
const displayNames = {
blank1: "弹性空白1",
logo: "Logo",
@ -72,31 +66,24 @@ const attributes = {
</li>
`,
methods: {
hidden()
{
hidden () {
return settings.customNavbarHidden.includes(this.item.name);
},
viewBorder(view)
{
viewBorder (view) {
const navbarItem = document.querySelector(`.custom-navbar li[data-name='${this.item.name}']`);
if (navbarItem !== null)
{
if (navbarItem !== null) {
navbarItem.classList[view ? "add" : "remove"]("view-border");
}
},
toggleHidden()
{
toggleHidden () {
const isHidden = this.hidden();
if (isHidden === false)
{
if (isHidden === false) {
settings.customNavbarHidden.push(this.item.name);
settings.customNavbarHidden = settings.customNavbarHidden;
}
else
{
else {
const index = settings.customNavbarHidden.indexOf(this.item.name);
if (index === -1)
{
if (index === -1) {
return;
}
settings.customNavbarHidden.splice(index, 1);
@ -104,45 +91,36 @@ const attributes = {
}
this.$forceUpdate();
const navbarItem = document.querySelector(`.custom-navbar li[data-name='${this.item.name}']`);
if (navbarItem !== null)
{
if (navbarItem !== null) {
navbarItem.style.display = isHidden ? "flex" : "none";
}
}
}
});
const updateBoundsPadding = debounce(value =>
{
const updateBoundsPadding = debounce(value => {
settings.customNavbarBoundsPadding = value;
document.body.style.setProperty("--navbar-bounds-padding", `0 ${value}%`);
}, 200);
new Vue({
el: ".custom-navbar-settings",
mounted()
{
mounted () {
const list = document.querySelector(".custom-navbar-settings .order-list");
const reorder = ({ sourceItem, targetItem, orderBefore, orderAfter }) =>
{
if (orderBefore === orderAfter)
{
const reorder = ({ sourceItem, targetItem, orderBefore, orderAfter }) => {
if (orderBefore === orderAfter) {
return;
}
const entires = Object.entries(settings.customNavbarOrder);
const names = entires.sort((a, b) => a[1] - b[1]).map(it => it[0]);
if (orderBefore < orderAfter)
{
for (let i = orderBefore + 1; i <= orderAfter; i++)
{
if (orderBefore < orderAfter) {
for (let i = orderBefore + 1; i <= orderAfter; i++) {
const name = names[i];
settings.customNavbarOrder[name] = i - 1;
document.querySelector(`.custom-navbar li[data-name='${name}']`).style.order = i - 1;
}
}
else
{
for (let i = orderBefore - 1; i >= orderAfter; i--)
{
else {
for (let i = orderBefore - 1; i >= orderAfter; i--) {
const name = names[i];
settings.customNavbarOrder[name] = i + 1;
document.querySelector(`.custom-navbar li[data-name='${name}']`).style.order = i + 1;
@ -154,16 +132,13 @@ const attributes = {
list.insertBefore(sourceItem, targetItem);
};
new Slip(list);
list.addEventListener("slip:beforewait", e =>
{
if (e.target.classList.contains("mdi-menu"))
{
list.addEventListener("slip:beforewait", e => {
if (e.target.classList.contains("mdi-menu")) {
e.preventDefault();
}
}, false);
list.addEventListener("slip:beforeswipe", e => e.preventDefault(), false);
list.addEventListener("slip:reorder", e =>
{
list.addEventListener("slip:reorder", e => {
reorder({
sourceItem: e.target,
targetItem: e.detail.insertBefore,
@ -174,11 +149,9 @@ const attributes = {
}, false);
},
computed: {
orderList()
{
orderList () {
const orders = Object.entries(settings.customNavbarOrder);
return orders.sort((a, b) => a[1] - b[1]).map(it =>
{
return orders.sort((a, b) => a[1] - b[1]).map(it => {
return {
displayName: displayNames[it[0]],
name: it[0],
@ -191,25 +164,20 @@ const attributes = {
boundsPadding: settings.customNavbarBoundsPadding,
},
watch: {
boundsPadding(value)
{
boundsPadding (value) {
updateBoundsPadding(value);
},
},
methods: {
close()
{
close () {
document.querySelector(".custom-navbar-settings").classList.remove("show");
},
restoreDefault()
{
if (typeof customNavbarDefaultOrders === "undefined")
{
restoreDefault () {
if (typeof customNavbarDefaultOrders === "undefined") {
Toast.error("未找到默认值设定, 请更新您的脚本.");
return;
}
if (confirm("确定要恢复默认顶栏布局吗? 恢复后页面将刷新."))
{
if (confirm("确定要恢复默认顶栏布局吗? 恢复后页面将刷新.")) {
this.boundsPadding = 5;
settings.customNavbarOrder = customNavbarDefaultOrders;
location.reload();
@ -220,25 +188,21 @@ const attributes = {
}, { once: true });
},
},
unload: () =>
{
unload: () => {
const navbar = document.querySelectorAll(".custom-navbar,.custom-navbar-settings");
navbar.forEach(it => it.style.display = "none");
resources.removeStyle("customNavbarStyle");
},
reload: () =>
{
reload: () => {
const navbar = document.querySelectorAll(".custom-navbar,.custom-navbar-settings");
navbar.forEach(it => it.style.display = "flex");
resources.applyImportantStyle("customNavbarStyle");
},
};
const classHandler = (key, value, element) =>
{
const classHandler = (key, value, element) => {
element.classList[value ? "add" : "remove"](key);
}
const darkHandler = value =>
{
const darkHandler = value => {
document.querySelector(".custom-navbar").classList[value ? "add" : "remove"]("dark");
document.querySelector(".custom-navbar-settings").classList[value ? "add" : "remove"]("dark");
};
@ -262,8 +226,7 @@ const unsupportedUrls = [
"/member.bilibili.com/video/upload",
]
if (!supportedUrls.some(it => document.URL.includes(it))
|| unsupportedUrls.some(it => document.URL.includes(it)))
{
|| unsupportedUrls.some(it => document.URL.includes(it))) {
showWidget = false;
return attributes;
}
@ -272,10 +235,8 @@ let userInfo = {};
let orders = {
};
class NavbarComponent
{
constructor()
{
class NavbarComponent {
constructor () {
this.html = ``;
this.popupHtml = ``;
this.flex = `0 0 auto`;
@ -287,51 +248,40 @@ class NavbarComponent
this.touch = settings.touchNavBar;
this.active = false;
}
get name()
{
get name () {
return "undefined";
}
get order()
{
get order () {
return settings.customNavbarOrder[this.name];
}
get hidden()
{
get hidden () {
return settings.customNavbarHidden.includes(this.name);
}
}
class Blank extends NavbarComponent
{
constructor(number)
{
class Blank extends NavbarComponent {
constructor (number) {
super();
this.number = number;
this.flex = "1 0 auto";
this.disabled = true;
}
get name()
{
get name () {
return "blank" + this.number;
}
}
class Logo extends NavbarComponent
{
constructor()
{
class Logo extends NavbarComponent {
constructor () {
super();
this.href = `https://www.bilibili.com/`;
this.html = /*html*/`<i class="custom-navbar-iconfont custom-navbar-icon-logo"></i>`;
this.touch = false;
}
get name()
{
get name () {
return "logo";
}
}
class SimpleLink extends NavbarComponent
{
constructor(name, link, linkName)
{
class SimpleLink extends NavbarComponent {
constructor (name, link, linkName) {
super();
this.linkName = linkName;
this.html = name;
@ -339,15 +289,12 @@ class SimpleLink extends NavbarComponent
this.touch = false;
this.active = document.URL.startsWith(link);
}
get name()
{
get name () {
return this.linkName + "Link";
}
}
class Upload extends NavbarComponent
{
constructor()
{
class Upload extends NavbarComponent {
constructor () {
super();
this.href = "https://member.bilibili.com/v2#/upload/video/frame";
this.html = /*html*/`
@ -365,15 +312,12 @@ class Upload extends NavbarComponent
</ul>
`;
}
get name()
{
get name () {
return "upload";
}
}
class Messages extends NavbarComponent
{
constructor()
{
class Messages extends NavbarComponent {
constructor () {
super();
this.href = "https://message.bilibili.com/";
this.html = "消息";
@ -389,44 +333,35 @@ class Messages extends NavbarComponent
this.active = document.URL.startsWith("https://message.bilibili.com/");
this.init();
}
get name()
{
get name () {
return "messages";
}
async init()
{
async init () {
const json = await Ajax.getJsonWithCredentials("https://message.bilibili.com/api/notify/query.notify.count.do");
const list = await SpinQuery.select("#message-list");
const items = [...list.querySelectorAll("a[data-name]")];
const names = items.map(it => it.getAttribute("data-name"));
if (json.code !== 0)
{
if (json.code !== 0) {
return;
}
const notifyElement = await SpinQuery.select(`.custom-navbar li[data-name='${this.name}'] .notify-count`);
let totalCount = names.reduce((acc, it) => acc + json.data[it], 0);
if (!totalCount)
{
if (!totalCount) {
return;
}
notifyElement.innerHTML = totalCount;
names.forEach((name, index) =>
{
names.forEach((name, index) => {
const count = json.data[name];
if (count > 0)
{
if (count > 0) {
items[index].setAttribute("data-count", count);
}
else
{
else {
items[index].removeAttribute("data-count");
}
});
items.forEach(item =>
{
item.addEventListener("click", () =>
{
items.forEach(item => {
item.addEventListener("click", () => {
const count = item.getAttribute("data-count");
item.removeAttribute("data-count");
totalCount -= count;
@ -435,10 +370,8 @@ class Messages extends NavbarComponent
})
}
}
class Category extends NavbarComponent
{
constructor()
{
class Category extends NavbarComponent {
constructor () {
super();
this.html = `主站`;
this.requestedPopup = true;
@ -460,8 +393,7 @@ class Category extends NavbarComponent
</li>
</ul>
`;
this.getOnlineInfo().then(info =>
{
this.getOnlineInfo().then(info => {
new Vue({
el: "#custom-navbar-home-popup",
data: {
@ -470,15 +402,12 @@ class Category extends NavbarComponent
});
});
}
get name()
{
get name () {
return "category";
}
async getOnlineInfo()
{
async getOnlineInfo () {
const json = await Ajax.getJson("https://api.bilibili.com/x/web-interface/online");
if (parseInt(json.code) !== 0)
{
if (parseInt(json.code) !== 0) {
throw new Error(`[自定义顶栏] 分区投稿信息获取失败: ${json.message}`);
}
const regionCount = json.data.region_count;
@ -575,11 +504,10 @@ class Category extends NavbarComponent
};
}
}
class UserInfo extends NavbarComponent
{
constructor()
{
class UserInfo extends NavbarComponent {
constructor () {
super();
this.noPadding = true;
this.href = "https://space.bilibili.com";
this.html = /*html*/`
<div class="user-face-container">
@ -592,7 +520,8 @@ class UserInfo extends NavbarComponent
<div v-if="isLogin" class="logged-in">
<a class="name" target="_blank" href="https://space.bilibili.com/">{{uname}}</a>
<div class="row">
<a target="_blank" title="等级" href="https://account.bilibili.com/site/record?type=exp" class="level">LV<strong>{{level_info.current_level}}</strong></a>
<a target="_blank" title="等级" href="https://account.bilibili.com/site/record?type=exp"
class="level">LV<strong>{{level_info.current_level}}</strong></a>
<a target="_blank" href="https://account.bilibili.com/account/big" class="type">{{userType}}</a>
<div class="level-progress">
<div class="level-progress-thumb" v-bind:style="levelProgressStyle"></div>
@ -602,13 +531,16 @@ class UserInfo extends NavbarComponent
<div class="row">
<div class="coins-container">
<a target="_blank" href="https://account.bilibili.com/site/coin" title="硬币" class="coins">{{money}}</a>
<a target="_blank" href="https://pay.bilibili.com/bb_balance.html" title="B币" class="b-coins">{{wallet.bcoin_balance}}</a>
<a target="_blank" href="https://pay.bilibili.com/bb_balance.html" title="B币"
class="b-coins">{{wallet.bcoin_balance}}</a>
</div>
<div class="verifications">
<a target="_blank" v-bind:class="{verified: email_verified }" title="邮箱验证" href="https://passport.bilibili.com/account/security#/bindmail">
<a target="_blank" v-bind:class="{verified: email_verified }" title="邮箱验证"
href="https://passport.bilibili.com/account/security#/bindmail">
<i class="mdi mdi-email"></i>
</a>
<a target="_blank" v-bind:class="{verified: mobile_verified }" title="手机验证" href="https://passport.bilibili.com/account/security#/bindphone">
<a target="_blank" v-bind:class="{verified: mobile_verified }" title="手机验证"
href="https://passport.bilibili.com/account/security#/bindphone">
<i class="mdi mdi-cellphone-android"></i>
</a>
</div>
@ -639,20 +571,19 @@ class UserInfo extends NavbarComponent
</div>
</div>
<div v-else class="not-logged-in">
<a href="https://passport.bilibili.com/login" class="login">登录</a>
<a href="https://passport.bilibili.com/register/phone.html" class="sign-up">注册</a>
<h1 class="welcome">欢迎来到 bilibili</h1>
<a href="https://passport.bilibili.com/register/phone.html" class="sign-up grey-button">注册</a>
<a href="https://passport.bilibili.com/login" class="login theme-button">登录</a>
</div>
</div>
`;
this.requestedPopup = true;
this.init();
}
get name()
{
get name () {
return "userInfo";
}
async init()
{
async init () {
const panel = await SpinQuery.select(".custom-navbar .user-info-panel");
new Vue({
el: panel,
@ -660,31 +591,24 @@ class UserInfo extends NavbarComponent
...userInfo,
},
computed: {
userType()
{
if (!this.isLogin)
{
userType () {
if (!this.isLogin) {
return "未登录";
}
if (this.level_info.current_level === 0)
{
if (this.level_info.current_level === 0) {
return "注册会员";
}
if (this.vipStatus === 1)
{
if (this.vipType === 1)
{
if (this.vipStatus === 1) {
if (this.vipType === 1) {
return this.vip_theme_type ? "小会员" : "大会员";
}
else if (this.vipType === 2)
{
else if (this.vipType === 2) {
return this.vip_theme_type ? "年度小会员" : "年度大会员";
}
}
return "正式会员";
},
levelProgressStyle()
{
levelProgressStyle () {
const progress = (this.level_info.next_exp - this.level_info.current_exp) / (this.level_info.next_exp - this.level_info.current_min);
return {
transform: `scaleX(${progress})`
@ -693,41 +617,34 @@ class UserInfo extends NavbarComponent
},
});
const face = await SpinQuery.select(".custom-navbar .user-face-container .user-face");
if (userInfo.isLogin)
{
if (userInfo.isLogin) {
const faceUrl = userInfo.face.replace("http", "https");
// face.setAttribute("src", faceUrl);
const faceBaseSize = 68;
const dpis = [1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4];
face.setAttribute("srcset", dpis.map(dpi =>
{
face.setAttribute("srcset", dpis.map(dpi => {
return `${faceUrl}@${parseInt(faceBaseSize * dpi)}w_${parseInt(faceBaseSize * dpi)}h.jpg ${dpi}x`;
}).join(","));
// face.style.backgroundImage = `url('${userInfo.face}@68w_68h.jpg')`;
if (userInfo.pendant.image)
{
if (userInfo.pendant.image) {
const pendant = await SpinQuery.select(".custom-navbar .user-face-container .user-pendant");
const pendantUrl = userInfo.pendant.image.replace("http", "https");
// pendant.setAttribute("src", pendantUrl);
const pendantBaseSize = 116;
pendant.setAttribute("srcset", dpis.reduce((acc, dpi) =>
{
pendant.setAttribute("srcset", dpis.reduce((acc, dpi) => {
return acc + `, ${pendantUrl}@${parseInt(pendantBaseSize * dpi)}w_${parseInt(pendantBaseSize * dpi)}h.png ${dpi}x`;
}, ""));
// pendant.style.backgroundImage = `url('${userInfo.pendant.image}@116w_116h.jpg')`;
}
}
else
{
else {
face.setAttribute("src", "https://static.hdslb.com/images/akari.jpg");
// face.style.backgroundImage = `url('https://static.hdslb.com/images/akari.jpg')`;
}
}
}
class SearchBox extends NavbarComponent
{
constructor()
{
class SearchBox extends NavbarComponent {
constructor () {
super();
this.disabled = true;
this.html = /*html*/`
@ -744,16 +661,12 @@ class SearchBox extends NavbarComponent
`;
this.init();
}
async init()
{
async init () {
const form = await SpinQuery.select("#custom-navbar-search");
const keyword = form.querySelector("input[name='keyword']");
form.addEventListener("submit", e =>
{
if (keyword.value === "")
{
if (!settings.hideTopSearch)
{
form.addEventListener("submit", e => {
if (keyword.value === "") {
if (!settings.hideTopSearch) {
form.querySelector(".recommended-target").click();
}
e.preventDefault();
@ -761,36 +674,28 @@ class SearchBox extends NavbarComponent
}
return true;
});
if (!settings.hideTopSearch)
{
if (!settings.hideTopSearch) {
const json = await Ajax.getJson("https://api.bilibili.com/x/web-interface/search/default");
if (json.code === 0)
{
if (json.code === 0) {
keyword.setAttribute("placeholder", json.data.show_name);
if (json.data.name.startsWith("av"))
{
if (json.data.name.startsWith("av")) {
form.querySelector(".recommended-target").setAttribute("href", `https://www.bilibili.com/${json.data.name}`);
}
else
{
else {
form.querySelector(".recommended-target").setAttribute("href", `https://search.bilibili.com/all?keyword=${json.data.name}`);
}
}
else
{
else {
console.error("[自定义顶栏] 获取搜索推荐词失败");
}
}
}
get name()
{
get name () {
return "search";
}
}
class Iframe extends NavbarComponent
{
constructor(name, link, { src, width, height, lazy, iframeName })
{
class Iframe extends NavbarComponent {
constructor (name, link, { src, width, height, lazy, iframeName }) {
super();
this.iframeName = iframeName;
this.html = name;
@ -803,46 +708,36 @@ class Iframe extends NavbarComponent
this.touch = false;
this.transparent = true;
}
get name()
{
get name () {
return this.iframeName + "Iframe";
}
}
class NotifyIframe extends Iframe
{
constructor(...args)
{
class NotifyIframe extends Iframe {
constructor (...args) {
super(...args);
this.touch = settings.touchNavBar;
this.getNotifyCount();
}
getApiUrl()
{
getApiUrl () {
return null;
}
getCount()
{
getCount () {
return 0;
}
async getNotifyCount()
{
async getNotifyCount () {
const notifyElement = await SpinQuery.select(`.custom-navbar li[data-name='${this.name}'] .notify-count`);
const json = await Ajax.getJsonWithCredentials(this.getApiUrl());
const count = this.getCount(json);
if (json.code === 0 && count)
{
if (json.code === 0 && count) {
notifyElement.innerHTML = count;
this.onPopup = () =>
{
this.onPopup = () => {
notifyElement.innerHTML = '';
};
}
}
}
class Activities extends NotifyIframe
{
constructor()
{
class Activities extends NotifyIframe {
constructor () {
super("动态",
settings.oldTweets ? "https://www.bilibili.com/account/dynamic" : "https://t.bilibili.com/",
{
@ -853,17 +748,14 @@ class Activities extends NotifyIframe
});
this.active = document.URL.replace(/\?.*$/, "") === "https://t.bilibili.com/";
}
getApiUrl()
{
getApiUrl () {
const updateNumber = document.cookie.replace(new RegExp(`(?:(?:^|.*;\\s*)bp_t_offset_${userInfo.mid}\\s*\\=\\s*([^;]*).*$)|^.*$`), "$1");
return `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_num?rsp_type=1&uid=${userInfo.mid}&update_num_dy_id=${updateNumber}&type_list=8,512,64`;
}
getCount(json)
{
getCount (json) {
return json.data.update_num;
}
get name()
{
get name () {
return "activities";
}
}
@ -887,10 +779,8 @@ class Activities extends NotifyIframe
// return Object.values(json.data).reduce((a, b) => a + b, 0);
// }
// }
class VideoList extends NavbarComponent
{
constructor({ mainUrl, name, apiUrl, listName, listMap })
{
class VideoList extends NavbarComponent {
constructor ({ mainUrl, name, apiUrl, listName, listMap }) {
super();
this.href = mainUrl;
this.listName = listName;
@ -901,20 +791,16 @@ class VideoList extends NavbarComponent
<li class="loading">加载中...</li>
</ol>
`;
this.onPopup = async () =>
{
if (!listMap)
{
this.onPopup = async () => {
if (!listMap) {
return;
}
const videoListElement = await SpinQuery.select(`.video-list.${listName}`);
if (videoListElement === null)
{
if (videoListElement === null) {
return;
}
const json = await Ajax.getJsonWithCredentials(apiUrl);
if (json.code !== 0)
{
if (json.code !== 0) {
logError(`加载${name}信息失败. 错误码: ${json.code} ${json.message}`);
return;
}
@ -925,24 +811,19 @@ class VideoList extends NavbarComponent
videoListElement.classList.add("loaded");
};
}
get name()
{
get name () {
return this.listName + "List";
}
}
class WatchlaterList extends VideoList
{
constructor()
{
class WatchlaterList extends VideoList {
constructor () {
super({
name: "稍后再看",
mainUrl: "https://www.bilibili.com/watchlater/#/list",
apiUrl: "https://api.bilibili.com/x/v2/history/toview/web",
listName: "watchlater",
listMap: json =>
{
return json.data.list.slice(0, 6).map(item =>
{
listMap: json => {
return json.data.list.slice(0, 6).map(item => {
const pages = item.pages.map(it => it.cid);
const page = item.cid === 0 ? 1 : pages.indexOf(item.cid) + 1;
const href = settings.watchLaterRedirect ?
@ -957,19 +838,15 @@ class WatchlaterList extends VideoList
this.active = document.URL.startsWith("https://www.bilibili.com/watchlater/");
}
}
class FavoritesList extends VideoList
{
constructor()
{
class FavoritesList extends VideoList {
constructor () {
super({
name: "收藏",
mainUrl: `https://space.bilibili.com/${userInfo.mid}/favlist`,
apiUrl: "https://api.bilibili.com/medialist/gateway/coll/resource/recent",
listName: "favorites",
listMap: json =>
{
return json.data.map(item =>
{
listMap: json => {
return json.data.map(item => {
return /*html*/`<li>
<a target="_blank" href="https://www.bilibili.com/video/av${item.id}">${item.title}</a>
</li>`;
@ -979,39 +856,31 @@ class FavoritesList extends VideoList
this.active = document.URL.replace(/\?.*$/, "") === `https://space.bilibili.com/${userInfo.mid}/favlist`;
}
}
class HistoryList extends VideoList
{
constructor()
{
class HistoryList extends VideoList {
constructor () {
super({
name: "历史",
mainUrl: "https://www.bilibili.com/account/history",
apiUrl: "https://api.bilibili.com/x/v2/history?pn=1&ps=6",
listName: "history",
listMap: json =>
{
return json.data.map(item =>
{
listMap: json => {
return json.data.map(item => {
let parameter = [];
let description = "";
const page = item.page ? item.page.page : 1;
const progress = item.progress >= 0 ? item.progress / item.duration : 1;
if (page !== 1)
{
if (page !== 1) {
parameter.push(`p=${page}`);
description += `看到第${page}`;
}
if (item.progress > 0 && item.progress < item.duration)
{
if (item.progress > 0 && item.progress < item.duration) {
parameter.push(`t=${item.progress}`);
description += ` ${Math.floor(progress * 100)}%`;
}
else if (item.progress === 0)
{
else if (item.progress === 0) {
description += ` 刚开始看`;
}
else
{
else {
description += " 100%";
}
return /*html*/`<li class="history-item">
@ -1028,28 +897,23 @@ class HistoryList extends VideoList
}
}
(async () =>
{
(async () => {
const html = await import("customNavbarHtml");
const json = await Ajax.getJsonWithCredentials("https://api.bilibili.com/x/web-interface/nav");
userInfo = json.data;
document.body.insertAdjacentHTML("beforeend", html);
addSettingsListener("useDarkStyle", darkHandler);
darkHandler(settings.useDarkStyle);
["Fill", "Shadow", "Compact", "Blur"].forEach(item =>
{
["Fill", "Shadow", "Compact", "Blur"].forEach(item => {
addSettingsListener("customNavbar" + item, value => classHandler(item.toLowerCase(), value, document.querySelector(".custom-navbar")));
classHandler(item.toLowerCase(), settings["customNavbar" + item], document.querySelector(".custom-navbar"));
});
SpinQuery.condition(() => document.getElementById("banner_link"),
banner => banner === null ? null : banner.style.backgroundImage,
banner =>
{
Observer.attributes(banner, () =>
{
banner => {
Observer.attributes(banner, () => {
const blurLayers = document.querySelectorAll(".custom-navbar .blur-layer");
blurLayers.forEach(blurLayer =>
{
blurLayers.forEach(blurLayer => {
blurLayer.style.backgroundImage = banner.style.backgroundImage;
blurLayer.setAttribute("data-image", banner.style.backgroundImage);
});
@ -1083,8 +947,7 @@ class HistoryList extends VideoList
new SearchBox,
new UserInfo,
];
if (userInfo.isLogin)
{
if (userInfo.isLogin) {
components.push(
new Messages,
new Activities,
@ -1100,10 +963,8 @@ class HistoryList extends VideoList
components,
},
methods: {
requestPopup(component)
{
if (!component.requestedPopup && !component.disabled && !component.active)
{
requestPopup (component) {
if (!component.requestedPopup && !component.disabled && !component.active) {
this.$set(component, `requestedPopup`, true);
component.onPopup && component.onPopup();
}